Imported Upstream version 0.6.15
[platform/upstream/libsolv.git] / src / linkedpkg.c
index c5adc9a..6387373 100644 (file)
@@ -21,7 +21,7 @@
  *
  * product:
  *   created from product data in the repository (which is generated from files
- *   in /etc/products.d. In the future we may switch to using product()
+ *   in /etc/products.d). In the future we may switch to using product()
  *   provides of packages.
  *
  * pattern:
@@ -37,6 +37,7 @@
 
 #include "pool.h"
 #include "repo.h"
+#include "evr.h"
 #include "linkedpkg.h"
 
 #ifdef ENABLE_LINKED_PKGS
@@ -47,12 +48,11 @@ find_application_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp
   Id req = 0;
   Id prv = 0;
   Id p, pp;
-  Id pkgname = 0;
+  Id pkgname = 0, appdataid = 0;
 
   /* find appdata requires */
   if (s->requires)
     {
-      Id appdataid = 0;
       Id *reqp = s->repo->idarraydata + s->requires;
       while ((req = *reqp++) != 0)            /* go through all requires */
        {
@@ -63,22 +63,34 @@ find_application_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp
          else
            pkgname = req;
        }
-      req = appdataid;
     }
+  req = appdataid ? appdataid : pkgname;
   if (!req)
     return;
   /* find application-appdata provides */
   if (s->provides)
     {
       Id *prvp = s->repo->idarraydata + s->provides;
+      const char *reqs = pool_id2str(pool, req);
+      const char *prvs;
       while ((prv = *prvp++) != 0)            /* go through all provides */
        {
          if (ISRELDEP(prv))
            continue;
-         if (strncmp("application-appdata(", pool_id2str(pool, prv), 20))
+         prvs = pool_id2str(pool, prv);
+         if (strncmp("application-appdata(", prvs, 20))
            continue;
-         if (!strcmp(pool_id2str(pool, prv) + 12, pool_id2str(pool, req)))
-           break;
+         if (appdataid)
+           {
+             if (!strcmp(prvs + 12, reqs))
+               break;
+           }
+         else
+           {
+             int reqsl = strlen(reqs);
+             if (!strncmp(prvs + 20, reqs, reqsl) && !strcmp(prvs + 20 + reqsl, ")"))
+               break;
+           }
        }
     }
   if (!prv)
@@ -88,7 +100,7 @@ find_application_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp
     if (pool->solvables[p].repo == s->repo)
       if (!pkgname || pool->solvables[p].name == pkgname)
         queue_push(qr, p);
-  if (!qr->count && pkgname)
+  if (!qr->count && pkgname && appdataid)
     {
       /* huh, no matching package? try without pkgname filter */
       FOR_PROVIDES(p, pp, req)
@@ -112,6 +124,7 @@ find_product_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Qu
 {
   Id p, pp, namerelid;
   char *str;
+  unsigned int sbt = 0;
 
   /* search for project requires */
   namerelid = 0;
@@ -149,6 +162,29 @@ find_product_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Qu
        continue;
       queue_push(qr, p);
     }
+  if (qr->count > 1)
+    {
+      /* multiple providers. try buildtime filter */
+      sbt = solvable_lookup_num(s, SOLVABLE_BUILDTIME, 0);
+      if (sbt)
+       {
+         unsigned int bt;
+         int i, j;
+         int filterqp = 1;
+         for (i = j = 0; i < qr->count; i++)
+           {
+             bt = solvable_lookup_num(pool->solvables + qr->elements[i], SOLVABLE_BUILDTIME, 0);
+             if (!bt)
+               filterqp = 0;   /* can't filter */
+             if (!bt || bt == sbt)
+               qr->elements[j++] = qr->elements[i];
+           }
+         if (j)
+           qr->count = j;
+         if (!j || !filterqp)
+           sbt = 0;    /* filter failed */
+       }
+    }
   if (!qr->count && s->repo == pool->installed)
     {
       /* oh no! Look up reference file */
@@ -174,6 +210,8 @@ find_product_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Qu
          Solvable *ps = pool->solvables + p;
          if (s->name != ps->name || ps->repo != s->repo || ps->arch != s->arch || s->evr != ps->evr)
            continue;
+         if (sbt && solvable_lookup_num(ps, SOLVABLE_BUILDTIME, 0) != sbt)
+           continue;
          queue_push(qp, p);
        }
     }
@@ -272,4 +310,72 @@ find_package_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Qu
     find_product_link(pool, s, reqidp, qr, prvidp, qp);
 }
 
+static int
+name_min_max(Pool *pool, Solvable *s, Id *namep, Id *minp, Id *maxp)
+{
+  Queue q;
+  Id qbuf[4];
+  Id name, min, max;
+  int i;
+
+  queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
+  find_package_link(pool, s, 0, &q, 0, 0);
+  if (!q.count)
+    {
+      queue_free(&q);
+      return 0;
+    }
+  s = pool->solvables + q.elements[0];
+  name = s->name;
+  min = max = s->evr;
+  for (i = 1; i < q.count; i++)
+    {
+      s = pool->solvables + q.elements[i];
+      if (s->name != name)
+       {
+          queue_free(&q);
+         return 0;
+       }
+      if (s->evr == min || s->evr == max)
+       continue;
+      if (pool_evrcmp(pool, min, s->evr, EVRCMP_COMPARE) >= 0)
+       min = s->evr;
+      else if (min == max || pool_evrcmp(pool, max, s->evr, EVRCMP_COMPARE) <= 0)
+       max = s->evr;
+    }
+  queue_free(&q);
+  *namep = name;
+  *minp = min;
+  *maxp = max;
+  return 1;
+}
+
+int
+pool_link_evrcmp(Pool *pool, Solvable *s1, Solvable *s2)
+{
+  Id name1, evrmin1, evrmax1;
+  Id name2, evrmin2, evrmax2;
+
+  if (s1->name != s2->name)
+    return 0;  /* can't compare */
+  if (!name_min_max(pool, s1, &name1, &evrmin1, &evrmax1))
+    return 0;
+  if (!name_min_max(pool, s2, &name2, &evrmin2, &evrmax2))
+    return 0;
+  /* compare linked names */
+  if (name1 != name2)
+    return 0;
+  if (evrmin1 == evrmin2 && evrmax1 == evrmax2)
+    return 0;
+  /* now compare evr intervals */
+  if (evrmin1 == evrmax1 && evrmin2 == evrmax2)
+    return pool_evrcmp(pool, evrmin1, evrmax2, EVRCMP_COMPARE);
+  if (evrmin1 != evrmax2 && pool_evrcmp(pool, evrmin1, evrmax2, EVRCMP_COMPARE) > 0)
+    return 1;
+  if (evrmax1 != evrmin2 && pool_evrcmp(pool, evrmax1, evrmin2, EVRCMP_COMPARE) < 0)
+    return -1;
+  return 0;
+}
+
+
 #endif