continue;
if (!pool->implicitobsoleteusesprovides && s->name != ps->name)
continue;
- if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
+ if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, ps))
continue;
if (s->name == ps->name)
addrpmrule(solv, -n, -p, SOLVER_RULE_RPM_SAME_NAME, 0);
{
if (MAPTST(&solv->multiversion, qs.elements[i]))
{
- /* it's ok if they have same nevra */
Solvable *ps = pool->solvables + qs.elements[i];
+ /* if keepexplicitobsoletes is set and the name is different,
+ * we assume that there is an obsoletes. XXX: not 100% correct */
+ if (solv->keepexplicitobsoletes && ps->name != s->name)
+ {
+ qs.elements[j++] = qs.elements[i];
+ continue;
+ }
+ /* it's ok if they have same nevra */
if (ps->name != s->name || ps->evr != s->evr || ps->arch != s->arch)
continue;
}
continue;
if (!pool->implicitobsoleteusesprovides && ps->name != s->name)
continue;
- if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
+ if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, ps))
continue;
queue_push(q, p2);
lastp2 = p2;
{
if (pool->disttype != DISTTYPE_DEB)
{
- const char *evr = pool_id2str(pool, rd->evr);
- if (strchr(evr, '-'))
- set |= SOLVER_SETEVR;
- else
- set |= SOLVER_SETEV;
+ const char *rel = strrchr(pool_id2str(pool, rd->evr), '-');
+ set |= rel ? SOLVER_SETEVR : SOLVER_SETEV;
}
else
set |= SOLVER_SETEVR;
*depp = solv->job.elements[jidx + 1];
if ((r->d == 0 || r->d == -1) && r->w2 == 0 && r->p == -SYSTEMSOLVABLE)
{
- if ((solv->job.elements[jidx] & (SOLVER_JOBMASK|SOLVER_SELECTMASK)) == (SOLVER_INSTALL|SOLVER_SOLVABLE_NAME))
+ Id how = solv->job.elements[jidx];
+ if ((how & (SOLVER_JOBMASK|SOLVER_SELECTMASK)) == (SOLVER_INSTALL|SOLVER_SOLVABLE_NAME))
+ return SOLVER_RULE_JOB_UNKNOWN_PACKAGE;
+ if ((how & (SOLVER_JOBMASK|SOLVER_SELECTMASK)) == (SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES))
return SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP;
- if ((solv->job.elements[jidx] & (SOLVER_JOBMASK|SOLVER_SELECTMASK)) == (SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES))
- return SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP;
- if ((solv->job.elements[jidx] & (SOLVER_JOBMASK|SOLVER_SELECTMASK)) == (SOLVER_ERASE|SOLVER_SOLVABLE_NAME))
+ if ((how & (SOLVER_JOBMASK|SOLVER_SELECTMASK)) == (SOLVER_ERASE|SOLVER_SOLVABLE_NAME))
return SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM;
- if ((solv->job.elements[jidx] & (SOLVER_JOBMASK|SOLVER_SELECTMASK)) == (SOLVER_ERASE|SOLVER_SOLVABLE_PROVIDES))
+ if ((how & (SOLVER_JOBMASK|SOLVER_SELECTMASK)) == (SOLVER_ERASE|SOLVER_SOLVABLE_PROVIDES))
return SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM;
+ return SOLVER_RULE_JOB_UNSUPPORTED;
}
return SOLVER_RULE_JOB;
}
return solv->job.elements[idx];
}
+Id
+solver_rule2solvable(Solver *solv, Id rid)
+{
+ if (rid >= solv->updaterules && rid < solv->updaterules_end)
+ return rid - solv->updaterules;
+ if (rid >= solv->featurerules && rid < solv->featurerules_end)
+ return rid - solv->featurerules;
+ return 0;
+}
+
+/* check if the newest versions of pi still provides the dependency we're looking for */
+static int
+solver_choicerulecheck(Solver *solv, Id pi, Rule *r, Map *m)
+{
+ Pool *pool = solv->pool;
+ Rule *ur;
+ Queue q;
+ Id p, pp, qbuf[32];
+ int i;
+
+ ur = solv->rules + solv->updaterules + (pi - pool->installed->start);
+ if (!ur->p)
+ ur = solv->rules + solv->featurerules + (pi - pool->installed->start);
+ if (!ur->p)
+ return 0;
+ queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
+ FOR_RULELITERALS(p, pp, ur)
+ if (p > 0)
+ queue_push(&q, p);
+ if (q.count > 1)
+ policy_filter_unwanted(solv, &q, POLICY_MODE_CHOOSE);
+ for (i = 0; i < q.count; i++)
+ if (MAPTST(m, q.elements[i]))
+ break;
+ /* 1: none of the newest versions provide it */
+ i = i == q.count ? 1 : 0;
+ queue_free(&q);
+ return i;
+}
+
+static inline void
+queue_removeelement(Queue *q, Id el)
+{
+ int i, j;
+ for (i = 0; i < q->count; i++)
+ if (q->elements[i] == el)
+ break;
+ if (i < q->count)
+ {
+ for (j = i++; i < q->count; i++)
+ if (q->elements[i] != el)
+ q->elements[j++] = q->elements[i];
+ queue_truncate(q, j);
+ }
+}
+
void
solver_addchoicerules(Solver *solv)
{
Solvable *s, *s2;
Id lastaddedp, lastaddedd;
int lastaddedcnt;
+ unsigned int now;
solv->choicerules = solv->nrules;
if (!pool->installed)
solv->choicerules_end = solv->nrules;
return;
}
+ now = solv_timems(0);
solv->choicerules_ref = solv_calloc(solv->rpmrules_end, sizeof(Id));
queue_init(&q);
queue_init(&qi);
continue;
if (!pool->implicitobsoleteusesprovides && s->name != s2->name)
continue;
- if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2))
+ if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, s2))
continue;
break;
}
continue;
if (policy_is_illegal(solv, s2, s, 0))
continue;
+#if 0
+ if (solver_choicerulecheck(solv, p2, r, &m))
+ continue;
queue_push(&qi, p2);
+#else
+ queue_push2(&qi, p2, p);
+#endif
queue_push(&q, p);
continue;
}
continue;
if (policy_is_illegal(solv, s2, s, 0))
continue;
+#if 0
+ if (solver_choicerulecheck(solv, p2, r, &m))
+ continue;
queue_push(&qi, p2);
+#else
+ queue_push2(&qi, p2, p);
+#endif
queue_push(&q, p);
continue;
}
/* package p is independent of the installed ones */
havechoice = 1;
}
- if (!havechoice || !q.count)
+ if (!havechoice || !q.count || !qi.count)
continue; /* no choice */
- /* now check the update rules of the installed package.
- * if all packages of the update rules are contained in
- * the dependency rules, there's no need to set up the choice rule */
- map_empty(&m);
FOR_RULELITERALS(p, pp, r)
if (p > 0)
MAPSET(&m, p);
+
+ /* do extra checking */
+ for (i = j = 0; i < qi.count; i += 2)
+ {
+ p2 = qi.elements[i];
+ if (!p2)
+ continue;
+ if (solver_choicerulecheck(solv, p2, r, &m))
+ {
+ /* oops, remove element p from q */
+ queue_removeelement(&q, qi.elements[i + 1]);
+ continue;
+ }
+ qi.elements[j++] = p2;
+ }
+ queue_truncate(&qi, j);
+ if (!q.count || !qi.count)
+ {
+ FOR_RULELITERALS(p, pp, r)
+ if (p > 0)
+ MAPCLR(&m, p);
+ continue;
+ }
+
+
+ /* now check the update rules of the installed package.
+ * if all packages of the update rules are contained in
+ * the dependency rules, there's no need to set up the choice rule */
for (i = 0; i < qi.count; i++)
{
Rule *ur;
if (qi.elements[i] == qi.elements[j])
qi.elements[j] = 0;
}
+ /* empty map again */
+ FOR_RULELITERALS(p, pp, r)
+ if (p > 0)
+ MAPCLR(&m, p);
if (i == qi.count)
{
#if 0
map_free(&m);
map_free(&mneg);
solv->choicerules_end = solv->nrules;
+ /* shrink choicerules_ref */
+ solv->choicerules_ref = solv_realloc2(solv->choicerules_ref, solv->choicerules_end - solv->choicerules, sizeof(Id));
+ POOL_DEBUG(SOLV_DEBUG_STATS, "choice rule creation took %d ms\n", solv_timems(now));
}
/* called when a choice rule is disabled by analyze_unsolvable. We also
*/
/* leave first element zero to make things easier */
/* also add trailing zero */
- queue_insertn(&edges, 0, 1 + count + 1);
+ queue_insertn(&edges, 0, 1 + count + 1, 0);
/* first requires and recommends */
for (i = 0; i < count; i++)