add pool_whatmatchesdep and selection_make_deps to query for packages intersecting...
authorMichael Schroeder <mls@suse.de>
Wed, 4 Sep 2013 16:54:57 +0000 (18:54 +0200)
committerMichael Schroeder <mls@suse.de>
Wed, 4 Sep 2013 16:54:57 +0000 (18:54 +0200)
examples/solv.c
src/libsolv.ver
src/pool.c
src/pool.h
src/selection.c
src/selection.h
src/solvable.c
src/solvable.h

index 7d6de97..d4a6b6c 100644 (file)
@@ -2598,6 +2598,7 @@ main(int argc, char **argv)
   int cleandeps = 0;
   int forcebest = 0;
   char *rootdir = 0;
+  char *keyname = 0;
 
   argc--;
   argv++;
@@ -2669,7 +2670,6 @@ main(int argc, char **argv)
          argc -= 2;
          argv += 2;
        }
-
       else if (argc > 1 && !strcmp(argv[1], "--clean"))
        {
          cleandeps = 1;
@@ -2682,6 +2682,12 @@ main(int argc, char **argv)
          argc--;
          argv++;
        }
+      if (argc > 2 && !strcmp(argv[1], "--keyname"))
+       {
+         keyname = argv[2];
+         argc -= 2;
+         argv += 2;
+       }
       else
        break;
     }
@@ -2851,6 +2857,8 @@ main(int argc, char **argv)
 #endif
   pool_createwhatprovides(pool);
 
+  if (keyname)
+    keyname = solv_dupjoin("solvable:", keyname, 0);
   queue_init(&job);
   for (i = 1; i < argc; i++)
     {
@@ -2869,13 +2877,19 @@ main(int argc, char **argv)
        flags |= SELECTION_WITH_SOURCE;
       if (argv[i][0] == '/')
        flags |= SELECTION_FILELIST | (mode == MODE_ERASE ? SELECTION_INSTALLED_ONLY : 0);
-      rflags = selection_make(pool, &job2, argv[i], flags);
+      if (!keyname)
+        rflags = selection_make(pool, &job2, argv[i], flags);
+      else
+        rflags = selection_make_deps(pool, &job2, argv[i], flags, pool_str2id(pool, keyname, 1));
       if (repofilter.count)
        selection_filter(pool, &job2, &repofilter);
       if (!job2.count)
        {
          flags |= SELECTION_NOCASE;
-          rflags = selection_make(pool, &job2, argv[i], flags);
+         if (!keyname)
+            rflags = selection_make(pool, &job2, argv[i], flags);
+         else
+           rflags = selection_make_deps(pool, &job2, argv[i], flags, pool_str2id(pool, keyname, 1));
          if (repofilter.count)
            selection_filter(pool, &job2, &repofilter);
          if (job2.count)
@@ -2894,6 +2908,7 @@ main(int argc, char **argv)
        queue_push(&job, job2.elements[j]);
       queue_free(&job2);
     }
+  keyname = solv_free(keyname);
 
   if (!job.count && (mainmode == MODE_UPDATE || mainmode == MODE_DISTUPGRADE || mainmode == MODE_VERIFY || repofilter.count))
     {
index 0fd6993..86ca660 100644 (file)
@@ -116,6 +116,7 @@ SOLV_1.0 {
                pool_trivial_installable;
                pool_trivial_installable_multiversionmap;
                pool_vendor2mask;
+               pool_whatmatchesdep;
                queue_alloc_one;
                queue_alloc_one_head;
                queue_delete;
@@ -239,6 +240,7 @@ SOLV_1.0 {
                selection_add;
                selection_filter;
                selection_make;
+               selection_make_deps;
                selection_solvables;
                solv_bin2hex;
                solv_calloc;
index d5a86ec..437e53d 100644 (file)
@@ -1065,6 +1065,25 @@ pool_flush_namespaceproviders(Pool *pool, Id ns, Id evr)
     }
 }
 
+/* intersect dependencies in keyname with dep, return list of matching packages */
+void
+pool_whatmatchesdep(Pool *pool, Id keyname, Id dep, Queue *q)
+{
+  Id p;
+
+  queue_empty(q);
+  FOR_POOL_SOLVABLES(p)
+    {
+      Solvable *s = pool->solvables + p;
+      if (s->repo->disabled)
+       continue;
+      if (s->repo != pool->installed && !pool_installable(pool, s))
+       continue;
+      if (solvable_matchesdep(s, keyname, dep))
+       queue_push(q, p);
+    }
+}
+
 /*************************************************************************/
 
 void
index 5527bfa..c0fdc3a 100644 (file)
@@ -329,6 +329,8 @@ static inline Id *pool_whatprovides_ptr(Pool *pool, Id d)
   return pool->whatprovidesdata + off;
 }
 
+void pool_whatmatchesdep(Pool *pool, Id keyname, Id dep, Queue *q);
+
 /* search the pool. the following filters are available:
  *   p     - search just this solvable
  *   key   - search only this key
index b4dcadf..2e6e82d 100644 (file)
@@ -573,6 +573,39 @@ selection_filelist(Pool *pool, Queue *selection, const char *name, int flags)
   return SELECTION_FILELIST;
 }
 
+static char *
+splitrel(char *rname, char *r, int *rflagsp)
+{
+  int nend = r - rname;
+  int rflags = 0;
+  if (nend && *r == '=' && r[-1] == '!') 
+    {
+      nend--;
+      r++;
+      rflags = REL_LT|REL_GT;
+    }
+  for (; *r; r++) 
+    {
+      if (*r == '<') 
+       rflags |= REL_LT;
+      else if (*r == '=') 
+       rflags |= REL_EQ;
+      else if (*r == '>') 
+       rflags |= REL_GT;
+      else
+       break;
+    }
+  while (*r && (*r == ' ' || *r == '\t'))
+    r++;
+  while (nend && (rname[nend - 1] == ' ' || rname[nend - 1] == '\t'))
+    nend--;
+  if (!*rname || !*r) 
+    return 0;
+  *rflagsp = rflags;
+  rname[nend] = 0; 
+  return r;
+}
+
 static int
 selection_rel(Pool *pool, Queue *selection, const char *name, int flags)
 {
@@ -586,34 +619,11 @@ selection_rel(Pool *pool, Queue *selection, const char *name, int flags)
   rname = solv_strdup(name);
   if ((r = strpbrk(rname, "<=>")) != 0)
     {
-      int nend = r - rname;
-      if (nend && *r == '=' && r[-1] == '!')
+      if ((r = splitrel(rname, r, &rflags)) == 0)
        {
-         nend--;
-         r++;
-         rflags = REL_LT|REL_GT;
-       }
-      for (; *r; r++)
-        {
-          if (*r == '<')
-            rflags |= REL_LT;
-          else if (*r == '=')
-            rflags |= REL_EQ;
-          else if (*r == '>')
-            rflags |= REL_GT;
-          else
-            break;
-        }
-      while (*r && (*r == ' ' || *r == '\t'))
-        r++;
-      while (nend && (rname[nend - 1] == ' ' || rname[nend -1 ] == '\t'))
-        nend--;
-      if (!*rname || !*r)
-        {
          solv_free(rname);
          return 0;
-        }
-      rname[nend] = 0;
+       }
     }
   if ((ret = selection_depglob_arch(pool, selection, rname, flags)) != 0)
     {
@@ -839,6 +849,104 @@ selection_make(Pool *pool, Queue *selection, const char *name, int flags)
   return ret;
 }
 
+static int
+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)
+       {
+         if (matchdep(pool, rd->name, rname, rflags, revr, flags))
+           return 1;
+         if (matchdep(pool, rd->evr, rname, rflags, revr, flags))
+           return 1;
+         return 0;
+       }
+      if (rd->flags == REL_ARCH)
+       return matchdep(pool, rd->name, rname, rflags, revr, flags);
+      if (!matchdep(pool, rd->name, rname, rflags, revr, flags))
+       return 0;
+      if (rflags)
+       {
+         /* XXX: need pool_match_flags_evr here */
+         if (!pool_match_dep(pool, pool_rel2id(pool, rd->name, pool_str2id(pool, revr, 1), rflags, 1), id))
+           return 0;
+       }
+      return 1;
+    }
+  if (flags & SELECTION_GLOB)
+    {
+      int globflags = (flags & SELECTION_NOCASE) != 0 ? FNM_CASEFOLD : 0;
+      return fnmatch(rname, pool_id2str(pool, id), globflags) == 0 ? 1 : 0;
+    }
+  if (flags & SELECTION_NOCASE)
+    return strcasecmp(rname, pool_id2str(pool, id)) == 0 ? 1 : 0;
+  return strcmp(rname, pool_id2str(pool, id)) == 0 ? 1 : 0;
+}
+
+/*
+ *  select against the dependencies in keyname
+ *  like SELECTION_REL and SELECTION_PROVIDES, but with the
+ *  deps in keyname instead of provides.
+ */
+int
+selection_make_deps(Pool *pool, Queue *selection, const char *name, int flags, int keyname)
+{
+  char *rname, *r;
+  int rflags = 0;
+  Id p;
+  Queue q;
+
+  queue_empty(selection);
+  rname = solv_strdup(name);
+  if ((r = strpbrk(rname, "<=>")) != 0)
+    {
+      if ((r = splitrel(rname, r, &rflags)) == 0)
+       {
+         solv_free(rname);
+         return 0;
+       }
+    }
+  if ((flags & SELECTION_GLOB) != 0 && !strpbrk(name, "[*?") != 0)
+    flags &= ~SELECTION_GLOB;
+
+  queue_init(&q);
+  FOR_POOL_SOLVABLES(p)
+    {
+      Solvable *s =  pool->solvables + p;
+      int i;
+
+      if (s->repo != pool->installed && !pool_installable(pool, s))
+       {
+         if (!(flags & SELECTION_SOURCE_ONLY) || (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC))
+           continue;
+         if (pool_disabled_solvable(pool, s))
+           continue;
+       }
+      if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
+       continue;
+      if ((s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) && !(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE))
+       continue;
+      queue_empty(&q);
+      repo_lookup_idarray(s->repo, p, keyname, &q);
+      for (i = 0; i < q.count; i++)
+       {
+         Id id = q.elements[i];
+         if (matchdep(pool, id, rname, rflags, r, flags))
+           break;
+       }
+      if (i < q.count)
+       queue_push2(selection, SOLVER_SOLVABLE | SOLVER_NOAUTOSET, p);
+    }
+  queue_free(&q);
+  if (!selection->count)
+    return 0;
+  if ((flags & SELECTION_FLAT) != 0)
+    selection_flatten(pool, selection);
+  return SELECTION_PROVIDES;
+}
+
 void
 selection_filter(Pool *pool, Queue *sel1, Queue *sel2)
 {
index 705768b..e1da169 100644 (file)
@@ -34,6 +34,8 @@ extern "C" {
 #define SELECTION_WITH_SOURCE          (1 << 13)
 
 extern int  selection_make(Pool *pool, Queue *selection, const char *name, int flags);
+extern int  selection_make_deps(Pool *pool, Queue *selection, const char *name, int flags, int keyname);
+
 extern void selection_filter(Pool *pool, Queue *sel1, Queue *sel2);
 extern void selection_add(Pool *pool, Queue *sel1, Queue *sel2);
 extern void selection_solvables(Pool *pool, Queue *selection, Queue *pkgs);
index 1633b73..b822784 100644 (file)
@@ -856,3 +856,20 @@ solvable_unset(Solvable *s, Id keyname)
 {
   repo_unset(s->repo, s - s->repo->pool->solvables, keyname);
 }
+
+/* return true if a dependency intersects dep in the keyname array */
+int
+solvable_matchesdep(Solvable *s, Id keyname, Id dep)
+{
+  int i;
+  Pool *pool = s->repo->pool;
+  Queue q;
+  queue_init(&q);
+  solvable_lookup_idarray(s, keyname, &q);
+  for (i = 0; i < q.count; i++)
+    if (pool_match_dep(pool, q.elements[i], dep))
+      break;
+  i = i == q.count ? 0 : 1;
+  queue_free(&q);
+  return i;
+}
index ad06533..356e7d6 100644 (file)
@@ -78,6 +78,7 @@ void solvable_unset(Solvable *s, Id keyname);
 
 int solvable_identical(Solvable *s1, Solvable *s2);
 Id solvable_selfprovidedep(Solvable *s); 
+int solvable_matchesdep(Solvable *s, Id keyname, Id dep);
 
 #ifdef __cplusplus
 }