add pool_add_userinstalled_jobs and solver_get_userinstalled functions
authorMichael Schroeder <mls@suse.de>
Thu, 3 Apr 2014 11:08:08 +0000 (13:08 +0200)
committerMichael Schroeder <mls@suse.de>
Thu, 3 Apr 2014 11:08:08 +0000 (13:08 +0200)
src/libsolv.ver
src/solver.c
src/solver.h

index 4be79f9..91337ea 100644 (file)
@@ -41,6 +41,7 @@ SOLV_1.0 {
                policy_illegal_vendorchange;
                policy_is_illegal;
                pool_add_fileconflicts_deps;
+               pool_add_userinstalled_jobs;
                pool_addfileprovides;
                pool_addfileprovides_queue;
                pool_addrelproviders;
@@ -336,6 +337,7 @@ SOLV_1.0 {
                solver_get_orphaned;
                solver_get_recommendations;
                solver_get_unneeded;
+               solver_get_userinstalled;
                solver_next_problem;
                solver_next_solution;
                solver_next_solutionelement;
index 9fe3f23..deb0736 100644 (file)
@@ -26,6 +26,7 @@
 #include "poolarch.h"
 #include "solverdebug.h"
 #include "cplxdeps.h"
+#include "linkedpkg.h"
 
 #define RULES_BLOCK 63
 
@@ -4480,6 +4481,248 @@ pool_isemptyupdatejob(Pool *pool, Id how, Id what)
   return 1;
 }
 
+static int
+get_userinstalled_cmp(const void *ap, const void *bp, void *dp)
+{
+  return *(Id *)ap - *(Id *)bp;
+}
+
+static int
+get_userinstalled_cmp_names(const void *ap, const void *bp, void *dp)
+{
+  Pool *pool = dp;
+  return strcmp(pool_id2str(pool, *(Id *)ap), pool_id2str(pool, *(Id *)bp));
+}
+
+static void
+get_userinstalled_sort_uniq(Pool *pool, Queue *q, int flags)
+{
+  Id lastp = -1;
+  int i, j;
+  if ((flags & GET_USERINSTALLED_NAMES) != 0)
+    solv_sort(q->elements, q->count, sizeof(Id), get_userinstalled_cmp_names, pool);
+  else
+    solv_sort(q->elements, q->count, sizeof(Id), get_userinstalled_cmp, 0);
+  for (i = j = 0; i < q->count; i++)
+    if (q->elements[i] != lastp)
+      q->elements[j++] = lastp = q->elements[i];
+  queue_truncate(q, j);
+}
+
+void
+solver_get_userinstalled(Solver *solv, Queue *q, int flags)
+{
+  Pool *pool = solv->pool;
+  Id p, p2, pp;
+  Solvable *s;
+  Repo *installed = solv->installed;
+  int i, j;
+  Map userinstalled;
+  
+  map_init(&userinstalled, 0);
+  queue_empty(q);
+  /* first process jobs */
+  for (i = 0; i < solv->job.count; i += 2)
+    {
+      Id how = solv->job.elements[i];
+      Id what, select;
+      if (installed && (how & SOLVER_JOBMASK) == SOLVER_USERINSTALLED)
+       {
+         if (!userinstalled.size)
+           map_grow(&userinstalled, installed->end - installed->start);
+         what = solv->job.elements[i + 1];
+         select = how & SOLVER_SELECTMASK;
+         if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && what == installed->repoid))
+           FOR_REPO_SOLVABLES(installed, p, s)
+             MAPSET(&userinstalled, p - installed->start);
+         FOR_JOB_SELECT(p, pp, select, what)
+           if (pool->solvables[p].repo == installed)
+             MAPSET(&userinstalled, p - installed->start);
+         continue;
+       }
+      if ((how & SOLVER_JOBMASK) != SOLVER_INSTALL)
+       continue;
+      what = solv->job.elements[i + 1];
+      select = how & SOLVER_SELECTMASK;
+      FOR_JOB_SELECT(p, pp, select, what)
+        if (solv->decisionmap[p] > 0)
+         {
+           queue_push(q, p);
+#ifdef ENABLE_LINKED_PKGS
+           if (has_package_link(pool, pool->solvables + p))
+             {
+               int j;
+               Queue lq;
+               queue_init(&lq);
+               find_package_link(pool, pool->solvables + p, 0, &lq, 0, 0);
+               for (j = 0; j < lq.count; j++)
+                 if (solv->decisionmap[lq.elements[j]] > 0)
+                   queue_push(q, lq.elements[j]);
+             }
+#endif
+         }
+    }
+  /* now process updates of userinstalled packages */
+  if (installed && userinstalled.size)
+    {
+      for (i = 1; i < solv->decisionq.count; i++)
+       {
+         p = solv->decisionq.elements[i];
+         if (p <= 0)
+           continue;
+         s = pool->solvables + p;
+         if (!s->repo)
+           continue;
+         if (s->repo == installed)
+           {
+             if (MAPTST(&userinstalled, p - installed->start))
+               queue_push(q, p);
+             continue;
+           }
+         /* new package, check if we replace a userinstalled one */
+         FOR_PROVIDES(p2, pp, s->name)
+           {
+             Solvable *ps = pool->solvables + p2;
+             if (p2 == p || ps->repo != installed || !MAPTST(&userinstalled, p2 - installed->start))
+               continue;
+             if (!pool->implicitobsoleteusesprovides && s->name != ps->name)
+               continue;
+             if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, ps))
+               continue;
+             queue_push(q, p);
+             break;
+           }
+         if (!p2 && s->repo != installed && s->obsoletes)
+           {
+             Id obs, *obsp = s->repo->idarraydata + s->obsoletes;
+             while ((obs = *obsp++) != 0)
+               {
+                 FOR_PROVIDES(p2, pp, obs)
+                   {
+                     Solvable *ps = pool->solvables + p2;
+                     if (p2 == p || ps->repo != installed || !MAPTST(&userinstalled, p2 - installed->start))
+                       continue;
+                     if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs))
+                       continue;
+                     if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps)) 
+                       continue;
+                     queue_push(q, p); 
+                     break;
+                   }
+                 if (p2)
+                   break;
+               }
+           }
+       }
+    }
+  map_free(&userinstalled);
+  /* convert to names if asked */
+  if ((flags & GET_USERINSTALLED_NAMES) != 0)
+    {
+      for (i = 0; i < q->count; i++)
+       {
+         s = pool->solvables + q->elements[i];
+         q->elements[i] = s->name;
+       }
+    }
+  /* sort and unify */
+  if (q->count > 1)
+    get_userinstalled_sort_uniq(pool, q, flags);
+  /* invert if asked */
+  if ((flags & GET_USERINSTALLED_INVERTED) != 0)
+    {
+      /* first generate queue with all installed packages */
+      Queue invq;
+      queue_init(&invq);
+      for (i = 1; i < solv->decisionq.count; i++)
+       {
+         p = solv->decisionq.elements[i];
+         if (p <= 0)
+           continue;
+         s = pool->solvables + p;
+         if (!s->repo)
+           continue;
+         if ((flags & GET_USERINSTALLED_NAMES) != 0)
+           queue_push(&invq, s->name);
+         else
+           queue_push(&invq, p);
+       }
+      /* push q on invq, just in case... */
+      queue_insertn(&invq, invq.count, q->count, q->elements);
+      if (invq.count > 1)
+       get_userinstalled_sort_uniq(pool, &invq, flags);
+      /* subtract queues (easy as they are sorted and invq is a superset of q) */
+      if (q->count)
+       {
+         for (i = j = 0; i < invq.count; i++)
+           if (invq.elements[i] == q->elements[j])
+             {
+               invq.elements[i] = 0;
+               if (++j >= q->count)
+                 break;
+             }
+         queue_empty(q);
+       }
+      for (i = j = 0; i < invq.count; i++)
+       if (invq.elements[i])
+         queue_push(q, invq.elements[i]);
+      queue_free(&invq);
+    }
+}
+
+void
+pool_add_userinstalled_jobs(Pool *pool, Queue *q, Queue *job, int flags)
+{
+  int i;
+
+  if (flags & GET_USERINSTALLED_INVERTED)
+    {
+      Queue invq;
+      Id p, lastid;
+      Solvable *s;
+      int bad;
+      if (!pool->installed)
+       return;
+      queue_init(&invq);
+      FOR_REPO_SOLVABLES(pool->installed, p, s)
+       queue_push(&invq, flags & GET_USERINSTALLED_NAMES ? s->name : p);
+      queue_insertn(&invq, invq.count, q->count, q->elements);
+      if (invq.count > 1)
+        get_userinstalled_sort_uniq(pool, &invq, flags);
+      /* now the fun part, add q again, sort, and remove all dups */
+      queue_insertn(&invq, invq.count, q->count, q->elements);
+      if (invq.count > 1)
+       {
+         if ((flags & GET_USERINSTALLED_NAMES) != 0)
+           solv_sort(invq.elements, invq.count, sizeof(Id), get_userinstalled_cmp_names, pool);
+         else
+           solv_sort(invq.elements, invq.count, sizeof(Id), get_userinstalled_cmp, 0);
+       }
+      lastid = -1;
+      bad = 1;
+      for (i = 0; i < invq.count; i++)
+       {
+         if (invq.elements[i] == lastid)
+           {
+             bad = 1;
+             continue;
+           }
+         if (!bad)
+           queue_push2(job, SOLVER_USERINSTALLED | (flags & GET_USERINSTALLED_NAMES ? SOLVER_SOLVABLE_NAME : SOLVER_SOLVABLE), lastid);
+         bad = 0;
+         lastid = invq.elements[i];
+       }
+      if (!bad)
+       queue_push2(job, SOLVER_USERINSTALLED | (flags & GET_USERINSTALLED_NAMES ? SOLVER_SOLVABLE_NAME : SOLVER_SOLVABLE), lastid);
+      queue_free(&invq);
+    }
+  else
+    {
+      for (i = 0; i < q->count; i++)
+       queue_push2(job, SOLVER_USERINSTALLED | (flags & GET_USERINSTALLED_NAMES ? SOLVER_SOLVABLE_NAME : SOLVER_SOLVABLE), q->elements[i]);
+    }
+}
+
 const char *
 solver_select2str(Pool *pool, Id select, Id what)
 {
index b14e367..daa0e08 100644 (file)
@@ -280,6 +280,9 @@ typedef struct _Solver Solver;
 #define SOLVER_FLAG_DUP_ALLOW_VENDORCHANGE     16
 #define SOLVER_FLAG_DUP_ALLOW_NAMECHANGE       17
 
+#define GET_USERINSTALLED_NAMES                        (1 << 0)        /* package names instead if ids */
+#define GET_USERINSTALLED_INVERTED             (1 << 1)        /* autoinstalled */
+
 extern Solver *solver_create(Pool *pool);
 extern void solver_free(Solver *solv);
 extern int  solver_solve(Solver *solv, Queue *job);
@@ -295,6 +298,8 @@ extern void solver_get_decisionblock(Solver *solv, int level, Queue *decisionq);
 extern void solver_get_orphaned(Solver *solv, Queue *orphanedq);
 extern void solver_get_recommendations(Solver *solv, Queue *recommendationsq, Queue *suggestionsq, int noselected);
 extern void solver_get_unneeded(Solver *solv, Queue *unneededq, int filtered);
+extern void solver_get_userinstalled(Solver *solv, Queue *q, int flags);
+extern void pool_add_userinstalled_jobs(Pool *pool, Queue *q, Queue *job, int flags);
 
 extern int  solver_describe_decision(Solver *solv, Id p, Id *infop);
 extern void solver_describe_weakdep_decision(Solver *solv, Id p, Queue *whyq);