/** 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->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. */ for(j = handle->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); int literal_upgrade = 0; if(spkg) { literal_upgrade = check_literal(handle, lpkg, spkg, enable_downgrade); if(literal_upgrade) { trans->add = alpm_list_add(trans->add, spkg); } /* jump to next local package */ break; } else { alpm_list_t *replacers; replacers = check_replacers(handle, lpkg, sdb); if(replacers) { trans->add = alpm_list_join(trans->add, replacers); } } } } return 0; }
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; }