summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Schroeder <mls@suse.de>2014-04-17 14:18:42 +0200
committerMichael Schroeder <mls@suse.de>2014-04-17 14:18:42 +0200
commit3ef3b1fc2683e955702472e838ff02bf2f68954a (patch)
treee617e75a90aef178ebeee77e510b2daada42d0d2
parent1a4fc4d68c2a8bd5d027bc2f76d3bfc2c187efea (diff)
downloadlibsolv-3ef3b1fc2683e955702472e838ff02bf2f68954a.tar.gz
libsolv-3ef3b1fc2683e955702472e838ff02bf2f68954a.tar.bz2
libsolv-3ef3b1fc2683e955702472e838ff02bf2f68954a.zip
implement SOLVER_FLAG_BREAK_ORPHANS
-rw-r--r--src/problems.c4
-rw-r--r--src/rules.c94
-rw-r--r--src/rules.h3
-rw-r--r--src/solver.c26
-rw-r--r--src/solver.h1
5 files changed, 127 insertions, 1 deletions
diff --git a/src/problems.c b/src/problems.c
index 7258c04..bb00aa6 100644
--- a/src/problems.c
+++ b/src/problems.c
@@ -160,6 +160,10 @@ enableweakrules(Solver *solv)
continue;
solver_enablerule(solv, r);
}
+ /* make sure broken orphan rules stay disabled */
+ if (solv->brokenorphanrules)
+ for (i = 0; i < solv->brokenorphanrules->count; i++)
+ solver_disablerule(solv, solv->rules + solv->brokenorphanrules->elements[i]);
}
diff --git a/src/rules.c b/src/rules.c
index b86ad77..78cc1e0 100644
--- a/src/rules.c
+++ b/src/rules.c
@@ -4329,4 +4329,96 @@ solver_get_unneeded(Solver *solv, Queue *unneededq, int filtered)
map_free(&cleandepsmap);
}
-/* EOF */
+
+void
+solver_breakorphans(Solver *solv)
+{
+ Pool *pool = solv->pool;
+ Repo *installed = solv->installed;
+ int i, rid;
+ Map m;
+
+ if (!installed || solv->droporphanedmap_all)
+ return;
+ solv->brokenorphanrules = solv_calloc(1, sizeof(Queue));
+ queue_init(solv->brokenorphanrules);
+ map_init(&m, installed->end - installed->start);
+ for (i = 0; i < solv->orphaned.count; i++)
+ {
+ Id p = solv->orphaned.elements[i];
+ if (pool->solvables[p].repo != installed)
+ continue;
+ if (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, p - installed->start))
+ continue;
+ MAPSET(&m, p - installed->start);
+ }
+ for (rid = 1; rid < solv->rpmrules_end ; rid++)
+ {
+ Id p, *dp;
+ Rule *r = solv->rules + rid;
+ /* ignore non-deps and simple conflicts */
+ if (r->p >= 0 || ((r->d == 0 || r->d == -1) && r->w2 < 0))
+ continue;
+ p = -r->p;
+ if (p < installed->start || p >= installed->end || !MAPTST(&m, p - installed->start))
+ {
+ /* need to check other literals */
+ if (r->d == 0 || r->d == -1)
+ continue;
+ for (dp = pool->whatprovidesdata + (r->d < 0 ? -r->d - 1 : r->d); *dp < 0; dp++)
+ {
+ p = -*dp;
+ if (p >= installed->start && p < installed->end && MAPTST(&m, p - installed->start))
+ break;
+ }
+ if (*dp >= 0)
+ continue;
+ }
+ /* ok, disable this rule */
+ queue_push(solv->brokenorphanrules, rid);
+ if (r->d >= 0)
+ solver_disablerule(solv, r);
+ }
+ map_free(&m);
+ if (!solv->brokenorphanrules->count)
+ {
+ queue_free(solv->brokenorphanrules);
+ solv->brokenorphanrules = solv_free(solv->brokenorphanrules);
+ }
+}
+
+void
+solver_check_brokenorphanrules(Solver *solv, Queue *dq)
+{
+ Pool *pool = solv->pool;
+ int i;
+ Id l, pp;
+
+ queue_empty(dq);
+ if (!solv->brokenorphanrules)
+ return;
+ for (i = 0; i < solv->brokenorphanrules->count; i++)
+ {
+ int rid = solv->brokenorphanrules->elements[i];
+ Rule *r = solv->rules + rid;
+ FOR_RULELITERALS(l, pp, r)
+ {
+ if (l < 0)
+ {
+ if (solv->decisionmap[-l] <= 0)
+ break;
+ }
+ else
+ {
+ if (solv->decisionmap[l] > 0 && pool->solvables[l].repo != solv->installed)
+ break;
+ }
+ }
+ if (l)
+ continue;
+ FOR_RULELITERALS(l, pp, r)
+ if (l > 0 && solv->decisionmap[l] == 0 && pool->solvables[l].repo != solv->installed)
+ queue_pushunique(dq, l);
+ }
+}
+
diff --git a/src/rules.h b/src/rules.h
index 15de00f..06048e4 100644
--- a/src/rules.h
+++ b/src/rules.h
@@ -142,6 +142,9 @@ extern Id solver_rule2job(struct _Solver *solv, Id rid, Id *whatp);
extern Id solver_rule2solvable(struct _Solver *solv, Id rid);
extern void solver_rule2rules(struct _Solver *solv, Id rid, Queue *q, int recursive);
+/* orphan handling */
+extern void solver_breakorphans(struct _Solver *solv);
+extern void solver_check_brokenorphanrules(struct _Solver *solv, Queue *dq);
#ifdef __cplusplus
}
diff --git a/src/solver.c b/src/solver.c
index 054567e..282dd78 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -1573,6 +1573,7 @@ solver_free(Solver *solv)
queuep_free(&solv->installsuppdepq);
queuep_free(&solv->recommendscplxq);
queuep_free(&solv->suggestscplxq);
+ queuep_free(&solv->brokenorphanrules);
map_free(&solv->recommendsmap);
map_free(&solv->suggestsmap);
@@ -2687,6 +2688,26 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
break;
continue; /* back to main loop */
}
+ 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));
+ olevel = level;
+ level = setpropagatelearn(solv, level, p, 0, 0);
+ if (level < olevel)
+ break;
+ }
+ if (level == 0)
+ break;
+ continue;
+ }
+ }
}
/* one final pass to make sure we decided all installed packages */
@@ -3303,6 +3324,7 @@ solver_solve(Solver *solv, Queue *job)
queuep_free(&solv->suggestscplxq);
solv->recommends_index = 0;
}
+ queuep_free(&solv->brokenorphanrules);
solv->specialupdaters = solv_free(solv->specialupdaters);
@@ -3880,6 +3902,10 @@ solver_solve(Solver *solv, Queue *job)
/* disable update rules that conflict with our job */
solver_disablepolicyrules(solv);
+ /* break orphans if requested */
+ if (solv->dupmap_all && solv->orphaned.count && solv->break_orphans)
+ solver_breakorphans(solv);
+
/* make initial decisions based on assertion rules */
makeruledecisions(solv);
POOL_DEBUG(SOLV_DEBUG_SOLVER, "problems so far: %d\n", solv->problems.count);
diff --git a/src/solver.h b/src/solver.h
index 3316e76..c8f51fc 100644
--- a/src/solver.h
+++ b/src/solver.h
@@ -187,6 +187,7 @@ struct _Solver {
Id *instbuddy; /* buddies of installed packages */
int keep_orphans; /* how to treat orphans */
int break_orphans; /* how to treat orphans */
+ Queue *brokenorphanrules; /* broken rules of orphaned packages */
#endif /* LIBSOLV_INTERNAL */
};