{
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;
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:
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 */
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))
{
/* 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;
}
{
/* 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;
}
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))
{
#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)
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)
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:
{
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);
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)
{
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;
}
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);
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))