From be95157b02e9631b1c4ed93bd08a0be6abe60d03 Mon Sep 17 00:00:00 2001 From: Marek Blaha Date: Wed, 22 Apr 2026 11:54:30 +0200 Subject: [PATCH] Fix unexpected downgrades in dependencies The patch drops reverts that were used as a workaround for the bug and instead backports the upstream patch https://github.com/openSUSE/libsolv/commit/2c85ed581422e072ad95119f3d7dc19eb45f29ac that fixes the issue. Resolves: RHEL-141449 --- ...evert-Improve-choice-rule-generation.patch | 348 ------------------ ...ex_deps-requirement-to-choice1b-test.patch | 23 -- 0004-Revert-Add-more-choicerules-tests.patch | 314 ---------------- ...o-do-solver_choicerulecheck-for-pack.patch | 53 +++ libsolv.spec | 11 +- 5 files changed, 60 insertions(+), 689 deletions(-) delete mode 100644 0002-Revert-Improve-choice-rule-generation.patch delete mode 100644 0003-Revert-Add-complex_deps-requirement-to-choice1b-test.patch delete mode 100644 0004-Revert-Add-more-choicerules-tests.patch create mode 100644 0013-choice-rules-also-do-solver_choicerulecheck-for-pack.patch diff --git a/0002-Revert-Improve-choice-rule-generation.patch b/0002-Revert-Improve-choice-rule-generation.patch deleted file mode 100644 index 1045808..0000000 --- a/0002-Revert-Improve-choice-rule-generation.patch +++ /dev/null @@ -1,348 +0,0 @@ -From 21090e6067660e4a22d6227118d5cfc30629d548 Mon Sep 17 00:00:00 2001 -From: Nicola Sella -Date: Wed, 7 Dec 2022 16:11:10 +0100 -Subject: [PATCH 1/3] Revert "Improve choice rule generation" - -This reverts commit 1da9bef88dd269055cbd7eda2f3572963d6d9b64. ---- - src/rules.c | 169 ++++++++++++++++++++++++++++++++++++++------------- - src/solver.c | 45 -------------- - 2 files changed, 126 insertions(+), 88 deletions(-) - -diff --git a/src/rules.c b/src/rules.c -index 2c56959c..a260c2de 100644 ---- a/src/rules.c -+++ b/src/rules.c -@@ -3255,12 +3255,6 @@ solver_rule2rules(Solver *solv, Id rid, Queue *q, int recursive) - - - /* check if the newest versions of pi still provides the dependency we're looking for */ --/* pi: installed package -- * r: rule for the dependency -- * m: map with all positive elements of r -- * return 0: at least one provider -- * return 1: the newest versions do not provide the dependency -- */ - static int - solver_choicerulecheck(Solver *solv, Id pi, Rule *r, Map *m, Queue *q) - { -@@ -3309,6 +3303,94 @@ solver_choicerulecheck(Solver *solv, Id pi, Rule *r, Map *m, Queue *q) - return 1; /* none of the new packages provided it */ - } - -+static int -+solver_choicerulecheck2(Solver *solv, Id pi, Id pt, Queue *q) -+{ -+ Pool *pool = solv->pool; -+ Rule *ur; -+ Id p, pp; -+ int i; -+ -+ if (!q->count || q->elements[0] != pi) -+ { -+ if (q->count) -+ queue_empty(q); -+ ur = solv->rules + solv->updaterules + (pi - pool->installed->start); -+ if (!ur->p) -+ ur = solv->rules + solv->featurerules + (pi - pool->installed->start); -+ if (!ur->p) -+ return 1; /* orphaned, thus newest */ -+ queue_push2(q, pi, 0); -+ FOR_RULELITERALS(p, pp, ur) -+ if (p > 0 && p != pi) -+ queue_push(q, p); -+ queue_push(q, pi); -+ } -+ if (q->count <= 3) -+ return q->count == 3 && q->elements[2] == pt ? 1 : 0; -+ if (!q->elements[1]) -+ { -+ queue_deleten(q, 0, 2); -+ policy_filter_unwanted(solv, q, POLICY_MODE_CHOOSE); -+ queue_unshift(q, 1); /* filter mark */ -+ queue_unshift(q, pi); -+ } -+ for (i = 2; i < q->count; i++) -+ if (q->elements[i] == pt) -+ return 1; -+ return 0; /* not newest */ -+} -+ -+static int -+solver_choicerulecheck3(Solver *solv, Id pt, Queue *q) -+{ -+ Pool *pool = solv->pool; -+ Id p, pp; -+ int i; -+ -+ if (!q->count || q->elements[0] != pt) -+ { -+ Solvable *s = pool->solvables + pt; -+ if (q->count) -+ queue_empty(q); -+ /* no installed package, so check all with same name */ -+ queue_push2(q, pt, 0); -+ FOR_PROVIDES(p, pp, s->name) -+ if (pool->solvables[p].name == s->name && p != pt) -+ queue_push(q, p); -+ queue_push(q, pt); -+ } -+ if (q->count <= 3) -+ return q->count == 3 && q->elements[2] == pt ? 1 : 0; -+ if (!q->elements[1]) -+ { -+ queue_deleten(q, 0, 2); -+ policy_filter_unwanted(solv, q, POLICY_MODE_CHOOSE); -+ queue_unshift(q, 1); /* filter mark */ -+ queue_unshift(q, pt); -+ } -+ for (i = 2; i < q->count; i++) -+ if (q->elements[i] == pt) -+ return 1; -+ return 0; /* not newest */ -+} -+ -+static inline void -+queue_removeelement(Queue *q, Id el) -+{ -+ int i, j; -+ for (i = 0; i < q->count; i++) -+ if (q->elements[i] == el) -+ break; -+ if (i < q->count) -+ { -+ for (j = i++; i < q->count; i++) -+ if (q->elements[i] != el) -+ q->elements[j++] = q->elements[i]; -+ queue_truncate(q, j); -+ } -+} -+ - static Id - choicerule_find_installed(Pool *pool, Id p) - { -@@ -3357,14 +3439,14 @@ solver_addchoicerules(Solver *solv) - Pool *pool = solv->pool; - Map m, mneg; - Rule *r; -- Queue q, qi, qcheck, infoq; -+ Queue q, qi, qcheck, qcheck2, infoq; - int i, j, rid, havechoice, negcnt; - Id p, d, pp, p2; - Solvable *s; - Id lastaddedp, lastaddedd; - int lastaddedcnt; - unsigned int now; -- int isinstalled; -+ int isnewest = 0; - - solv->choicerules = solv->nrules; - if (!pool->installed) -@@ -3376,6 +3458,7 @@ solver_addchoicerules(Solver *solv) - queue_init(&q); - queue_init(&qi); - queue_init(&qcheck); -+ queue_init(&qcheck2); - queue_init(&infoq); - map_init(&m, pool->nsolvables); - map_init(&mneg, pool->nsolvables); -@@ -3395,28 +3478,20 @@ solver_addchoicerules(Solver *solv) - if (r->p >= 0 || ((r->d == 0 || r->d == -1) && r->w2 <= 0)) - continue; /* only look at requires rules */ - /* solver_printrule(solv, SOLV_DEBUG_RESULT, r); */ -+ queue_empty(&q); - queue_empty(&qi); - havechoice = 0; -- isinstalled = 0; - FOR_RULELITERALS(p, pp, r) - { - if (p < 0) -- { -- Solvable *s = pool->solvables - p; -- p2 = s->repo == pool->installed ? -p : 0; -- if (p2) -- { -- if (!(solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, p2 - solv->installed->start)))) -- isinstalled = 1; -- } -- continue; -- } -+ continue; - s = pool->solvables + p; - if (!s->repo) - continue; - if (s->repo == pool->installed) - { - queue_push2(&qi, p, p); -+ queue_push(&q, p); - continue; - } - /* find an installed package p2 that we can update/downgrade to p */ -@@ -3428,6 +3503,7 @@ solver_addchoicerules(Solver *solv) - if (policy_is_illegal(solv, pool->solvables + p2, s, 0)) - continue; - queue_push2(&qi, p2, p); -+ queue_push(&q, p); - continue; - } - /* package p is independent of the installed ones */ -@@ -3436,31 +3512,47 @@ solver_addchoicerules(Solver *solv) - #if 0 - printf("havechoice: %d qcount %d qicount %d\n", havechoice, q.count, qi.count); - #endif -- if (!havechoice || !qi.count) -+ if (!havechoice || !q.count || !qi.count) - continue; /* no choice */ - - FOR_RULELITERALS(p, pp, r) - if (p > 0) - MAPSET(&m, p); - -- if (!isinstalled) -+ isnewest = 1; -+ FOR_RULELITERALS(p, pp, r) - { -- /* do extra checking for packages related to installed packages */ -- for (i = j = 0; i < qi.count; i += 2) -+ if (p > 0) -+ break; -+ p2 = choicerule_find_installed(pool, -p); -+ if (p2 && !solver_choicerulecheck2(solv, p2, -p, &qcheck2)) - { -- p2 = qi.elements[i]; -- if (solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, p2 - solv->installed->start))) -- { -- if (solver_choicerulecheck(solv, p2, r, &m, &qcheck)) -- continue; -- } -- qi.elements[j++] = p2; -- qi.elements[j++] = qi.elements[i + 1]; -+ isnewest = 0; -+ break; -+ } -+ if (!p2 && !solver_choicerulecheck3(solv, -p, &qcheck2)) -+ { -+ isnewest = 0; -+ break; - } -- queue_truncate(&qi, j); - } -+ /* do extra checking */ -+ for (i = j = 0; i < qi.count; i += 2) -+ { -+ p2 = qi.elements[i]; -+ if (!p2) -+ continue; -+ if (isnewest && solver_choicerulecheck(solv, p2, r, &m, &qcheck)) -+ { -+ /* oops, remove element p from q */ -+ queue_removeelement(&q, qi.elements[i + 1]); -+ continue; -+ } -+ qi.elements[j++] = p2; -+ } -+ queue_truncate(&qi, j); - -- if (!qi.count) -+ if (!q.count || !qi.count) - { - FOR_RULELITERALS(p, pp, r) - if (p > 0) -@@ -3468,15 +3560,6 @@ solver_addchoicerules(Solver *solv) - continue; - } - -- queue_empty(&q); -- /* split q from qi */ -- for (i = j = 0; i < qi.count; i += 2) -- { -- queue_push(&q, qi.elements[i + 1]); -- qi.elements[j++] = qi.elements[i]; -- } -- queue_truncate(&qi, j); -- - - /* now check the update rules of the installed package. - * if all packages of the update rules are contained in -@@ -3496,7 +3579,6 @@ solver_addchoicerules(Solver *solv) - break; - if (p) - break; -- /* speed improvement: only check each package once */ - for (j = i + 1; j < qi.count; j++) - if (qi.elements[i] == qi.elements[j]) - qi.elements[j] = 0; -@@ -3554,6 +3636,7 @@ solver_addchoicerules(Solver *solv) - queue_free(&q); - queue_free(&qi); - queue_free(&qcheck); -+ queue_free(&qcheck2); - queue_free(&infoq); - map_free(&m); - map_free(&mneg); -diff --git a/src/solver.c b/src/solver.c -index 28341d6d..23285ff2 100644 ---- a/src/solver.c -+++ b/src/solver.c -@@ -2620,43 +2620,6 @@ resolve_orphaned(Solver *solv, int level, int disablerules, Queue *dq, int *reru - return level; - } - --int --solver_check_unneeded_choicerules(Solver *solv) --{ -- Pool *pool = solv->pool; -- Rule *r, *or; -- Id p, pp, p2, pp2; -- int i; -- int havedisabled = 0; -- -- /* check if some choice rules could have been broken */ -- for (i = solv->choicerules, r = solv->rules + i; i < solv->choicerules_end; i++, r++) -- { -- if (r->d < 0) -- continue; -- or = solv->rules + solv->choicerules_info[i - solv->choicerules]; -- if (or->d < 0) -- continue; -- FOR_RULELITERALS(p, pp, or) -- { -- if (p < 0 || solv->decisionmap[p] <= 0) -- continue; -- FOR_RULELITERALS(p2, pp2, r) -- if (p2 == p) -- break; -- if (!p2) -- { -- /* did not find p in choice rule, disable it */ -- POOL_DEBUG(SOLV_DEBUG_SOLVER, "disabling unneeded choice rule #%d\n", i); -- solver_disablechoicerules(solv, r); -- havedisabled = 1; -- break; -- } -- } -- } -- return havedisabled; --} -- - /*------------------------------------------------------------------- - * - * solver_run_sat -@@ -2842,14 +2805,6 @@ solver_run_sat(Solver *solv, int disablerules, int doweak) - continue; - } - -- if (solv->choicerules != solv->choicerules_end && solver_check_unneeded_choicerules(solv)) -- { -- POOL_DEBUG(SOLV_DEBUG_SOLVER, "did choice rule minimization, rerunning solver\n"); -- solver_reset(solv); -- level = 0; /* restart from scratch */ -- continue; -- } -- - if (solv->solution_callback) - { - solv->solution_callback(solv, solv->solution_callback_data); --- -2.38.1 - diff --git a/0003-Revert-Add-complex_deps-requirement-to-choice1b-test.patch b/0003-Revert-Add-complex_deps-requirement-to-choice1b-test.patch deleted file mode 100644 index 83e0c1a..0000000 --- a/0003-Revert-Add-complex_deps-requirement-to-choice1b-test.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 6087b30a65d1a742ff0ff75f00aedd39ded33bf6 Mon Sep 17 00:00:00 2001 -From: Nicola Sella -Date: Wed, 7 Dec 2022 16:53:58 +0100 -Subject: [PATCH 2/3] Revert "Add complex_deps requirement to choice1b - testcase" - -This reverts commit 9cb62e9db34cb62031cc5b0a444b4bff16d39db9. ---- - test/testcases/choicerules/choice1b.t | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/test/testcases/choicerules/choice1b.t b/test/testcases/choicerules/choice1b.t -index cf6051ce..fc47b722 100644 ---- a/test/testcases/choicerules/choice1b.t -+++ b/test/testcases/choicerules/choice1b.t -@@ -1,4 +1,3 @@ --feature complex_deps - repo system 0 testtags - #>=Pkg: B 1 1 noarch - #>=Prv: P = 1 --- -2.38.1 - diff --git a/0004-Revert-Add-more-choicerules-tests.patch b/0004-Revert-Add-more-choicerules-tests.patch deleted file mode 100644 index 644b475..0000000 --- a/0004-Revert-Add-more-choicerules-tests.patch +++ /dev/null @@ -1,314 +0,0 @@ -From 5fef9bb8c9899e64306a87ab89574f3afb9968de Mon Sep 17 00:00:00 2001 -From: Nicola Sella -Date: Wed, 7 Dec 2022 16:54:02 +0100 -Subject: [PATCH 3/3] Revert "Add more choicerules tests" - -This reverts commit ce9dda7d3e5b27f4cd883eb69e7ea5cace0a2828. ---- - test/testcases/choicerules/choice1.t | 27 --------------- - test/testcases/choicerules/choice1b.t | 18 ---------- - test/testcases/choicerules/choice2.t | 21 ------------ - test/testcases/choicerules/choice2b.t | 47 --------------------------- - test/testcases/choicerules/choice3.t | 16 --------- - test/testcases/choicerules/choice3b.t | 31 ------------------ - test/testcases/choicerules/choice4.t | 18 ---------- - test/testcases/choicerules/choice5.t | 21 ------------ - test/testcases/choicerules/choice6.t | 28 ---------------- - 9 files changed, 227 deletions(-) - delete mode 100644 test/testcases/choicerules/choice1.t - delete mode 100644 test/testcases/choicerules/choice1b.t - delete mode 100644 test/testcases/choicerules/choice2b.t - delete mode 100644 test/testcases/choicerules/choice3b.t - delete mode 100644 test/testcases/choicerules/choice5.t - delete mode 100644 test/testcases/choicerules/choice6.t - -diff --git a/test/testcases/choicerules/choice1.t b/test/testcases/choicerules/choice1.t -deleted file mode 100644 -index fbd5184a..00000000 ---- a/test/testcases/choicerules/choice1.t -+++ /dev/null -@@ -1,27 +0,0 @@ --# --#Rule #2: --# !A-2-1.noarch [3] (w1) --# B-2-1.noarch [4] (w2) --# C-2-1.noarch [5] --# --# ==> Choice Rule --# !A-2-1.noarch [3] (w1) --# B-2-1.noarch [4] (w2) --# --repo system 0 testtags --#>=Pkg: B 1 1 noarch --#>=Prv: P = 1 --repo available 0 testtags --#>=Pkg: A 2 1 noarch --#>=Req: P = 2 --#>=Pkg: B 2 1 noarch --#>=Prv: P = 2 --#>=Pkg: C 2 1 noarch --#>=Prv: P = 2 --system i686 rpm system -- --job install name A --result transaction,problems --result transaction,problems --#>install A-2-1.noarch@available --#>upgrade B-1-1.noarch@system B-2-1.noarch@available -diff --git a/test/testcases/choicerules/choice1b.t b/test/testcases/choicerules/choice1b.t -deleted file mode 100644 -index fc47b722..00000000 ---- a/test/testcases/choicerules/choice1b.t -+++ /dev/null -@@ -1,18 +0,0 @@ --repo system 0 testtags --#>=Pkg: B 1 1 noarch --#>=Prv: P = 1 --repo available 0 testtags --#>=Pkg: X 1 1 noarch --#>=Pkg: Y 1 1 noarch --#>=Pkg: A 2 1 noarch --#>=Req: P = 2 (X & Y) --#>=Pkg: B 2 1 noarch --#>=Prv: P = 2 --#>=Pkg: C 2 1 noarch --#>=Prv: P = 2 --system i686 rpm system -- --job install name A --result transaction,problems --result transaction,problems --#>install A-2-1.noarch@available -diff --git a/test/testcases/choicerules/choice2.t b/test/testcases/choicerules/choice2.t -index 1eb6c7c3..cb067b18 100644 ---- a/test/testcases/choicerules/choice2.t -+++ b/test/testcases/choicerules/choice2.t -@@ -1,24 +1,3 @@ --# --# Test that updating package B will update package A --# instead of pulling in new package C --# --#Rule #5: --# !A-2-2.noarch [5] (w1) --# B-2-1.noarch [6] (w2) --# C-2-1.noarch [8] --#Rule #7: --# !A-2-1.noarch [4] (w1) --# B-2-1.noarch [6] (w2) --# C-2-1.noarch [8] --#Rule #8: --# !A-1-1.noarch [2]I (w1) --# B-1-1.noarch [3]I (w2) --# C-1-1.noarch [7] --# --# ==> Choice Rule for #8: --# !A-1-1.noarch [2]I (w1) --# B-1-1.noarch [3]I (w2) --# - repo system 0 testtags - #>=Pkg: A 1 1 noarch - #>=Req: P = 1 -diff --git a/test/testcases/choicerules/choice2b.t b/test/testcases/choicerules/choice2b.t -deleted file mode 100644 -index ae619f77..00000000 ---- a/test/testcases/choicerules/choice2b.t -+++ /dev/null -@@ -1,47 +0,0 @@ --# --# Test that updating package B will update package A --# instead of pulling in new package C --# --#Rule #5: --# !A-2-2.noarch [5] (w1) --# B-2-1.noarch [6] (w2) --# C-2-1.noarch [8] --#Rule #7: --# !A-2-1.noarch [4] (w1) --# B-2-1.noarch [6] (w2) --# C-2-1.noarch [8] --#Rule #8: --# !A-1-1.noarch [2]I (w1) --# B-1-1.noarch [3]I (w2) --# C-1-1.noarch [7] --# --# ==> Choice Rule for #8: --# !A-1-1.noarch [2]I (w1) --# B-1-1.noarch [3]I (w2) --# --repo system 0 testtags --#>=Pkg: A 1 1 noarch --#>=Req: P = 1 --#>=Pkg: B 1 1 noarch --#>=Prv: P = 1 --repo available 0 testtags --#>=Pkg: A 1 1 noarch --#>=Req: P = 1 --#>=Pkg: B 1 1 noarch --#>=Prv: P = 1 --#>=Pkg: A 2 1 noarch --#>=Req: P = 2 --#>=Pkg: A 2 2 noarch --#>=Req: P = 2 --#>=Pkg: B 2 1 noarch --#>=Prv: P = 2 --#>=Pkg: C 1 1 noarch --#>=Prv: P = 1 --#>=Pkg: C 2 1 noarch --#>=Prv: P = 2 --system i686 rpm system -- --job update name B --result transaction,problems --#>upgrade A-1-1.noarch@system A-2-2.noarch@available --#>upgrade B-1-1.noarch@system B-2-1.noarch@available -diff --git a/test/testcases/choicerules/choice3.t b/test/testcases/choicerules/choice3.t -index 1b82e691..d5d41acc 100644 ---- a/test/testcases/choicerules/choice3.t -+++ b/test/testcases/choicerules/choice3.t -@@ -1,19 +1,3 @@ --# Do not block an update because of a choice rule --# --#Rule #3: --# !B-1-1.noarch [4] (w1) --# A-1-1.noarch [2]I (w2) --# Anew-2-1.noarch [6] --#Rule #4: --# !B-1-1.noarch [3]I (w1) --# A-1-1.noarch [2]I (w2) --# Anew-2-1.noarch [6] --# --# ==> No choice rule for Rule#4! --# ==> Choice Rule for #3: --# !B-1-1.noarch [4] (w1) --# A-1-1.noarch [2]I (w2) --# - repo system 0 testtags - #>=Pkg: A 1 1 noarch - #>=Prv: libA -diff --git a/test/testcases/choicerules/choice3b.t b/test/testcases/choicerules/choice3b.t -deleted file mode 100644 -index fb9c7250..00000000 ---- a/test/testcases/choicerules/choice3b.t -+++ /dev/null -@@ -1,31 +0,0 @@ --# Do not block an update because of a choice rule --# --#Rule #3: --# !B-1-1.noarch [4] (w1) --# A-1-1.noarch [2]I (w2) --# Anew-2-1.noarch [6] --#Rule #4: --# !B-1-1.noarch [3]I (w1) --# A-1-1.noarch [2]I (w2) --# Anew-2-1.noarch [6] --# --# ==> No choice rule for Rule#4! --# ==> Choice Rule for #3: --# !B-1-1.noarch [4] (w1) --# A-1-1.noarch [2]I (w2) --# --repo system 0 testtags --#>=Pkg: A 1 1 noarch --#>=Prv: libA --#>=Pkg: B 1 1 noarch --#>=Req: libA --repo available 0 testtags --#>=Pkg: A 2 1 noarch --#>=Pkg: Anew 2 1 noarch --#>=Prv: libA --system i686 rpm system -- --job update all packages --result transaction,problems --#>install Anew-2-1.noarch@available --#>upgrade A-1-1.noarch@system A-2-1.noarch@available -diff --git a/test/testcases/choicerules/choice4.t b/test/testcases/choicerules/choice4.t -index 7378a569..1bf9f487 100644 ---- a/test/testcases/choicerules/choice4.t -+++ b/test/testcases/choicerules/choice4.t -@@ -1,21 +1,3 @@ --# This tests that A is updated instead of Anew being installed --# --#Rule #4: --# !B-2-2.noarch [11] (w1) --# A-2-2.noarch [9] (w2) --# Anew-2-2.noarch [10] --#Rule #11: --# !B-2-1.noarch [8] (w1) --# A-2-1.noarch [6] (w2) --# Anew-2-1.noarch [7] --# --#Choice Rule for #4: --# !B-2-2.noarch [11] (w1) --# A-2-2.noarch [9] (w2) --#Choice Rule for #11 --# !B-2-1.noarch [8] (w1) --# A-2-1.noarch [6] (w2) --# - repo system 0 testtags - #>=Pkg: A 1 1 noarch - #>=Prv: libA = 1-1 -diff --git a/test/testcases/choicerules/choice5.t b/test/testcases/choicerules/choice5.t -deleted file mode 100644 -index 9f43c8a3..00000000 ---- a/test/testcases/choicerules/choice5.t -+++ /dev/null -@@ -1,21 +0,0 @@ --# --# test that a package split does not update unrelated packages --# --repo system 0 testtags --#>=Pkg: A 1 1 noarch --#>=Prv: libA --#>=Pkg: B 1 1 noarch --#>=Req: libA --repo available 0 testtags --#>=Pkg: A 1 1 noarch --#>=Prv: libA --#>=Pkg: A 2 1 noarch --#>=Pkg: Asplit 2 1 noarch --#>=Prv: libA --#>=Pkg: B 2 1 noarch --#>=Req: libA --system i686 rpm system --job update name A --result transaction,problems --#>install Asplit-2-1.noarch@available --#>upgrade A-1-1.noarch@system A-2-1.noarch@available -diff --git a/test/testcases/choicerules/choice6.t b/test/testcases/choicerules/choice6.t -deleted file mode 100644 -index e860ae20..00000000 ---- a/test/testcases/choicerules/choice6.t -+++ /dev/null -@@ -1,28 +0,0 @@ --#Rule #4: --# !php-fpm-7.2.24-1.noarch [5] (w1) --# glibc-2.17-325.noarch [2]I (w2) --# libcrypt-4.1.1-6.noarch [7] --#=> no choice rule for #4 --# --repo @System 0 testtags --#>=Pkg: glibc 2.17 325 noarch --#>=Prv: libcrypt --#>=Pkg: php 5.4.16 48 noarch --repo available 0 testtags --#>=Pkg: php 7.2.24 1 noarch --#>=Rec: php-fpm = 7.2.24-1 --#>=Pkg: php-fpm 7.2.24 1 noarch --#>=Req: libcrypt --#>=Pkg: php-fpm 8.0.13 2 noarch --#>=Req: libcrypt --#>=Pkg: libcrypt 4.1.1 6 noarch --#>=Req: libc --#>=Pkg: glibc 2.28 181 noarch --#>=Prv: libc --system i686 rpm @System --job update all packages --result transaction,problems --#>install libcrypt-4.1.1-6.noarch@available --#>install php-fpm-7.2.24-1.noarch@available --#>upgrade glibc-2.17-325.noarch@@System glibc-2.28-181.noarch@available --#>upgrade php-5.4.16-48.noarch@@System php-7.2.24-1.noarch@available --- -2.38.1 - diff --git a/0013-choice-rules-also-do-solver_choicerulecheck-for-pack.patch b/0013-choice-rules-also-do-solver_choicerulecheck-for-pack.patch new file mode 100644 index 0000000..486852f --- /dev/null +++ b/0013-choice-rules-also-do-solver_choicerulecheck-for-pack.patch @@ -0,0 +1,53 @@ +From 6c45846e51a7bdcc47ac986f0e8c7045048cb974 Mon Sep 17 00:00:00 2001 +From: Michael Schroeder +Date: Fri, 19 May 2023 15:17:53 +0200 +Subject: [PATCH] choice rules: also do solver_choicerulecheck for package + downgrades + +Fixes issue #514 +--- + src/rules.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/src/rules.c b/src/rules.c +index 660656f0..7d57cfde 100644 +--- a/src/rules.c ++++ b/src/rules.c +@@ -3449,6 +3449,7 @@ solver_addchoicerules(Solver *solv) + int lastaddedcnt; + unsigned int now; + int isinstalled; ++ int dodowngradecheck = solv->allowdowngrade; + + solv->choicerules = solv->nrules; + if (!pool->installed) +@@ -3457,6 +3458,8 @@ solver_addchoicerules(Solver *solv) + return; + } + now = solv_timems(0); ++ if ((solv->dupinvolvedmap_all || solv->dupinvolvedmap.size) && solv->dup_allowdowngrade) ++ dodowngradecheck = 1; + queue_init(&q); + queue_init(&qi); + queue_init(&qcheck); +@@ -3532,8 +3535,16 @@ solver_addchoicerules(Solver *solv) + /* do extra checking for packages related to installed packages */ + for (i = j = 0; i < qi.count; i += 2) + { ++ int isdowngrade = 0; + p2 = qi.elements[i]; +- if (solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, p2 - solv->installed->start))) ++ if (dodowngradecheck) ++ { ++ p = qi.elements[i + 1]; ++ if (pool->solvables[p2].name == pool->solvables[p].name) ++ if (pool_evrcmp(pool, pool->solvables[p2].evr, pool->solvables[p].evr, EVRCMP_COMPARE) > 0) ++ isdowngrade = 1; ++ } ++ if (isdowngrade || solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, p2 - solv->installed->start))) + { + if (solver_choicerulecheck(solv, p2, r, &m, &qcheck)) + continue; +-- +2.53.0 + diff --git a/libsolv.spec b/libsolv.spec index 758b8f0..f0d035b 100644 --- a/libsolv.spec +++ b/libsolv.spec @@ -23,7 +23,7 @@ Name: lib%{libname} Version: 0.7.24 -Release: 4%{?dist} +Release: 5%{?dist} Summary: Package dependency solver License: BSD @@ -31,9 +31,6 @@ URL: https://github.com/openSUSE/libsolv Source: %{url}/archive/%{version}/%{name}-%{version}.tar.gz # https://bugzilla.redhat.com/show_bug.cgi?id=1993126 Patch1: 0001-Add-support-for-computing-hashes-using-OpenSSL.patch -Patch2: 0002-Revert-Improve-choice-rule-generation.patch -Patch3: 0003-Revert-Add-complex_deps-requirement-to-choice1b-test.patch -Patch4: 0004-Revert-Add-more-choicerules-tests.patch Patch5: 0005-Treat-condition-both-as-positive-and-negative-litera.patch Patch6: 0006-Allow_break_arch_lock_step_on_erase.patch Patch7: libsolv-0.7.24-static_analysis_fixes.patch @@ -44,6 +41,8 @@ Patch11: 0011-Implement-color-filtering-when-adding-update-targets.patch # Patch merged upstream: https://github.com/openSUSE/libsolv/pull/604 Patch12: 0012-Add-testcase-for-color-filtering-when-adding-update-.patch +# upstream patch: https://github.com/openSUSE/libsolv/commit/2c85ed581422e072ad95119f3d7dc19eb45f29ac +Patch13: 0013-choice-rules-also-do-solver_choicerulecheck-for-pack.patch BuildRequires: cmake BuildRequires: gcc-c++ @@ -270,6 +269,10 @@ export LD_LIBRARY_PATH=%{buildroot}%{_libdir} %endif %changelog +* Wed Apr 22 2026 Marek Blaha - 0.7.24-5 +- Backport "choice rules: also do solver_choicerulecheck for package downgrades" + Resolves: RHEL-141449 + * Thu Jan 22 2026 Evan Goode - 0.7.24-4 - Backport "Implement color filtering when adding update targets" Resolves: RHEL-103995