+ Id p2, pp2;
+ s = pool->solvables + p;
+ FOR_PROVIDES(p2, pp2, s->name)
+ if (solv->decisionmap[p2] > 0 && pool->solvables[p2].name == s->name)
+ break;
+ if (p2)
+ continue; /* ignore this package */
+ }
+ dqs->elements[j++] = p;
+ }
+ dqs->count = j;
+ }
+
+ /* implicitobsoleteusescolors doesn't mix well with supplements.
+ * filter supplemented packages where we already decided
+ * to install a different architecture */
+ if (dqs->count && pool->implicitobsoleteusescolors)
+ {
+ for (i = j = 0; i < dqs->count; i++)
+ {
+ Id p2, pp2;
+ p = dqs->elements[i];
+ s = pool->solvables + p;
+ FOR_PROVIDES(p2, pp2, s->name)
+ if (solv->decisionmap[p2] > 0 && pool->solvables[p2].name == s->name && pool->solvables[p2].arch != s->arch)
+ break;
+ if (p2)
+ continue; /* ignore this package */
+ dqs->elements[j++] = p;
+ }
+ dqs->count = j;
+ }
+
+ /* make dq contain both recommended and supplemented pkgs */
+ if (dqs->count)
+ {
+ for (i = 0; i < dqs->count; i++)
+ queue_pushunique(dq, dqs->elements[i]);
+ }
+
+ if (!dq->count)
+ return level;
+ *rerunp = 1;
+
+ if (dq->count == 1)
+ {
+ /* simple case, just one package. no need to choose to best version */
+ p = dq->elements[0];
+ if (dqs->count)
+ POOL_DEBUG(SOLV_DEBUG_POLICY, "installing supplemented %s\n", pool_solvid2str(pool, p));
+ else
+ POOL_DEBUG(SOLV_DEBUG_POLICY, "installing recommended %s\n", pool_solvid2str(pool, p));
+ return setpropagatelearn(solv, level, p, 0, 0, SOLVER_REASON_WEAKDEP);
+ }
+
+ /* filter packages, this gives us the best versions */
+ policy_filter_unwanted(solv, dq, POLICY_MODE_RECOMMEND);
+
+ /* create map of result */
+ map_init(&dqmap, pool->nsolvables);
+ for (i = 0; i < dq->count; i++)
+ MAPSET(&dqmap, dq->elements[i]);
+
+ /* prune dqs so that it only contains the best versions */
+ for (i = j = 0; i < dqs->count; i++)
+ {
+ p = dqs->elements[i];
+ if (MAPTST(&dqmap, p))
+ dqs->elements[j++] = p;
+ }
+ dqs->count = j;
+
+ /* install all supplemented packages, but order first */
+ if (dqs->count > 1)
+ policy_filter_unwanted(solv, dqs, POLICY_MODE_SUPPLEMENT);
+ decisioncount = solv->decisionq.count;
+ for (i = 0; i < dqs->count; i++)
+ {
+ p = dqs->elements[i];
+ if (solv->decisionmap[p])
+ continue;
+ POOL_DEBUG(SOLV_DEBUG_POLICY, "installing supplemented %s\n", pool_solvid2str(pool, p));
+ olevel = level;
+ level = setpropagatelearn(solv, level, p, 0, 0, SOLVER_REASON_WEAKDEP);
+ if (level <= olevel)
+ break;
+ }
+ if (i < dqs->count || solv->decisionq.count < decisioncount)
+ {
+ map_free(&dqmap);
+ return level;
+ }
+
+ /* install all recommended packages */
+ /* more work as we want to created branches if multiple
+ * choices are valid */
+ for (i = 0; i < decisioncount; i++)
+ {
+ Id rec, *recp, pp;
+ p = solv->decisionq.elements[i];
+ if (p < 0)
+ continue;
+ s = pool->solvables + p;
+ if (!s->repo || (!solv->addalreadyrecommended && s->repo == solv->installed))
+ continue;
+ if (!s->recommends)
+ continue;
+ recp = s->repo->idarraydata + s->recommends;
+ while ((rec = *recp++) != 0)
+ {
+ queue_empty(dq);
+#ifdef ENABLE_COMPLEX_DEPS
+ if (pool_is_complex_dep(pool, rec))
+ add_complex_recommends(solv, rec, dq, &dqmap);
+ else
+#endif
+ FOR_PROVIDES(p, pp, rec)
+ {
+ if (solv->decisionmap[p] > 0)
+ {
+ dq->count = 0;
+ break;
+ }
+ else if (solv->decisionmap[p] == 0 && MAPTST(&dqmap, p))
+ queue_push(dq, p);
+ }
+ if (!dq->count)
+ continue;
+ if (dq->count > 1)
+ policy_filter_unwanted(solv, dq, POLICY_MODE_CHOOSE);
+ /* if we have multiple candidates we open a branch */
+ if (dq->count > 1)
+ createbranch(solv, level, dq, s - pool->solvables, rec);
+ p = dq->elements[0];
+ POOL_DEBUG(SOLV_DEBUG_POLICY, "installing recommended %s\n", pool_solvid2str(pool, p));
+ olevel = level;
+ level = setpropagatelearn(solv, level, p, 0, 0, SOLVER_REASON_WEAKDEP);
+ if (level <= olevel || solv->decisionq.count < decisioncount)
+ break; /* we had to revert some decisions */
+ }
+ if (rec)
+ break; /* had a problem above, quit loop */
+ }
+ map_free(&dqmap);
+ return level;
+}
+
+static int
+resolve_cleandeps(Solver *solv, int level, int disablerules, int *rerunp)
+{
+ Pool *pool = solv->pool;
+ Repo *installed = solv->installed;
+ int olevel;
+ Id p;
+ Solvable *s;
+
+ if (!installed || !solv->cleandepsmap.size)
+ return level;
+ POOL_DEBUG(SOLV_DEBUG_SOLVER, "deciding cleandeps packages\n");
+ for (p = installed->start; p < installed->end; p++)
+ {
+ s = pool->solvables + p;
+ if (s->repo != installed)
+ continue;
+ if (solv->decisionmap[p] != 0 || !MAPTST(&solv->cleandepsmap, p - installed->start))
+ continue;
+ POOL_DEBUG(SOLV_DEBUG_POLICY, "cleandeps erasing %s\n", pool_solvid2str(pool, p));
+ olevel = level;
+ level = setpropagatelearn(solv, level, -p, 0, 0, SOLVER_REASON_CLEANDEPS_ERASE);
+ if (level < olevel)
+ break;
+ }
+ if (p < installed->end)
+ *rerunp = 1;
+ return level;
+}
+
+static int
+resolve_orphaned(Solver *solv, int level, int disablerules, Queue *dq, int *rerunp)
+{
+ Pool *pool = solv->pool;
+ int i;
+ Id p;
+ int installedone = 0;
+ int olevel;
+
+ /* let's see if we can install some unsupported package */
+ POOL_DEBUG(SOLV_DEBUG_SOLVER, "deciding orphaned packages\n");
+ for (i = 0; i < solv->orphaned.count; i++)
+ {
+ p = solv->orphaned.elements[i];
+ if (solv->decisionmap[p])
+ continue; /* already decided */
+ 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, SOLVER_REASON_RESOLVE_ORPHAN);
+ installedone = 1;
+ if (level < olevel)
+ break;
+ }
+ if (installedone || i < solv->orphaned.count)
+ {
+ *rerunp = 1;
+ return level;
+ }
+ for (i = 0; i < solv->orphaned.count; i++)
+ {
+ p = solv->orphaned.elements[i];
+ if (solv->decisionmap[p])
+ continue; /* already decided */
+ POOL_DEBUG(SOLV_DEBUG_SOLVER, "removing orphaned %s\n", pool_solvid2str(pool, p));
+ olevel = level;
+ level = setpropagatelearn(solv, level, -p, 0, 0, SOLVER_REASON_RESOLVE_ORPHAN);
+ if (level < olevel)
+ {
+ *rerunp = 1;
+ return level;
+ }
+ }
+ if (solv->brokenorphanrules)
+ {
+ solver_check_brokenorphanrules(solv, dq);
+ if (dq->count)
+ {
+ policy_filter_unwanted(solv, dq, POLICY_MODE_CHOOSE);
+ for (i = 0; i < dq->count; i++)
+ {
+ p = dq->elements[i];
+ POOL_DEBUG(SOLV_DEBUG_POLICY, "installing orphaned dep %s\n", pool_solvid2str(pool, p));