312 lines
10 KiB
Diff
312 lines
10 KiB
Diff
From 6c9cef4ef810cd32ffeee20986a16e0871fc0bae Mon Sep 17 00:00:00 2001
|
|
From: Michael Schroeder <mls@suse.de>
|
|
Date: Mon, 7 Mar 2016 14:09:40 +0100
|
|
Subject: [PATCH 9/9] Rework orphan handling in dup mode
|
|
|
|
The old code had problems when the updaters contained other
|
|
installed packages.
|
|
---
|
|
src/rules.c | 193 +++++++++++++++++++++++++++++++++++++++++++----------------
|
|
src/rules.h | 3 +-
|
|
src/solver.c | 7 ++-
|
|
3 files changed, 149 insertions(+), 54 deletions(-)
|
|
|
|
diff --git a/src/rules.c b/src/rules.c
|
|
index 4cd53d3..0e2c955 100644
|
|
--- a/src/rules.c
|
|
+++ b/src/rules.c
|
|
@@ -1170,35 +1170,56 @@ solver_addpkgrulesforupdaters(Solver *solv, Solvable *s, Map *m, int allow_all)
|
|
***
|
|
***/
|
|
|
|
+static int
|
|
+dup_maykeepinstalled(Solver *solv, Solvable *s)
|
|
+{
|
|
+ Pool *pool = solv->pool;
|
|
+ Id ip, pp;
|
|
+
|
|
+ if (solv->dupmap.size && MAPTST(&solv->dupmap, s - pool->solvables))
|
|
+ return 1;
|
|
+ /* is installed identical to a good one? */
|
|
+ FOR_PROVIDES(ip, pp, s->name)
|
|
+ {
|
|
+ Solvable *is = pool->solvables + ip;
|
|
+ if (is->evr != s->evr)
|
|
+ continue;
|
|
+ if (solv->dupmap.size)
|
|
+ {
|
|
+ if (!MAPTST(&solv->dupmap, ip))
|
|
+ continue;
|
|
+ }
|
|
+ else if (is->repo == pool->installed)
|
|
+ continue;
|
|
+ if (solvable_identical(s, is))
|
|
+ return 1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
static Id
|
|
-finddistupgradepackages(Solver *solv, Solvable *s, Queue *qs, int allow_all)
|
|
+finddistupgradepackages(Solver *solv, Solvable *s, Queue *qs)
|
|
{
|
|
Pool *pool = solv->pool;
|
|
- int i;
|
|
+ int i, j;
|
|
|
|
- policy_findupdatepackages(solv, s, qs, allow_all ? allow_all : 2);
|
|
- if (!qs->count)
|
|
+ policy_findupdatepackages(solv, s, qs, 2);
|
|
+ if (qs->count)
|
|
{
|
|
- if (allow_all)
|
|
- return 0; /* orphaned, don't create feature rule */
|
|
- /* check if this is an orphaned package */
|
|
- policy_findupdatepackages(solv, s, qs, 1);
|
|
- if (!qs->count)
|
|
- return 0; /* orphaned, don't create update rule */
|
|
- qs->count = 0;
|
|
- return -SYSTEMSOLVABLE; /* supported but not installable */
|
|
+ /* remove installed packages we can't keep */
|
|
+ for (i = j = 0; i < qs->count; i++)
|
|
+ {
|
|
+ Solvable *ns = pool->solvables + qs->elements[i];
|
|
+ if (ns->repo == pool->installed && !dup_maykeepinstalled(solv, ns))
|
|
+ continue;
|
|
+ qs->elements[j++] = qs->elements[i];
|
|
+ }
|
|
+ queue_truncate(qs, j);
|
|
}
|
|
- if (allow_all)
|
|
- return s - pool->solvables;
|
|
/* check if it is ok to keep the installed package */
|
|
- if (solv->dupmap.size && MAPTST(&solv->dupmap, s - pool->solvables))
|
|
+ if (dup_maykeepinstalled(solv, s))
|
|
return s - pool->solvables;
|
|
- for (i = 0; i < qs->count; i++)
|
|
- {
|
|
- Solvable *ns = pool->solvables + qs->elements[i];
|
|
- if (s->evr == ns->evr && solvable_identical(s, ns))
|
|
- return s - pool->solvables;
|
|
- }
|
|
/* nope, it must be some other package */
|
|
return -SYSTEMSOLVABLE;
|
|
}
|
|
@@ -1240,6 +1261,73 @@ set_specialupdaters(Solver *solv, Solvable *s, Id d)
|
|
solv->specialupdaters[s - solv->pool->solvables - installed->start] = d;
|
|
}
|
|
|
|
+#ifdef ENABLE_LINKED_PKGS
|
|
+/* Check if this is a linked pseudo package. As it is linked, we do not need an update/feature rule */
|
|
+static inline int
|
|
+is_linked_pseudo_package(Solver *solv, Solvable *s)
|
|
+{
|
|
+ Pool *pool = solv->pool;
|
|
+ if (solv->instbuddy && solv->instbuddy[s - pool->solvables - solv->installed->start])
|
|
+ {
|
|
+ const char *name = pool_id2str(pool, s->name);
|
|
+ if (strncmp(name, "pattern:", 8) == 0 || strncmp(name, "application:", 12) == 0)
|
|
+ return 1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+#endif
|
|
+
|
|
+void
|
|
+solver_addfeaturerule(Solver *solv, Solvable *s)
|
|
+{
|
|
+ Pool *pool = solv->pool;
|
|
+ int i;
|
|
+ Id p;
|
|
+ Queue qs;
|
|
+ Id qsbuf[64];
|
|
+
|
|
+#ifdef ENABLE_LINKED_PKGS
|
|
+ if (is_linked_pseudo_package(solv, s))
|
|
+ {
|
|
+ solver_addrule(solv, 0, 0, 0); /* no feature rules for those */
|
|
+ return;
|
|
+ }
|
|
+#endif
|
|
+ queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
|
|
+ p = s - pool->solvables;
|
|
+ policy_findupdatepackages(solv, s, &qs, 1);
|
|
+ if (solv->dupmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p)))
|
|
+ {
|
|
+ if (!dup_maykeepinstalled(solv, s))
|
|
+ {
|
|
+ for (i = 0; i < qs.count; i++)
|
|
+ {
|
|
+ Solvable *ns = pool->solvables + qs.elements[i];
|
|
+ if (ns->repo != pool->installed || dup_maykeepinstalled(solv, ns))
|
|
+ break;
|
|
+ }
|
|
+ if (i == qs.count)
|
|
+ {
|
|
+ solver_addrule(solv, 0, 0, 0); /* this is an orphan */
|
|
+ queue_free(&qs);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (qs.count > 1)
|
|
+ {
|
|
+ Id d = pool_queuetowhatprovides(pool, &qs);
|
|
+ queue_free(&qs);
|
|
+ solver_addrule(solv, p, 0, d); /* allow update of s */
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ Id d = qs.count ? qs.elements[0] : 0;
|
|
+ queue_free(&qs);
|
|
+ solver_addrule(solv, p, d, 0); /* allow update of s */
|
|
+ }
|
|
+}
|
|
+
|
|
/*-------------------------------------------------------------------
|
|
*
|
|
* add rule for update
|
|
@@ -1249,7 +1337,7 @@ set_specialupdaters(Solver *solv, Solvable *s, Id d)
|
|
*/
|
|
|
|
void
|
|
-solver_addupdaterule(Solver *solv, Solvable *s, int allow_all)
|
|
+solver_addupdaterule(Solver *solv, Solvable *s)
|
|
{
|
|
/* installed packages get a special upgrade allowed rule */
|
|
Pool *pool = solv->pool;
|
|
@@ -1257,48 +1345,53 @@ solver_addupdaterule(Solver *solv, Solvable *s, int allow_all)
|
|
Queue qs;
|
|
Id qsbuf[64];
|
|
int isorphaned = 0;
|
|
+ Rule *r;
|
|
+ int islinkedpseudo = 0;
|
|
|
|
- queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
|
|
p = s - pool->solvables;
|
|
+#ifdef ENABLE_LINKED_PKGS
|
|
+ islinkedpseudo = is_linked_pseudo_package(solv, s);
|
|
+#endif
|
|
+
|
|
+ /* Orphan detection. We cheat by looking at the feature rule, which
|
|
+ * we already calculated */
|
|
+ r = solv->rules + solv->featurerules + (p - solv->installed->start);
|
|
+ if (!r->p && !islinkedpseudo)
|
|
+ {
|
|
+ p = 0;
|
|
+ queue_push(&solv->orphaned, s - pool->solvables); /* an orphaned package */
|
|
+ if (solv->keep_orphans && !(solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, s - pool->solvables - solv->installed->start))))
|
|
+ p = s - pool->solvables; /* keep this orphaned package installed */
|
|
+ solver_addrule(solv, p, 0, 0);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
|
|
/* find update candidates for 's' */
|
|
if (solv->dupmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p)))
|
|
- p = finddistupgradepackages(solv, s, &qs, allow_all);
|
|
+ p = finddistupgradepackages(solv, s, &qs);
|
|
else
|
|
- policy_findupdatepackages(solv, s, &qs, allow_all);
|
|
+ policy_findupdatepackages(solv, s, &qs, 0);
|
|
|
|
#ifdef ENABLE_LINKED_PKGS
|
|
- if (solv->instbuddy && solv->instbuddy[s - pool->solvables - solv->installed->start])
|
|
+ if (islinkedpseudo)
|
|
{
|
|
- const char *name = pool_id2str(pool, s->name);
|
|
- if (strncmp(name, "pattern:", 8) == 0 || strncmp(name, "application:", 12) == 0)
|
|
+ /* a linked pseudo package. As it is linked, we do not need an update/feature rule */
|
|
+ /* nevertheless we set specialupdaters so we can update */
|
|
+ solver_addrule(solv, 0, 0, 0);
|
|
+ if (qs.count)
|
|
{
|
|
- /* a linked pseudo package. As it is linked, we do not need an update/feature rule */
|
|
- /* nevertheless we set specialupdaters so we can update */
|
|
- solver_addrule(solv, 0, 0, 0);
|
|
- if (!allow_all && qs.count)
|
|
- {
|
|
- if (p != -SYSTEMSOLVABLE)
|
|
- queue_unshift(&qs, p);
|
|
- if (qs.count)
|
|
- set_specialupdaters(solv, s, pool_queuetowhatprovides(pool, &qs));
|
|
- }
|
|
- queue_free(&qs);
|
|
- return;
|
|
+ if (p != -SYSTEMSOLVABLE)
|
|
+ queue_unshift(&qs, p);
|
|
+ if (qs.count)
|
|
+ set_specialupdaters(solv, s, pool_queuetowhatprovides(pool, &qs));
|
|
}
|
|
- }
|
|
-#endif
|
|
-
|
|
- if (!allow_all && !p) /* !p implies qs.count == 0 */
|
|
- {
|
|
- queue_push(&solv->orphaned, s - pool->solvables); /* an orphaned package */
|
|
- if (solv->keep_orphans && !(solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, s - pool->solvables - solv->installed->start))))
|
|
- p = s - pool->solvables; /* keep this orphaned package installed */
|
|
queue_free(&qs);
|
|
- solver_addrule(solv, p, 0, 0);
|
|
return;
|
|
}
|
|
+#endif
|
|
|
|
- if (!allow_all && qs.count && solv->multiversion.size)
|
|
+ if (qs.count && solv->multiversion.size)
|
|
{
|
|
int i, j;
|
|
|
|
diff --git a/src/rules.h b/src/rules.h
|
|
index 606819b..29325ea 100644
|
|
--- a/src/rules.h
|
|
+++ b/src/rules.h
|
|
@@ -111,7 +111,8 @@ extern void solver_addpkgrulesforlinked(struct _Solver *solv, Map *m);
|
|
extern void solver_addpkgrulesforupdaters(struct _Solver *solv, Solvable *s, Map *m, int allow_all);
|
|
|
|
/* update/feature rules */
|
|
-extern void solver_addupdaterule(struct _Solver *solv, Solvable *s, int allow_all);
|
|
+extern void solver_addfeaturerule(struct _Solver *solv, Solvable *s);
|
|
+extern void solver_addupdaterule(struct _Solver *solv, Solvable *s);
|
|
|
|
/* infarch rules */
|
|
extern void solver_addinfarchrules(struct _Solver *solv, Map *addedmap);
|
|
diff --git a/src/solver.c b/src/solver.c
|
|
index 261f367..15a3114 100644
|
|
--- a/src/solver.c
|
|
+++ b/src/solver.c
|
|
@@ -3716,7 +3716,7 @@ solver_solve(Solver *solv, Queue *job)
|
|
solver_addrule(solv, 0, 0, 0); /* create dummy rule */
|
|
continue;
|
|
}
|
|
- solver_addupdaterule(solv, s, 1); /* allow s to be updated */
|
|
+ solver_addfeaturerule(solv, s);
|
|
}
|
|
/* make sure we accounted for all rules */
|
|
assert(solv->nrules - solv->featurerules == installed->end - installed->start);
|
|
@@ -3744,7 +3744,7 @@ solver_solve(Solver *solv, Queue *job)
|
|
solver_addrule(solv, 0, 0, 0); /* create dummy rule */
|
|
continue;
|
|
}
|
|
- solver_addupdaterule(solv, s, 0); /* allowall = 0: downgrades not allowed */
|
|
+ solver_addupdaterule(solv, s);
|
|
/*
|
|
* check for and remove duplicate
|
|
*/
|
|
@@ -3759,9 +3759,10 @@ solver_solve(Solver *solv, Queue *job)
|
|
/* it's also orphaned if the feature rule consists just of the installed package */
|
|
if (!solv->dupmap_all && sr->p == i && !sr->d && !sr->w2)
|
|
queue_push(&solv->orphaned, i);
|
|
+
|
|
if (!solver_rulecmp(solv, r, sr))
|
|
memset(sr, 0, sizeof(*sr)); /* delete unneeded feature rule */
|
|
- else
|
|
+ else if (sr->p)
|
|
solver_disablerule(solv, sr); /* disable feature rule for now */
|
|
}
|
|
/* consistency check: we added a rule for _every_ installed solvable */
|
|
--
|
|
2.5.0
|
|
|