summaryrefslogtreecommitdiff
path: root/src/solver.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/solver.c')
-rw-r--r--src/solver.c80
1 files changed, 66 insertions, 14 deletions
diff --git a/src/solver.c b/src/solver.c
index b89e0d1..3358b6b 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -200,15 +200,25 @@ autouninstall(Solver *solv, Id *problem)
int lastfeature = 0, lastupdate = 0;
Id v;
Id extraflags = -1;
+ Map *m = 0;
+ if (!solv->allowuninstall && !solv->allowuninstall_all)
+ {
+ if (!solv->allowuninstallmap.size)
+ return 0; /* why did we get called? */
+ m = &solv->allowuninstallmap;
+ }
for (i = 0; (v = problem[i]) != 0; i++)
{
if (v < 0)
extraflags &= solv->job.elements[-v - 1];
if (v >= solv->updaterules && v < solv->updaterules_end)
{
+ Rule *r;
+ if (m && !MAPTST(m, v - solv->updaterules))
+ continue;
/* check if identical to feature rule, we don't like that */
- Rule *r = solv->rules + solv->featurerules + (v - solv->updaterules);
+ r = solv->rules + solv->featurerules + (v - solv->updaterules);
if (!r->p)
{
/* update rule == feature rule */
@@ -427,8 +437,16 @@ makeruledecisions(Solver *solv)
v = ri;
queue_push(&solv->problems, v);
queue_push(&solv->problems, 0);
- if (solv->allowuninstall && v >= solv->featurerules && v < solv->updaterules_end)
- solv->problems.count = oldproblemcount;
+ if (v >= solv->featurerules && v < solv->updaterules_end)
+ {
+ if (solv->allowuninstall || solv->allowuninstall_all || solv->allowuninstallmap.size)
+ if (autouninstall(solv, solv->problems.elements + oldproblemcount + 1) != 0)
+ {
+ solv->problems.count = oldproblemcount;
+ havedisabled = 1;
+ break; /* start over */
+ }
+ }
solver_disableproblem(solv, v);
havedisabled = 1;
break; /* start over */
@@ -458,8 +476,16 @@ makeruledecisions(Solver *solv)
v = ri;
queue_push(&solv->problems, v);
queue_push(&solv->problems, 0);
- if (solv->allowuninstall && v >= solv->featurerules && v < solv->updaterules_end)
- solv->problems.count = oldproblemcount;
+ if (v >= solv->featurerules && v < solv->updaterules_end)
+ {
+ if (solv->allowuninstall || solv->allowuninstall_all || solv->allowuninstallmap.size)
+ if (autouninstall(solv, solv->problems.elements + oldproblemcount + 1) != 0)
+ {
+ solv->problems.count = oldproblemcount;
+ havedisabled = 1;
+ break; /* start over */
+ }
+ }
solver_disableproblem(solv, v);
havedisabled = 1;
break; /* start over */
@@ -507,8 +533,13 @@ makeruledecisions(Solver *solv)
}
queue_push(&solv->problems, 0);
- if (solv->allowuninstall && (v = autouninstall(solv, solv->problems.elements + oldproblemcount + 1)) != 0)
- solv->problems.count = oldproblemcount;
+ if (solv->allowuninstall || solv->allowuninstall_all || solv->allowuninstallmap.size)
+ if (autouninstall(solv, solv->problems.elements + oldproblemcount + 1) != 0)
+ {
+ solv->problems.count = oldproblemcount;
+ havedisabled = 1;
+ break; /* start over */
+ }
for (i = oldproblemcount + 1; i < solv->problems.count - 1; i++)
solver_disableproblem(solv, solv->problems.elements[i]);
@@ -1245,13 +1276,14 @@ analyze_unsolvable(Solver *solv, Rule *cr, int disablerules)
return 0;
}
- if (solv->allowuninstall && (v = autouninstall(solv, solv->problems.elements + oldproblemcount + 1)) != 0)
- {
- solv->problems.count = oldproblemcount;
- solv->learnt_pool.count = oldlearntpoolcount;
- solver_reset(solv);
- return 0;
- }
+ if (solv->allowuninstall || solv->allowuninstall_all || solv->allowuninstallmap.size)
+ if (autouninstall(solv, solv->problems.elements + oldproblemcount + 1) != 0)
+ {
+ solv->problems.count = oldproblemcount;
+ solv->learnt_pool.count = oldlearntpoolcount;
+ solver_reset(solv);
+ return 0;
+ }
/* finish proof */
if (record_proof)
@@ -1672,6 +1704,7 @@ solver_free(Solver *solv)
map_free(&solv->dupinvolvedmap);
map_free(&solv->droporphanedmap);
map_free(&solv->cleandepsmap);
+ map_free(&solv->allowuninstallmap);
solv_free(solv->decisionmap);
solv_free(solv->rules);
@@ -3359,6 +3392,8 @@ solver_solve(Solver *solv, Queue *job)
map_zerosize(&solv->dupinvolvedmap);
solv->droporphanedmap_all = 0;
map_zerosize(&solv->droporphanedmap);
+ solv->allowuninstall_all = 0;
+ map_zerosize(&solv->allowuninstallmap);
map_zerosize(&solv->cleandepsmap);
map_zerosize(&solv->weakrulemap);
queue_empty(&solv->weakruleq);
@@ -3873,6 +3908,20 @@ solver_solve(Solver *solv, Queue *job)
case SOLVER_USERINSTALLED:
POOL_DEBUG(SOLV_DEBUG_JOB, "job: user installed %s\n", solver_select2str(pool, select, what));
break;
+ case SOLVER_ALLOWUNINSTALL:
+ POOL_DEBUG(SOLV_DEBUG_JOB, "job: allowuninstall %s\n", solver_select2str(pool, select, what));
+ if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && installed && what == installed->repoid))
+ solv->allowuninstall_all = 1;
+ FOR_JOB_SELECT(p, pp, select, what)
+ {
+ s = pool->solvables + p;
+ if (s->repo != installed)
+ continue;
+ if (!solv->allowuninstallmap.size)
+ map_grow(&solv->allowuninstallmap, installed->end - installed->start);
+ MAPSET(&solv->allowuninstallmap, p - installed->start);
+ }
+ break;
default:
POOL_DEBUG(SOLV_DEBUG_JOB, "job: unknown job\n");
break;
@@ -5082,6 +5131,9 @@ pool_job2str(Pool *pool, Id how, Id what, Id flagmask)
case SOLVER_USERINSTALLED:
strstart = "regard ", strend = " as userinstalled";
break;
+ case SOLVER_ALLOWUNINSTALL:
+ strstart = "allow deinstallation of ";
+ break;
default:
strstart = "unknown job ";
break;