{ SOLVER_RULE_YUMOBS, "yumobs" },
{ SOLVER_RULE_BLACK, "black" },
{ SOLVER_RULE_RECOMMENDS, "recommends" },
+ { SOLVER_RULE_TRACKFEATURE, "trackfeature" },
{ 0, 0 }
};
return v;
}
+static inline int
+queue_contains(Queue *q, Id id)
+{
+ int i;
+ for (i = 0; i < q->count; i++)
+ if (q->elements[i] == id)
+ return 1;
+ return 0;
+}
+
+static int
+autoallowtrackfeature_sortcmp(const void *ap, const void *bp, void *dp)
+{
+ Pool *pool = dp;
+ Id *a = (Id *)ap, *b = (Id *)bp;
+ if (a[1] != b[1])
+ return a[1] - b[1];
+ if (a[0] != b[0])
+ return strcmp(pool_id2str(pool, b[0]), pool_id2str(pool, a[0]));
+ return 0;
+}
+
+/*-------------------------------------------------------------------
+ * try to fix a problem by autodisabling trackfeature rules
+ */
+Id
+solver_autoallowtrackfeature(Solver *solv, int start)
+{
+ Pool *pool = solv->pool;
+ int i, j, cnt, oldcount;
+ Id v, p, id;
+ Queue q, dq;
+
+ if (!solv->allowedtrackfeatureq)
+ return 0;
+ queue_init(&q);
+ queue_init(&dq);
+ for (i = start + 1; i < solv->problems.count - 1; i++)
+ {
+ v = solv->problems.elements[i];
+ if (v < solv->trackfeaturerules || v >= solv->trackfeaturerules_end)
+ continue;
+ p = -solv->rules[v].p;
+ solvable_lookup_idarray(pool->solvables + p, SOLVABLE_TRACK_FEATURES, &q);
+ cnt = 0;
+ oldcount = dq.count;
+ for (j = 0; j < q.count; j++)
+ {
+ if (queue_contains(solv->allowedtrackfeatureq, q.elements[j]))
+ continue;
+ queue_push2(&dq, q.elements[j], 0);
+ cnt++;
+ }
+ for (j = oldcount; j < dq.count; j += 2)
+ dq.elements[j + 1] = cnt;
+ }
+ if (dq.count > 2)
+ solv_sort(dq.elements, dq.count / 2, sizeof(Id) * 2, autoallowtrackfeature_sortcmp, pool);
+ id = dq.count ? dq.elements[0] : 0;
+ queue_free(&dq);
+ queue_free(&q);
+ if (id)
+ {
+ POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "autoallowing track feature %s\n", pool_id2str(pool, id));
+ solver_allow_trackfeature(solv, id);
+ }
+ return id;
+}
/*-------------------------------------------------------------------
* enable weak rules
void solver_recordproblem(struct s_Solver *solv, Id rid);
void solver_fixproblem(struct s_Solver *solv, Id rid);
Id solver_autouninstall(struct s_Solver *solv, int start);
+Id solver_autoallowtrackfeature(struct s_Solver *solv, int start);
void solver_disableproblemset(struct s_Solver *solv, int start);
int solver_prepare_solutions(struct s_Solver *solv);
*fromp = -r->p;
return SOLVER_RULE_BLACK;
}
+ if (rid >= solv->trackfeaturerules && rid < solv->trackfeaturerules_end)
+ {
+ if (fromp)
+ *fromp = -r->p;
+ return SOLVER_RULE_TRACKFEATURE;
+ }
if (rid >= solv->choicerules && rid < solv->choicerules_end)
return SOLVER_RULE_CHOICE;
if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end)
return SOLVER_RULE_RECOMMENDS;
if (rid >= solv->blackrules && rid < solv->blackrules_end)
return SOLVER_RULE_BLACK;
+ if (rid >= solv->trackfeaturerules && rid < solv->trackfeaturerules_end)
+ return SOLVER_RULE_TRACKFEATURE;
if (rid >= solv->learntrules && rid < solv->nrules)
return SOLVER_RULE_LEARNT;
return SOLVER_RULE_UNKNOWN;
}
}
+static int
+queue_contains_sorted(Queue *q, Id id, int insert)
+{
+ int i;
+ for (i = 0; i < q->count; i++)
+ {
+ if (q->elements[i] == id)
+ return 1;
+ if (q->elements[i] > id)
+ break;
+ }
+ if (insert)
+ queue_insert(q, i, id);
+ return 0;
+}
+
+void
+solver_allow_trackfeature(Solver *solv, Id id)
+{
+ Pool *pool = solv->pool;
+ int i, j;
+ Rule *r;
+ Queue q;
+ Id p;
+ if (queue_contains_sorted(solv->allowedtrackfeatureq, id, 1))
+ return; /* already allowed? */
+ queue_init(&q);
+ for (i = solv->trackfeaturerules, r = solv->rules + i; i < solv->trackfeaturerules_end; i++, r++)
+ {
+ if (r->d < 0)
+ continue; /* already disabled */
+ p = -r->p;
+ solvable_lookup_idarray(pool->solvables + p, SOLVABLE_TRACK_FEATURES, &q);
+ if (!queue_contains_sorted(&q, id, 0))
+ continue;
+ for (j = 0; j < q.count; j++)
+ if (q.elements[j] != id && !queue_contains_sorted(solv->allowedtrackfeatureq, q.elements[j], 0))
+ break;
+ if (j == q.count)
+ solver_disablerule(solv, r);
+ }
+ queue_free(&q);
+}
+
+void
+solver_addtrackfeaturerules(Solver *solv, Map *addedmap)
+{
+ Pool *pool = solv->pool;
+ Repo *installed = solv->installed;
+ Id p;
+ Solvable *s;
+ Queue q;
+ int i;
+
+ solv->trackfeaturerules = solv->nrules;
+ queue_init(&q);
+ solv->allowedtrackfeatureq = solv_calloc(1, sizeof(Queue));
+ queue_init(solv->allowedtrackfeatureq);
+ FOR_REPO_SOLVABLES(installed, p, s)
+ {
+ solvable_lookup_idarray(s, SOLVABLE_TRACK_FEATURES, &q);
+ if (!q.elements)
+ continue;
+ for (i = 0; i < q.count; i++)
+ queue_contains_sorted(solv->allowedtrackfeatureq, q.elements[i], 1);
+ }
+ FOR_POOL_SOLVABLES(p)
+ {
+ Solvable *s = pool->solvables + p;
+ if (s->repo == installed)
+ continue;
+ if (!MAPTST(addedmap, p))
+ continue; /* not possible to install */
+ solvable_lookup_idarray(s, SOLVABLE_TRACK_FEATURES, &q);
+ if (!q.count)
+ continue;
+ for (i = 0; i < q.count; i++)
+ if (!queue_contains_sorted(solv->allowedtrackfeatureq, q.elements[i], 0))
+ break;
+ if (i < q.count) {
+ solver_addrule(solv, -p, 0, 0);
+}
+ }
+ solv->trackfeaturerules_end = solv->nrules;
+ if (solv->trackfeaturerules == solv->trackfeaturerules_end)
+ {
+ queue_free(solv->allowedtrackfeatureq);
+ solv->allowedtrackfeatureq = solv_free(solv->allowedtrackfeatureq);
+ }
+ queue_free(&q);
+}
SOLVER_RULE_BEST = 0x900,
SOLVER_RULE_YUMOBS = 0xa00,
SOLVER_RULE_RECOMMENDS = 0xb00,
- SOLVER_RULE_BLACK = 0xc00
+ SOLVER_RULE_BLACK = 0xc00,
+ SOLVER_RULE_TRACKFEATURE = 0xd00
} SolverRuleinfo;
#define SOLVER_RULE_TYPEMASK 0xff00
/* recommends rules */
extern void solver_addrecommendsrules(struct s_Solver *solv);
+/* trackfeature rules */
+void solver_allow_trackfeature(struct s_Solver *solv, Id id);
+void solver_addtrackfeaturerules(struct s_Solver *solv, Map *addedmap);
+
/* policy rule disabling/reenabling */
extern void solver_disablepolicyrules(struct s_Solver *solv);
extern void solver_reenablepolicyrules(struct s_Solver *solv, int jobidx);
}
queue_push(&solv->problems, 0); /* finish problem */
+ if (solv->allowedtrackfeatureq && solver_autoallowtrackfeature(solv, oldproblemcount) != 0)
+ {
+ solv->problems.count = oldproblemcount;
+ havedisabled = 1;
+ break; /* start over */
+ }
+
/* try autouninstall if requested */
if (doautouninstall)
{
}
queue_free(&weakq);
+ if (solv->allowedtrackfeatureq && solver_autoallowtrackfeature(solv, oldproblemcount) != 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 (solver_autouninstall(solv, oldproblemcount) != 0)
{
queuep_free(&solv->suggestscplxq);
queuep_free(&solv->brokenorphanrules);
queuep_free(&solv->recommendsruleq);
+ queuep_free(&solv->allowedtrackfeatureq);
map_free(&solv->recommendsmap);
map_free(&solv->suggestsmap);
/* free old stuff in case we re-run a solver */
queuep_free(&solv->update_targets);
queuep_free(&solv->cleandeps_updatepkgs);
+ queuep_free(&solv->allowedtrackfeatureq);
queue_empty(&solv->ruleassertions);
solv->bestrules_info = solv_free(solv->bestrules_info);
solv->yumobsrules_info = solv_free(solv->yumobsrules_info);
else
solv->blackrules = solv->blackrules_end = solv->nrules;
+ if (pool->disttype == DISTTYPE_CONDA)
+ solver_addtrackfeaturerules(solv, &addedmap);
+ else
+ solv->trackfeaturerules = solv->trackfeaturerules_end = solv->nrules;
+
if (solv->havedisfavored && solv->strongrecommends && solv->recommendsruleq)
solver_addrecommendsrules(solv);
else
map_free(&installcandidatemap);
queue_free(&q);
- POOL_DEBUG(SOLV_DEBUG_STATS, "%d pkg rules, 2 * %d update rules, %d job rules, %d infarch rules, %d dup rules, %d choice rules, %d best rules, %d yumobs rules\n", solv->pkgrules_end - 1, solv->updaterules_end - solv->updaterules, solv->jobrules_end - solv->jobrules, solv->infarchrules_end - solv->infarchrules, solv->duprules_end - solv->duprules, solv->choicerules_end - solv->choicerules, solv->bestrules_end - solv->bestrules, solv->yumobsrules_end - solv->yumobsrules);
+ POOL_DEBUG(SOLV_DEBUG_STATS, "%d pkg rules, 2 * %d update rules, %d job rules, %d infarch rules, %d dup rules, %d choice rules, %d best rules, %d yumobs rules, %d trackfeature rules\n", solv->pkgrules_end - 1, solv->updaterules_end - solv->updaterules, solv->jobrules_end - solv->jobrules, solv->infarchrules_end - solv->infarchrules, solv->duprules_end - solv->duprules, solv->choicerules_end - solv->choicerules, solv->bestrules_end - solv->bestrules, solv->yumobsrules_end - solv->yumobsrules, solv->trackfeaturerules_end - solv->trackfeaturerules);
POOL_DEBUG(SOLV_DEBUG_STATS, "overall rule memory used: %d K\n", solv->nrules * (int)sizeof(Rule) / 1024);
/* create weak map */
Id blackrules; /* rules from blacklisted packages */
Id blackrules_end;
+ Id trackfeaturerules; /* rules from packages containing track features */
+ Id trackfeaturerules_end;
+
Id choicerules; /* choice rules (always weak) */
Id choicerules_end;
Id *choicerules_info; /* the rule we used to generate the choice rule */
int do_extra_reordering; /* reorder for future installed packages */
Queue *recommendsruleq; /* pkg rules comming from recommends */
+
+ Queue *allowedtrackfeatureq; /* which track features may be installed */
#endif /* LIBSOLV_INTERNAL */
};
POOL_DEBUG(type, "BLACK ");
else if (p >= solv->recommendsrules && p < solv->recommendsrules_end)
POOL_DEBUG(type, "RECOMMENDS ");
+ else if (p >= solv->trackfeaturerules && p < solv->trackfeaturerules_end)
+ POOL_DEBUG(type, "TRACKFEATURE ");
solver_printrule(solv, type, r);
}