r->n1 = 0;
r->n2 = 0;
- if (solv->pool->verbose > 3) {
+ if (solv->pool->verbose > 3)
+ {
printf (" Add rule: ");
printrule (solv, r);
- }
+ }
return r;
}
{
/* conflict with rpm rule, need only disable our rule */
printf("conflict with rpm rule, disabling rule #%d\n", ri);
+ if (v < 0 && v != -SYSTEMSOLVABLE)
+ abort();
+ queue_push(&solv->problems, 0);
+ if (v == -SYSTEMSOLVABLE)
+ queue_push(&solv->problems, 0); /* sigh, we don't have a rule for that */
+ else
+ queue_push(&solv->problems, -v); /* sigh, we don't have a rule for that */
v = ri;
if (ri < solv->systemrules)
v = -(solv->ruletojob.elements[ri - solv->jobrules] + 1);
/* conflict with another job or system rule */
/* remove old decision */
printf("conflicting system/job rules over literal %d\n", vv);
+ queue_push(&solv->problems, 0);
+ queue_push(&solv->problems, solv->decisionq_why.elements[i]);
/* push all of our rules asserting this literal on the problem stack */
for (i = solv->jobrules, rr = solv->rules + i; i < solv->nrules; i++, rr++)
{
Id *dp;
Id n;
- if (solv->pool->verbose > 3) {
- printf ("----- addrpmrulesforsolvable -----\n");
- }
+ if (solv->pool->verbose > 3)
+ printf ("----- addrpmrulesforsolvable -----\n");
queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
queue_push(&q, s - pool->solvables); /* push solvable Id */
{
/* nothing provides req! */
if (pool->verbose)
- printf("package %s-%s.%s [%ld] is not installable (%s)\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), (long int)(s - pool->solvables), dep2str(pool, req));
+ printf("package %s-%s.%s [%d] is not installable (%s)\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), (Id)(s - pool->solvables), dep2str(pool, req));
addrule(solv, -n, 0); /* mark requestor as uninstallable */
if (solv->rc_output)
printf(">!> !unflag %s-%s.%s[%s]\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), repo_name(s->repo));
}
if (pool->verbose > 2)
- {
- printf("addrule %s-%s.%s %s %d %zd\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), dep2str(pool, req), -n, dp - pool->whatprovidesdata);
+ {
+ printf("addrule %s-%s.%s %s %d %u\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), dep2str(pool, req), -n, (Offset)(dp - pool->whatprovidesdata));
for (i = 0; dp[i]; i++)
- printf(" %s-%s.%s\n", id2str(pool, pool->solvables[dp[i]].name), id2str(pool, pool->solvables[dp[i]].evr), id2str(pool, pool->solvables[dp[i]].arch));
- }
+ printf(" %s-%s.%s\n", id2str(pool, pool->solvables[dp[i]].name), id2str(pool, pool->solvables[dp[i]].evr), id2str(pool, pool->solvables[dp[i]].arch));
+ }
/* add 'requires' dependency */
/* rule: (-requestor|provider1|provider2|...|providerN) */
Queue qs;
Id qsbuf[64];
- if (solv->pool->verbose > 3) {
- printf ("----- addrpmrulesforupdaters -----\n");
- }
+ if (solv->pool->verbose > 3)
+ printf ("----- addrpmrulesforupdaters -----\n");
- if (!MAPTST(m, s - pool->solvables)) /* add rule for s if not already done */
- addrpmrulesforsolvable(solv, s, m);
queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
policy_findupdatepackages(solv, s, &qs, allowall);
+ if (!MAPTST(m, s - pool->solvables)) /* add rule for s if not already done */
+ addrpmrulesforsolvable(solv, s, m);
for (i = 0; i < qs.count; i++)
if (!MAPTST(m, qs.elements[i]))
addrpmrulesforsolvable(solv, pool->solvables + qs.elements[i], m);
Queue qs;
Id qsbuf[64];
- if (solv->pool->verbose > 3) {
- printf ("----- addupdaterule -----\n");
- }
+ if (solv->pool->verbose > 3)
+ printf ("----- addupdaterule -----\n");
queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
policy_findupdatepackages(solv, s, &qs, allowall);
/* negate because our watches trigger if literal goes FALSE */
pkg = -solv->decisionq.elements[solv->propagate_index++];
if (pool->verbose > 3)
- {
+ {
printf("popagate for decision %d level %d\n", -pkg, level);
printruleelement(solv, 0, -pkg);
- }
+ }
for (rp = watches + pkg; *rp; rp = nrp)
{
r = solv->rules + *rp;
if (pool->verbose > 3)
- {
+ {
printf(" watch triggered ");
printrule(solv, r);
- }
+ }
if (pkg == r->w1)
{
{
/* p is free to watch, move watch to p */
if (pool->verbose > 3)
- {
+ {
if (p > 0)
- printf(" -> move w%d to %s-%s.%s\n", (pkg == r->w1 ? 1 : 2), id2str(pool, pool->solvables[p].name), id2str(pool, pool->solvables[p].evr), id2str(pool, pool->solvables[p].arch));
+ printf(" -> move w%d to %s-%s.%s\n", (pkg == r->w1 ? 1 : 2), id2str(pool, pool->solvables[p].name), id2str(pool, pool->solvables[p].evr), id2str(pool, pool->solvables[p].arch));
else
- printf(" -> move w%d to !%s-%s.%s\n", (pkg == r->w1 ? 1 : 2), id2str(pool, pool->solvables[-p].name), id2str(pool, pool->solvables[-p].evr), id2str(pool, pool->solvables[-p].arch));
- }
+ printf(" -> move w%d to !%s-%s.%s\n", (pkg == r->w1 ? 1 : 2), id2str(pool, pool->solvables[-p].name), id2str(pool, pool->solvables[-p].evr), id2str(pool, pool->solvables[-p].arch));
+ }
*rp = *nrp;
nrp = rp;
if (pkg == r->w1)
queue_push(&solv->decisionq, ow);
queue_push(&solv->decisionq_why, r - solv->rules);
if (pool->verbose > 3)
- {
{
Solvable *s = pool->solvables + (ow > 0 ? ow : -ow);
if (ow > 0)
else
printf(" -> decided to conflict %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
}
- }
}
}
return 0; /* all is well */
{
queue_push(&r, v);
if (pool->verbose > 3)
- {
+ {
printf("PUSH %d ", v);
printruleelement(solv, 0, v);
- }
+ }
if (l > rlevel)
rlevel = l;
}
}
if (pool->verbose > 3)
- {
- printf("num = %d\n", num);
- }
+ printf("num = %d\n", num);
if (num <= 0)
abort();
for (;;)
map_free(&seen);
queue_push(&solv->learnt_pool, 0);
if (pool->verbose > 3)
- {
+ {
for (i = learnt_why; solv->learnt_pool.elements[i]; i++)
- {
+ {
printf("learnt_why ");
printrule(solv, solv->rules + solv->learnt_pool.elements[i]);
- }
- }
- if (why)
- *why = learnt_why;
- return rlevel;
+ }
+ }
+ if (why)
+ *why = learnt_why;
+ return rlevel;
}
if (solv->problems.count)
{
for (i = solv->problems.count - 1; i >= 0; i--)
- if (solv->problems.elements[i] == 0)
+ if (solv->problems.elements[i] == 0) /* end of last problem reached? */
break;
else if (solv->problems.elements[i] == why)
return;
*/
static int
-analyze_unsolvable(Solver *solv, Rule *r, int disablerules)
+analyze_unsolvable(Solver *solv, Rule *cr, int disablerules)
{
Pool *pool = solv->pool;
- Map seen; /* global? */
+ Rule *r;
+ Map seen; /* global to speed things up? */
Id v, vv, *dp, why;
int l, i, idx;
Id *decisionmap = solv->decisionmap;
if (pool->verbose > 1)
printf("ANALYZE UNSOLVABLE ----------------------\n");
oldproblemcount = solv->problems.count;
+
+ /* make room for conflicting rule */
+ queue_push(&solv->problems, 0);
+ queue_push(&solv->problems, 0);
+
+ r = cr;
map_init(&seen, pool->nsolvables);
analyze_unsolvable_rule(solv, r);
dp = r->d ? pool->whatprovidesdata + r->d : 0;
if (!why)
{
if (pool->verbose > 3)
- {
+ {
printf("RPM ");
printruleelement(solv, 0, v);
- }
+ }
continue;
}
r = solv->rules + why;
lastweak = 0;
if (solv->weakrules != solv->learntrules)
{
- for (i = oldproblemcount; i < solv->problems.count - 1; i++)
+ for (i = oldproblemcount + 2; i < solv->problems.count - 1; i++)
{
why = solv->problems.elements[i];
if (why < solv->weakrules || why >= solv->learntrules)
reset_solver(solv);
return 1;
}
- else if (disablerules)
+
+ /* patch conflicting rule data */
+ if (cr - solv->rules >= solv->learntrules)
+ {
+ /* we have to store the rule internals for learnt rules
+ * as they get freed for every solver run */
+ solv->problems.elements[oldproblemcount] = cr->p;
+ solv->problems.elements[oldproblemcount + 1] = cr->d;
+ }
+ else
+ solv->problems.elements[oldproblemcount + 1] = cr - solv->rules;
+
+ if (disablerules)
{
- for (i = oldproblemcount; i < solv->problems.count - 1; i++)
+ for (i = oldproblemcount + 2; i < solv->problems.count - 1; i++)
disableproblem(solv, solv->problems.elements[i]);
reset_solver(solv);
return 1;
if (solv->decisionmap[vv] <= level && solv->decisionmap[vv] >= -level)
break;
if (solv->pool->verbose > 3)
- {
- printf("reverting decision %d at %d\n", v, solv->decisionmap[vv]);
- }
+ printf("reverting decision %d at %d\n", v, solv->decisionmap[vv]);
solv->decisionmap[vv] = 0;
solv->decisionq.count--;
solv->decisionq_why.count--;
p = dq->elements[i];
if (pool->verbose > 3)
- {
+ {
Solvable *s = pool->solvables + p;
printf("installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
- }
+ }
return setpropagatelearn(solv, level, p, disablerules);
}
Id p, *dp;
if (pool->verbose > 3)
- {
+ {
printf("number of rules: %d\n", solv->nrules);
for (i = 0; i < solv->nrules; i++)
- printrule(solv, solv->rules + i);
- }
+ printrule(solv, solv->rules + i);
+ }
/* all new rules are learnt after this point */
solv->learntrules = solv->nrules;
if (solv->decisionmap[i] != 0)
continue;
if (pool->verbose > 3)
- {
- printf("keeping %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
- }
+ printf("keeping %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
olevel = level;
level = setpropagatelearn(solv, level, i, disablerules);
if (level == 0)
p = dq.elements[0];
s = pool->solvables + p;
if (pool->verbose > 0)
- {
- printf("installing recommended %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
- }
+ printf("installing recommended %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
level = setpropagatelearn(solv, level, p, 0);
continue;
}
break;
p = solv->branches.elements[i];
if (pool->verbose > 0)
- {
+ {
s = pool->solvables + p;
printf("branching with %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
- }
+ }
queue_empty(&dq);
for (j = i + 1; j < solv->branches.count; j++)
queue_push(&dq, solv->branches.elements[j]);
solv->branches.elements[lasti] = 0;
s = pool->solvables + p;
if (pool->verbose > 0)
- {
- printf("minimizing %d -> %d with %s-%s.%s\n", solv->decisionmap[p], l, id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
- }
+ printf("minimizing %d -> %d with %s-%s.%s\n", solv->decisionmap[p], l, id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
level = lastl;
revert(solv, level);
break; /* great, no more problems */
}
disabledcnt = disabled.count;
- for (i = 0; i < solv->problems.count - 1; i++)
+ /* skip over problem rule */
+ for (i = 2; i < solv->problems.count - 1; i++)
{
/* ignore solutions in refined */
v = solv->problems.elements[i];
Id why;
int i, j;
+ if (!solv->problems.count)
+ return;
queue_clone(&problems, &solv->problems);
queue_init(&solution);
queue_init(&solutions);
- problem = problems.elements;
- for (i = 0; i < problems.count; i++)
+ /* copy over problem rule */
+ queue_push(&solutions, problems.elements[0]);
+ queue_push(&solutions, problems.elements[1]);
+ problem = problems.elements + 2;
+ for (i = 2; i < problems.count; i++)
{
Id v = problems.elements[i];
if (v == 0)
queue_push(&solutions, 0);
if (i + 1 == problems.count)
break;
+ /* copy over problem rule of next problem */
+ queue_push(&solutions, problems.elements[i + 1]);
+ queue_push(&solutions, problems.elements[i + 2]);
+ i += 2;
problem = problems.elements + i + 1;
continue;
}
}
}
+int
+printconflicts(Solver *solv, Solvable *s, Id pc)
+{
+ Pool *pool = solv->pool;
+ Solvable *sc = pool->solvables + pc;
+ Id p, *pp, con, *conp, obs, *obsp;
+ int numc = 0;
+
+ if (s->conflicts)
+ {
+ conp = s->repo->idarraydata + s->conflicts;
+ while ((con = *conp++) != 0)
+ {
+ FOR_PROVIDES(p, pp, con)
+ {
+ if (p != pc)
+ continue;
+ printf("packags %s-%s.%s conflicts with %s, which is provided by %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), dep2str(pool, con), id2str(pool, sc->name), id2str(pool, sc->evr), id2str(pool, sc->arch));
+ numc++;
+ }
+ }
+ }
+ if (s->obsoletes && (!solv->installed || s - pool->solvables < solv->installed->start || s - pool->solvables >= solv->installed->start + solv->installed->nsolvables))
+ {
+ obsp = s->repo->idarraydata + s->obsoletes;
+ while ((obs = *obsp++) != 0)
+ {
+ FOR_PROVIDES(p, pp, obs)
+ {
+ if (p != pc)
+ continue;
+ printf("packags %s-%s.%s obsolets %s, which is provided by %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), dep2str(pool, obs), id2str(pool, sc->name), id2str(pool, sc->evr), id2str(pool, sc->arch));
+ numc++;
+ }
+ }
+ }
+ return numc;
+}
+
+void
+printprobleminfo(Solver *solv, Id p, Id d, Queue *job, Id firstp, Id firstrp)
+{
+ Pool *pool = solv->pool;
+ Rule *r;
+ Solvable *s;
+ Id what;
+
+ if (p != 0)
+ {
+ /* learnt rule, ignore for now */
+ printf("some learnt rule...\n");
+ return;
+ }
+ if (d == 0)
+ {
+ /* conflict with system solvable, i.e. could not create rule */
+ if (firstp)
+ {
+ printf("got firstp\n");
+ abort();
+ }
+ what = job->elements[firstrp];
+ switch (job->elements[firstrp - 1])
+ {
+ case SOLVER_INSTALL_SOLVABLE_NAME:
+ printf("no solvable exists with name %s\n", dep2str(pool, what));
+ break;
+ case SOLVER_INSTALL_SOLVABLE_PROVIDES:
+ printf("no solvable provides %s\n", dep2str(pool, what));
+ break;
+ default:
+ printf("unknown job\n");
+ abort();
+ }
+ return;
+ }
+ else if (d < 0)
+ {
+ Id req, *reqp, *dp;
+ int count = 0;
+ /* conflict with rpm rule, package -d is not installable */
+ s = pool->solvables + (-d);
+ if (s->requires)
+ {
+ reqp = s->repo->idarraydata + s->requires;
+ while ((req = *reqp++) != 0)
+ {
+ if (req == SOLVABLE_PREREQMARKER)
+ continue;
+ dp = GET_PROVIDESP(req, p);
+ if (*dp)
+ continue;
+ printf("package %s-%s.%s requires %s, but no package provides it\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), dep2str(pool, req));
+ count++;
+ }
+ }
+ if (!count)
+ printf("package %s-%s.%s is not installable\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
+ return;
+ }
+ if (d >= solv->jobrules)
+ {
+ r = solv->rules + d;
+ p = r->p;
+ d = r->d;
+ if (p < 0 && d < 0)
+ {
+ Solvable *sp, *sd;
+ sp = pool->solvables + (-p);
+ sd = pool->solvables + (-d);
+ printf("package %s-%s.%s cannot be installed with package %s-%s.%s\n", id2str(pool, sp->name), id2str(pool, sp->evr), id2str(pool, sp->arch), id2str(pool, sd->name), id2str(pool, sd->evr), id2str(pool, sd->arch));
+ return;
+ }
+ printf("some job rule...\n");
+ printrule(solv, r);
+ return;
+ }
+ r = solv->rules + d;
+ p = r->p;
+ if (p >= 0)
+ abort();
+ d = r->d;
+ if (d == 0 && r->w2 < 0)
+ {
+ Solvable *sp, *sd;
+ d = r->w2;
+ sp = pool->solvables + (-p);
+ sd = pool->solvables + (-d);
+ if (sp->name == sd->name)
+ {
+ printf("cannot install both %s-%s.%s and %s-%s.%s\n", id2str(pool, sp->name), id2str(pool, sp->evr), id2str(pool, sp->arch), id2str(pool, sd->name), id2str(pool, sd->evr), id2str(pool, sd->arch));
+ }
+ else
+ {
+ printconflicts(solv, pool->solvables + (-p), -d);
+ printconflicts(solv, pool->solvables + (-d), -p);
+ }
+ }
+ else
+ {
+ /* find requires of p that corresponds with our rule */
+ Id req, *reqp, *dp;
+ s = pool->solvables + (-p);
+ reqp = s->repo->idarraydata + s->requires;
+ while ((req = *reqp++) != 0)
+ {
+ if (req == SOLVABLE_PREREQMARKER)
+ continue;
+ dp = GET_PROVIDESP(req, p);
+ if (d == 0)
+ {
+ if (*dp == r->w2 && dp[1] == 0)
+ break;
+ }
+ else if (dp - pool->whatprovidesdata == d)
+ break;
+ }
+ if (!req)
+ {
+ printf("req not found\n");
+ abort();
+ }
+ printf("package %s-%s.%s requires %s, but none of its providers can be installed\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), dep2str(pool, req));
+ }
+}
+
void
printsolutions(Solver *solv, Queue *job)
{
Pool *pool = solv->pool;
int pcnt;
int i;
- Id p, rp, what;
+ Id p, d, rp, what;
Solvable *s, *sd;
printf("Encountered problems! Here are the solutions:\n\n");
{
printf("Problem %d:\n", pcnt++);
printf("====================================\n");
+ p = solv->problems.elements[i++];
+ d = solv->problems.elements[i++];
+ printprobleminfo(solv, p, d, job, solv->problems.elements[i], solv->problems.elements[i + 1]);
+ printf("\n");
for (;;)
{
if (solv->problems.elements[i] == 0 && solv->problems.elements[i + 1] == 0)
}
else
{
- printf("- allow deinstallation of %s-%s.%s [%ld]\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), (long int)(s - pool->solvables));
+ printf("- allow deinstallation of %s-%s.%s [%d]\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), (Id)(s - pool->solvables));
}
}
* so called: rpm rules
*
*/
- if (solv->pool->verbose > 3) {
- printf ("*** create rules for installed solvables -> keep them installed ***\n");
- }
+ if (solv->pool->verbose > 3)
+ printf ("*** create rules for installed solvables -> keep them installed ***\n");
for (i = solv->installed->start; i < solv->installed->start + solv->installed->nsolvables; i++)
addrpmrulesforsolvable(solv, pool->solvables + i, &addedmap);
* solvable rules
* process job rules for solvables
*/
- if (solv->pool->verbose > 3) {
- printf ("*** create install rules ***\n");
- }
+ if (solv->pool->verbose > 3)
+ printf ("*** create install rules ***\n");
for (i = 0; i < job->count; i += 2)
{