From ed477952f4b9f83f9b04ae83b3896965aa47fae1 Mon Sep 17 00:00:00 2001 From: Michael Schroeder Date: Wed, 1 Feb 2012 14:08:47 +0100 Subject: [PATCH] - add cleandeps support for install/update --- examples/solv.c | 20 ++- package/libsolv.changes | 15 ++ src/problems.c | 14 ++ src/rules.c | 465 ++++++++++++++++++++++++++++++++++-------------- src/solver.c | 117 +++++++++++- src/solver.h | 3 + 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 */ }; -- 2.7.4