]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
Add support for REL_UNLESS
authorMichael Schroeder <mls@suse.de>
Mon, 4 Sep 2017 09:36:22 +0000 (11:36 +0200)
committerMichael Schroeder <mls@suse.de>
Mon, 4 Sep 2017 09:52:36 +0000 (11:52 +0200)
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))

src/cplxdeps.c
src/pool.c
src/pool.h
src/poolid.c
src/rules.c
src/selection.c
src/solver.c
src/solver_private.h

index 8579eb6ad3a68b11d0d249e9ef5ab75639310d50..6c40752e2483764fd677e38e8df042f55c2817fd 100644 (file)
@@ -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))
index 5d2d033bf028cecac30b5798c0e0e16266d59272..b596ace25f67e1078cd9da19d404a343844e3747 100644 (file)
@@ -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))
                {
index 1d15de25017841558db4cb8779a745019e3efed9..f6a5493474a7c4f145f05bba7eefc1236fdec939 100644 (file)
@@ -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)
 
index de1ce29cac4033079cb08823c5cfea54e492677b..bb8d4f6de26c0aff443b25cfb364638da62dbdd5 100644 (file)
@@ -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);
index 6c28cdda20ae31032cbdbe05d8b7145e4d100165..5654330bdc36b5a4cddd82c6dc58e31dc2a6be76 100644 (file)
@@ -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)
            {
index e6ea84b53b239f0680673be56af014f2f0686ef2..16fe3a7d8245dd495444620a2719679f586047bf 100644 (file)
@@ -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;
        }
index bec1d9f91a4d8df9f1a507976013baa096ab4b57..842f67cd1ff16b45dfd9e86ee23e01abe09e8b5b 100644 (file)
@@ -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);
index fe80881337cc9735720d56bec4cd8923a7b52561..c796e4ca3cc38bf9b0f0fdf2f7fb4af9a8be5f3a 100644 (file)
@@ -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))