int essentialok;
unsigned int now;
int oldmistakes = solv->cleandeps_mistakes ? solv->cleandeps_mistakes->count : 0;
+ Id extraflags = -1;
now = solv_timems(0);
queue_init(&redoq);
if (!v)
break;
queue_push(&problem, v);
+ if (v < 0)
+ extraflags &= solv->job.elements[-v - 1];
}
+ if (extraflags == -1)
+ extraflags = 0;
if (problem.count > 1)
solv_sort(problem.elements, problem.count, sizeof(Id), problems_sortcmp, &solv->job);
queue_push(&problem, 0); /* mark end for refine_suggestion */
queue_push(&solv->solutions, 0); /* add end marker */
queue_push(&solv->solutions, 0); /* add end marker */
queue_push(&solv->solutions, problem.elements[i]); /* just for bookkeeping */
+ queue_push(&solv->solutions, extraflags & SOLVER_CLEANDEPS); /* our extraflags */
solv->solutions.elements[solidx + 1 + nsol++] = solstart;
}
solv->solutions.elements[solidx + 1 + nsol] = 0; /* end marker */
return solv->solutions.elements[solidx + 2 * solv->solutions.elements[solidx] + 3];
}
+Id
+solver_solutionelement_extrajobflags(Solver *solv, Id problem, Id solution)
+{
+ Id solidx = solv->problems.elements[problem * 2 - 1];
+ solidx = solv->solutions.elements[solidx + solution];
+ return solv->solutions.elements[solidx + 2 * solv->solutions.elements[solidx] + 4];
+}
+
/*
* return the next item of the proposed solution
}
void
-solver_take_solutionelement(Solver *solv, Id p, Id rp, Queue *job)
+solver_take_solutionelement(Solver *solv, Id p, Id rp, Id extrajobflags, Queue *job)
{
int i;
if (rp <= 0 && p <= 0)
return; /* just in case */
if (rp > 0)
- p = SOLVER_INSTALL|SOLVER_SOLVABLE;
+ p = SOLVER_INSTALL|SOLVER_SOLVABLE|extrajobflags;
else
{
rp = p;
- p = SOLVER_ERASE|SOLVER_SOLVABLE;
+ p = SOLVER_ERASE|SOLVER_SOLVABLE|extrajobflags;
}
for (i = 0; i < job->count; i += 2)
if (job->elements[i] == p && job->elements[i + 1] == rp)
solver_take_solution(Solver *solv, Id problem, Id solution, Queue *job)
{
Id p, rp, element = 0;
+ Id extrajobflags = solver_solutionelement_extrajobflags(solv, problem, solution);
while ((element = solver_next_solutionelement(solv, problem, solution, element, &p, &rp)) != 0)
- solver_take_solutionelement(solv, p, rp, job);
+ solver_take_solutionelement(solv, p, rp, extrajobflags, job);
}
}
+static Id
+autouninstall(Solver *solv, Id *problem)
+{
+ Pool *pool = solv->pool;
+ int i;
+ int lastfeature = 0, lastupdate = 0;
+ Id v;
+ Id extraflags = -1;
+
+ for (i = 0; (v = problem[i]) != 0; i++)
+ {
+ if (v < 0)
+ extraflags &= solv->job.elements[-v - 1];
+ if (v >= solv->featurerules && v < solv->featurerules_end)
+ if (v > lastfeature)
+ lastfeature = v;
+ if (v >= solv->updaterules && v < solv->updaterules_end)
+ {
+ /* check if identical to feature rule */
+ Id p = solv->rules[v].p;
+ if (p <= 0)
+ continue;
+ Rule *r = solv->rules + solv->featurerules + (p - solv->installed->start);
+ if (!r->p)
+ {
+ /* update rule == feature rule */
+ if (v > lastfeature)
+ lastfeature = v;
+ continue;
+ }
+ if (v > lastupdate)
+ lastupdate = v;
+ }
+ }
+ if (!lastupdate && !lastfeature)
+ return 0;
+ v = lastupdate ? lastupdate : lastfeature;
+ POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "allowuninstall disabling ");
+ solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, solv->rules + v);
+ solver_disableproblem(solv, v);
+ if (extraflags != -1 && (extraflags & SOLVER_CLEANDEPS) != 0 && solv->cleandepsmap.size)
+ {
+ /* add the package to the updatepkgs list, this will automatically turn
+ * on cleandeps mode */
+ Id p = solv->rules[v].p;
+ if (!solv->cleandeps_updatepkgs)
+ {
+ solv->cleandeps_updatepkgs = solv_calloc(1, sizeof(Queue));
+ queue_init(solv->cleandeps_updatepkgs);
+ }
+ if (p > 0)
+ {
+ int oldupdatepkgscnt = solv->cleandeps_updatepkgs->count;
+ queue_pushunique(solv->cleandeps_updatepkgs, p);
+ if (solv->cleandeps_updatepkgs->count != oldupdatepkgscnt)
+ solver_disablepolicyrules(solv);
+ }
+ }
+ return v;
+}
/************************************************************************/
Id v, vv;
int decisionstart;
int record_proof = 1;
+ int oldproblemcount;
/* The system solvable is always installed first */
assert(solv->decisionq.count == 0);
queue_push(&solv->decisionq_why, 0);
solv->decisionmap[SYSTEMSOLVABLE] = 1; /* installed at level '1' */
+ /* note that the ruleassertions queue is ordered */
decisionstart = solv->decisionq.count;
for (ii = 0; ii < solv->ruleassertions.count; ii++)
{
if (!solv->decisionmap[vv]) /* if not yet decided */
{
- /*
- * decide !
- */
queue_push(&solv->decisionq, v);
queue_push(&solv->decisionq_why, r - solv->rules);
solv->decisionmap[vv] = v > 0 ? 1 : -1;
}
continue;
}
- /*
- * check previous decision: is it sane ?
- */
-
+
+ /*
+ * check against previous decision: is there a conflict ?
+ */
if (v > 0 && solv->decisionmap[vv] > 0) /* ok to install */
continue;
if (v < 0 && solv->decisionmap[vv] < 0) /* ok to remove */
continue;
- /*
- * found a conflict!
- *
- * The rule (r) we're currently processing says something
- * different (v = r->p) than a previous decision (decisionmap[abs(v)])
- * on this literal
- */
+ /*
+ * found a conflict!
+ *
+ * The rule (r) we're currently processing says something
+ * different (v = r->p) than a previous decision (decisionmap[abs(v)])
+ * on this literal
+ */
if (ri >= solv->learntrules)
{
if (solv->decisionq.elements[i] == -v)
break;
assert(i < solv->decisionq.count); /* assert that we found it */
+ oldproblemcount = solv->problems.count;
/*
* conflict with system solvable ?
*/
-
if (v == -SYSTEMSOLVABLE)
{
- /* conflict with system solvable */
if (record_proof)
{
queue_push(&solv->problems, solv->learnt_pool.count);
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;
solver_disableproblem(solv, v);
continue;
}
/*
* conflict with an rpm rule ?
*/
-
if (solv->decisionq_why.elements[i] < solv->rpmrules_end)
{
- /* conflict with rpm rule assertion */
if (record_proof)
{
queue_push(&solv->problems, solv->learnt_pool.count);
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;
solver_disableproblem(solv, v);
continue;
}
POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "conflicting update/job assertions over literal %d\n", vv);
- /*
- * push all of our rules (can only be feature or job rules)
- * asserting this literal on the problem stack
- */
-
+ /*
+ * push all of our rules (can only be feature or job rules)
+ * asserting this literal on the problem stack
+ */
for (i = solv->featurerules, rr = solv->rules + i; i < solv->learntrules; i++, rr++)
{
if (rr->d < 0 /* disabled */
continue;
POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, " - disabling rule #%d\n", i);
-
solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, solv->rules + i);
v = i;
- /* is is a job rule ? */
if (i >= solv->jobrules && i < solv->jobrules_end)
v = -(solv->ruletojob.elements[i - solv->jobrules] + 1);
-
queue_push(&solv->problems, v);
- solver_disableproblem(solv, v);
}
queue_push(&solv->problems, 0);
+ if (solv->allowuninstall && (v = autouninstall(solv, solv->problems.elements + oldproblemcount + 1)) != 0)
+ solv->problems.count = oldproblemcount;
+
+ for (i = oldproblemcount + 1; i < solv->problems.count - 1; i++)
+ solver_disableproblem(solv, solv->problems.elements[i]);
+
/*
* start over
* (back up from decisions)
if (lastweak)
{
- Id v;
/* disable last weak rule */
solv->problems.count = oldproblemcount;
solv->learnt_pool.count = oldlearntpoolcount;
return 1;
}
+ 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 1;
+ }
+
/* finish proof */
if (record_proof)
{
continue;
}
if (!solver_samerule(solv, r, sr))
- {
- /* identical rule, kill unneeded one */
- if (solv->allowuninstall)
- {
- /* keep feature rule, make it weak */
- memset(r, 0, sizeof(*r));
- queue_push(&solv->weakruleq, sr - solv->rules);
- }
- else
- {
- /* keep update rule */
- memset(sr, 0, sizeof(*sr));
- }
- }
- else if (solv->allowuninstall)
- {
- /* make both feature and update rule weak */
- queue_push(&solv->weakruleq, r - solv->rules);
- queue_push(&solv->weakruleq, sr - solv->rules);
- }
+ memset(sr, 0, sizeof(*sr)); /* delete unneeded feature rule */
else
- solver_disablerule(solv, sr);
+ solver_disablerule(solv, sr); /* disable feature rule */
}
/* consistency check: we added a rule for _every_ installed solvable */
assert(solv->nrules - solv->updaterules == installed->end - installed->start);