From: Michael Schroeder Date: Mon, 4 Sep 2017 09:36:22 +0000 (+0200) Subject: Add support for REL_UNLESS X-Git-Tag: 0.6.29~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0c8cd38903fbcf738545ee5a79ae8ee118d8e414;p=thirdparty%2Flibsolv.git Add support for REL_UNLESS This is similar to REL_COND, except that it uses AND, not OR. Thus: (A REL_UNLESS B) is equivalent to (A AND NOT(B)) (A REL_UNLESS (B REL_ELSE C)) is equivalent to ((A AND NOT(B)) OR (C AND B)) --- diff --git a/src/cplxdeps.c b/src/cplxdeps.c index 8579eb6a..6c40752e 100644 --- a/src/cplxdeps.c +++ b/src/cplxdeps.c @@ -29,7 +29,7 @@ pool_is_complex_dep_rd(Pool *pool, Reldep *rd) { for (;;) { - if (rd->flags == REL_AND || rd->flags == REL_COND) /* those two are the complex ones */ + if (rd->flags == REL_AND || rd->flags == REL_COND || rd->flags == REL_UNLESS) /* those two are the complex ones */ return 1; if (rd->flags != REL_OR) return 0; @@ -264,6 +264,29 @@ normalize_dep_if_else(Pool *pool, Id dep1, Id dep2, Id dep3, Queue *bq, int flag return -1; } +static int +normalize_dep_unless_else(Pool *pool, Id dep1, Id dep2, Id dep3, Queue *bq, int flags) +{ + /* A UNLESS (B ELSE C) -> (A AND ~B) OR (C AND B) */ + int r1, r2, bqcnt2, bqcnt = bq->count; + r1 = normalize_dep_and(pool, dep1, dep2, bq, flags, CPLXDEPS_TODNF); + if (r1 == 1) + return 1; /* early exit */ + bqcnt2 = bq->count; + r2 = normalize_dep_and(pool, dep2, dep3, bq, flags, 0); + if (r1 == 1 || r2 == 1) + { + queue_truncate(bq, bqcnt); + return 1; + } + if (r1 == 0) + return r2; + if (r2 == 0) + return r1; + if ((flags & CPLXDEPS_TODNF) == 0) + return distribute_depblocks(pool, bq, bqcnt, bqcnt2, flags); + return -1; +} /* * returns: @@ -280,24 +303,32 @@ normalize_dep(Pool *pool, Id dep, Queue *bq, int flags) if (pool_is_complex_dep(pool, dep)) { Reldep *rd = GETRELDEP(pool, dep); - if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_COND) - { - if (rd->flags == REL_COND) - { - Id evr = rd->evr; - if (ISRELDEP(evr)) - { - Reldep *rd2 = GETRELDEP(pool, evr); - if (rd2->flags == REL_ELSE) - return normalize_dep_if_else(pool, rd->name, rd2->name, rd2->evr, bq, flags); - } - return normalize_dep_or(pool, rd->name, rd->evr, bq, flags, CPLXDEPS_TODNF); - } - if (rd->flags == REL_OR) - return normalize_dep_or(pool, rd->name, rd->evr, bq, flags, 0); - if (rd->flags == REL_AND) - return normalize_dep_and(pool, rd->name, rd->evr, bq, flags, 0); - } + if (rd->flags == REL_COND) + { + Id evr = rd->evr; + if (ISRELDEP(evr)) + { + Reldep *rd2 = GETRELDEP(pool, evr); + if (rd2->flags == REL_ELSE) + return normalize_dep_if_else(pool, rd->name, rd2->name, rd2->evr, bq, flags); + } + return normalize_dep_or(pool, rd->name, rd->evr, bq, flags, CPLXDEPS_TODNF); + } + if (rd->flags == REL_UNLESS) + { + Id evr = rd->evr; + if (ISRELDEP(evr)) + { + Reldep *rd2 = GETRELDEP(pool, evr); + if (rd2->flags == REL_ELSE) + return normalize_dep_unless_else(pool, rd->name, rd2->name, rd2->evr, bq, flags); + } + return normalize_dep_and(pool, rd->name, rd->evr, bq, flags, CPLXDEPS_TODNF); + } + if (rd->flags == REL_OR) + return normalize_dep_or(pool, rd->name, rd->evr, bq, flags, 0); + if (rd->flags == REL_AND) + return normalize_dep_and(pool, rd->name, rd->evr, bq, flags, 0); } /* fallback case: just use package list */ @@ -362,11 +393,11 @@ pool_add_pos_literals_complex_dep(Pool *pool, Id dep, Queue *q, Map *m, int neg) while (ISRELDEP(dep)) { Reldep *rd = GETRELDEP(pool, dep); - if (rd->flags != REL_AND && rd->flags != REL_OR && rd->flags != REL_COND) + if (rd->flags != REL_AND && rd->flags != REL_OR && rd->flags != REL_COND && rd->flags != REL_UNLESS) break; pool_add_pos_literals_complex_dep(pool, rd->name, q, m, neg); dep = rd->evr; - if (rd->flags == REL_COND) + if (rd->flags == REL_COND || rd->flags == REL_UNLESS) { neg = !neg; if (ISRELDEP(dep)) diff --git a/src/pool.c b/src/pool.c index 5d2d033b..b596ace2 100644 --- a/src/pool.c +++ b/src/pool.c @@ -822,17 +822,17 @@ pool_match_dep(Pool *pool, Id d1, Id d2) { /* we use potentially matches for complex deps */ rd1 = GETRELDEP(pool, d1); - if (rd1->flags == REL_AND || rd1->flags == REL_OR || rd1->flags == REL_WITH || rd1->flags == REL_WITHOUT || rd1->flags == REL_COND) + if (rd1->flags == REL_AND || rd1->flags == REL_OR || rd1->flags == REL_WITH || rd1->flags == REL_WITHOUT || rd1->flags == REL_COND || rd1->flags == REL_UNLESS) { if (pool_match_dep(pool, rd1->name, d2)) return 1; - if (rd1->flags == REL_COND && ISRELDEP(rd1->evr)) + if ((rd1->flags == REL_COND || rd1->flags == REL_UNLESS) && ISRELDEP(rd1->evr)) { rd1 = GETRELDEP(pool, rd1->evr); if (rd1->flags != REL_ELSE) return 0; } - if (rd1->flags != REL_COND && rd1->flags != REL_WITHOUT && pool_match_dep(pool, rd1->evr, d2)) + if (rd1->flags != REL_COND && rd1->flags != REL_UNLESS && rd1->flags != REL_WITHOUT && pool_match_dep(pool, rd1->evr, d2)) return 1; return 0; } @@ -841,17 +841,17 @@ pool_match_dep(Pool *pool, Id d1, Id d2) { /* we use potentially matches for complex deps */ rd2 = GETRELDEP(pool, d2); - if (rd2->flags == REL_AND || rd2->flags == REL_OR || rd2->flags == REL_WITH || rd2->flags == REL_WITHOUT || rd2->flags == REL_COND) + if (rd2->flags == REL_AND || rd2->flags == REL_OR || rd2->flags == REL_WITH || rd2->flags == REL_WITHOUT || rd2->flags == REL_COND || rd2->flags == REL_UNLESS) { if (pool_match_dep(pool, d1, rd2->name)) return 1; - if (rd2->flags == REL_COND && ISRELDEP(rd2->evr)) + if ((rd2->flags == REL_COND || rd2->flags == REL_UNLESS) && ISRELDEP(rd2->evr)) { rd2 = GETRELDEP(pool, rd2->evr); if (rd2->flags != REL_ELSE) return 0; } - if (rd2->flags != REL_COND && rd2->flags != REL_WITHOUT && pool_match_dep(pool, d1, rd2->evr)) + if (rd2->flags != REL_COND && rd2->flags != REL_UNLESS && rd2->flags != REL_WITHOUT && pool_match_dep(pool, d1, rd2->evr)) return 1; return 0; } @@ -1130,7 +1130,8 @@ pool_addrelproviders(Pool *pool, Id d) case REL_AND: case REL_OR: case REL_COND: - if (flags == REL_COND) + case REL_UNLESS: + if (flags == REL_COND || flags == REL_UNLESS) { if (ISRELDEP(evr)) { diff --git a/src/pool.h b/src/pool.h index 1d15de25..f6a54934 100644 --- a/src/pool.h +++ b/src/pool.h @@ -223,13 +223,14 @@ struct _Pool { #define REL_NAMESPACE 19 #define REL_ARCH 20 #define REL_FILECONFLICT 21 -#define REL_COND 22 +#define REL_COND 22 /* OR_NOT */ #define REL_COMPAT 23 #define REL_KIND 24 /* for filters only */ #define REL_MULTIARCH 25 /* debian multiarch annotation */ -#define REL_ELSE 26 /* only as evr part of REL_COND */ +#define REL_ELSE 26 /* only as evr part of REL_COND/REL_UNLESS */ #define REL_ERROR 27 /* parse errors and the like */ #define REL_WITHOUT 28 +#define REL_UNLESS 29 /* AND_NOT */ #if !defined(__GNUC__) && !defined(__attribute__) # define __attribute__(x) @@ -399,11 +400,6 @@ void pool_add_fileconflicts_deps(Pool *pool, Queue *conflicts); continue; \ else -#ifdef ENABLE_COMPS -#define ISCONDDEP(id) (ISRELDEP(id) && (GETRELDEP(pool, id))->flags == REL_COND) -#define MODIFYCONDDEP(id, tst) do { Reldep *condrd = GETRELDEP(pool, id); Id condp, condpp; FOR_PROVIDES(condrd->evr, condp, condpp) if (tst) break; id = condp ? condrd->name : 0;} while(0) -#endif - #define POOL_DEBUG(type, ...) do {if ((pool->debugmask & (type)) != 0) pool_debug(pool, (type), __VA_ARGS__);} while (0) #define IF_POOLDEBUG(type) if ((pool->debugmask & (type)) != 0) diff --git a/src/poolid.c b/src/poolid.c index de1ce29c..bb8d4f6d 100644 --- a/src/poolid.c +++ b/src/poolid.c @@ -190,6 +190,8 @@ pool_id2rel(const Pool *pool, Id id) return " FILECONFLICT "; case REL_COND: return pool->disttype == DISTTYPE_RPM ? " if " : " IF "; + case REL_UNLESS: + return pool->disttype == DISTTYPE_RPM ? " unless " : " UNLESS "; case REL_COMPAT: return " compat >= "; case REL_KIND: @@ -240,9 +242,9 @@ dep2strcpy(const Pool *pool, char *p, Id id, int oldrel) { Reldep *rd = GETRELDEP(pool, id); int rel = rd->flags; - if (oldrel == REL_AND || oldrel == REL_OR || oldrel == REL_WITH || oldrel == REL_WITHOUT || oldrel == REL_COND || oldrel == REL_ELSE || oldrel == -1) - if (rel == REL_AND || rel == REL_OR || rel == REL_WITH || rel == REL_WITHOUT || rel == REL_COND || rel == REL_ELSE) - if ((oldrel != rel || rel == REL_COND || rel == REL_ELSE) && !(oldrel == REL_COND && rel == REL_ELSE)) + if (oldrel == REL_AND || oldrel == REL_OR || oldrel == REL_WITH || oldrel == REL_WITHOUT || oldrel == REL_COND || oldrel == REL_UNLESS || oldrel == REL_ELSE || oldrel == -1) + if (rel == REL_AND || rel == REL_OR || rel == REL_WITH || rel == REL_WITHOUT || rel == REL_COND || rel == REL_UNLESS || rel == REL_ELSE) + if ((oldrel != rel || rel == REL_COND || rel == REL_UNLESS || rel == REL_ELSE) && !((oldrel == REL_COND || oldrel == REL_UNLESS) && rel == REL_ELSE)) { *p++ = '('; dep2strcpy(pool, p, rd->name, rd->flags); diff --git a/src/rules.c b/src/rules.c index 6c28cdda..5654330b 100644 --- a/src/rules.c +++ b/src/rules.c @@ -52,7 +52,7 @@ dep_possible(Solver *solv, Id dep, Map *m) Reldep *rd = GETRELDEP(pool, dep); if (rd->flags >= 8) { - if (rd->flags == REL_COND) + if (rd->flags == REL_COND || rd->flags == REL_UNLESS) return 1; if (rd->flags == REL_AND) { diff --git a/src/selection.c b/src/selection.c index e6ea84b5..16fe3a7d 100644 --- a/src/selection.c +++ b/src/selection.c @@ -890,17 +890,17 @@ matchdep(Pool *pool, Id id, char *rname, int rflags, char *revr, int flags) if (ISRELDEP(id)) { Reldep *rd = GETRELDEP(pool, id); - if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_WITH || rd->flags == REL_WITHOUT || rd->flags == REL_COND) + if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_WITH || rd->flags == REL_WITHOUT || rd->flags == REL_COND || rd->flags == REL_UNLESS) { if (matchdep(pool, rd->name, rname, rflags, revr, flags)) return 1; - if (rd->flags == REL_COND && ISRELDEP(rd->evr)) + if ((rd->flags == REL_COND || rd->flags == REL_UNLESS) && ISRELDEP(rd->evr)) { rd = GETRELDEP(pool, rd->evr); if (rd->flags != REL_ELSE) return 0; } - if (rd->flags != REL_COND && rd->flags != REL_WITHOUT && matchdep(pool, rd->evr, rname, rflags, revr, flags)) + if (rd->flags != REL_COND && rd->flags != REL_UNLESS && rd->flags != REL_WITHOUT && matchdep(pool, rd->evr, rname, rflags, revr, flags)) return 1; return 0; } diff --git a/src/solver.c b/src/solver.c index bec1d9f9..842f67cd 100644 --- a/src/solver.c +++ b/src/solver.c @@ -140,6 +140,30 @@ solver_dep_fulfilled_alreadyinstalled(Solver *solv, Id dep) return 0; return r1 == 2 ? 2 : 1; } + if (rd->flags == REL_UNLESS) + { + int r1, r2; + if (ISRELDEP(rd->evr)) + { + Reldep *rd2 = GETRELDEP(pool, rd->evr); + if (rd2->flags == REL_ELSE) + { + r1 = solver_dep_fulfilled_alreadyinstalled(solv, rd2->name); + if (r1) + { + r2 = solver_dep_fulfilled_alreadyinstalled(solv, rd2->evr); + return r2 && r1 == 2 ? 2 : r2; + } + return solver_dep_fulfilled_alreadyinstalled(solv, rd->name); + } + } + /* A AND NOT(B) */ + r1 = solver_dep_fulfilled_alreadyinstalled(solv, rd->name); + r2 = !solver_dep_fulfilled_alreadyinstalled(solv, rd->evr); + if (!r1 || !r2) + return 0; + return r1 == 2 ? 2 : 1; + } if (rd->flags == REL_AND) { int r2, r1 = solver_dep_fulfilled_alreadyinstalled(solv, rd->name); diff --git a/src/solver_private.h b/src/solver_private.h index fe808813..c796e4ca 100644 --- a/src/solver_private.h +++ b/src/solver_private.h @@ -43,6 +43,22 @@ solver_dep_fulfilled(Solver *solv, Id dep) return 1; return !solver_dep_fulfilled(solv, rd->evr); } + if (rd->flags == REL_UNLESS) + { + if (ISRELDEP(rd->evr)) + { + Reldep *rd2 = GETRELDEP(pool, rd->evr); + if (rd2->flags == REL_ELSE) + { + if (!solver_dep_fulfilled(solv, rd2->name)) + return solver_dep_fulfilled(solv, rd->name); + return solver_dep_fulfilled(solv, rd2->evr); + } + } + if (!solver_dep_fulfilled(solv, rd->name)) + return 0; + return !solver_dep_fulfilled(solv, rd->evr); + } if (rd->flags == REL_AND) { if (!solver_dep_fulfilled(solv, rd->name))