]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
Add selection_make_matchsolvable and selection_make_matchsolvablelist
authorMichael Schroeder <mls@suse.de>
Fri, 5 Oct 2018 12:41:20 +0000 (14:41 +0200)
committerMichael Schroeder <mls@suse.de>
Fri, 5 Oct 2018 12:41:20 +0000 (14:41 +0200)
This is like pool_whatmatchessolvable, but works on a selection.
The advantage is that it supports filtering.

examples/solv/solv.c
src/libsolv.ver
src/selection.c
src/selection.h

index b23669f819af67b090648aad8bd835e709cf871d..6a5dab7360614e61aee241bc35fbaae4f76951fd 100644 (file)
@@ -169,34 +169,6 @@ find_repo(const char *name, Pool *pool, struct repoinfo *repoinfos, int nrepoinf
   return 0;
 }
 
-static void
-selection_alldeps(Pool *pool, Queue *selection, int keyname, int marker)
-{
-  Queue pkgs, q;
-  int i, j;
-
-  queue_init(&pkgs);
-  queue_init(&q);
-  selection_solvables(pool, selection, &pkgs);
-  queue_empty(selection);
-  for (i = 0; i < pkgs.count; i++)
-    {
-      queue_empty(&q);
-      pool_whatmatchessolvable(pool, keyname, pkgs.elements[i], &q, marker);
-      for (j = 0; j < q.count; j++)
-        queue_pushunique(selection, q.elements[j]);
-    }
-  queue_free(&q);
-  queue_free(&pkgs);
-  j = selection->count;
-  queue_insertn(selection, 0, j, 0);
-  for (i = 0; i < j; i++)
-    {
-      selection->elements[2 * i] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
-      selection->elements[2 * i + 1] = selection->elements[i + j];
-    }
-}
-
 #define MODE_LIST        0
 #define MODE_INSTALL     1
 #define MODE_ERASE       2
@@ -609,7 +581,13 @@ main(int argc, char **argv)
       if (rflags & SELECTION_PROVIDES)
        printf("[using capability match for '%s']\n", argv[i]);
       if (keyname && keyname_alldeps)
-        selection_alldeps(pool, &job2, pool_str2id(pool, keyname, 1), 0);
+       {
+         Queue q;
+         queue_init(&q);
+         selection_solvables(pool, &job2, &q);
+         selection_make_matchsolvablelist(pool, &job2, &q, 0, pool_str2id(pool, keyname, 1), 0);
+         queue_free(&q);
+       }
       queue_insertn(&job, job.count, job2.count, job2.elements);
       queue_free(&job2);
     }
index c2acc137f0f11d1ea4fa1b7ca28e6a239f73b5e7..db453a01ab777eccf567f151bca2c80136e715bd 100644 (file)
@@ -259,6 +259,8 @@ SOLV_1.0 {
                selection_make;
                selection_make_matchdepid;
                selection_make_matchdeps;
+               selection_make_matchsolvable;
+               selection_make_matchsolvablelist;
                selection_solvables;
                solv_bin2hex;
                solv_calloc;
index f0422d4f6fd8f278214878b1a697a4cb37cd480a..9277dfd78f1ef81cf65f482370b640ce9bd671ba 100644 (file)
@@ -1430,6 +1430,137 @@ matchdep(Pool *pool, Id id, char *rname, int rflags, Id revr, int flags)
   return matchdep_str(rname, pool_id2str(pool, id), flags);
 }
 
+static int
+selection_make_matchsolvable_common_limited(Pool *pool, Queue *selection, Queue *solvidq, Id solvid, int flags, int keyname, int marker, struct limiter *limiter)
+{
+  Id *wp;
+  Map m, missc;
+  int reloff, boff;
+  int li, i, j;
+  Id p;
+  Queue q;
+
+  if (solvidq)
+    {
+      map_init(&m, pool->nsolvables);
+      for (i = 0; i < solvidq->count; i++)
+       MAPSET(&m, solvidq->elements[i]);
+    }
+  queue_init(&q);
+  reloff = pool->ss.nstrings;
+  map_init(&missc, reloff + pool->nrels);
+  for (li = limiter->start; li < limiter->end; li++)
+    {
+      Solvable *s;
+      p = limiter->mapper ? limiter->mapper[li] : li;
+      if (solvidq && MAPTST(&m, p))
+       continue;
+      if (!solvidq && p == solvid)
+       continue;
+      s = pool->solvables + p;
+      if (!s->repo || (limiter->repofilter && s->repo != limiter->repofilter))
+       continue;
+      if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
+       {
+         if (!(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE))
+           continue;
+         if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s))
+           continue;
+       }
+      else
+       {
+         if ((flags & SELECTION_SOURCE_ONLY) != 0)
+           continue;
+         if (s->repo != pool->installed)
+           {
+             if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s))
+               continue;
+             if (!(flags & SELECTION_WITH_BADARCH) && pool_badarch_solvable(pool, s))
+               continue;
+           }
+       }
+      if (q.count)
+       queue_empty(&q);
+      repo_lookup_deparray(s->repo, p, keyname, &q, marker);
+      if (!q.count)
+       continue;
+      for (i = 0; i < q.count; i++)
+       {
+         Id dep = q.elements[i];
+         boff = ISRELDEP(dep) ? reloff + GETRELID(dep) : dep;
+         if (MAPTST(&missc, boff))
+           continue;
+         if (ISRELDEP(dep))
+           {
+             Reldep *rd = GETRELDEP(pool, dep);
+             if (!ISRELDEP(rd->name) && rd->flags < 8)
+               {
+                 /* do pre-filtering on the base */
+                 if (MAPTST(&missc, rd->name))
+                   continue;
+                 wp = pool_whatprovides_ptr(pool, rd->name);
+                 if (solvidq)
+                   {
+                     for (wp = pool_whatprovides_ptr(pool, dep); *wp; wp++)
+                       if (MAPTST(&m, *wp))
+                         break;
+                   }
+                 else
+                   {
+                     for (wp = pool_whatprovides_ptr(pool, dep); *wp; wp++)
+                       if (*wp == solvid)
+                         break;
+                   }
+                 if (!*wp)
+                   {
+                     /* the base does not include solvid, no need to check the complete dep */
+                     MAPSET(&missc, rd->name);
+                     MAPSET(&missc, boff);
+                     continue;
+                   }
+               }
+           }
+         wp = pool_whatprovides_ptr(pool, dep);
+         if (solvidq)
+           {
+             for (wp = pool_whatprovides_ptr(pool, dep); *wp; wp++)
+               if (MAPTST(&m, *wp))
+                 break;
+           }
+         else
+           {
+             for (wp = pool_whatprovides_ptr(pool, dep); *wp; wp++)
+               if (*wp == solvid)
+                 break;
+           }
+         if (*wp)
+           {
+             queue_push(selection, p);
+             break;
+           }
+         MAPSET(&missc, boff);
+       }
+    }
+  queue_free(&q);
+  map_free(&missc);
+  if (solvidq)
+    map_free(&m);
+  if (!selection->count)
+    return 0;
+
+  /* convert package list to selection */
+  j = selection->count;
+  queue_insertn(selection, 0, selection->count, 0);
+  for (i = 0; i < selection->count; )
+    {
+      selection->elements[i++] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
+      selection->elements[i++] = selection->elements[j++];
+    }
+  if ((flags & SELECTION_FLAT) != 0)
+    selection_flatten(pool, selection);
+  return SELECTION_PROVIDES;
+}
+
 static int
 selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char *name, Id dep, int flags, int keyname, int marker, struct limiter *limiter)
 {
@@ -1449,6 +1580,9 @@ selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char
   if (name && dep)
     return 0;
 
+  if ((flags & SELECTION_MATCH_SOLVABLE) != 0)
+    return selection_make_matchsolvable_common_limited(pool, selection, (Queue *)name, dep, flags, keyname, marker, limiter);
+
   if ((flags & SELECTION_MATCH_DEPSTR) != 0)
     flags &= ~SELECTION_REL;
 
@@ -1558,7 +1692,8 @@ selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char
          queue_push(selection, p);
          continue;
        }
-      queue_empty(&q);
+      if (q.count)
+        queue_empty(&q);
       repo_lookup_deparray(s->repo, p, keyname, &q, marker);
       if (!q.count)
        continue;
@@ -1708,6 +1843,18 @@ selection_make_matchdepid(Pool *pool, Queue *selection, Id dep, int flags, int k
   return selection_make_matchdeps_common(pool, selection, 0, dep, flags, keyname, marker);
 }
 
+int
+selection_make_matchsolvable(Pool *pool, Queue *selection, Id solvid, int flags, int keyname, int marker)
+{
+  return selection_make_matchdeps_common(pool, selection, 0, solvid, flags | SELECTION_MATCH_SOLVABLE, keyname, marker);
+}
+
+int
+selection_make_matchsolvablelist(Pool *pool, Queue *selection, Queue *solvidq, int flags, int keyname, int marker)
+{
+  return selection_make_matchdeps_common(pool, selection, (const char *)solvidq, 0, flags | SELECTION_MATCH_SOLVABLE, keyname, marker);
+}
+
 static inline int
 pool_is_kind(Pool *pool, Id name, Id kind)
 {
index 9938c2f925ed515385c79f2da2fc657ae2d4ffe1..f3ed2c20f7c536d0092429fed21a397319fc3536 100644 (file)
@@ -52,16 +52,20 @@ extern "C" {
 #define SELECTION_SUBTRACT             (2 << 28)
 #define SELECTION_FILTER               (3 << 28)
 
-#define SELECTION_MODEBITS             (3 << 28)       /* internal */
 
 /* extra SELECTION_FILTER bits */
 #define SELECTION_FILTER_KEEP_IFEMPTY  (1 << 30)
 #define SELECTION_FILTER_SWAPPED       (1 << 31)
 
+/* internal */
+#define SELECTION_MATCH_SOLVABLE       (1 << 27)
+#define SELECTION_MODEBITS             (3 << 28)
 
 extern int  selection_make(Pool *pool, Queue *selection, const char *name, int flags);
 extern int  selection_make_matchdeps(Pool *pool, Queue *selection, const char *name, int flags, int keyname, int marker);
 extern int  selection_make_matchdepid(Pool *pool, Queue *selection, Id dep, int flags, int keyname, int marker);
+extern int selection_make_matchsolvable(Pool *pool, Queue *selection, Id solvid, int flags, int keyname, int marker);
+extern int selection_make_matchsolvablelist(Pool *pool, Queue *selection, Queue *solvidq, int flags, int keyname, int marker);
 
 extern void selection_filter(Pool *pool, Queue *sel1, Queue *sel2);
 extern void selection_add(Pool *pool, Queue *sel1, Queue *sel2);