make pattern translations also look at the linked packages
authorMichael Schroeder <mls@suse.de>
Wed, 16 Oct 2013 10:06:07 +0000 (12:06 +0200)
committerMichael Schroeder <mls@suse.de>
Wed, 16 Oct 2013 10:06:07 +0000 (12:06 +0200)
src/linkedpkg.c [new file with mode: 0644]
src/linkedpkg.h [new file with mode: 0644]
src/solvable.c

diff --git a/src/linkedpkg.c b/src/linkedpkg.c
new file mode 100644 (file)
index 0000000..6df497c
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2013, SUSE Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+/*
+ * linkedpkg.c
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+
+#include "pool.h"
+#include "repo.h"
+#include "linkedpkg.h"
+
+#ifdef ENABLE_LINKED_PKGS
+
+void
+find_application_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp)
+{
+  Id req = 0;
+  Id prv = 0;
+  Id p, pp;
+
+  /* find appdata requires */
+  if (s->requires)
+    {
+      Id *reqp = s->repo->idarraydata + s->requires;
+      while ((req = *reqp++) != 0)            /* go through all requires */
+       {
+         if (ISRELDEP(req))
+           continue;
+         if (!strncmp("appdata(", pool_id2str(pool, req), 8))
+           break;
+       }
+    }
+  if (!req)
+    return;
+  /* find application-appdata provides */
+  if (s->provides)
+    {
+      Id *prvp = s->repo->idarraydata + s->provides;
+      while ((prv = *prvp++) != 0)            /* go through all provides */
+       {
+         if (ISRELDEP(prv))
+           continue;
+         if (strncmp("application-appdata(", pool_id2str(pool, prv), 20))
+           continue;
+         if (!strcmp(pool_id2str(pool, prv) + 12, pool_id2str(pool, req)))
+           break;
+       }
+    }
+  if (!prv)
+    return;
+  /* now link em */
+  FOR_PROVIDES(p, pp, req)
+    if (pool->solvables[p].repo == s->repo)
+      queue_push(qr, p);
+  if (reqidp)
+    *reqidp = req;
+  if (qp)
+    {
+      FOR_PROVIDES(p, pp, prv)
+       if (pool->solvables[p].repo == s->repo)
+         queue_push(qp, pp);
+      if (prvidp)
+       *prvidp = req;
+    }
+}
+
+void
+find_product_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp)
+{
+  Id n = s - pool->solvables;
+  Id p, pp, namerelid;
+  char *str;
+
+  if (pool->nscallback)
+    {
+      Id buddy = pool->nscallback(pool, pool->nscallbackdata, NAMESPACE_PRODUCTBUDDY, n);
+      if (buddy > 0 && buddy != SYSTEMSOLVABLE && buddy != n && buddy < pool->nsolvables)
+       {
+         if (reqidp)
+           *reqidp = solvable_selfprovidedep(pool->solvables + buddy);
+         queue_push(qr, buddy);
+         if (prvidp)
+           *prvidp = solvable_selfprovidedep(s);
+         if (qp)
+           queue_push(qp, n);
+         return;
+       }
+    }
+  /* search for project requires */
+  namerelid = 0;
+  if (s->requires)
+    {
+      Id req, *reqp = s->repo->idarraydata + s->requires;
+      const char *nn = pool_id2str(pool, s->name);
+      int nnl = strlen(nn);
+      while ((req = *reqp++) != 0)            /* go through all requires */
+       if (ISRELDEP(req))
+         {
+           const char *rn;
+           Reldep *rd = GETRELDEP(pool, req);
+           if (rd->flags != REL_EQ || rd->evr != s->evr)
+             continue;
+           rn = pool_id2str(pool, rd->name);
+           if (!strncmp(rn, "product(", 8) && !strncmp(rn + 8, nn + 8, nnl - 8) && !strcmp( rn + nnl, ")"))
+             {
+               namerelid = req;
+               break;
+             }
+         }
+    }
+  if (!namerelid)
+    {
+      /* too bad. construct from scratch */
+      str = pool_tmpjoin(pool, pool_id2str(pool, s->name), ")", 0);
+      str[7] = '(';
+      namerelid = pool_rel2id(pool, pool_str2id(pool, str, 1), s->evr, REL_EQ, 1);
+    }
+  FOR_PROVIDES(p, pp, namerelid)
+    {
+      Solvable *ps = pool->solvables + p;
+      if (ps->repo != s->repo || ps->arch != s->arch)
+       continue;
+      queue_push(qr, p);
+    }
+  if (!qr->count && s->repo == pool->installed)
+    {
+      /* oh no! Look up reference file */
+      Dataiterator di;
+      const char *refbasename = solvable_lookup_str(s, PRODUCT_REFERENCEFILE);
+      dataiterator_init(&di, pool, s->repo, 0, SOLVABLE_FILELIST, refbasename, SEARCH_STRING);
+      while (dataiterator_step(&di))
+       queue_push(qr, di.solvid);
+      dataiterator_free(&di);
+      if (qp)
+       {
+         dataiterator_init(&di, pool, s->repo, 0, PRODUCT_REFERENCEFILE, refbasename, SEARCH_STRING);
+         while (dataiterator_step(&di))
+           queue_push(qp, di.solvid);
+         dataiterator_free(&di);
+       }
+    }
+  else
+    {
+      /* find qp */
+      FOR_PROVIDES(p, pp, s->name)
+       {
+         Solvable *ps = pool->solvables + p;
+         if (s->name != ps->name || ps->repo != s->repo || ps->arch != s->arch || s->evr != ps->evr)
+           continue;
+         queue_push(qp, p);
+       }
+    }
+  if (reqidp)
+    *reqidp = namerelid;
+  if (prvidp)
+    *prvidp = solvable_selfprovidedep(s);
+}
+
+void
+find_pattern_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp)
+{
+  Id p, pp, *pr, apevr = 0, aprel = 0;
+
+  /* check if autopattern */
+  if (!s->provides)
+    return;
+  for (pr = s->repo->idarraydata + s->provides; (p = *pr++) != 0; )
+    if (ISRELDEP(p))
+      {
+       Reldep *rd = GETRELDEP(pool, p);
+       if (rd->flags == REL_EQ && !strcmp(pool_id2str(pool, rd->name), "autopattern()"))
+         {
+           aprel = p;
+           apevr = rd->evr;
+           break;
+         }
+      }
+  if (!apevr)
+    return;
+  FOR_PROVIDES(p, pp, apevr)
+    {
+      Solvable *s2 = pool->solvables + p;
+      if (s2->repo == s->repo && s2->name == apevr && s2->evr == s->evr && s2->vendor == s->vendor)
+        queue_push(qr, p);
+    }
+  if (qp)
+    {
+      FOR_PROVIDES(p, pp, aprel)
+       {
+         Solvable *s2 = pool->solvables + p;
+         if (s2->repo == s->repo && s2->evr == s->evr && s2->vendor == s->vendor)
+           queue_push(qp, pp);
+       }
+    }
+  if (reqidp)
+    *reqidp = apevr;
+  if (prvidp)
+    *prvidp = aprel;
+}
+
+Id
+find_autopattern_name(Pool *pool, Solvable *s)
+{
+  Id prv, *prvp;
+  if (!s->provides)
+    return 0;
+  for (prvp = s->repo->idarraydata + s->provides; (prv = *prvp++) != 0; )
+    if (ISRELDEP(prv))
+      {   
+        Reldep *rd = GETRELDEP(pool, prv);
+        if (rd->flags == REL_EQ && !strcmp(pool_id2str(pool, rd->name), "autopattern()"))
+          return strncmp(pool_id2str(pool, rd->evr), "pattern:", 8) != 0 ? rd->evr : 0;
+      }   
+  return 0;
+}
+
+void
+find_package_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp)
+{
+  const char *name = pool_id2str(pool, s->name);
+  if (name[0] == 'a' && !strncmp("application:", name, 12))
+    find_application_link(pool, s, reqidp, qr, prvidp, qp);
+  else if (name[0] == 'p' && !strncmp("pattern:", name, 7))
+    find_pattern_link(pool, s, reqidp, qr, prvidp, qp);
+  else if (name[0] == 'p' && !strncmp("product:", name, 8))
+    find_product_link(pool, s, reqidp, qr, prvidp, qp);
+}
+
+#endif
diff --git a/src/linkedpkg.h b/src/linkedpkg.h
new file mode 100644 (file)
index 0000000..3114702
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Novell Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+/*
+ * linkedpkg.h (internal)
+ */
+
+#ifndef LIBSOLV_LINKEDPKG_H
+#define LIBSOLV_LINKEDPKG_H
+
+static inline int
+has_package_link(Pool *pool, Solvable *s)
+{
+  const char *name = pool_id2str(pool, s->name);
+  if (name[0] == 'a' && !strncmp("application:", name, 12))
+    return 1;
+  if (name[0] == 'p' && !strncmp("pattern:", name, 7))
+    return 1;
+  if (name[0] == 'p' && !strncmp("product:", name, 8))
+    return 1;
+  return 0;
+}
+
+extern void find_application_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp);
+extern void find_product_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp);
+extern void find_pattern_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp);
+
+extern Id find_autopattern_name(Pool *pool, Solvable *s);
+
+/* generic */
+extern void find_package_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp);
+
+#endif
index bfe25ce..c07f4c8 100644 (file)
@@ -23,6 +23,7 @@
 #include "policy.h"
 #include "poolvendor.h"
 #include "chksum.h"
+#include "linkedpkg.h"
 
 const char *
 pool_solvable2str(Pool *pool, Solvable *s)
@@ -134,7 +135,7 @@ solvable_lookup_str_base(Solvable *s, Id keyname, Id basekeyname, int usebase)
 {
   Pool *pool;
   const char *str, *basestr;
-  Id p, pp;
+  Id p, pp, name;
   Solvable *s2;
   int pass;
 
@@ -151,13 +152,14 @@ solvable_lookup_str_base(Solvable *s, Id keyname, Id basekeyname, int usebase)
    * translation */
   if (!pool->whatprovides)
     return usebase ? basestr : 0;
+  name = s->name;
   /* we do this in two passes, first same vendor, then all other vendors */
   for (pass = 0; pass < 2; pass++)
     {
-      FOR_PROVIDES(p, pp, s->name)
+      FOR_PROVIDES(p, pp, name)
        {
          s2 = pool->solvables + p;
-         if (s2->name != s->name)
+         if (s2->name != name)
            continue;
          if ((s->vendor == s2->vendor) != (pass == 0))
            continue;
@@ -168,6 +170,11 @@ solvable_lookup_str_base(Solvable *s, Id keyname, Id basekeyname, int usebase)
          if (str)
            return str;
        }
+#ifdef ENABLE_LINKED_PKGS
+      /* autopattern translation magic */
+      if (pass && !strncmp("pattern:", pool_id2str(pool, name), 8) && (name = find_autopattern_name(pool, s)) != 0)
+       pass = -1;
+#endif
     }
   return usebase ? basestr : 0;
 }