/** * Import a key defined by a fingerprint into the local keyring. * @param handle the context handle * @param fpr the fingerprint key ID to import * @return 0 on success, -1 on error */ int _alpm_key_import(alpm_handle_t *handle, const char *fpr) { int answer = 0, ret = -1; alpm_pgpkey_t fetch_key; memset(&fetch_key, 0, sizeof(fetch_key)); if(key_search(handle, fpr, &fetch_key) == 1) { _alpm_log(handle, ALPM_LOG_DEBUG, "unknown key, found %s on keyserver\n", fetch_key.uid); if(!_alpm_access(handle, handle->gpgdir, "pubring.gpg", W_OK)) { QUESTION(handle, ALPM_QUESTION_IMPORT_KEY, &fetch_key, NULL, NULL, &answer); if(answer) { if(key_import(handle, &fetch_key) == 0) { ret = 0; } else { _alpm_log(handle, ALPM_LOG_ERROR, _("key \"%s\" could not be imported\n"), fetch_key.uid); } } } else { /* keyring directory was not writable, so we don't even try */ _alpm_log(handle, ALPM_LOG_WARNING, _("key %s, \"%s\" found on keyserver, keyring is not writable\n"), fetch_key.fingerprint, fetch_key.uid); } } else { _alpm_log(handle, ALPM_LOG_ERROR, _("key \"%s\" could not be looked up remotely\n"), fpr); } gpgme_key_unref(fetch_key.data); return ret; }
/** Find group members across a list of databases. * If a member exists in several databases, only the first database is used. * IgnorePkg is also handled. * @param dbs the list of alpm_db_t * * @pram name the name of the group * @return the list of alpm_pkg_t * (caller is responsible for alpm_list_free) */ alpm_list_t SYMEXPORT *alpm_find_group_pkgs(alpm_list_t *dbs, const char *name) { alpm_list_t *i, *j, *pkgs = NULL, *ignorelist = NULL; for(i = dbs; i; i = i->next) { alpm_db_t *db = i->data; alpm_group_t *grp = alpm_db_readgroup(db, name); if(!grp) continue; for(j = grp->packages; j; j = j->next) { alpm_pkg_t *pkg = j->data; if(_alpm_pkg_find(ignorelist, alpm_pkg_get_name(pkg))) { continue; } if(_alpm_pkg_should_ignore(db->handle, pkg)) { ignorelist = alpm_list_add(ignorelist, pkg); int install = 0; QUESTION(db->handle->trans, ALPM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, NULL, NULL, &install); if(!install) continue; } if(!_alpm_pkg_find(pkgs, alpm_pkg_get_name(pkg))) { pkgs = alpm_list_add(pkgs, pkg); } } } alpm_list_free(ignorelist); return pkgs; }
void MyWriteMsg::reject() { try { if (self->plainTextEdit->toPlainText().trimmed().isEmpty()) { QDialog::reject(); return; } if (QUESTION(utf8("提醒"), utf8("是否存为草稿?")) == QMessageBox::No) { QDialog::reject(); return; } Message msg; msg.setContent(self->plainTextEdit->toPlainText()); msg.setTime(QDateTime::currentDateTime()); msg.setType(Message::DRAFT); MessageService * msgServer = new MessageService; msgServer->saveMsg(msg); delete msgServer; QDialog::reject(); } CATCH_BLOCKS }
/** * Prompts to delete the file now that we know it is invalid. * @param handle the context handle * @param filename the absolute path of the file to test * @param reason an error code indicating the reason for package invalidity * * @return 1 if file was removed, 0 otherwise */ static int prompt_to_delete(alpm_handle_t *handle, const char *filepath, alpm_errno_t reason) { int doremove = 0; QUESTION(handle, ALPM_QUESTION_CORRUPTED_PKG, (char *)filepath, &reason, NULL, &doremove); if(doremove) { unlink(filepath); } return doremove; }
/** Compares the md5sum of a file to the expected value. * * If the md5sum does not match, the user is asked whether the file * should be deleted. * * @param trans the transaction * @param filename the absolute path of the file to test * @param md5sum the expected md5sum of the file * * @return 0 if the md5sum matched, 1 if not, -1 in case of errors */ static int test_md5sum(alpm_trans_t *trans, const char *filepath, const char *md5sum) { int ret = _alpm_test_md5sum(filepath, md5sum); if(ret == 1) { int doremove = 0; QUESTION(trans, ALPM_TRANS_CONV_CORRUPTED_PKG, (char *)filepath, NULL, NULL, &doremove); if(doremove) { unlink(filepath); } } return ret; }
/** Find group members across a list of databases. * If a member exists in several databases, only the first database is used. * IgnorePkg is also handled. * @param dbs the list of alpm_db_t * * @param name the name of the group * @return the list of alpm_pkg_t * (caller is responsible for alpm_list_free) */ alpm_list_t SYMEXPORT *alpm_find_group_pkgs(alpm_list_t *dbs, const char *name) { alpm_list_t *i, *j, *pkgs = NULL, *ignorelist = NULL; for(i = dbs; i; i = i->next) { alpm_db_t *db = i->data; alpm_group_t *grp = alpm_db_get_group(db, name); if(!grp) continue; for(j = grp->packages; j; j = j->next) { alpm_pkg_t *pkg = j->data; if(alpm_pkg_find(ignorelist, pkg->name)) { continue; } if(alpm_pkg_should_ignore(db->handle, pkg)) { alpm_question_install_ignorepkg_t question = { .type = ALPM_QUESTION_INSTALL_IGNOREPKG, .install = 0, .pkg = pkg }; ignorelist = alpm_list_add(ignorelist, pkg); QUESTION(db->handle, &question); if(!question.install) continue; } if(!alpm_pkg_find(pkgs, pkg->name)) { pkgs = alpm_list_add(pkgs, pkg); } } } alpm_list_free(ignorelist); return pkgs; }
int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data) { alpm_list_t *i, *j; alpm_list_t *deps = NULL; alpm_list_t *unresolvable = NULL; int from_sync = 0; int ret = 0; alpm_trans_t *trans = handle->trans; alpm_event_t event; if(data) { *data = NULL; } for(i = trans->add; i; i = i->next) { alpm_pkg_t *spkg = i->data; if (spkg->origin == ALPM_PKG_FROM_SYNCDB){ from_sync = 1; break; } } /* ensure all sync database are valid if we will be using them */ for(i = handle->dbs_sync; i; i = i->next) { const alpm_db_t *db = i->data; if(db->status & DB_STATUS_INVALID) { RET_ERR(handle, ALPM_ERR_DB_INVALID, -1); } /* missing databases are not allowed if we have sync targets */ if(from_sync && db->status & DB_STATUS_MISSING) { RET_ERR(handle, ALPM_ERR_DB_NOT_FOUND, -1); } } if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) { alpm_list_t *resolved = NULL; alpm_list_t *remove = alpm_list_copy(trans->remove); alpm_list_t *localpkgs; /* Build up list by repeatedly resolving each transaction package */ /* Resolve targets dependencies */ event.type = ALPM_EVENT_RESOLVEDEPS_START; EVENT(handle, &event); _alpm_log(handle, ALPM_LOG_DEBUG, "resolving target's dependencies\n"); /* build remove list for resolvedeps */ for(i = trans->add; i; i = i->next) { alpm_pkg_t *spkg = i->data; for(j = spkg->removes; j; j = j->next) { remove = alpm_list_add(remove, j->data); } } /* Compute the fake local database for resolvedeps (partial fix for the * phonon/qt issue) */ localpkgs = alpm_list_diff(_alpm_db_get_pkgcache(handle->db_local), trans->add, _alpm_pkg_cmp); /* Resolve packages in the transaction one at a time, in addition building up a list of packages which could not be resolved. */ for(i = trans->add; i; i = i->next) { alpm_pkg_t *pkg = i->data; if(_alpm_resolvedeps(handle, localpkgs, pkg, trans->add, &resolved, remove, data) == -1) { unresolvable = alpm_list_add(unresolvable, pkg); } /* Else, [resolved] now additionally contains [pkg] and all of its dependencies not already on the list */ } alpm_list_free(localpkgs); alpm_list_free(remove); /* If there were unresolvable top-level packages, prompt the user to see if they'd like to ignore them rather than failing the sync */ if(unresolvable != NULL) { alpm_question_remove_pkgs_t question = { .type = ALPM_QUESTION_REMOVE_PKGS, .skip = 0, .packages = unresolvable }; QUESTION(handle, &question); if(question.skip) { /* User wants to remove the unresolvable packages from the transaction. The packages will be removed from the actual transaction when the transaction packages are replaced with a dependency-reordered list below */ handle->pm_errno = 0; if(data) { alpm_list_free_inner(*data, (alpm_list_fn_free)alpm_depmissing_free); alpm_list_free(*data); *data = NULL; } } else { /* pm_errno was set by resolvedeps, callback may have overwrote it */ handle->pm_errno = ALPM_ERR_UNSATISFIED_DEPS; alpm_list_free(resolved); alpm_list_free(unresolvable); ret = -1; goto cleanup; } } /* Set DEPEND reason for pulled packages */ for(i = resolved; i; i = i->next) { alpm_pkg_t *pkg = i->data; if(!alpm_pkg_find(trans->add, pkg->name)) { pkg->reason = ALPM_PKG_REASON_DEPEND; } } /* Unresolvable packages will be removed from the target list; set these * aside in the transaction as a list we won't operate on. If we free them * before the end of the transaction, we may kill pointers the frontend * holds to package objects. */ trans->unresolvable = unresolvable; alpm_list_free(trans->add); trans->add = resolved; event.type = ALPM_EVENT_RESOLVEDEPS_DONE; EVENT(handle, &event); }
static alpm_list_t *check_replacers(alpm_handle_t *handle, alpm_pkg_t *lpkg, alpm_db_t *sdb) { /* 2. search for replacers in sdb */ alpm_list_t *replacers = NULL; alpm_list_t *k; _alpm_log(handle, ALPM_LOG_DEBUG, "searching for replacements for %s in %s\n", lpkg->name, sdb->treename); for(k = _alpm_db_get_pkgcache(sdb); k; k = k->next) { int found = 0; alpm_pkg_t *spkg = k->data; alpm_list_t *l; for(l = alpm_pkg_get_replaces(spkg); l; l = l->next) { alpm_depend_t *replace = l->data; /* we only want to consider literal matches at this point. */ if(_alpm_depcmp_literal(lpkg, replace)) { found = 1; break; } } if(found) { alpm_question_replace_t question = { .type = ALPM_QUESTION_REPLACE_PKG, .replace = 0, .oldpkg = lpkg, .newpkg = spkg, .newdb = sdb }; alpm_pkg_t *tpkg; /* check IgnorePkg/IgnoreGroup */ if(alpm_pkg_should_ignore(handle, spkg) || alpm_pkg_should_ignore(handle, lpkg)) { _alpm_log(handle, ALPM_LOG_WARNING, _("ignoring package replacement (%s-%s => %s-%s)\n"), lpkg->name, lpkg->version, spkg->name, spkg->version); continue; } QUESTION(handle, &question); if(!question.replace) { continue; } /* If spkg is already in the target list, we append lpkg to spkg's * removes list */ tpkg = alpm_pkg_find(handle->trans->add, spkg->name); if(tpkg) { /* sanity check, multiple repos can contain spkg->name */ if(tpkg->origin_data.db != sdb) { _alpm_log(handle, ALPM_LOG_WARNING, _("cannot replace %s by %s\n"), lpkg->name, spkg->name); continue; } _alpm_log(handle, ALPM_LOG_DEBUG, "appending %s to the removes list of %s\n", lpkg->name, tpkg->name); tpkg->removes = alpm_list_add(tpkg->removes, lpkg); /* check the to-be-replaced package's reason field */ if(alpm_pkg_get_reason(lpkg) == ALPM_PKG_REASON_EXPLICIT) { tpkg->reason = ALPM_PKG_REASON_EXPLICIT; } } else { /* add spkg to the target list */ /* copy over reason */ spkg->reason = alpm_pkg_get_reason(lpkg); spkg->removes = alpm_list_add(NULL, lpkg); _alpm_log(handle, ALPM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", spkg->name, spkg->version); replacers = alpm_list_add(replacers, spkg); } } } return replacers; } /** Search for packages to upgrade and add them to the transaction. */ int SYMEXPORT alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade) { alpm_list_t *i, *j; alpm_trans_t *trans; CHECK_HANDLE(handle, return -1); trans = handle->trans; ASSERT(trans != NULL, RET_ERR(handle, ALPM_ERR_TRANS_NULL, -1)); ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(handle, ALPM_ERR_TRANS_NOT_INITIALIZED, -1)); _alpm_log(handle, ALPM_LOG_DEBUG, "checking for package upgrades\n"); for(i = _alpm_db_get_pkgcache(handle->db_local); i; i = i->next) { alpm_pkg_t *lpkg = i->data; if(alpm_pkg_find(trans->remove, lpkg->name)) { _alpm_log(handle, ALPM_LOG_DEBUG, "%s is marked for removal -- skipping\n", lpkg->name); continue; } if(alpm_pkg_find(trans->add, lpkg->name)) { _alpm_log(handle, ALPM_LOG_DEBUG, "%s is already in the target list -- skipping\n", lpkg->name); continue; } /* Search for replacers then literal (if no replacer) in each sync database. */ for(j = handle->dbs_sync; j; j = j->next) { alpm_db_t *sdb = j->data; alpm_list_t *replacers; if(!(sdb->usage & ALPM_DB_USAGE_UPGRADE)) { continue; } /* Check sdb */ replacers = check_replacers(handle, lpkg, sdb); if(replacers) { trans->add = alpm_list_join(trans->add, replacers); /* jump to next local package */ break; } else { alpm_pkg_t *spkg = _alpm_db_get_pkgfromcache(sdb, lpkg->name); if(spkg) { if(check_literal(handle, lpkg, spkg, enable_downgrade)) { trans->add = alpm_list_add(trans->add, spkg); } /* jump to next local package */ break; } } } } return 0; }
/** * helper function for resolvedeps: search for dep satisfier in dbs * * @param handle the context handle * @param dep is the dependency to search for * @param dbs are the databases to search * @param excluding are the packages to exclude from the search * @param prompt if true, will cause an unresolvable dependency to issue an * interactive prompt asking whether the package should be removed from * the transaction or the transaction aborted; if false, simply returns * an error code without prompting * @return the resolved package **/ static pmpkg_t *resolvedep(pmhandle_t *handle, pmdepend_t *dep, alpm_list_t *dbs, alpm_list_t *excluding, int prompt) { alpm_list_t *i, *j; int ignored = 0; alpm_list_t *providers = NULL; int count; /* 1. literals */ for(i = dbs; i; i = i->next) { pmpkg_t *pkg = _alpm_db_get_pkgfromcache(i->data, dep->name); if(pkg && _alpm_depcmp(pkg, dep) && !_alpm_pkg_find(excluding, pkg->name)) { if(_alpm_pkg_should_ignore(handle, pkg)) { int install = 0; if(prompt) { QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, NULL, NULL, &install); } else { _alpm_log(handle, PM_LOG_WARNING, _("ignoring package %s-%s\n"), pkg->name, pkg->version); } if(!install) { ignored = 1; continue; } } return pkg; } } /* 2. satisfiers (skip literals here) */ for(i = dbs; i; i = i->next) { for(j = _alpm_db_get_pkgcache(i->data); j; j = j->next) { pmpkg_t *pkg = j->data; if(_alpm_depcmp(pkg, dep) && strcmp(pkg->name, dep->name) != 0 && !_alpm_pkg_find(excluding, pkg->name)) { if(_alpm_pkg_should_ignore(handle, pkg)) { int install = 0; if(prompt) { QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, NULL, NULL, &install); } else { _alpm_log(handle, PM_LOG_WARNING, _("ignoring package %s-%s\n"), pkg->name, pkg->version); } if(!install) { ignored = 1; continue; } } _alpm_log(handle, PM_LOG_DEBUG, "provider found (%s provides %s)\n", pkg->name, dep->name); providers = alpm_list_add(providers, pkg); /* keep looking for other providers in the all dbs */ } } } /* first check if one provider is already installed locally */ for(i = providers; i; i = i->next) { pmpkg_t *pkg = i->data; if(_alpm_pkghash_find(_alpm_db_get_pkgcache_hash(handle->db_local), pkg->name)) { alpm_list_free(providers); return pkg; } } count = alpm_list_count(providers); if(count >= 1) { /* default to first provider if there is no QUESTION callback */ int index = 0; if(count > 1) { /* if there is more than one provider, we ask the user */ QUESTION(handle->trans, PM_TRANS_CONV_SELECT_PROVIDER, providers, dep, NULL, &index); } if(index >= 0 && index < count) { pmpkg_t *pkg = alpm_list_getdata(alpm_list_nth(providers, index)); alpm_list_free(providers); return pkg; } alpm_list_free(providers); providers = NULL; } if(ignored) { /* resolvedeps will override these */ handle->pm_errno = PM_ERR_PKG_IGNORED; } else { handle->pm_errno = PM_ERR_PKG_NOT_FOUND; } return NULL; }
/** Search for packages to upgrade and add them to the transaction. */ int SYMEXPORT alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade) { alpm_list_t *i, *j, *k; alpm_trans_t *trans; alpm_db_t *db_local; alpm_list_t *dbs_sync; CHECK_HANDLE(handle, return -1); trans = handle->trans; db_local = handle->db_local; dbs_sync = handle->dbs_sync; ASSERT(trans != NULL, RET_ERR(handle, ALPM_ERR_TRANS_NULL, -1)); ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(handle, ALPM_ERR_TRANS_NOT_INITIALIZED, -1)); _alpm_log(handle, ALPM_LOG_DEBUG, "checking for package upgrades\n"); for(i = _alpm_db_get_pkgcache(db_local); i; i = i->next) { alpm_pkg_t *lpkg = i->data; if(_alpm_pkg_find(trans->add, lpkg->name)) { _alpm_log(handle, ALPM_LOG_DEBUG, "%s is already in the target list -- skipping\n", lpkg->name); continue; } /* Search for literal then replacers in each sync database. * If found, don't check other databases */ for(j = dbs_sync; j; j = j->next) { alpm_db_t *sdb = j->data; /* Check sdb */ alpm_pkg_t *spkg = _alpm_db_get_pkgfromcache(sdb, lpkg->name); if(spkg) { /* 1. literal was found in sdb */ int cmp = _alpm_pkg_compare_versions(spkg, lpkg); if(cmp > 0) { _alpm_log(handle, ALPM_LOG_DEBUG, "new version of '%s' found (%s => %s)\n", lpkg->name, lpkg->version, spkg->version); /* check IgnorePkg/IgnoreGroup */ if(_alpm_pkg_should_ignore(handle, spkg) || _alpm_pkg_should_ignore(handle, lpkg)) { _alpm_log(handle, ALPM_LOG_WARNING, _("%s: ignoring package upgrade (%s => %s)\n"), lpkg->name, lpkg->version, spkg->version); } else { _alpm_log(handle, ALPM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", spkg->name, spkg->version); trans->add = alpm_list_add(trans->add, spkg); } } else if(cmp < 0) { if(enable_downgrade) { /* check IgnorePkg/IgnoreGroup */ if(_alpm_pkg_should_ignore(handle, spkg) || _alpm_pkg_should_ignore(handle, lpkg)) { _alpm_log(handle, ALPM_LOG_WARNING, _("%s: ignoring package downgrade (%s => %s)\n"), lpkg->name, lpkg->version, spkg->version); } else { _alpm_log(handle, ALPM_LOG_WARNING, _("%s: downgrading from version %s to version %s\n"), lpkg->name, lpkg->version, spkg->version); trans->add = alpm_list_add(trans->add, spkg); } } else { _alpm_log(handle, ALPM_LOG_WARNING, _("%s: local (%s) is newer than %s (%s)\n"), lpkg->name, lpkg->version, sdb->treename, spkg->version); } } /* jump to next local package */ break; } else { /* 2. search for replacers in sdb */ int found = 0; for(k = _alpm_db_get_pkgcache(sdb); k; k = k->next) { spkg = k->data; if(alpm_list_find_str(alpm_pkg_get_replaces(spkg), lpkg->name)) { found = 1; /* check IgnorePkg/IgnoreGroup */ if(_alpm_pkg_should_ignore(handle, spkg) || _alpm_pkg_should_ignore(handle, lpkg)) { _alpm_log(handle, ALPM_LOG_WARNING, _("ignoring package replacement (%s-%s => %s-%s)\n"), lpkg->name, lpkg->version, spkg->name, spkg->version); continue; } int doreplace = 0; QUESTION(trans, ALPM_TRANS_CONV_REPLACE_PKG, lpkg, spkg, sdb->treename, &doreplace); if(!doreplace) { continue; } /* If spkg is already in the target list, we append lpkg to spkg's * removes list */ alpm_pkg_t *tpkg = _alpm_pkg_find(trans->add, spkg->name); if(tpkg) { /* sanity check, multiple repos can contain spkg->name */ if(tpkg->origin_data.db != sdb) { _alpm_log(handle, ALPM_LOG_WARNING, _("cannot replace %s by %s\n"), lpkg->name, spkg->name); continue; } _alpm_log(handle, ALPM_LOG_DEBUG, "appending %s to the removes list of %s\n", lpkg->name, tpkg->name); tpkg->removes = alpm_list_add(tpkg->removes, lpkg); /* check the to-be-replaced package's reason field */ if(alpm_pkg_get_reason(lpkg) == ALPM_PKG_REASON_EXPLICIT) { tpkg->reason = ALPM_PKG_REASON_EXPLICIT; } } else { /* add spkg to the target list */ /* copy over reason */ spkg->reason = alpm_pkg_get_reason(lpkg); spkg->removes = alpm_list_add(NULL, lpkg); _alpm_log(handle, ALPM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", spkg->name, spkg->version); trans->add = alpm_list_add(trans->add, spkg); } } } if(found) { break; /* jump to next local package */ } } } } return 0; }
int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data) { alpm_list_t *i, *j; alpm_list_t *deps = NULL; alpm_list_t *unresolvable = NULL; alpm_list_t *remove = NULL; int ret = 0; alpm_trans_t *trans = handle->trans; if(data) { *data = NULL; } /* ensure all sync database are valid since we will be using them */ for(i = handle->dbs_sync; i; i = i->next) { const alpm_db_t *db = i->data; if(!(db->status & DB_STATUS_VALID)) { RET_ERR(handle, ALPM_ERR_DB_INVALID, -1); } } if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) { alpm_list_t *resolved = NULL; /* target list after resolvedeps */ /* Build up list by repeatedly resolving each transaction package */ /* Resolve targets dependencies */ EVENT(trans, ALPM_TRANS_EVT_RESOLVEDEPS_START, NULL, NULL); _alpm_log(handle, ALPM_LOG_DEBUG, "resolving target's dependencies\n"); /* build remove list for resolvedeps */ for(i = trans->add; i; i = i->next) { alpm_pkg_t *spkg = i->data; for(j = spkg->removes; j; j = j->next) { remove = alpm_list_add(remove, j->data); } } /* Compute the fake local database for resolvedeps (partial fix for the * phonon/qt issue) */ alpm_list_t *localpkgs = alpm_list_diff(_alpm_db_get_pkgcache(handle->db_local), trans->add, _alpm_pkg_cmp); /* Resolve packages in the transaction one at a time, in addition building up a list of packages which could not be resolved. */ for(i = trans->add; i; i = i->next) { alpm_pkg_t *pkg = i->data; if(_alpm_resolvedeps(handle, localpkgs, pkg, trans->add, &resolved, remove, data) == -1) { unresolvable = alpm_list_add(unresolvable, pkg); } /* Else, [resolved] now additionally contains [pkg] and all of its dependencies not already on the list */ } alpm_list_free(localpkgs); /* If there were unresolvable top-level packages, prompt the user to see if they'd like to ignore them rather than failing the sync */ if(unresolvable != NULL) { int remove_unresolvable = 0; QUESTION(trans, ALPM_TRANS_CONV_REMOVE_PKGS, unresolvable, NULL, NULL, &remove_unresolvable); if(remove_unresolvable) { /* User wants to remove the unresolvable packages from the transaction. The packages will be removed from the actual transaction when the transaction packages are replaced with a dependency-reordered list below */ handle->pm_errno = 0; /* pm_errno was set by resolvedeps */ if(data) { alpm_list_free_inner(*data, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(*data); *data = NULL; } } else { /* pm_errno is set by resolvedeps */ alpm_list_free(resolved); ret = -1; goto cleanup; } } /* Set DEPEND reason for pulled packages */ for(i = resolved; i; i = i->next) { alpm_pkg_t *pkg = i->data; if(!_alpm_pkg_find(trans->add, pkg->name)) { pkg->reason = ALPM_PKG_REASON_DEPEND; } } /* Unresolvable packages will be removed from the target list, so we free the transaction specific fields */ alpm_list_free_inner(unresolvable, (alpm_list_fn_free)_alpm_pkg_free_trans); /* re-order w.r.t. dependencies */ alpm_list_free(trans->add); trans->add = _alpm_sortbydeps(handle, resolved, 0); alpm_list_free(resolved); EVENT(trans, ALPM_TRANS_EVT_RESOLVEDEPS_DONE, NULL, NULL); } if(!(trans->flags & ALPM_TRANS_FLAG_NOCONFLICTS)) { /* check for inter-conflicts and whatnot */ EVENT(trans, ALPM_TRANS_EVT_INTERCONFLICTS_START, NULL, NULL); _alpm_log(handle, ALPM_LOG_DEBUG, "looking for conflicts\n"); /* 1. check for conflicts in the target list */ _alpm_log(handle, ALPM_LOG_DEBUG, "check targets vs targets\n"); deps = _alpm_innerconflicts(handle, trans->add); for(i = deps; i; i = i->next) { alpm_conflict_t *conflict = i->data; alpm_pkg_t *rsync, *sync, *sync1, *sync2; /* have we already removed one of the conflicting targets? */ sync1 = _alpm_pkg_find(trans->add, conflict->package1); sync2 = _alpm_pkg_find(trans->add, conflict->package2); if(!sync1 || !sync2) { continue; } _alpm_log(handle, ALPM_LOG_DEBUG, "conflicting packages in the sync list: '%s' <-> '%s'\n", conflict->package1, conflict->package2); /* if sync1 provides sync2, we remove sync2 from the targets, and vice versa */ alpm_depend_t *dep1 = _alpm_splitdep(conflict->package1); alpm_depend_t *dep2 = _alpm_splitdep(conflict->package2); if(_alpm_depcmp(sync1, dep2)) { rsync = sync2; sync = sync1; } else if(_alpm_depcmp(sync2, dep1)) { rsync = sync1; sync = sync2; } else { _alpm_log(handle, ALPM_LOG_ERROR, _("unresolvable package conflicts detected\n")); handle->pm_errno = ALPM_ERR_CONFLICTING_DEPS; ret = -1; if(data) { alpm_conflict_t *newconflict = _alpm_conflict_dup(conflict); if(newconflict) { *data = alpm_list_add(*data, newconflict); } } alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free); alpm_list_free(deps); _alpm_dep_free(dep1); _alpm_dep_free(dep2); goto cleanup; } _alpm_dep_free(dep1); _alpm_dep_free(dep2); /* Prints warning */ _alpm_log(handle, ALPM_LOG_WARNING, _("removing '%s' from target list because it conflicts with '%s'\n"), rsync->name, sync->name); trans->add = alpm_list_remove(trans->add, rsync, _alpm_pkg_cmp, NULL); _alpm_pkg_free_trans(rsync); /* rsync is not transaction target anymore */ continue; } alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free); alpm_list_free(deps); deps = NULL; /* 2. we check for target vs db conflicts (and resolve)*/ _alpm_log(handle, ALPM_LOG_DEBUG, "check targets vs db and db vs targets\n"); deps = _alpm_outerconflicts(handle->db_local, trans->add); for(i = deps; i; i = i->next) { alpm_conflict_t *conflict = i->data; /* if conflict->package2 (the local package) is not elected for removal, we ask the user */ int found = 0; for(j = trans->add; j && !found; j = j->next) { alpm_pkg_t *spkg = j->data; if(_alpm_pkg_find(spkg->removes, conflict->package2)) { found = 1; } } if(found) { continue; } _alpm_log(handle, ALPM_LOG_DEBUG, "package '%s' conflicts with '%s'\n", conflict->package1, conflict->package2); alpm_pkg_t *sync = _alpm_pkg_find(trans->add, conflict->package1); alpm_pkg_t *local = _alpm_db_get_pkgfromcache(handle->db_local, conflict->package2); int doremove = 0; QUESTION(trans, ALPM_TRANS_CONV_CONFLICT_PKG, conflict->package1, conflict->package2, conflict->reason, &doremove); if(doremove) { /* append to the removes list */ _alpm_log(handle, ALPM_LOG_DEBUG, "electing '%s' for removal\n", conflict->package2); sync->removes = alpm_list_add(sync->removes, local); } else { /* abort */ _alpm_log(handle, ALPM_LOG_ERROR, _("unresolvable package conflicts detected\n")); handle->pm_errno = ALPM_ERR_CONFLICTING_DEPS; ret = -1; if(data) { alpm_conflict_t *newconflict = _alpm_conflict_dup(conflict); if(newconflict) { *data = alpm_list_add(*data, newconflict); } } alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free); alpm_list_free(deps); goto cleanup; } } EVENT(trans, ALPM_TRANS_EVT_INTERCONFLICTS_DONE, NULL, NULL); alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free); alpm_list_free(deps); } /* Build trans->remove list */ for(i = trans->add; i; i = i->next) { alpm_pkg_t *spkg = i->data; for(j = spkg->removes; j; j = j->next) { alpm_pkg_t *rpkg = j->data; if(!_alpm_pkg_find(trans->remove, rpkg->name)) { _alpm_log(handle, ALPM_LOG_DEBUG, "adding '%s' to remove list\n", rpkg->name); trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(rpkg)); } } } if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) { _alpm_log(handle, ALPM_LOG_DEBUG, "checking dependencies\n"); deps = alpm_checkdeps(handle, _alpm_db_get_pkgcache(handle->db_local), trans->remove, trans->add, 1); if(deps) { handle->pm_errno = ALPM_ERR_UNSATISFIED_DEPS; ret = -1; if(data) { *data = deps; } else { alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(deps); } goto cleanup; } } for(i = trans->add; i; i = i->next) { /* update download size field */ alpm_pkg_t *spkg = i->data; if(compute_download_size(spkg) != 0) { ret = -1; goto cleanup; } } cleanup: alpm_list_free(unresolvable); alpm_list_free(remove); return ret; }
static alpm_list_t *check_replacers(alpm_handle_t *handle, alpm_pkg_t *lpkg, alpm_db_t *sdb) { /* 2. search for replacers in sdb */ alpm_list_t *replacers = NULL; alpm_list_t *k; _alpm_log(handle, ALPM_LOG_DEBUG, "searching for replacements for %s in %s\n", lpkg->name, sdb->treename); for(k = _alpm_db_get_pkgcache(sdb); k; k = k->next) { int found = 0; alpm_pkg_t *spkg = k->data; alpm_list_t *l; for(l = alpm_pkg_get_replaces(spkg); l; l = l->next) { alpm_depend_t *replace = l->data; /* we only want to consider literal matches at this point. */ if(_alpm_depcmp_literal(lpkg, replace)) { found = 1; break; } } if(found) { int doreplace = 0; alpm_pkg_t *tpkg; /* check IgnorePkg/IgnoreGroup */ if(_alpm_pkg_should_ignore(handle, spkg) || _alpm_pkg_should_ignore(handle, lpkg)) { _alpm_log(handle, ALPM_LOG_WARNING, _("ignoring package replacement (%s-%s => %s-%s)\n"), lpkg->name, lpkg->version, spkg->name, spkg->version); continue; } QUESTION(handle, ALPM_QUESTION_REPLACE_PKG, lpkg, spkg, sdb->treename, &doreplace); if(!doreplace) { continue; } /* If spkg is already in the target list, we append lpkg to spkg's * removes list */ tpkg = alpm_pkg_find(handle->trans->add, spkg->name); if(tpkg) { /* sanity check, multiple repos can contain spkg->name */ if(tpkg->origin_data.db != sdb) { _alpm_log(handle, ALPM_LOG_WARNING, _("cannot replace %s by %s\n"), lpkg->name, spkg->name); continue; } _alpm_log(handle, ALPM_LOG_DEBUG, "appending %s to the removes list of %s\n", lpkg->name, tpkg->name); tpkg->removes = alpm_list_add(tpkg->removes, lpkg); /* check the to-be-replaced package's reason field */ if(alpm_pkg_get_reason(lpkg) == ALPM_PKG_REASON_EXPLICIT) { tpkg->reason = ALPM_PKG_REASON_EXPLICIT; } } else { /* add spkg to the target list */ /* copy over reason */ spkg->reason = alpm_pkg_get_reason(lpkg); spkg->removes = alpm_list_add(NULL, lpkg); _alpm_log(handle, ALPM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", spkg->name, spkg->version); replacers = alpm_list_add(replacers, spkg); } } } return replacers; }
int _pacman_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, pmlist_t *dbs_sync) { pmlist_t *i, *j, *k; /* this is a sysupgrade, so that install reasons are not touched */ handle->sysupgrade = 1; /* check for "recommended" package replacements */ _pacman_log(PM_LOG_FLOW1, _("checking for package replacements")); for(i = dbs_sync; i; i = i->next) { for(j = _pacman_db_get_pkgcache(i->data); j; j = j->next) { pmpkg_t *spkg = j->data; for(k = _pacman_pkg_getinfo(spkg, PM_PKG_REPLACES); k; k = k->next) { pmlist_t *m; for(m = _pacman_db_get_pkgcache(db_local); m; m = m->next) { pmpkg_t *lpkg = m->data; if(!strcmp(k->data, lpkg->name)) { _pacman_log(PM_LOG_DEBUG, _("checking replacement '%s' for package '%s'"), k->data, spkg->name); if(_pacman_list_is_strin(lpkg->name, handle->ignorepkg)) { _pacman_log(PM_LOG_WARNING, _("%s-%s: ignoring package upgrade (to be replaced by %s-%s)"), lpkg->name, lpkg->version, spkg->name, spkg->version); } else { /* get confirmation for the replacement */ int doreplace = 0; QUESTION(trans, PM_TRANS_CONV_REPLACE_PKG, lpkg, spkg, ((pmdb_t *)i->data)->treename, &doreplace); if(doreplace) { /* if confirmed, add this to the 'final' list, designating 'lpkg' as * the package to replace. */ pmsyncpkg_t *ps; pmpkg_t *dummy = _pacman_pkg_new(lpkg->name, NULL); if(dummy == NULL) { pm_errno = PM_ERR_MEMORY; goto error; } dummy->requiredby = _pacman_list_strdup(lpkg->requiredby); /* check if spkg->name is already in the packages list. */ ps = find_pkginsync(spkg->name, trans->packages); if(ps) { /* found it -- just append to the replaces list */ ps->data = _pacman_list_add(ps->data, dummy); } else { /* none found -- enter pkg into the final sync list */ ps = _pacman_sync_new(PM_SYNC_TYPE_REPLACE, spkg, NULL); if(ps == NULL) { FREEPKG(dummy); pm_errno = PM_ERR_MEMORY; goto error; } ps->data = _pacman_list_add(NULL, dummy); trans->packages = _pacman_list_add(trans->packages, ps); } _pacman_log(PM_LOG_FLOW2, _("%s-%s elected for upgrade (to be replaced by %s-%s)"), lpkg->name, lpkg->version, spkg->name, spkg->version); } } break; } } } } } /* match installed packages with the sync dbs and compare versions */ _pacman_log(PM_LOG_FLOW1, _("checking for package upgrades")); for(i = _pacman_db_get_pkgcache(db_local); i; i = i->next) { int cmp; int replace=0; pmpkg_t *local = i->data; pmpkg_t *spkg = NULL; pmsyncpkg_t *ps; for(j = dbs_sync; !spkg && j; j = j->next) { spkg = _pacman_db_get_pkgfromcache(j->data, local->name); } if(spkg == NULL) { _pacman_log(PM_LOG_DEBUG, _("'%s' not found in sync db -- skipping"), local->name); continue; } /* we don't care about a to-be-replaced package's newer version */ for(j = trans->packages; j && !replace; j=j->next) { ps = j->data; if(ps->type == PM_SYNC_TYPE_REPLACE) { if(_pacman_pkg_isin(spkg->name, ps->data)) { replace=1; } } } if(replace) { _pacman_log(PM_LOG_DEBUG, _("'%s' is already elected for removal -- skipping"), local->name); continue; } /* compare versions and see if we need to upgrade */ cmp = _pacman_versioncmp(local->version, spkg->version); if(cmp > 0 && !_pacman_pkg_getinfo(spkg, PM_PKG_FORCE) && !(trans->flags & PM_TRANS_FLAG_DOWNGRADE)) { /* local version is newer */ _pacman_log(PM_LOG_WARNING, _("%s-%s: local version is newer"), local->name, local->version); } else if(cmp == 0) { /* versions are identical */ } else if(_pacman_list_is_strin(local->name, handle->ignorepkg)) { /* package should be ignored (IgnorePkg) */ _pacman_log(PM_LOG_WARNING, _("%s-%s: ignoring package upgrade (%s)"), local->name, local->version, spkg->version); } else if(istoonew(spkg)) { /* package too new (UpgradeDelay) */ _pacman_log(PM_LOG_FLOW1, _("%s-%s: delaying upgrade of package (%s)\n"), local->name, local->version, spkg->version); } else if(_pacman_pkg_getinfo(spkg, PM_PKG_STICK)) { _pacman_log(PM_LOG_WARNING, _("%s-%s: please upgrade manually (%s => %s)"), local->name, local->version, local->version, spkg->version); } else { _pacman_log(PM_LOG_FLOW2, _("%s-%s elected for upgrade (%s => %s)"), local->name, local->version, local->version, spkg->version); /* check if spkg->name is already in the packages list. */ if(!find_pkginsync(spkg->name, trans->packages)) { pmpkg_t *dummy = _pacman_pkg_new(local->name, local->version); if(dummy == NULL) { goto error; } ps = _pacman_sync_new(PM_SYNC_TYPE_UPGRADE, spkg, dummy); if(ps == NULL) { FREEPKG(dummy); goto error; } trans->packages = _pacman_list_add(trans->packages, ps); } else { /* spkg->name is already in the packages list -- just ignore it */ } } } return(0); error: return(-1); }