summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Schroeder <mls@suse.de>2012-02-01 14:08:47 +0100
committerMichael Schroeder <mls@suse.de>2012-02-01 14:08:47 +0100
commited477952f4b9f83f9b04ae83b3896965aa47fae1 (patch)
tree9470be566097d60d1075272ae864251994ba3b48
parent53072a6ccbf6f2a38af74fd27ccd8d8ab97f99b2 (diff)
downloadlibsolv-ed477952f4b9f83f9b04ae83b3896965aa47fae1.tar.gz
libsolv-ed477952f4b9f83f9b04ae83b3896965aa47fae1.tar.bz2
libsolv-ed477952f4b9f83f9b04ae83b3896965aa47fae1.zip
- add cleandeps support for install/update
-rw-r--r--examples/solv.c20
-rw-r--r--package/libsolv.changes15
-rw-r--r--src/problems.c14
-rw-r--r--src/rules.c465
-rw-r--r--src/solver.c117
-rw-r--r--src/solver.h3
6 files changed, 488 insertions, 146 deletions
diff --git a/examples/solv.c b/examples/solv.c
index 01ea65a..09a9221 100644
--- a/examples/solv.c
+++ b/examples/solv.c
@@ -2585,7 +2585,6 @@ select_patches(Pool *pool, Queue *job)
#define MODE_INFO 7
#define MODE_REPOLIST 8
#define MODE_SEARCH 9
-#define MODE_ERASECLEAN 10
void
usage(int r)
@@ -2625,6 +2624,7 @@ main(int argc, char **argv)
FILE **newpkgsfps;
Id *addedfileprovides = 0;
Id repofilter = 0;
+ int cleandeps = 0;
argc--;
argv++;
@@ -2645,11 +2645,6 @@ main(int argc, char **argv)
mainmode = MODE_ERASE;
mode = SOLVER_ERASE;
}
- else if (!strcmp(argv[0], "eraseclean") || !strcmp(argv[0], "rmclean"))
- {
- mainmode = MODE_ERASECLEAN;
- mode = SOLVER_ERASE;
- }
else if (!strcmp(argv[0], "list"))
{
mainmode = MODE_LIST;
@@ -2688,6 +2683,13 @@ main(int argc, char **argv)
else
usage(1);
+ if (argc > 1 && !strcmp(argv[1], "--clean"))
+ {
+ cleandeps = 1;
+ argc--;
+ argv++;
+ }
+
pool = pool_create();
#if 0
@@ -2939,11 +2941,13 @@ main(int argc, char **argv)
if (!p)
{
job.elements[i] |= SOLVER_INSTALL;
+ if (cleandeps)
+ job.elements[i] |= SOLVER_CLEANDEPS;
continue;
}
}
job.elements[i] |= mode;
- if (mainmode == MODE_ERASECLEAN)
+ if (cleandeps)
job.elements[i] |= SOLVER_CLEANDEPS;
}
@@ -2989,7 +2993,7 @@ rerunsolver:
solv = solver_create(pool);
solver_set_flag(solv, SOLVER_FLAG_IGNORE_ALREADY_RECOMMENDED, 1);
solver_set_flag(solv, SOLVER_FLAG_SPLITPROVIDES, 1);
- if (mainmode == MODE_ERASE || mainmode == MODE_ERASECLEAN)
+ if (mainmode == MODE_ERASE)
solver_set_flag(solv, SOLVER_FLAG_ALLOW_UNINSTALL, 1); /* don't nag */
if (!solver_solve(solv, &job))
diff --git a/package/libsolv.changes b/package/libsolv.changes
index 22544ff..03ba8e6 100644
--- a/package/libsolv.changes
+++ b/package/libsolv.changes
@@ -1,4 +1,19 @@
-------------------------------------------------------------------
+Wed Feb 1 14:06:59 CET 2012 - mls@suse.de
+
+- add cleandeps support for install/update
+- check for cleandeps mistakes (untested)
+
+-------------------------------------------------------------------
+Fri Jan 27 14:10:34 CET 2012 - mls@suse.de
+
+- make repo type code selection modular
+- add more solvable_ functions
+- add dependency getter/setter code to bindings
+- cleanup dup handling
+- hide more internals
+
+-------------------------------------------------------------------
Mon Oct 24 13:26:18 CEST 2011 - ma@suse.de
- mls fixed package provides/obsoletes, but forgot to write
diff --git a/src/problems.c b/src/problems.c
index 6d8f831..976d99a 100644
--- a/src/problems.c
+++ b/src/problems.c
@@ -530,6 +530,7 @@ create_solutions(Solver *solv, int probnr, int solidx)
int i, j, nsol;
int essentialok;
unsigned int now;
+ int oldmistakes = solv->cleandeps_mistakes ? solv->cleandeps_mistakes->count : 0;
now = solv_timems(0);
queue_init(&redoq);
@@ -629,6 +630,18 @@ create_solutions(Solver *solv, int probnr, int solidx)
/* restore problems */
queue_free(&solv->problems);
solv->problems = problems_save;
+
+ if (solv->cleandeps_mistakes)
+ {
+ if (oldmistakes)
+ queue_truncate(solv->cleandeps_mistakes, oldmistakes);
+ else
+ {
+ queue_free(solv->cleandeps_mistakes);
+ solv->cleandeps_mistakes = solv_free(solv->cleandeps_mistakes);
+ }
+ }
+
POOL_DEBUG(SOLV_DEBUG_STATS, "create_solutions for problem #%d took %d ms\n", probnr, solv_timems(now));
}
@@ -872,6 +885,7 @@ solver_findproblemrule(Solver *solv, Id problem)
if (jobr)
return jobr; /* a user request */
assert(0);
+ return 0;
}
/*-------------------------------------------------------------------*/
diff --git a/src/rules.c b/src/rules.c
index e90714e..3962bee 100644
--- a/src/rules.c
+++ b/src/rules.c
@@ -1323,6 +1323,117 @@ reenableduprule(Solver *solv, Id name)
#define DISABLE_INFARCH 2
#define DISABLE_DUP 3
+/*
+ * add all installed packages that package p obsoletes to Queue q.
+ * Package p is not installed and not in oobs map.
+ * Entries may get added multiple times.
+ */
+static void
+add_obsoletes(Solver *solv, Id p, Queue *q)
+{
+ Pool *pool = solv->pool;
+ Repo *installed = solv->installed;
+ Id p2, pp2;
+ Solvable *s = pool->solvables + p;
+ Id obs, *obsp;
+ Id lastp2 = 0;
+
+ /* we already know: p is not installed, p is not noobs */
+ FOR_PROVIDES(p2, pp2, s->name)
+ {
+ Solvable *ps = pool->solvables + p2;
+ if (ps->repo != installed)
+ continue;
+ if (!pool->implicitobsoleteusesprovides && ps->name != s->name)
+ continue;
+ if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
+ continue;
+ queue_push(q, p2);
+ lastp2 = p2;
+ }
+ if (!s->obsoletes)
+ return;
+ obsp = s->repo->idarraydata + s->obsoletes;
+ while ((obs = *obsp++) != 0)
+ FOR_PROVIDES(p2, pp2, obs)
+ {
+ Solvable *ps = pool->solvables + p2;
+ if (ps->repo != installed)
+ continue;
+ if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs))
+ continue;
+ if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
+ continue;
+ if (p2 == lastp2)
+ continue;
+ queue_push(q, p2);
+ lastp2 = p2;
+ }
+}
+
+/*
+ * Call add_obsoletes and intersect the result with the
+ * elements in Queue q starting at qstart.
+ * Assumes that it's the first call if qstart == q->count.
+ * May use auxillary map m for the intersection process, all
+ * elements of q starting at qstart must have their bit cleared.
+ * (This is also true after the function returns.)
+ */
+static void
+intersect_obsoletes(Solver *solv, Id p, Queue *q, int qstart, Map *m)
+{
+ int i, j;
+ int qcount = q->count;
+
+ add_obsoletes(solv, p, q);
+ if (qcount == qstart)
+ return; /* first call */
+ if (qcount == q->count)
+ j = qstart;
+ else if (qcount == qstart + 1)
+ {
+ /* easy if there's just one element */
+ j = qstart;
+ for (i = qcount; i < q->count; i++)
+ if (q->elements[i] == q->elements[qstart])
+ {
+ j++; /* keep the element */
+ break;
+ }
+ }
+ else if (!m->size && q->count - qstart <= 8)
+ {
+ /* faster than a map most of the time */
+ int k;
+ for (i = j = qstart; i < qcount; i++)
+ {
+ Id ip = q->elements[i];
+ for (k = qcount; k < q->count; k++)
+ if (q->elements[k] == ip)
+ {
+ q->elements[j++] = ip;
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* for the really pathologic cases we use the map */
+ Repo *installed = solv->installed;
+ if (!m->size)
+ map_init(m, installed->end - installed->start);
+ for (i = qcount; i < q->count; i++)
+ MAPSET(m, q->elements[i] - installed->start);
+ for (i = j = qstart; i < qcount; i++)
+ if (MAPTST(m, q->elements[i] - installed->start))
+ {
+ MAPCLR(m, q->elements[i] - installed->start);
+ q->elements[j++] = q->elements[i];
+ }
+ }
+ queue_truncate(q, j);
+}
+
static void
jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
{
@@ -1330,7 +1441,7 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
Id select, p, pp;
Repo *installed;
Solvable *s;
- int i, j, set, qstart, pass;
+ int i, j, set, qstart;
Map omap;
installed = solv->installed;
@@ -1409,94 +1520,57 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
}
}
}
- if (!installed)
+ if (!installed || installed->end == installed->start)
return;
/* now the hard part: disable some update rules */
/* first check if we have noobs or installed packages in the job */
+ i = j = 0;
FOR_JOB_SELECT(p, pp, select, what)
{
if (pool->solvables[p].repo == installed)
- {
- if (select == SOLVER_SOLVABLE)
- queue_push2(q, DISABLE_UPDATE, what);
- return;
- }
- if (solv->noobsoletes.size && MAPTST(&solv->noobsoletes, p))
+ j = p;
+ else if (solv->noobsoletes.size && MAPTST(&solv->noobsoletes, p))
return;
+ i++;
+ }
+ if (j) /* have installed packages */
+ {
+ /* this is for dupmap_all jobs, it can go away if we create
+ * duprules for them */
+ if (i == 1 && (set & SOLVER_SETREPO) != 0)
+ queue_push2(q, DISABLE_UPDATE, j);
+ return;
}
- /* all job packages obsolete */
+ omap.size = 0;
qstart = q->count;
- pass = 0;
- memset(&omap, 0, sizeof(omap));
FOR_JOB_SELECT(p, pp, select, what)
{
- Id p2, pp2;
-
- if (pass == 1)
- map_grow(&omap, installed->end - installed->start);
- s = pool->solvables + p;
- if (s->obsoletes)
- {
- Id obs, *obsp;
- obsp = s->repo->idarraydata + s->obsoletes;
- while ((obs = *obsp++) != 0)
- FOR_PROVIDES(p2, pp2, obs)
- {
- Solvable *ps = pool->solvables + p2;
- if (ps->repo != installed)
- continue;
- if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs))
- continue;
- if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
- continue;
- if (pass)
- MAPSET(&omap, p2 - installed->start);
- else
- queue_push2(q, DISABLE_UPDATE, p2);
- }
- }
- FOR_PROVIDES(p2, pp2, s->name)
- {
- Solvable *ps = pool->solvables + p2;
- if (ps->repo != installed)
- continue;
- if (!pool->implicitobsoleteusesprovides && ps->name != s->name)
- continue;
- if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
- continue;
- if (pass)
- MAPSET(&omap, p2 - installed->start);
- else
- queue_push2(q, DISABLE_UPDATE, p2);
- }
- if (pass)
- {
- for (i = j = qstart; i < q->count; i += 2)
- {
- if (MAPTST(&omap, q->elements[i + 1] - installed->start))
- {
- MAPCLR(&omap, q->elements[i + 1] - installed->start);
- q->elements[j + 1] = q->elements[i + 1];
- j += 2;
- }
- }
- queue_truncate(q, j);
- }
+ intersect_obsoletes(solv, p, q, qstart, &omap);
if (q->count == qstart)
break;
- pass++;
}
if (omap.size)
map_free(&omap);
if (qstart == q->count)
return; /* nothing to prune */
- if ((set & (SOLVER_SETEVR | SOLVER_SETARCH | SOLVER_SETVENDOR)) == (SOLVER_SETEVR | SOLVER_SETARCH | SOLVER_SETVENDOR))
- return; /* all is set */
+
+ /* convert result to (DISABLE_UPDATE, p) pairs */
+ i = q->count;
+ for (j = qstart; j < i; j++)
+ queue_push(q, q->elements[j]);
+ for (j = qstart; j < q->count; j += 2)
+ {
+ q->elements[j] = DISABLE_UPDATE;
+ q->elements[j + 1] = q->elements[i++];
+ }
/* now that we know which installed packages are obsoleted check each of them */
+ if ((set & (SOLVER_SETEVR | SOLVER_SETARCH | SOLVER_SETVENDOR)) == (SOLVER_SETEVR | SOLVER_SETARCH | SOLVER_SETVENDOR))
+ return; /* all is set, nothing to do */
+
for (i = j = qstart; i < q->count; i += 2)
{
Solvable *is = pool->solvables + q->elements[i + 1];
@@ -2183,6 +2257,36 @@ solver_disablechoicerules(Solver *solv, Rule *r)
}
}
+#undef CLEANDEPSDEBUG
+
+static inline void
+dep_pkgcheck(Solver *solv, Id dep, Map *m, Queue *q)
+{
+ Pool *pool = solv->pool;
+ Id p, pp;
+
+ if (ISRELDEP(dep))
+ {
+ Reldep *rd = GETRELDEP(pool, dep);
+ if (rd->flags >= 8)
+ {
+ if (rd->flags == REL_AND)
+ {
+ dep_pkgcheck(solv, rd->name, m, q);
+ dep_pkgcheck(solv, rd->evr, m, q);
+ return;
+ }
+ if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
+ return;
+ if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
+ return;
+ }
+ }
+ FOR_PROVIDES(p, pp, dep)
+ if (MAPTST(m, p))
+ queue_push(q, p);
+}
+
static void solver_createcleandepsmap(Solver *solv)
{
Pool *pool = solv->pool;
@@ -2199,6 +2303,8 @@ static void solver_createcleandepsmap(Solver *solv)
Queue iq;
int i;
+ if (installed->end == installed->start)
+ return;
map_init(&userinstalled, installed->end - installed->start);
map_init(&im, pool->nsolvables);
map_init(&installedm, pool->nsolvables);
@@ -2223,24 +2329,90 @@ static void solver_createcleandepsmap(Solver *solv)
r = solv->rules + rid;
if (r->d < 0)
continue;
+ i = solv->ruletojob.elements[rid - solv->jobrules];
+ if ((job->elements[i] & SOLVER_CLEANDEPS) == SOLVER_CLEANDEPS)
+ continue;
FOR_RULELITERALS(p, jp, r)
if (p > 0 && pool->solvables[p].repo == installed)
MAPSET(&userinstalled, p - installed->start);
}
+
+ /* add all cleandeps candidates to iq */
for (rid = solv->jobrules; rid < solv->jobrules_end; rid++)
{
r = solv->rules + rid;
- if (r->p >= 0 || r->d != 0)
- continue; /* disabled or not erase */
- p = -r->p;
- if (pool->solvables[p].repo != installed)
+ if (r->d < 0)
continue;
- MAPCLR(&userinstalled, p - installed->start);
- i = solv->ruletojob.elements[rid - solv->jobrules];
- how = job->elements[i];
- if ((how & (SOLVER_JOBMASK|SOLVER_CLEANDEPS)) == (SOLVER_ERASE|SOLVER_CLEANDEPS))
- queue_push(&iq, p);
+ if (r->d == 0 && r->p < 0 && r->w2 == 0)
+ {
+ p = -r->p;
+ if (pool->solvables[p].repo != installed)
+ continue;
+ MAPCLR(&userinstalled, p - installed->start);
+ i = solv->ruletojob.elements[rid - solv->jobrules];
+ how = job->elements[i];
+ if ((how & (SOLVER_JOBMASK|SOLVER_CLEANDEPS)) == (SOLVER_ERASE|SOLVER_CLEANDEPS))
+ queue_push(&iq, p);
+ }
+ else if (r->p > 0)
+ {
+ i = solv->ruletojob.elements[rid - solv->jobrules];
+ if ((job->elements[i] & SOLVER_CLEANDEPS) == SOLVER_CLEANDEPS)
+ {
+ /* check if the literals all obsolete some installed package */
+ Map om;
+ int iqstart;
+
+ /* just one installed literal */
+ if (r->d == 0 && r->w2 == 0 && pool->solvables[r->p].repo == installed)
+ continue;
+ /* noobs is bad */
+ if (solv->noobsoletes.size)
+ {
+ FOR_RULELITERALS(p, jp, r)
+ if (MAPTST(&solv->noobsoletes, p))
+ break;
+ if (p)
+ continue;
+ }
+
+ om.size = 0;
+ iqstart = iq.count;
+ FOR_RULELITERALS(p, jp, r)
+ {
+ if (p < 0)
+ {
+ queue_truncate(&iq, iqstart); /* abort */
+ break;
+ }
+ if (pool->solvables[p].repo == installed)
+ {
+ if (iq.count == iqstart)
+ queue_push(&iq, p);
+ else
+ {
+ for (i = iqstart; i < iq.count; i++)
+ if (iq.elements[i] == p)
+ break;
+ queue_truncate(&iq, iqstart);
+ if (i < iq.count)
+ queue_push(&iq, p);
+ }
+ }
+ else
+ intersect_obsoletes(solv, p, &iq, iqstart, &om);
+ if (iq.count == iqstart)
+ break;
+ }
+ if (om.size)
+ map_free(&om);
+ }
+ }
}
+ if (solv->cleandeps_updatepkgs)
+ for (i = 0; i < solv->cleandeps_updatepkgs->count; i++)
+ queue_push(&iq, solv->cleandeps_updatepkgs->elements[i]);
+
for (p = installed->start; p < installed->end; p++)
{
if (pool->solvables[p].repo != installed)
@@ -2249,8 +2421,53 @@ static void solver_createcleandepsmap(Solver *solv)
MAPSET(&im, p);
}
- while (iq.count)
+#ifdef CLEANDEPSDEBUG
+ printf("HELLO PASS\n");
+#endif
+ for (;;)
{
+ if (!iq.count)
+ {
+ /* supplements pass */
+ for (ip = solv->installed->start; ip < solv->installed->end; ip++)
+ {
+ if (!MAPTST(&installedm, ip))
+ continue;
+ s = pool->solvables + ip;
+ if (!s->supplements)
+ continue;
+ if (!MAPTST(&im, ip))
+ continue;
+ supp = s->repo->idarraydata + s->supplements;
+ while ((sup = *supp++) != 0)
+ if (dep_possible(solv, sup, &im))
+ break;
+ if (!sup)
+ {
+ supp = s->repo->idarraydata + s->supplements;
+ while ((sup = *supp++) != 0)
+ if (dep_possible(solv, sup, &installedm))
+ {
+ /* no longer supplemented, also erase */
+ int iqcount = iq.count;
+ dep_pkgcheck(solv, sup, &im, &iq);
+ for (i = iqcount; i < iq.count; i++)
+ {
+ Id pqp = iq.elements[i];
+ if (pool->solvables[pqp].repo == installed)
+ MAPSET(&userinstalled, pqp - installed->start);
+ }
+ queue_truncate(&iq, iqcount);
+#ifdef CLEANDEPSDEBUG
+ printf("%s supplemented\n", pool_solvid2str(pool, ip));
+#endif
+ queue_push(&iq, ip);
+ }
+ }
+ }
+ if (!iq.count)
+ break;
+ }
ip = queue_shift(&iq);
s = pool->solvables + ip;
if (!MAPTST(&im, ip))
@@ -2316,32 +2533,6 @@ static void solver_createcleandepsmap(Solver *solv)
}
}
}
- if (!iq.count)
- {
- /* supplements pass */
- for (ip = solv->installed->start; ip < solv->installed->end; ip++)
- {
- if (!MAPTST(&installedm, ip))
- continue;
- s = pool->solvables + ip;
- if (!s->supplements)
- continue;
- if (!MAPTST(&im, ip))
- continue;
- supp = s->repo->idarraydata + s->supplements;
- while ((sup = *supp++) != 0)
- if (!dep_possible(solv, sup, &im) && dep_possible(solv, sup, &installedm))
- break;
- /* no longer supplemented, also erase */
- if (sup)
- {
-#ifdef CLEANDEPSDEBUG
- printf("%s supplemented\n", pool_solvid2str(pool, ip));
-#endif
- queue_push(&iq, ip);
- }
- }
- }
}
/* turn userinstalled into remove set for pruning */
@@ -2381,8 +2572,42 @@ static void solver_createcleandepsmap(Solver *solv)
queue_push(&iq, what);
}
}
- while (iq.count)
+
+#ifdef CLEANDEPSDEBUG
+ printf("BYE PASS\n");
+#endif
+ for (;;)
{
+ if (!iq.count)
+ {
+ /* supplements pass */
+ for (ip = installed->start; ip < installed->end; ip++)
+ {
+ if (!MAPTST(&installedm, ip))
+ continue;
+ if (MAPTST(&userinstalled, ip - installed->start))
+ continue;
+ s = pool->solvables + ip;
+ if (!s->supplements)
+ continue;
+ if (MAPTST(&im, ip))
+ continue;
+ supp = s->repo->idarraydata + s->supplements;
+ while ((sup = *supp++) != 0)
+ if (dep_possible(solv, sup, &im))
+ break;
+ if (sup)
+ {
+#ifdef CLEANDEPSDEBUG
+ printf("%s supplemented\n", pool_solvid2str(pool, ip));
+#endif
+ MAPSET(&im, ip);
+ queue_push(&iq, ip);
+ }
+ }
+ if (!iq.count)
+ break;
+ }
ip = queue_shift(&iq);
s = pool->solvables + ip;
#ifdef CLEANDEPSDEBUG
@@ -2432,37 +2657,15 @@ static void solver_createcleandepsmap(Solver *solv)
}
}
}
- if (!iq.count)
- {
- /* supplements pass */
- for (ip = installed->start; ip < installed->end; ip++)
- {
- if (!MAPTST(&installedm, ip))
- continue;
- if (MAPTST(&userinstalled, ip - installed->start))
- continue;
- s = pool->solvables + ip;
- if (!s->supplements)
- continue;
- if (MAPTST(&im, ip) || !MAPTST(&installedm, ip))
- continue;
- supp = s->repo->idarraydata + s->supplements;
- while ((sup = *supp++) != 0)
- if (dep_possible(solv, sup, &im))
- break;
- if (sup)
- {
-#ifdef CLEANDEPSDEBUG
- printf("%s supplemented\n", pool_solvid2str(pool, ip));
-#endif
- MAPSET(&im, ip);
- queue_push(&iq, ip);
- }
- }
- }
}
queue_free(&iq);
+ if (solv->cleandeps_updatepkgs)
+ for (i = 0; i < solv->cleandeps_updatepkgs->count; i++)
+ MAPSET(&im, solv->cleandeps_updatepkgs->elements[i]);
+ if (solv->cleandeps_mistakes)
+ for (i = 0; i < solv->cleandeps_mistakes->count; i++)
+ MAPSET(&im, solv->cleandeps_mistakes->elements[i]);
for (p = installed->start; p < installed->end; p++)
{
if (pool->solvables[p].repo != installed)
diff --git a/src/solver.c b/src/solver.c
index be0a5a5..80b5ae0 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -1332,6 +1332,16 @@ solver_free(Solver *solv)
queue_free(&solv->branches);
queue_free(&solv->weakruleq);
queue_free(&solv->ruleassertions);
+ if (solv->cleandeps_updatepkgs)
+ {
+ queue_free(solv->cleandeps_updatepkgs);
+ solv->cleandeps_updatepkgs = solv_free(solv->cleandeps_updatepkgs);
+ }
+ if (solv->cleandeps_mistakes)
+ {
+ queue_free(solv->cleandeps_mistakes);
+ solv->cleandeps_mistakes = solv_free(solv->cleandeps_mistakes);
+ }
map_free(&solv->recommendsmap);
map_free(&solv->suggestsmap);
@@ -1424,6 +1434,62 @@ solver_set_flag(Solver *solv, int flag, int value)
return old;
}
+int
+cleandeps_check_mistakes(Solver *solv, int level)
+{
+ Pool *pool = solv->pool;
+ Rule *r;
+ Id p, *dp;
+ int i;
+ int mademistake = 0;
+
+ if (!solv->cleandepsmap.size)
+ return level;
+ /* check for mistakes */
+ for (i = solv->installed->start; i < solv->installed->end; i++)
+ {
+ if (!MAPTST(&solv->cleandepsmap, i - solv->installed->start))
+ continue;
+ r = solv->rules + solv->featurerules + (i - solv->installed->start);
+ /* a mistake is when the featurerule is true but the updaterule is false */
+ if (r->p)
+ {
+ FOR_RULELITERALS(p, dp, r)
+ if (p > 0 && solv->decisionmap[p] > 0)
+ break;
+ if (p)
+ {
+ r = solv->rules + solv->updaterules + (i - solv->installed->start);
+ if (!r->p)
+ continue;
+ FOR_RULELITERALS(p, dp, r)
+ if (p > 0 && solv->decisionmap[p] > 0)
+ break;
+ if (!p)
+ {
+ POOL_DEBUG(SOLV_DEBUG_SOLVER, "cleandeps mistake: ");
+ solver_printruleclass(solv, SOLV_DEBUG_SOLVER, r);
+ POOL_DEBUG(SOLV_DEBUG_SOLVER, "feature rule: ");
+ solver_printruleclass(solv, SOLV_DEBUG_SOLVER, solv->rules + solv->featurerules + (i - solv->installed->start));
+ if (!solv->cleandeps_mistakes)
+ {
+ solv->cleandeps_mistakes = solv_calloc(1, sizeof(Queue));
+ queue_init(solv->cleandeps_mistakes);
+ }
+ queue_push(solv->cleandeps_mistakes, i);
+ MAPCLR(&solv->cleandepsmap, i - solv->installed->start);
+ mademistake = 1;
+ }
+ }
+ }
+ }
+ if (mademistake)
+ {
+ level = 1;
+ revert(solv, level);
+ }
+ return level;
+}
/*-------------------------------------------------------------------
*
@@ -2072,19 +2138,17 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
p = solv->orphaned.elements[i];
if (solv->decisionmap[p])
continue; /* already decided */
- olevel = level;
if (solv->droporphanedmap_all)
continue;
if (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, p - solv->installed->start))
continue;
POOL_DEBUG(SOLV_DEBUG_SOLVER, "keeping orphaned %s\n", pool_solvid2str(pool, p));
+ olevel = level;
level = setpropagatelearn(solv, level, p, 0, 0);
installedone = 1;
if (level < olevel)
break;
}
- if (level == 0)
- break;
if (installedone || i < solv->orphaned.count)
{
if (level == 0)
@@ -2110,6 +2174,14 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
}
}
+ if (solv->installed && solv->cleandepsmap.size)
+ {
+ olevel = level;
+ level = cleandeps_check_mistakes(solv, level);
+ if (level < olevel)
+ continue;
+ }
+
if (solv->solution_callback)
{
solv->solution_callback(solv, solv->solution_callback_data);
@@ -2673,6 +2745,11 @@ solver_solve(Solver *solv, Queue *job)
*/
solv->jobrules = solv->nrules;
+ if (solv->cleandeps_updatepkgs)
+ {
+ queue_free(solv->cleandeps_updatepkgs);
+ solv->cleandeps_updatepkgs = solv_free(solv->cleandeps_updatepkgs);
+ }
for (i = 0; i < job->count; i += 2)
{
oldnrules = solv->nrules;
@@ -2685,6 +2762,8 @@ solver_solve(Solver *solv, Queue *job)
{
case SOLVER_INSTALL:
POOL_DEBUG(SOLV_DEBUG_JOB, "job: %sinstall %s\n", weak ? "weak " : "", solver_select2str(pool, select, what));
+ if ((how & SOLVER_CLEANDEPS) != 0 && !solv->cleandepsmap.size && installed)
+ map_grow(&solv->cleandepsmap, installed->end - installed->start);
if (select == SOLVER_SOLVABLE)
{
p = what;
@@ -2707,9 +2786,9 @@ solver_solve(Solver *solv, Queue *job)
break;
case SOLVER_ERASE:
POOL_DEBUG(SOLV_DEBUG_JOB, "job: %s%serase %s\n", weak ? "weak " : "", how & SOLVER_CLEANDEPS ? "clean deps " : "", solver_select2str(pool, select, what));
- if ((how & SOLVER_CLEANDEPS) != 0 && !solv->cleandepsmap.size && solv->installed)
- map_grow(&solv->cleandepsmap, solv->installed->end - solv->installed->start);
- if (select == SOLVER_SOLVABLE && solv->installed && pool->solvables[what].repo == solv->installed)
+ if ((how & SOLVER_CLEANDEPS) != 0 && !solv->cleandepsmap.size && installed)
+ map_grow(&solv->cleandepsmap, installed->end - installed->start);
+ if (select == SOLVER_SOLVABLE && installed && pool->solvables[what].repo == installed)
{
/* special case for "erase a specific solvable": we also
* erase all other solvables with that name, so that they
@@ -2724,7 +2803,7 @@ solver_solve(Solver *solv, Queue *job)
if (s->name != name)
continue;
/* keep other versions installed */
- if (s->repo == solv->installed)
+ if (s->repo == installed)
continue;
/* keep installcandidates of other jobs */
if (MAPTST(&installcandidatemap, p))
@@ -2737,6 +2816,23 @@ solver_solve(Solver *solv, Queue *job)
break;
case SOLVER_UPDATE:
+ if ((how & SOLVER_CLEANDEPS) != 0 && installed)
+ {
+ FOR_JOB_SELECT(p, pp, select, what)
+ {
+ s = pool->solvables + p;
+ if (s->repo != installed)
+ continue;
+ if (!solv->cleandeps_updatepkgs)
+ {
+ solv->cleandeps_updatepkgs = solv_calloc(1, sizeof(Queue));
+ queue_init(solv->cleandeps_updatepkgs);
+ }
+ queue_pushunique(solv->cleandeps_updatepkgs, p);
+ if (!solv->cleandepsmap.size)
+ map_grow(&solv->cleandepsmap, installed->end - installed->start);
+ }
+ }
POOL_DEBUG(SOLV_DEBUG_JOB, "job: %supdate %s\n", weak ? "weak " : "", solver_select2str(pool, select, what));
break;
case SOLVER_VERIFY:
@@ -2871,6 +2967,13 @@ solver_solve(Solver *solv, Queue *job)
makeruledecisions(solv);
POOL_DEBUG(SOLV_DEBUG_SOLVER, "problems so far: %d\n", solv->problems.count);
+ /* no mistakes */
+ if (solv->cleandeps_mistakes)
+ {
+ queue_free(solv->cleandeps_mistakes);
+ solv->cleandeps_mistakes = solv_free(solv->cleandeps_mistakes);
+ }
+
/*
* ********************************************
* solve!
diff --git a/src/solver.h b/src/solver.h
index 02cc5e0..e7d24b2 100644
--- a/src/solver.h
+++ b/src/solver.h
@@ -208,6 +208,9 @@ struct _Solver {
Map cleandepsmap; /* try to drop these packages as of cleandeps erases */
Queue *ruleinfoq; /* tmp space for solver_ruleinfo() */
+
+ Queue *cleandeps_updatepkgs; /* packages we update in cleandeps mode */
+ Queue *cleandeps_mistakes; /* mistakes we made */
#endif /* LIBSOLV_INTERNAL */
};