From: Michael Schroeder Date: Fri, 24 Jul 2009 12:55:55 +0000 (+0200) Subject: - add experimental support for choice rules to fix #485409 X-Git-Tag: BASE-SuSE-Code-12_1-Branch~165^2~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cce95701fe3ee583fc1ea9c18279677ff2ae8b00;p=thirdparty%2Flibsolv.git - add experimental support for choice rules to fix #485409 --- diff --git a/examples/solv.c b/examples/solv.c index 051d547e..52a965e2 100644 --- a/examples/solv.c +++ b/examples/solv.c @@ -62,6 +62,7 @@ #else # define REPOINFO_PATH "/etc/zypp/repos.d" # define PRODUCTS_PATH "/etc/products.d" +# define SOFTLOCKS_PATH "/var/lib/zypp/SoftLocks" #endif #define SOLVCACHE_PATH "/var/cache/solv" @@ -1932,6 +1933,49 @@ nscallback(Pool *pool, void *data, Id name, Id evr) return 0; } +#ifdef SOFTLOCKS_PATH + +void +addsoftlocks(Pool *pool, Queue *job) +{ + FILE *fp; + Id type, id, p, pp; + char *bp, *ep, buf[4096]; + + if ((fp = fopen(SOFTLOCKS_PATH, "r")) == 0) + return; + while((bp = fgets(buf, sizeof(buf), fp)) != 0) + { + while (*bp == ' ' || *bp == '\t') + bp++; + if (!*bp || *bp == '#') + continue; + for (ep = bp; *ep; ep++) + if (*ep == ' ' || *ep == '\t' || *ep == '\n') + break; + *ep = 0; + type = SOLVER_SOLVABLE_NAME; + if (!strncmp(bp, "provides:", 9) && bp[9]) + { + type = SOLVER_SOLVABLE_PROVIDES; + bp += 9; + } + id = str2id(pool, bp, 1); + if (pool->installed) + { + FOR_JOB_SELECT(p, pp, type, id) + if (pool->solvables[p].repo == pool->installed) + break; + if (p) + continue; /* ignore, as it is already installed */ + } + queue_push2(job, SOLVER_LOCK|SOLVER_WEAK|type, id); + } + fclose(fp); +} + +#endif + #define MODE_LIST 0 #define MODE_INSTALL 1 #define MODE_ERASE 2 @@ -2259,6 +2303,10 @@ main(int argc, char **argv) // queue_push2(&job, SOLVER_NOOBSOLETES|SOLVER_SOLVABLE_NAME, str2id(pool, "kernel-pae-base", 1)); // queue_push2(&job, SOLVER_NOOBSOLETES|SOLVER_SOLVABLE_NAME, str2id(pool, "kernel-pae-extra", 1)); +#ifdef SOFTLOCKS_PATH + addsoftlocks(pool, &job); +#endif + rerunsolver: for (;;) { diff --git a/src/rules.c b/src/rules.c index 02a918d1..4429f504 100644 --- a/src/rules.c +++ b/src/rules.c @@ -1760,6 +1760,10 @@ solver_ruleinfo(Solver *solv, Id rid, Id *fromp, Id *top, Id *depp) *depp = pool->solvables[-r->p].name; return SOLVER_RULE_INFARCH; } + if (rid >= solv->choicerules && rid < solv->choicerules_end) + { + return SOLVER_RULE_CHOICE; + } if (rid >= solv->learntrules) { return SOLVER_RULE_LEARNT; @@ -1767,4 +1771,130 @@ solver_ruleinfo(Solver *solv, Id rid, Id *fromp, Id *top, Id *depp) return SOLVER_RULE_UNKNOWN; } +void +addchoicerules(Solver *solv) +{ + Pool *pool = solv->pool; + Rule *r; + Queue q; + int i, rid, havechoice; + Id p, d, *pp; + Id p2, pp2; + Solvable *s, *s2; + + solv->choicerules = solv->nrules; + if (!pool->installed) + { + solv->choicerules_end = solv->nrules; + return; + } + queue_init(&q); + for (rid = 1; rid < solv->rpmrules_end ; rid++) + { + r = solv->rules + rid; + if (r->p >= 0 || ((r->d == 0 || r->d == -1) && r->w2 < 0)) + continue; /* only look at requires rules */ + // solver_printrule(solv, SAT_DEBUG_RESULT, r); + queue_empty(&q); + havechoice = 0; + FOR_RULELITERALS(p, pp, r) + { + if (p < 0) + continue; + s = pool->solvables + p; + if (!s->repo) + continue; + if (s->repo == pool->installed) + { + queue_push(&q, p); + continue; + } + /* check if this package is "blocked" by a installed package */ + s2 = 0; + FOR_PROVIDES(p2, pp2, s->name) + { + s2 = pool->solvables + p2; + if (s2->repo != pool->installed) + continue; + if (!pool->implicitobsoleteusesprovides && s->name != s2->name) + continue; + if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2)) + continue; + break; + } + if (p2) + { + /* found one */ + if (!solv->allowarchchange && s->arch != s2->arch && policy_illegal_archchange(solv, s, s2)) + continue; + if (!solv->allowvendorchange && s->vendor != s2->vendor && policy_illegal_vendorchange(solv, s, s2)) + continue; + queue_push(&q, p); + continue; + } + if (s->obsoletes) + { + Id obs, *obsp = s->repo->idarraydata + s->obsoletes; + s2 = 0; + while ((obs = *obsp++) != 0) + { + FOR_PROVIDES(p2, pp2, obs) + { + s2 = pool->solvables + p2; + if (s2->repo != pool->installed) + continue; + if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + p2, obs)) + continue; + if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2)) + continue; + break; + } + if (p2) + break; + } + if (obs) + { + /* found one */ + if (!solv->allowarchchange && s->arch != s2->arch && policy_illegal_archchange(solv, s, s2)) + continue; + if (!solv->allowvendorchange && s->vendor != s2->vendor && policy_illegal_vendorchange(solv, s, s2)) + continue; + queue_push(&q, p); + continue; + } + } + /* this package is independent if the installed ones */ + havechoice = 1; + } + if (!havechoice || !q.count) + continue; /* no choice */ + for (i = 0; i < q.count; i++) + { + int j; + s = pool->solvables + q.elements[i]; + if (s->repo == pool->installed) + continue; + for (j = 0; j < q.count; j++) + { + if (i == j) + continue; + s2 = pool->solvables + q.elements[j]; + if (s2->repo != pool->installed) + continue; + if (solvable_identical(s, s2)) + break; + } + if (j == q.count) + break; + } + if (i == q.count) + continue; /* only (identical to) installed packages */ + d = q.count ? pool_queuetowhatprovides(pool, &q) : 0; + solver_addrule(solv, r->p, d); + queue_push(&solv->weakruleq, solv->nrules - 1); + } + queue_free(&q); + solv->choicerules_end = solv->nrules; +} + /* EOF */ diff --git a/src/rules.h b/src/rules.h index d9f4e363..2cd4035f 100644 --- a/src/rules.h +++ b/src/rules.h @@ -63,7 +63,8 @@ typedef enum { SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP, SOLVER_RULE_DISTUPGRADE = 0x500, SOLVER_RULE_INFARCH = 0x600, - SOLVER_RULE_LEARNT = 0x700 + SOLVER_RULE_CHOICE = 0x700, + SOLVER_RULE_LEARNT = 0x800 } SolverRuleinfo; #define SOLVER_RULE_TYPEMASK 0xff00 diff --git a/src/solver.c b/src/solver.c index c45d6767..206be136 100644 --- a/src/solver.c +++ b/src/solver.c @@ -2804,6 +2804,11 @@ solver_solve(Solver *solv, Queue *job) else solv->duprules = solv->duprules_end = solv->nrules; + if (1) + { + extern void addchoicerules(Solver *solv); + addchoicerules(solv); + } /* all rules created * -------------------------------------------------------------- @@ -2815,7 +2820,7 @@ solver_solve(Solver *solv, Queue *job) map_free(&installcandidatemap); queue_free(&q); - POOL_DEBUG(SAT_DEBUG_STATS, "%d rpm rules, %d job rules, %d infarch rules, %d dup rules\n", solv->rpmrules_end - 1, solv->jobrules_end - solv->jobrules, solv->infarchrules_end - solv->infarchrules, solv->duprules_end - solv->duprules); + POOL_DEBUG(SAT_DEBUG_STATS, "%d rpm rules, %d job rules, %d infarch rules, %d dup rules, %d choice rules\n", solv->rpmrules_end - 1, solv->jobrules_end - solv->jobrules, solv->infarchrules_end - solv->infarchrules, solv->duprules_end - solv->duprules, solv->choicerules_end - solv->choicerules); /* create weak map */ map_init(&solv->weakrulemap, solv->nrules); diff --git a/src/solver.h b/src/solver.h index 096d378c..91a7664b 100644 --- a/src/solver.h +++ b/src/solver.h @@ -74,6 +74,9 @@ typedef struct _Solver { Id duprules; /* dist upgrade rules */ Id duprules_end; + Id choicerules; /* choice rules (always weak) */ + Id choicerules_end; + Id learntrules; /* learnt rules, (end == nrules) */ Map noupdate; /* don't try to update these diff --git a/src/solverdebug.c b/src/solverdebug.c index d95416aa..ee43212c 100644 --- a/src/solverdebug.c +++ b/src/solverdebug.c @@ -136,6 +136,8 @@ solver_printruleelement(Solver *solv, int type, Rule *r, Id v) s = pool->solvables + v; POOL_DEBUG(type, " %s [%d]", solvable2str(pool, s), v); } + if (pool->installed && s->repo == pool->installed) + POOL_DEBUG(type, "I"); if (r) { if (r->w1 == v) @@ -203,6 +205,8 @@ solver_printruleclass(Solver *solv, int type, Rule *r) POOL_DEBUG(type, "WEAK "); if (p >= solv->learntrules) POOL_DEBUG(type, "LEARNT "); + else if (p >= solv->choicerules && p < solv->choicerules_end) + POOL_DEBUG(type, "CHOICE "); else if (p >= solv->infarchrules && p < solv->infarchrules_end) POOL_DEBUG(type, "INFARCH "); else if (p >= solv->duprules && p < solv->duprules_end) @@ -561,6 +565,7 @@ solver_printprobleminfo(Solver *solv, Id problem) case SOLVER_RULE_UNKNOWN: case SOLVER_RULE_FEATURE: case SOLVER_RULE_LEARNT: + case SOLVER_RULE_CHOICE: POOL_DEBUG(SAT_DEBUG_RESULT, "bad rule type\n"); return; }