]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
Add new file suse.c
authorMichael Schroeder <mls@suse.de>
Tue, 14 Jun 2016 14:52:30 +0000 (16:52 +0200)
committerMichael Schroeder <mls@suse.de>
Tue, 14 Jun 2016 14:52:30 +0000 (16:52 +0200)
src/suse.c [new file with mode: 0644]

diff --git a/src/suse.c b/src/suse.c
new file mode 100644 (file)
index 0000000..6106f3f
--- /dev/null
@@ -0,0 +1,748 @@
+/*
+ * Copyright (c) 2016, SUSE LLC.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+/* weird SUSE stuff. better not use it for your projects. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "solver.h"
+#include "solver_private.h"
+#include "bitmap.h"
+#include "pool.h"
+#include "poolvendor.h"
+#include "util.h"
+
+Offset
+repo_fix_supplements(Repo *repo, Offset provides, Offset supplements, Offset freshens)
+{
+  Pool *pool = repo->pool;
+  Id id, idp, idl;
+  char buf[1024], *p, *dep;
+  int i, l;
+
+  if (provides)
+    {
+      for (i = provides; repo->idarraydata[i]; i++)
+       {
+         id = repo->idarraydata[i];
+         if (ISRELDEP(id))
+           continue;
+         dep = (char *)pool_id2str(pool, id);
+         if (!strncmp(dep, "locale(", 7) && strlen(dep) < sizeof(buf) - 2)
+           {
+             idp = 0;
+             strcpy(buf + 2, dep);
+             dep = buf + 2 + 7;
+             if ((p = strchr(dep, ':')) != 0 && p != dep)
+               {
+                 *p++ = 0;
+                 idp = pool_str2id(pool, dep, 1);
+                 dep = p;
+               }
+             id = 0;
+             while ((p = strchr(dep, ';')) != 0)
+               {
+                 if (p == dep)
+                   {
+                     dep = p + 1;
+                     continue;
+                   }
+                 *p++ = 0;
+                 idl = pool_str2id(pool, dep, 1);
+                 idl = pool_rel2id(pool, NAMESPACE_LANGUAGE, idl, REL_NAMESPACE, 1);
+                 if (id)
+                   id = pool_rel2id(pool, id, idl, REL_OR, 1);
+                 else
+                   id = idl;
+                 dep = p;
+               }
+             if (dep[0] && dep[1])
+               {
+                 for (p = dep; *p && *p != ')'; p++)
+                   ;
+                 *p = 0;
+                 idl = pool_str2id(pool, dep, 1);
+                 idl = pool_rel2id(pool, NAMESPACE_LANGUAGE, idl, REL_NAMESPACE, 1);
+                 if (id)
+                   id = pool_rel2id(pool, id, idl, REL_OR, 1);
+                 else
+                   id = idl;
+               }
+             if (idp)
+               id = pool_rel2id(pool, idp, id, REL_AND, 1);
+             if (id)
+               supplements = repo_addid_dep(repo, supplements, id, 0);
+           }
+         else if ((p = strchr(dep, ':')) != 0 && p != dep && p[1] == '/' && strlen(dep) < sizeof(buf))
+           {
+             strcpy(buf, dep);
+             p = buf + (p - dep);
+             *p++ = 0;
+             idp = pool_str2id(pool, buf, 1);
+             /* strip trailing slashes */
+             l = strlen(p);
+             while (l > 1 && p[l - 1] == '/')
+               p[--l] = 0;
+             id = pool_str2id(pool, p, 1);
+             id = pool_rel2id(pool, idp, id, REL_WITH, 1);
+             id = pool_rel2id(pool, NAMESPACE_SPLITPROVIDES, id, REL_NAMESPACE, 1);
+             supplements = repo_addid_dep(repo, supplements, id, 0);
+           }
+       }
+    }
+  if (supplements)
+    {
+      for (i = supplements; repo->idarraydata[i]; i++)
+       {
+         id = repo->idarraydata[i];
+         if (ISRELDEP(id))
+           continue;
+         dep = (char *)pool_id2str(pool, id);
+         if (!strncmp(dep, "system:modalias(", 16))
+           dep += 7;
+         if (!strncmp(dep, "modalias(", 9) && dep[9] && dep[10] && strlen(dep) < sizeof(buf))
+           {
+             strcpy(buf, dep);
+             p = strchr(buf + 9, ':');
+             if (p && p != buf + 9 && strchr(p + 1, ':'))
+               {
+                 *p++ = 0;
+                 idp = pool_str2id(pool, buf + 9, 1);
+                 p[strlen(p) - 1] = 0;
+                 id = pool_str2id(pool, p, 1);
+                 id = pool_rel2id(pool, NAMESPACE_MODALIAS, id, REL_NAMESPACE, 1);
+                 id = pool_rel2id(pool, idp, id, REL_AND, 1);
+               }
+             else
+               {
+                 p = buf + 9;
+                 p[strlen(p) - 1] = 0;
+                 id = pool_str2id(pool, p, 1);
+                 id = pool_rel2id(pool, NAMESPACE_MODALIAS, id, REL_NAMESPACE, 1);
+               }
+             if (id)
+               repo->idarraydata[i] = id;
+           }
+         else if (!strncmp(dep, "packageand(", 11) && strlen(dep) < sizeof(buf))
+           {
+             strcpy(buf, dep);
+             id = 0;
+             dep = buf + 11;
+             while ((p = strchr(dep, ':')) != 0)
+               {
+                 if (p == dep)
+                   {
+                     dep = p + 1;
+                     continue;
+                   }
+                 /* argh, allow pattern: prefix. sigh */
+                 if (p - dep == 7 && !strncmp(dep, "pattern", 7))
+                   {
+                     p = strchr(p + 1, ':');
+                     if (!p)
+                       break;
+                   }
+                 *p++ = 0;
+                 idp = pool_str2id(pool, dep, 1);
+                 if (id)
+                   id = pool_rel2id(pool, id, idp, REL_AND, 1);
+                 else
+                   id = idp;
+                 dep = p;
+               }
+             if (dep[0] && dep[1])
+               {
+                 dep[strlen(dep) - 1] = 0;
+                 idp = pool_str2id(pool, dep, 1);
+                 if (id)
+                   id = pool_rel2id(pool, id, idp, REL_AND, 1);
+                 else
+                   id = idp;
+               }
+             if (id)
+               repo->idarraydata[i] = id;
+           }
+         else if (!strncmp(dep, "filesystem(", 11) && strlen(dep) < sizeof(buf))
+           {
+             strcpy(buf, dep + 11);
+             if ((p = strrchr(buf, ')')) != 0)
+               *p = 0;
+             id = pool_str2id(pool, buf, 1);
+             id = pool_rel2id(pool, NAMESPACE_FILESYSTEM, id, REL_NAMESPACE, 1);
+             repo->idarraydata[i] = id;
+           }
+       }
+    }
+  if (freshens && repo->idarraydata[freshens])
+    {
+      Id idsupp = 0, idfresh = 0;
+      if (!supplements || !repo->idarraydata[supplements])
+       return freshens;
+      for (i = supplements; repo->idarraydata[i]; i++)
+        {
+         if (!idsupp)
+           idsupp = repo->idarraydata[i];
+         else
+           idsupp = pool_rel2id(pool, idsupp, repo->idarraydata[i], REL_OR, 1);
+        }
+      for (i = freshens; repo->idarraydata[i]; i++)
+        {
+         if (!idfresh)
+           idfresh = repo->idarraydata[i];
+         else
+           idfresh = pool_rel2id(pool, idfresh, repo->idarraydata[i], REL_OR, 1);
+        }
+      if (!idsupp)
+        idsupp = idfresh;
+      else
+       idsupp = pool_rel2id(pool, idsupp, idfresh, REL_AND, 1);
+      supplements = repo_addid_dep(repo, 0, idsupp, 0);
+    }
+  return supplements;
+}
+
+Offset
+repo_fix_conflicts(Repo *repo, Offset conflicts)
+{
+  char buf[1024], *p, *dep;
+  Pool *pool = repo->pool;
+  Id id;
+  int i;
+
+  if (!conflicts)
+    return conflicts;
+  for (i = conflicts; repo->idarraydata[i]; i++)
+    {
+      id = repo->idarraydata[i];
+      if (ISRELDEP(id))
+       continue;
+      dep = (char *)pool_id2str(pool, id);
+      if (!strncmp(dep, "otherproviders(", 15) && strlen(dep) < sizeof(buf) - 2)
+       {
+         strcpy(buf, dep + 15);
+         if ((p = strchr(buf, ')')) != 0)
+           *p = 0;
+         id = pool_str2id(pool, buf, 1);
+         id = pool_rel2id(pool, NAMESPACE_OTHERPROVIDERS, id, REL_NAMESPACE, 1);
+         repo->idarraydata[i] = id;
+       }
+    }
+  return conflicts;
+}
+
+void
+repo_rewrite_suse_deps(Solvable *s, Offset freshens)
+{
+  s->supplements = repo_fix_supplements(s->repo, s->provides, s->supplements, freshens);
+  if (s->conflicts)
+    s->conflicts = repo_fix_conflicts(s->repo, s->conflicts);
+}
+
+/**********************************************************************************/
+
+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;
+}
+
+/* xmap:
+ *  1: installed
+ *  2: conflicts with installed
+ *  8: interesting (only true if installed)
+ * 16: undecided
+ */
+
+static int
+providedbyinstalled_multiversion_xmap(Pool *pool, unsigned char *map, 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 ((map[p] & 9) != 9)
+        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_xmap(Pool *pool, unsigned char *map, Id dep, int ispatch, Map *multiversionmap)
+{
+  Id p, pp;
+  int r = 0; 
+  FOR_PROVIDES(p, pp, dep) 
+    {    
+      if (p == SYSTEMSOLVABLE)
+        return 1;       /* always boring, as never constraining */
+      if (ispatch && !pool_match_nevr(pool, pool->solvables + p, dep))
+        continue;
+      if (ispatch && multiversionmap && multiversionmap->size && MAPTST(multiversionmap, p) && ISRELDEP(dep))
+        if (providedbyinstalled_multiversion_xmap(pool, map, p, dep))
+          continue;
+      if ((map[p] & 9) == 9)
+        return 9;
+      r |= map[p] & 17;
+    }    
+  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;
+}
+
+/*
+ * solvable_trivial_installable_map - answers if 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 (!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;
+}
+
+/*
+ * pool_trivial_installable - calculate if a set of solvables is
+ * trivial installable without any other installs/deinstalls of
+ * packages not belonging to the set.
+ *
+ * the state is returned in the result queue:
+ * 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
+ */
+
+void
+pool_trivial_installable_multiversionmap(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res, Map *multiversionmap)
+{
+  int i, r, m, did;
+  Id p, *dp, con, *conp, req, *reqp;
+  unsigned char *map;
+  Solvable *s;
+
+  map = solv_calloc(pool->nsolvables, 1);
+  for (p = 1; p < pool->nsolvables; p++)
+    {
+      if (!MAPTST(installedmap, p))
+       continue;
+      map[p] |= 9;
+      s = pool->solvables + p;
+      if (!s->conflicts)
+       continue;
+      conp = s->repo->idarraydata + s->conflicts;
+      while ((con = *conp++) != 0)
+       {
+         dp = pool_whatprovides_ptr(pool, con);
+         for (; *dp; dp++)
+           map[p] |= 2;        /* XXX: self conflict ? */
+       }
+    }
+  for (i = 0; i < pkgs->count; i++)
+    map[pkgs->elements[i]] = 16;
+
+  for (i = 0, did = 0; did < pkgs->count; i++, did++)
+    {
+      if (i == pkgs->count)
+       i = 0;
+      p = pkgs->elements[i];
+      if ((map[p] & 16) == 0)
+       continue;
+      if ((map[p] & 2) != 0)
+       {
+         map[p] = 2;
+         continue;
+       }
+      s = pool->solvables + p;
+      m = 1;
+      if (s->requires)
+       {
+         reqp = s->repo->idarraydata + s->requires;
+         while ((req = *reqp++) != 0)
+           {
+             if (req == SOLVABLE_PREREQMARKER)
+               continue;
+             r = providedbyinstalled_xmap(pool, map, req, 0, 0);
+             if (!r)
+               {
+                 /* decided and miss */
+                 map[p] = 2;
+                 did = 0;
+                 break;
+               }
+             if (r == 16)
+               break;  /* undecided */
+             m |= r;   /* 1 | 9 | 17 */
+           }
+         if (req)
+           continue;
+         if ((m & 9) == 9)
+           m = 9;
+       }
+      if (s->conflicts)
+       {
+         int ispatch = 0;      /* see solver.c patch handling */
+
+         if (!strncmp("patch:", pool_id2str(pool, s->name), 6))
+           ispatch = 1;
+         conp = s->repo->idarraydata + s->conflicts;
+         while ((con = *conp++) != 0)
+           {
+             if ((providedbyinstalled_xmap(pool, map, con, ispatch, multiversionmap) & 1) != 0)
+               {
+                 map[p] = 2;
+                 did = 0;
+                 break;
+               }
+             if ((m == 1 || m == 17) && ISRELDEP(con))
+               {
+                 con = dep2name(pool, con);
+                 if ((providedbyinstalled_xmap(pool, map, con, ispatch, multiversionmap) & 1) != 0)
+                   m = 9;
+               }
+           }
+         if (con)
+           continue;   /* found a conflict */
+       }
+      if (m != map[p])
+       {
+         map[p] = m;
+         did = 0;
+       }
+    }
+  queue_free(res);
+  queue_init_clone(res, pkgs);
+  for (i = 0; i < pkgs->count; i++)
+    {
+      m = map[pkgs->elements[i]];
+      if ((m & 9) == 9)
+       r = 1;
+      else if (m & 1)
+       r = -1;
+      else
+       r = 0;
+      res->elements[i] = r;
+    }
+  free(map);
+}
+
+void
+pool_trivial_installable(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res)
+{
+  pool_trivial_installable_multiversionmap(pool, installedmap, pkgs, res, 0);
+}
+
+void
+solver_trivial_installable(Solver *solv, Queue *pkgs, Queue *res)
+{
+  Pool *pool = solv->pool;
+  Map installedmap;
+  int i;
+  pool_create_state_maps(pool,  &solv->decisionq, &installedmap, 0);
+  pool_trivial_installable_multiversionmap(pool, &installedmap, pkgs, res, solv->multiversion.size ? &solv->multiversion : 0);
+  for (i = 0; i < res->count; i++) 
+    if (res->elements[i] != -1)
+      {    
+        Solvable *s = pool->solvables + pkgs->elements[i];
+        if (!strncmp("patch:", pool_id2str(pool, s->name), 6) && solvable_is_irrelevant_patch(s, &installedmap))
+          res->elements[i] = -1;
+      }    
+  map_free(&installedmap);
+}
+
+void
+solver_printtrivial(Solver *solv)
+{
+  Pool *pool = solv->pool;
+  Queue in, out;
+  Id p;
+  const char *n; 
+  Solvable *s; 
+  int i;
+
+  queue_init(&in);
+  for (p = 1, s = pool->solvables + p; p < solv->pool->nsolvables; p++, s++)
+    {   
+      n = pool_id2str(pool, s->name);
+      if (strncmp(n, "patch:", 6) != 0 && strncmp(n, "pattern:", 8) != 0)
+        continue;
+      queue_push(&in, p); 
+    }   
+  if (!in.count)
+    {   
+      queue_free(&in);
+      return;
+    }   
+  queue_init(&out);
+  solver_trivial_installable(solv, &in, &out);
+  POOL_DEBUG(SOLV_DEBUG_RESULT, "trivial installable status:\n");
+  for (i = 0; i < in.count; i++)
+    POOL_DEBUG(SOLV_DEBUG_RESULT, "  %s: %d\n", pool_solvid2str(pool, in.elements[i]), out.elements[i]);
+  POOL_DEBUG(SOLV_DEBUG_RESULT, "\n");
+  queue_free(&in);
+  queue_free(&out);
+}
+
+