From 0775ad46cf1be3c0a4c6e34e9f97e03cc3b7b974 Mon Sep 17 00:00:00 2001 From: LuWu <2398491106@qq.com> Date: Tue, 23 Jul 2024 10:20:54 +0800 Subject: [PATCH] libsolv:Handle installed packages in three passes Reference:https://github.com/openSUSE/libsolv/commit/553c69b514c1ca85a6311373b48c6096886dcff3 https://github.com/openSUSE/libsolv/commit/bbd1801748e74259f7d8d7d7eee369064961962b https://github.com/openSUSE/libsolv/commit/bbd1801748e74259f7d8d7d7eee369064961962b Conflict:no (cherry picked from commit 9386dfaa0602b66bc1e5bb2f9575a3e7f34e48b4) --- ...e-installed-packages-in-three-passes.patch | 72 +++++++ ...aters-handling-into-its-own-function.patch | 192 ++++++++++++++++++ ...t-resolve_installed-remove-dead-code.patch | 32 +++ libsolv.spec | 8 +- 4 files changed, 303 insertions(+), 1 deletion(-) create mode 100644 backport-Handle-installed-packages-in-three-passes.patch create mode 100644 backport-Move-special-updaters-handling-into-its-own-function.patch create mode 100644 backport-resolve_installed-remove-dead-code.patch diff --git a/backport-Handle-installed-packages-in-three-passes.patch b/backport-Handle-installed-packages-in-three-passes.patch new file mode 100644 index 0000000..4bdfbe2 --- /dev/null +++ b/backport-Handle-installed-packages-in-three-passes.patch @@ -0,0 +1,72 @@ +From bbd1801748e74259f7d8d7d7eee369064961962b Mon Sep 17 00:00:00 2001 +From: Michael Schroeder +Date: Tue, 13 Feb 2024 15:25:47 +0100 +Subject: [PATCH] Handle installed packages in three passes + +Fixes issue #550 + +Conflict:NA +Reference:https://github.com/openSUSE/libsolv/commit/bbd1801748e74259f7d8d7d7eee369064961962b +--- + src/solver.c | 21 ++++++++++++++++----- + 1 file changed, 16 insertions(+), 5 deletions(-) + +diff --git a/src/solver.c b/src/solver.c +index 741aa1b2f..a1a41f677 100644 +--- a/src/solver.c ++++ b/src/solver.c +@@ -1836,7 +1836,7 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + { + Pool *pool = solv->pool; + Repo *installed = solv->installed; +- int i, n, pass; ++ int i, n, pass, startpass; + int installedpos = solv->installedpos; + Solvable *s; + Id p, pp; +@@ -1845,10 +1845,14 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + POOL_DEBUG(SOLV_DEBUG_SOLVER, "resolving installed packages\n"); + if (!installedpos) + installedpos = installed->start; +- /* we use two passes if we need to update packages +- * to create a better user experience */ +- for (pass = !solv->updatemap_all && solv->updatemap.size ? 0 : 1; pass < 2; ) ++ /* we use passes if we need to update packages to create a better user experience: ++ * pass 0: update the packages requested by the user ++ * pass 1: keep the installed packages if we can ++ * pass 2: update the packages that could not be kept */ ++ startpass = solv->updatemap_all ? 2 : solv->updatemap.size ? 0 : 1; ++ for (pass = startpass; pass < 3; ) + { ++ int needpass2 = 0; + int passlevel = level; + Id *specialupdaters = solv->specialupdaters; + /* start with installedpos, the position that gave us problems the last time */ +@@ -1880,6 +1884,11 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + * the installed package and not replace it with a newer version */ + if (!MAPTST(&solv->noupdate, i - installed->start) && (solv->decisionmap[i] < 0 || solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, i - installed->start)))) + { ++ if (pass == 1) ++ { ++ needpass2 = 1; /* first do the packages we do not want/need to update */ ++ continue; ++ } + if (dq->count) + queue_empty(dq); + /* find update candidates */ +@@ -1964,12 +1973,14 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + if (level < origlevel) + break; /* ran into trouble */ + /* re-run all passes */ +- pass = !solv->updatemap_all && solv->updatemap.size ? 0 : 1; ++ pass = startpass; + continue; + } + /* reset installedpos, advance to next pass */ + installedpos = installed->start; + pass++; ++ if (pass == 2 && !needpass2) ++ break; + } + solv->installedpos = installedpos; + return level; diff --git a/backport-Move-special-updaters-handling-into-its-own-function.patch b/backport-Move-special-updaters-handling-into-its-own-function.patch new file mode 100644 index 0000000..89c9726 --- /dev/null +++ b/backport-Move-special-updaters-handling-into-its-own-function.patch @@ -0,0 +1,192 @@ +From 4c7ce065280f062c52ae19d75344c49e5f562108 Mon Sep 17 00:00:00 2001 +From: Michael Schroeder +Date: Tue, 13 Feb 2024 14:42:25 +0100 +Subject: [PATCH] Move special updaters handling into its own function + +Conflict:NA +Reference:https://github.com/openSUSE/libsolv/commit/4c7ce065280f062c52ae19d75344c49e5f562108 +--- + src/solver.c | 127 ++++++++++++++++++++++++++++----------------------- + 1 file changed, 71 insertions(+), 56 deletions(-) + +diff --git a/src/solver.c b/src/solver.c +index 0c3333d87..741aa1b2f 100644 +--- a/src/solver.c ++++ b/src/solver.c +@@ -1788,6 +1788,49 @@ prune_to_update_targets(Solver *solv, Id *cp, Queue *q) + queue_truncate(q, j); + } + ++static void ++get_special_updaters(Solver *solv, int i, Rule *rr, Queue *dq) ++{ ++ Pool *pool = solv->pool; ++ Repo *installed = solv->installed; ++ int specoff = solv->specialupdaters[i - installed->start]; ++ int j, d; ++ Id p; ++ ++ /* special multiversion handling, make sure best version is chosen */ ++ if (rr->p == i && solv->decisionmap[i] >= 0) ++ queue_push(dq, i); ++ for (d = specoff; (p = pool->whatprovidesdata[d]) != 0; d++) ++ if (solv->decisionmap[p] >= 0) ++ queue_push(dq, p); ++ /* if we have installed packages try to find identical ones to get ++ * repo priorities. see issue #343 */ ++ for (j = 0; j < dq->count; j++) ++ { ++ Id p2 = dq->elements[j]; ++ if (pool->solvables[p2].repo != installed) ++ continue; ++ for (d = specoff; (p = pool->whatprovidesdata[d]) != 0; d++) ++ { ++ if (solv->decisionmap[p] >= 0 || pool->solvables[p].repo == installed) ++ continue; ++ if (solvable_identical(pool->solvables + p, pool->solvables + p2)) ++ queue_push(dq, p); /* identical to installed, put it on the list so we have a repo prio */ ++ } ++ } ++ if (dq->count && solv->update_targets && solv->update_targets->elements[i - installed->start]) ++ prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[i - installed->start], dq); ++ if (dq->count) ++ { ++ policy_filter_unwanted(solv, dq, POLICY_MODE_CHOOSE); ++ p = dq->elements[0]; ++ if (p != i && solv->decisionmap[p] == 0) ++ dq->count = 1; ++ else ++ dq->count = 0; ++ } ++} ++ + static int + resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + { +@@ -1804,7 +1847,7 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + installedpos = installed->start; + /* we use two passes if we need to update packages + * to create a better user experience */ +- for (pass = solv->updatemap.size ? 0 : 1; pass < 2; ) ++ for (pass = !solv->updatemap_all && solv->updatemap.size ? 0 : 1; pass < 2; ) + { + int passlevel = level; + Id *specialupdaters = solv->specialupdaters; +@@ -1812,7 +1855,6 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + for (i = installedpos, n = installed->start; n < installed->end; i++, n++) + { + Rule *r, *rr; +- Id d; + + if (i == installed->end) + i = installed->start; +@@ -1836,48 +1878,20 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + /* check if we should update this package to the latest version + * noupdate is set for erase jobs, in that case we want to deinstall + * the installed package and not replace it with a newer version */ +- if (dq->count) +- queue_empty(dq); + if (!MAPTST(&solv->noupdate, i - installed->start) && (solv->decisionmap[i] < 0 || solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, i - installed->start)))) + { +- if (specialupdaters && (d = specialupdaters[i - installed->start]) != 0) ++ if (dq->count) ++ queue_empty(dq); ++ /* find update candidates */ ++ if (specialupdaters && specialupdaters[i - installed->start] != 0) + { +- int j; +- /* special multiversion handling, make sure best version is chosen */ +- if (rr->p == i && solv->decisionmap[i] >= 0) +- queue_push(dq, i); +- while ((p = pool->whatprovidesdata[d++]) != 0) +- if (solv->decisionmap[p] >= 0) +- queue_push(dq, p); +- for (j = 0; j < dq->count; j++) +- { +- Id p2 = dq->elements[j]; +- if (pool->solvables[p2].repo != installed) +- continue; +- d = specialupdaters[i - installed->start]; +- while ((p = pool->whatprovidesdata[d++]) != 0) +- { +- if (solv->decisionmap[p] >= 0 || pool->solvables[p].repo == installed) +- continue; +- if (solvable_identical(pool->solvables + p, pool->solvables + p2)) +- queue_push(dq, p); /* identical to installed, put it on the list so we have a repo prio */ +- } +- } +- if (dq->count && solv->update_targets && solv->update_targets->elements[i - installed->start]) +- prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[i - installed->start], dq); ++ get_special_updaters(solv, i, rr, dq); ++ /* if we have an update set rr to the feature rule */ + if (dq->count) + { +- policy_filter_unwanted(solv, dq, POLICY_MODE_CHOOSE); +- p = dq->elements[0]; +- if (p != i && solv->decisionmap[p] == 0) +- { +- rr = solv->rules + solv->featurerules + (i - solv->installed->start); +- if (!rr->p) /* update rule == feature rule? */ +- rr = rr - solv->featurerules + solv->updaterules; +- dq->count = 1; +- } +- else +- dq->count = 0; ++ rr = solv->rules + solv->featurerules + (i - solv->installed->start); ++ if (!rr->p) /* update rule == feature rule? */ ++ rr = rr - solv->featurerules + solv->updaterules; + } + } + else +@@ -1894,24 +1908,25 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + queue_push(dq, p); + } + } +- } +- if (dq->count && solv->update_targets && solv->update_targets->elements[i - installed->start]) +- prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[i - installed->start], dq); +- /* install best version */ +- if (dq->count) +- { +- olevel = level; +- level = selectandinstall(solv, level, dq, disablerules, rr - solv->rules, SOLVER_REASON_UPDATE_INSTALLED); +- if (level <= olevel) ++ if (dq->count && solv->update_targets && solv->update_targets->elements[i - installed->start]) ++ prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[i - installed->start], dq); ++ /* install best version */ ++ if (dq->count) + { +- if (level < passlevel) +- break; /* trouble */ +- if (level < olevel) +- n = installed->start; /* redo all */ +- i--; +- n--; +- continue; ++ olevel = level; ++ level = selectandinstall(solv, level, dq, disablerules, rr - solv->rules, SOLVER_REASON_UPDATE_INSTALLED); ++ if (level <= olevel) ++ { ++ if (level < passlevel) ++ break; /* trouble */ ++ if (level < olevel) ++ n = installed->start; /* redo all */ ++ i--; ++ n--; ++ continue; ++ } + } ++ /* check original package even if we installed an update */ + } + /* if still undecided keep package */ + if (solv->decisionmap[i] == 0) +@@ -1949,7 +1964,7 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + if (level < origlevel) + break; /* ran into trouble */ + /* re-run all passes */ +- pass = solv->updatemap.size ? 0 : 1; ++ pass = !solv->updatemap_all && solv->updatemap.size ? 0 : 1; + continue; + } + /* reset installedpos, advance to next pass */ + diff --git a/backport-resolve_installed-remove-dead-code.patch b/backport-resolve_installed-remove-dead-code.patch new file mode 100644 index 0000000..199c934 --- /dev/null +++ b/backport-resolve_installed-remove-dead-code.patch @@ -0,0 +1,32 @@ +From 553c69b514c1ca85a6311373b48c6096886dcff3 Mon Sep 17 00:00:00 2001 +From: Michael Schroeder +Date: Tue, 13 Feb 2024 12:43:50 +0100 +Subject: [PATCH] resolve_installed: remove dead code + +Since we simplified our dup handling the update rules always +start with the installed package. + +Conflict:NA +Reference:https://github.com/openSUSE/libsolv/commit/553c69b514c1ca85a6311373b48c6096886dcff3 +--- + src/solver.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/src/solver.c b/src/solver.c +index 363d88734..0c3333d87 100644 +--- a/src/solver.c ++++ b/src/solver.c +@@ -1835,11 +1835,10 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) + + /* check if we should update this package to the latest version + * noupdate is set for erase jobs, in that case we want to deinstall +- * the installed package and not replace it with a newer version +- * rr->p != i is for dup jobs where the installed package cannot be kept */ ++ * the installed package and not replace it with a newer version */ + if (dq->count) + queue_empty(dq); +- if (!MAPTST(&solv->noupdate, i - installed->start) && (solv->decisionmap[i] < 0 || solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, i - installed->start)) || (rr->p && rr->p != i))) ++ if (!MAPTST(&solv->noupdate, i - installed->start) && (solv->decisionmap[i] < 0 || solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, i - installed->start)))) + { + if (specialupdaters && (d = specialupdaters[i - installed->start]) != 0) + { diff --git a/libsolv.spec b/libsolv.spec index a409e23..3ef1311 100644 --- a/libsolv.spec +++ b/libsolv.spec @@ -15,7 +15,7 @@ Name: libsolv Version: 0.7.24 -Release: 2 +Release: 3 Summary: Package dependency solver License: BSD URL: https://github.com/openSUSE/libsolv @@ -25,6 +25,9 @@ Patch6001: backport-Treat-condition-both-as-positive-and-negative-literal-in-po Patch6002: backport-Add-testcase-for-last-commit.patch Patch6003: backport-choice-rules-also-do-solver_choicerulecheck-for-package-downgrades.patch Patch6004: backport-Fix-a-couple-small-static-analysis-findings-for-uninitialized-structs.patch +Patch6005: backport-resolve_installed-remove-dead-code.patch +Patch6006: backport-Move-special-updaters-handling-into-its-own-function.patch +Patch6007: backport-Handle-installed-packages-in-three-passes.patch BuildRequires: cmake gcc-c++ ninja-build pkgconfig(rpm) zlib-devel BuildRequires: libxml2-devel xz-devel bzip2-devel @@ -218,6 +221,9 @@ Python 3 version. %{_mandir}/man3/%{name}*.3* %changelog +* Tue Jul 23 2024 LuWu <2398491106@qq.com> - 0.7.24-3 +- Handle installed packages in three passes + * Tue Jun 18 2024 guojunding - 0.7.24-2 - Fix a couple small static analysis findings for uninitialized structs -- Gitee