diff options
author | William Pitcock <nenolod@dereferenced.org> | 2017-04-27 23:23:47 +0000 |
---|---|---|
committer | William Pitcock <nenolod@dereferenced.org> | 2017-04-27 23:23:47 +0000 |
commit | ba7b50c0f8ac7c8a88b03856037d9ca6618cccd5 (patch) | |
tree | 415f9ae0570e30dafc33dba1d342e599160f9baf /src | |
parent | 027df02dc28f3a73823282038fe1ab1d3ae3e65f (diff) | |
download | apk-tools-ba7b50c0f8ac7c8a88b03856037d9ca6618cccd5.tar.gz apk-tools-ba7b50c0f8ac7c8a88b03856037d9ca6618cccd5.tar.bz2 apk-tools-ba7b50c0f8ac7c8a88b03856037d9ca6618cccd5.tar.xz apk-tools-ba7b50c0f8ac7c8a88b03856037d9ca6618cccd5.zip |
solver: don't clobber package swaps in cases where an installed package is being replaced by a provider
Diffstat (limited to 'src')
-rw-r--r-- | src/solver.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/src/solver.c b/src/solver.c index 248fa27..5c08887 100644 --- a/src/solver.c +++ b/src/solver.c @@ -727,7 +727,12 @@ static void cset_track_deps_removed(struct apk_solver_state *ss, struct apk_pack static void cset_check_removal_by_deps(struct apk_solver_state *ss, struct apk_package *pkg) { - if (pkg->name->ss.requirers == 0) + /* NOTE: an orphaned package name may have 0 requirers because it is now being satisfied + * through an alternate provider. In these cases, we will handle this later as an adjustment + * operation using cset_gen_name_change(). As such, only insert a removal into the transaction + * if there is no other resolved provider. + */ + if (pkg->name->ss.requirers == 0 && pkg->name->ss.chosen.pkg == NULL) cset_gen_name_remove(ss, pkg); } @@ -775,12 +780,16 @@ static void cset_gen_name_change(struct apk_solver_state *ss, struct apk_name *n if (name->ss.in_changeset) return; pkg = name->ss.chosen.pkg; - if (pkg == NULL) { - /* Package removal */ + if (pkg == NULL || pkg->name != name) { + /* Original package dependency name was orphaned, emit a removal. + * See cset_gen_name_remove() for more details. */ opkg = name->ss.installed_pkg; if (opkg) cset_gen_name_remove(ss, opkg); name->ss.in_changeset = 1; - return; + + /* If a replacement is not provided, then we're done here. */ + if (pkg == NULL) + return; } if (pkg->ss.in_changeset) return; @@ -881,8 +890,12 @@ static void generate_changeset(struct apk_solver_state *ss, struct apk_dependenc foreach_array_item(d, world) cset_gen_dep(ss, NULL, d); + /* NOTE: We used to call cset_gen_name_remove() directly here. While slightly faster, this clobbered + * dependency nodes where a new package was provided under a different name (using provides). As such, + * treat everything as a change first and then call cset_gen_name_remove() from there if appropriate. + */ list_for_each_entry(ipkg, &ss->db->installed.packages, installed_pkgs_list) - cset_gen_name_remove(ss, ipkg->pkg); + cset_gen_name_change(ss, ipkg->pkg->name); changeset->num_total_changes = changeset->num_install + |