Imported Upstream version 0.7.5
[platform/upstream/libsolv.git] / src / solvable.c
index 5afb481..d3d2d31 100644 (file)
@@ -32,9 +32,9 @@ pool_solvable2str(Pool *pool, Solvable *s)
   int nl, el, al;
   char *p;
   n = pool_id2str(pool, s->name);
-  e = pool_id2str(pool, s->evr);
+  e = s->evr ? pool_id2str(pool, s->evr) : "";
   /* XXX: may want to skip the epoch here */
-  a = pool_id2str(pool, s->arch);
+  a = s->arch ? pool_id2str(pool, s->arch) : "";
   nl = strlen(n);
   el = strlen(e);
   al = strlen(a);
@@ -58,6 +58,16 @@ pool_solvable2str(Pool *pool, Solvable *s)
       p[nl + el] = pool->disttype == DISTTYPE_HAIKU ? '-' : '.';
       strcpy(p + nl + el + 1, a);
     }
+  if (pool->disttype == DISTTYPE_CONDA && solvable_lookup_type(s, SOLVABLE_BUILDFLAVOR))
+    {
+      Queue flavorq;
+      int i;
+      queue_init(&flavorq);
+      solvable_lookup_idarray(s, SOLVABLE_BUILDFLAVOR, &flavorq);
+      for (i = 0; i < flavorq.count; i++)
+       p = pool_tmpappend(pool, p, "-", pool_id2str(pool, flavorq.elements[i]));
+      queue_free(&flavorq);
+    }
   return p;
 }
 
@@ -110,10 +120,15 @@ solvable_lookup_str_joinarray(Solvable *s, Id keyname, const char *joinstr)
   if (solvable_lookup_idarray(s, keyname, &q) && q.count)
     {
       Pool *pool = s->repo->pool;
-      int i;
-      str = pool_tmpjoin(pool, pool_id2str(pool, q.elements[0]), 0, 0);
-      for (i = 1; i < q.count; i++)
-       str = pool_tmpappend(pool, str, joinstr, pool_id2str(pool, q.elements[i]));
+      if (q.count == 1)
+       str = (char *)pool_id2str(pool, q.elements[0]);
+      else
+       {
+         int i;
+         str = pool_tmpjoin(pool, pool_id2str(pool, q.elements[0]), 0, 0);
+         for (i = 1; i < q.count; i++)
+           str = pool_tmpappend(pool, str, joinstr, pool_id2str(pool, q.elements[i]));
+       }
     }
   queue_free(&q);
   return str;
@@ -126,7 +141,7 @@ solvable_lookup_str(Solvable *s, Id keyname)
   if (!s->repo)
     return 0;
   str = repo_lookup_str(s->repo, s - s->repo->pool->solvables, keyname);
-  if (!str && (keyname == SOLVABLE_LICENSE || keyname == SOLVABLE_GROUP))
+  if (!str && (keyname == SOLVABLE_LICENSE || keyname == SOLVABLE_GROUP || keyname == SOLVABLE_BUILDFLAVOR))
     str = solvable_lookup_str_joinarray(s, keyname, ", ");
   return str;
 }
@@ -172,9 +187,18 @@ solvable_lookup_str_base(Solvable *s, Id keyname, Id basekeyname, int usebase)
            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;
+      /* autopattern/product translation magic */
+      if (pass)
+       {
+         const char *n = pool_id2str(pool, name);
+         if (*n == 'p')
+           {
+             if (!strncmp("pattern:", n, 8) && (name = find_autopattern_name(pool, s)) != 0)
+               pass = -1;
+             if (!strncmp("product:", n, 8) && (name = find_autoproduct_name(pool, s)) != 0)
+               pass = -1;
+           }
+       }
 #endif
     }
   return usebase ? basestr : 0;
@@ -229,14 +253,14 @@ solvable_lookup_str_poollang(Solvable *s, Id keyname)
 const char *
 solvable_lookup_str_lang(Solvable *s, Id keyname, const char *lang, int usebase)
 {
-  if (s->repo)
-    {
-      Id id = pool_id2langid(s->repo->pool, keyname, lang, 0);
-      if (id)
-        return solvable_lookup_str_base(s, id, keyname, usebase);
-      if (!usebase)
-       return 0;
-    }
+  Id id;
+  if (!s->repo)
+    return 0;
+  id = pool_id2langid(s->repo->pool, keyname, lang, 0);
+  if (id)
+    return solvable_lookup_str_base(s, id, keyname, usebase);
+  if (!usebase)
+    return 0;
   return solvable_lookup_str(s, keyname);
 }
 
@@ -248,14 +272,14 @@ solvable_lookup_num(Solvable *s, Id keyname, unsigned long long notfound)
   return repo_lookup_num(s->repo, s - s->repo->pool->solvables, keyname, notfound);
 }
 
-unsigned int
-solvable_lookup_sizek(Solvable *s, Id keyname, unsigned int notfound)
+unsigned long long
+solvable_lookup_sizek(Solvable *s, Id keyname, unsigned long long notfound)
 {
   unsigned long long size;
   if (!s->repo)
     return notfound;
-  size = solvable_lookup_num(s, keyname, (unsigned long long)notfound << 10);
-  return (unsigned int)((size + 1023) >> 10);
+  size = solvable_lookup_num(s, keyname, (unsigned long long)-1);
+  return size == (unsigned long long)-1 ? notfound : ((size + 1023) >> 10);
 }
 
 int
@@ -269,25 +293,27 @@ solvable_lookup_void(Solvable *s, Id keyname)
 int
 solvable_lookup_bool(Solvable *s, Id keyname)
 {
+  Id type;
   if (!s->repo)
     return 0;
   /* historic nonsense: there are two ways of storing a bool, as num == 1 or void. test both. */
-  if (repo_lookup_type(s->repo, s - s->repo->pool->solvables, keyname) == REPOKEY_TYPE_VOID)
+  type = repo_lookup_type(s->repo, s - s->repo->pool->solvables, keyname);
+  if (type == REPOKEY_TYPE_VOID)
     return 1;
-  return repo_lookup_num(s->repo, s - s->repo->pool->solvables, keyname, 0) == 1;
+  if (type == REPOKEY_TYPE_NUM || type == REPOKEY_TYPE_CONSTANT)
+    return repo_lookup_num(s->repo, s - s->repo->pool->solvables, keyname, 0) == 1;
+  return 0;
 }
 
 const unsigned char *
 solvable_lookup_bin_checksum(Solvable *s, Id keyname, Id *typep)
 {
-  Repo *repo = s->repo;
-
-  if (!repo)
+  if (!s->repo)
     {
       *typep = 0;
       return 0;
     }
-  return repo_lookup_bin_checksum(repo, s - repo->pool->solvables, keyname, typep);
+  return repo_lookup_bin_checksum(s->repo, s - s->repo->pool->solvables, keyname, typep);
 }
 
 const char *
@@ -400,305 +426,12 @@ solvable_lookup_sourcepkg(Solvable *s)
 
 /*****************************************************************************/
 
-static inline Id dep2name(Pool *pool, Id dep)
-{
-  while (ISRELDEP(dep))
-    {
-      Reldep *rd = GETRELDEP(pool, dep);
-      dep = rd->name;
-    }
-  return dep;
-}
-
-static int providedbyinstalled_multiversion(Pool *pool, Map *installed, Id n, Id con)
-{
-  Id p, pp;
-  Solvable *sn = pool->solvables + n;
-
-  FOR_PROVIDES(p, pp, sn->name)
-    {
-      Solvable *s = pool->solvables + p;
-      if (s->name != sn->name || s->arch != sn->arch)
-        continue;
-      if (!MAPTST(installed, p))
-        continue;
-      if (pool_match_nevr(pool, pool->solvables + p, con))
-        continue;
-      return 1;         /* found installed package that doesn't conflict */
-    }
-  return 0;
-}
-
-static inline int providedbyinstalled(Pool *pool, Map *installed, Id dep, int ispatch, Map *multiversionmap)
-{
-  Id p, pp;
-  FOR_PROVIDES(p, pp, dep)
-    {
-      if (p == SYSTEMSOLVABLE)
-       return -1;
-      if (ispatch && !pool_match_nevr(pool, pool->solvables + p, dep))
-       continue;
-      if (ispatch && multiversionmap && multiversionmap->size && MAPTST(multiversionmap, p) && ISRELDEP(dep))
-       if (providedbyinstalled_multiversion(pool, installed, p, dep))
-         continue;
-      if (MAPTST(installed, p))
-       return 1;
-    }
-  return 0;
-}
-
-/*
- * solvable_trivial_installable_map - anwers is a solvable is installable
- * without any other installs/deinstalls.
- * The packages considered to be installed are provided via the
- * installedmap bitmap. A additional "conflictsmap" bitmap providing
- * information about the conflicts of the installed packages can be
- * used for extra speed up. Provide a NULL pointer if you do not
- * have this information.
- * Both maps can be created with pool_create_state_maps() or
- * solver_create_state_maps().
- *
- * returns:
- * 1:  solvable is installable without any other package changes
- * 0:  solvable is not installable
- * -1: solvable is installable, but doesn't constrain any installed packages
- */
-int
-solvable_trivial_installable_map(Solvable *s, Map *installedmap, Map *conflictsmap, Map *multiversionmap)
-{
-  Pool *pool = s->repo->pool;
-  Solvable *s2;
-  Id p, *dp;
-  Id *reqp, req;
-  Id *conp, con;
-  int r, interesting = 0;
-
-  if (conflictsmap && MAPTST(conflictsmap, s - pool->solvables))
-    return 0;
-  if (s->requires)
-    {
-      reqp = s->repo->idarraydata + s->requires;
-      while ((req = *reqp++) != 0)
-       {
-         if (req == SOLVABLE_PREREQMARKER)
-           continue;
-          r = providedbyinstalled(pool, installedmap, req, 0, 0);
-         if (!r)
-           return 0;
-         if (r > 0)
-           interesting = 1;
-       }
-    }
-  if (s->conflicts)
-    {
-      int ispatch = 0;
-
-      if (!strncmp("patch:", pool_id2str(pool, s->name), 6))
-       ispatch = 1;
-      conp = s->repo->idarraydata + s->conflicts;
-      while ((con = *conp++) != 0)
-       {
-         if (providedbyinstalled(pool, installedmap, con, ispatch, multiversionmap))
-           {
-             if (ispatch && solvable_is_irrelevant_patch(s, installedmap))
-               return -1;
-             return 0;
-           }
-         if (!interesting && ISRELDEP(con))
-           {
-              con = dep2name(pool, con);
-             if (providedbyinstalled(pool, installedmap, con, ispatch, multiversionmap))
-               interesting = 1;
-           }
-       }
-      if (ispatch && interesting && solvable_is_irrelevant_patch(s, installedmap))
-       interesting = 0;
-    }
-#if 0
-  if (s->repo)
-    {
-      Id *obsp, obs;
-      Repo *installed = 0;
-      if (s->obsoletes && s->repo != installed)
-       {
-         obsp = s->repo->idarraydata + s->obsoletes;
-         while ((obs = *obsp++) != 0)
-           {
-             if (providedbyinstalled(pool, installedmap, obs, 0, 0))
-               return 0;
-           }
-       }
-      if (s->repo != installed)
-       {
-         Id pp;
-         FOR_PROVIDES(p, pp, s->name)
-           {
-             s2 = pool->solvables + p;
-             if (s2->repo == installed && s2->name == s->name)
-               return 0;
-           }
-       }
-    }
-#endif
-  if (!conflictsmap)
-    {
-      int i;
-
-      p = s - pool->solvables;
-      for (i = 1; i < pool->nsolvables; i++)
-       {
-         if (!MAPTST(installedmap, i))
-           continue;
-         s2 = pool->solvables + i;
-         if (!s2->conflicts)
-           continue;
-         conp = s2->repo->idarraydata + s2->conflicts;
-         while ((con = *conp++) != 0)
-           {
-             dp = pool_whatprovides_ptr(pool, con);
-             for (; *dp; dp++)
-               if (*dp == p)
-                 return 0;
-           }
-       }
-     }
-  return interesting ? 1 : -1;
-}
-
-/*
- * different interface for solvable_trivial_installable_map, where
- * the information about the installed packages is provided
- * by a queue.
- */
-int
-solvable_trivial_installable_queue(Solvable *s, Queue *installed, Map *multiversionmap)
-{
-  Pool *pool = s->repo->pool;
-  int i;
-  Id p;
-  Map installedmap;
-  int r;
-
-  map_init(&installedmap, pool->nsolvables);
-  for (i = 0; i < installed->count; i++)
-    {
-      p = installed->elements[i];
-      if (p > 0)               /* makes it work with decisionq */
-       MAPSET(&installedmap, p);
-    }
-  r = solvable_trivial_installable_map(s, &installedmap, 0, multiversionmap);
-  map_free(&installedmap);
-  return r;
-}
-
-/*
- * different interface for solvable_trivial_installable_map, where
- * the information about the installed packages is provided
- * by a repo containing the installed solvables.
- */
-int
-solvable_trivial_installable_repo(Solvable *s, Repo *installed, Map *multiversionmap)
-{
-  Pool *pool = s->repo->pool;
-  Id p;
-  Solvable *s2;
-  Map installedmap;
-  int r;
-
-  map_init(&installedmap, pool->nsolvables);
-  FOR_REPO_SOLVABLES(installed, p, s2)
-    MAPSET(&installedmap, p);
-  r = solvable_trivial_installable_map(s, &installedmap, 0, multiversionmap);
-  map_free(&installedmap);
-  return r;
-}
-
-/* FIXME: this mirrors policy_illegal_vendorchange */
-static int
-pool_illegal_vendorchange(Pool *pool, Solvable *s1, Solvable *s2)
-{
-  Id v1, v2;
-  Id vendormask1, vendormask2;
-
-  if (pool->custom_vendorcheck)
-    return pool->custom_vendorcheck(pool, s1, s2);
-  /* treat a missing vendor as empty string */
-  v1 = s1->vendor ? s1->vendor : ID_EMPTY;
-  v2 = s2->vendor ? s2->vendor : ID_EMPTY;
-  if (v1 == v2)
-    return 0;
-  vendormask1 = pool_vendor2mask(pool, v1);
-  if (!vendormask1)
-    return 1;   /* can't match */
-  vendormask2 = pool_vendor2mask(pool, v2);
-  if ((vendormask1 & vendormask2) != 0)
-    return 0;
-  return 1;     /* no class matches */
-}
-
-/* check if this patch is relevant according to the vendor. To bad that patches
- * don't have a vendor, so we need to do some careful repo testing. */
-int
-solvable_is_irrelevant_patch(Solvable *s, Map *installedmap)
-{
-  Pool *pool = s->repo->pool;
-  Id con, *conp;
-  int hadpatchpackage = 0;
-
-  if (!s->conflicts)
-    return 0;
-  conp = s->repo->idarraydata + s->conflicts;
-  while ((con = *conp++) != 0)
-    {
-      Reldep *rd;
-      Id p, pp, p2, pp2;
-      if (!ISRELDEP(con))
-       continue;
-      rd = GETRELDEP(pool, con);
-      if (rd->flags != REL_LT)
-       continue;
-      FOR_PROVIDES(p, pp, con)
-       {
-         Solvable *si;
-         if (!MAPTST(installedmap, p))
-           continue;
-         si = pool->solvables + p;
-         if (!pool_match_nevr(pool, si, con))
-           continue;
-         FOR_PROVIDES(p2, pp2, rd->name)
-           {
-             Solvable *s2 = pool->solvables + p2;
-             if (!pool_match_nevr(pool, s2, rd->name))
-               continue;
-             if (pool_match_nevr(pool, s2, con))
-               continue;       /* does not fulfill patch */
-             if (s2->repo == s->repo)
-               {
-                 hadpatchpackage = 1;
-                 /* ok, we have a package from the patch repo that solves the conflict. check vendor */
-                 if (si->vendor == s2->vendor)
-                   return 0;
-                 if (!pool_illegal_vendorchange(pool, si, s2))
-                   return 0;
-                 /* vendor change was illegal, ignore conflict */
-               }
-           }
-       }
-    }
-  /* if we didn't find a patchpackage don't claim that the patch is irrelevant */
-  if (!hadpatchpackage)
-    return 0;
-  return 1;
-}
-
-/*****************************************************************************/
-
 /*
  * Create maps containing the state of each solvable. Input is a "installed" queue,
  * it contains all solvable ids that are considered to be installed.
  *
- * The created maps can be used for solvable_trivial_installable_map(),
- * pool_calc_duchanges(), pool_calc_installsizechange().
+ * The created maps can be used for * pool_calc_duchanges() and
+ * pool_calc_installsizechange().
  *
  */
 void
@@ -736,22 +469,28 @@ pool_create_state_maps(Pool *pool, Queue *installed, Map *installedmap, Map *con
 /* Tests if two solvables have identical content. Currently
  * both solvables need to come from the same pool
  */
+
 int
 solvable_identical(Solvable *s1, Solvable *s2)
 {
-  unsigned int bt1, bt2;
+  unsigned long long bt1, bt2;
   Id rq1, rq2;
   Id *reqp;
-
   if (s1->name != s2->name)
     return 0;
   if (s1->arch != s2->arch)
     return 0;
   if (s1->evr != s2->evr)
     return 0;
-  /* map missing vendor to empty string */
+
+  /* check vendor, map missing vendor to empty string */
   if ((s1->vendor ? s1->vendor : 1) != (s2->vendor ? s2->vendor : 1))
-    return 0;
+    {
+      /* workaround for bug 881493 */
+      if (s1->repo && !strncmp(pool_id2str(s1->repo->pool, s1->name), "product:", 8))
+       return 1;
+      return 0;
+    }
 
   /* looking good, try some fancier stuff */
   /* might also look up the package checksum here */
@@ -764,6 +503,13 @@ solvable_identical(Solvable *s1, Solvable *s2)
     }
   else
     {
+      if (s1->repo)
+       {
+          /* workaround for bugs 881493 and 885830*/
+         const char *n = pool_id2str(s1->repo->pool, s1->name);
+         if (!strncmp(n, "product:", 8) || !strncmp(n, "application:", 12))
+           return 1;
+       }
       /* look at requires in a last attempt to find recompiled packages */
       rq1 = rq2 = 0;
       if (s1->requires)
@@ -775,6 +521,19 @@ solvable_identical(Solvable *s1, Solvable *s2)
       if (rq1 != rq2)
         return 0;
     }
+  if (s1->repo && s1->repo->pool->disttype == DISTTYPE_CONDA)
+    {
+      /* check buildflavor and buildversion */
+      const char *str1, *str2;
+      str1 = solvable_lookup_str(s1, SOLVABLE_BUILDFLAVOR);
+      str2 = solvable_lookup_str(s2, SOLVABLE_BUILDFLAVOR);
+      if (str1 != str2 && (!str1 || !str2 || strcmp(str1, str2) != 0))
+       return 0;
+      str1 = solvable_lookup_str(s1, SOLVABLE_BUILDVERSION);
+      str2 = solvable_lookup_str(s2, SOLVABLE_BUILDVERSION);
+      if (str1 != str2 && (!str1 || !str2 || strcmp(str1, str2) != 0))
+       return 0;
+    }
   return 1;
 }
 
@@ -872,6 +631,9 @@ solvable_matchesdep(Solvable *s, Id keyname, Id dep, int marker)
   int i;
   Pool *pool = s->repo->pool;
   Queue q;
+
+  if (keyname == SOLVABLE_NAME)
+    return pool_match_nevr(pool, s, dep) ? 1 : 0;      /* nevr match hack */
   queue_init(&q);
   solvable_lookup_deparray(s, keyname, &q, marker);
   for (i = 0; i < q.count; i++)
@@ -881,3 +643,67 @@ solvable_matchesdep(Solvable *s, Id keyname, Id dep, int marker)
   queue_free(&q);
   return i;
 }
+
+int
+solvable_matchessolvable_int(Solvable *s, Id keyname, int marker, Id solvid, Map *solvidmap, Queue *depq, Map *missc, int reloff)
+{
+  Pool *pool = s->repo->pool;
+  int i, boff;
+  Id *wp;
+
+  if (depq->count)
+    queue_empty(depq);
+  solvable_lookup_deparray(s, keyname, depq, marker);
+  for (i = 0; i < depq->count; i++)
+    {
+      Id dep = depq->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 (solvidmap)
+               {
+                 for (; *wp; wp++)
+                   if (MAPTST(solvidmap, *wp))
+                     break;
+               }
+             else
+               {
+                 for (; *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 (solvidmap)
+       {
+         for (; *wp; wp++)
+           if (MAPTST(solvidmap, *wp))
+             return 1;
+       }
+      else
+       {
+         for (; *wp; wp++)
+           if (*wp == solvid)
+             return 1;
+       }
+      MAPSET(missc, boff);
+    }
+  return 0;
+}