- add erase with dependency cleaning:
authorMichael Schroeder <mls@suse.de>
Wed, 14 Apr 2010 09:13:02 +0000 (11:13 +0200)
committerMichael Schroeder <mls@suse.de>
Wed, 14 Apr 2010 09:13:02 +0000 (11:13 +0200)
  * SOLVER_CLEANDEPS flag
  * SOLVER_USERINSTALLED job

examples/solv.c
src/rules.c
src/solver.c
src/solver.h

index 46aea12..887fe88 100644 (file)
@@ -2170,6 +2170,7 @@ rewrite_repos(Pool *pool, Id *addedfileprovides)
 #define MODE_INFO        7
 #define MODE_REPOLIST    8
 #define MODE_SEARCH     9
+#define MODE_ERASECLEAN  10
 
 void
 usage(int r)
@@ -2230,6 +2231,11 @@ main(int argc, char **argv)
       mainmode = MODE_ERASE;
       mode = SOLVER_ERASE;
     }
+  else if (!strcmp(argv[0], "eraseclean") || !strcmp(argv[0], "rmclean"))
+    {
+      mainmode = MODE_ERASECLEAN;
+      mode = SOLVER_ERASE;
+    }
   else if (!strcmp(argv[0], "list"))
     {
       mainmode = MODE_LIST;
@@ -2544,6 +2550,8 @@ main(int argc, char **argv)
            }
        }
       job.elements[i] |= mode;
+      if (mainmode == MODE_ERASECLEAN)
+        job.elements[i] |= SOLVER_CLEANDEPS;
     }
 
   if (mainmode == MODE_DISTUPGRADE && allpkgs && repofilter)
@@ -2576,7 +2584,7 @@ rerunsolver:
          solv->allowarchchange = 1;
          solv->allowvendorchange = 1;
        }
-      if (mainmode == MODE_ERASE)
+      if (mainmode == MODE_ERASE || mainmode == MODE_ERASECLEAN)
        solv->allowuninstall = 1;       /* don't nag */
 
       solver_solve(solv, &job);
@@ -2665,6 +2673,14 @@ rerunsolver:
   if (!yesno("OK to continue (y/n)? "))
     {
       printf("Abort.\n");
+      solver_free(solv);
+      queue_free(&job);
+      pool_free(pool);
+      free_repoinfos(repoinfos, nrepoinfos);
+      sat_free(commandlinepkgs);
+#ifdef FEDORA
+      yum_substitute(pool, 0);
+#endif
       exit(1);
     }
 
index cc14c88..c6b1a6b 100644 (file)
@@ -28,6 +28,7 @@
 #define RULES_BLOCK 63
 
 static void addrpmruleinfo(Solver *solv, Id p, Id d, int type, Id dep);
+static void solver_createcleandepsmap(Solver *solv);
 
 /*-------------------------------------------------------------------
  * Check if dependency is possible
@@ -1358,8 +1359,7 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
                      break;
                  if (i < q->count)
                    continue;
-                 queue_push(q, DISABLE_INFARCH);
-                 queue_push(q, s->name);
+                 queue_push2(q, DISABLE_INFARCH, s->name);
                }
            }
        }
@@ -1367,32 +1367,21 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
        break;
       s = pool->solvables + what;
       if (solv->infarchrules != solv->infarchrules_end)
-       {
-         queue_push(q, DISABLE_INFARCH);
-         queue_push(q, s->name);
-       }
+       queue_push2(q, DISABLE_INFARCH, s->name);
       if (solv->duprules != solv->duprules_end)
-       {
-         queue_push(q, DISABLE_DUP);
-         queue_push(q, s->name);
-       }
+       queue_push2(q, DISABLE_DUP, s->name);
       if (!installed)
        return;
       if (solv->noobsoletes.size && MAPTST(&solv->noobsoletes, what))
        {
          /* XXX: remove if we always do distupgrade with DUP rules */
          if (solv->distupgrade && s->repo == installed)
-           {
-             queue_push(q, DISABLE_UPDATE);
-             queue_push(q, what);
-             return;
-           }
+           queue_push2(q, DISABLE_UPDATE, what);
          return;
        }
       if (s->repo == installed)
        {
-         queue_push(q, DISABLE_UPDATE);
-         queue_push(q, what);
+         queue_push2(q, DISABLE_UPDATE, what);
          return;
        }
       if (s->obsoletes)
@@ -1409,8 +1398,7 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
                  continue;
                if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
                  continue;
-               queue_push(q, DISABLE_UPDATE);
-               queue_push(q, p);
+               queue_push2(q, DISABLE_UPDATE, p);
              }
        }
       FOR_PROVIDES(p, pp, s->name)
@@ -1422,8 +1410,7 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
            continue;
          if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
            continue;
-         queue_push(q, DISABLE_UPDATE);
-         queue_push(q, p);
+         queue_push2(q, DISABLE_UPDATE, p);
        }
       return;
     case SOLVER_ERASE:
@@ -1431,10 +1418,7 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
        break;
       FOR_JOB_SELECT(p, pp, select, what)
        if (pool->solvables[p].repo == installed)
-         {
-           queue_push(q, DISABLE_UPDATE);
-           queue_push(q, p);
-         }
+         queue_push2(q, DISABLE_UPDATE, p);
       return;
     default:
       return;
@@ -1465,6 +1449,13 @@ solver_disablepolicyrules(Solver *solv)
       lastjob = j;
       jobtodisablelist(solv, job->elements[j], job->elements[j + 1], &allq);
     }
+  if (solv->cleandepsmap.size)
+    {
+      solver_createcleandepsmap(solv);
+      for (i = solv->installed->start; i < solv->installed->end; i++)
+       if (MAPTST(&solv->cleandepsmap, i - solv->installed->start))
+         queue_push2(&allq, DISABLE_UPDATE, i);
+    }
   MAPZERO(&solv->noupdate);
   for (i = 0; i < allq.count; i += 2)
     {
@@ -1515,6 +1506,13 @@ solver_reenablepolicyrules(Solver *solv, int jobidx)
       lastjob = j;
       jobtodisablelist(solv, job->elements[j], job->elements[j + 1], &allq);
     }
+  if (solv->cleandepsmap.size)
+    {
+      solver_createcleandepsmap(solv);
+      for (i = solv->installed->start; i < solv->installed->end; i++)
+       if (MAPTST(&solv->cleandepsmap, i - solv->installed->start))
+         queue_push2(&allq, DISABLE_UPDATE, i);
+    }
   for (j = 0; j < q.count; j += 2)
     {
       Id type = q.elements[j], arg = q.elements[j + 1];
@@ -2007,4 +2005,284 @@ disablechoicerules(Solver *solv, Rule *r)
     }
 }
 
+void solver_createcleandepsmap(Solver *solv)
+{
+  Pool *pool = solv->pool;
+  Repo *installed = solv->installed;
+  Queue *job = &solv->job;
+  Map userinstalled;
+  Map im;
+  Map installedm;
+  Rule *r;
+  Id rid, how, what, select;
+  Id p, pp, ip, *jp;
+  Id req, *reqp, sup, *supp;
+  Solvable *s;
+  Queue iq;
+  int i;
+
+  map_init(&userinstalled, installed->end - installed->start);
+  map_init(&im, pool->nsolvables);
+  map_init(&installedm, pool->nsolvables);
+  map_empty(&solv->cleandepsmap);
+  queue_init(&iq);
+
+  for (i = 0; i < job->count; i += 2)
+    {
+      how = job->elements[i];
+      switch (how & SOLVER_JOBMASK)
+       {
+       case SOLVER_USERINSTALLED:
+         what = job->elements[i + 1];
+         select = how & SOLVER_SELECTMASK;
+         FOR_JOB_SELECT(p, pp, select, what)
+           if (pool->solvables[p].repo == installed)
+             MAPSET(&userinstalled, p - installed->start);
+         break;
+       }
+    }
+  /* add all positive elements (e.g. locks) to "userinstalled" */
+  for (rid = solv->jobrules; rid < solv->jobrules_end; rid++)
+    {
+      r = solv->rules + rid;
+      if (r->d < 0)
+       continue;
+      FOR_RULELITERALS(p, jp, r)
+       if (p > 0 && pool->solvables[p].repo == installed)
+         MAPSET(&userinstalled, p - installed->start);
+    }
+  for (rid = solv->jobrules; rid < solv->jobrules_end; rid++)
+    {
+      r = solv->rules + rid;
+      if (r->p >= 0 || r->d != 0)
+       continue;       /* disabled or not erase */
+      p = -r->p;
+      if (pool->solvables[p].repo != installed)
+       continue;
+      MAPCLR(&userinstalled, p - installed->start);
+      i = solv->ruletojob.elements[rid - solv->jobrules];
+      how = job->elements[i];
+      if ((how & (SOLVER_JOBMASK|SOLVER_CLEANDEPS)) == (SOLVER_ERASE|SOLVER_CLEANDEPS))
+       queue_push(&iq, p);
+    }
+  for (p = installed->start; p < installed->end; p++)
+    {
+      if (pool->solvables[p].repo != installed)
+       continue;
+      MAPSET(&installedm, p);
+      MAPSET(&im, p);
+    }
+
+  while (iq.count)
+    {
+      ip = queue_shift(&iq);
+      if (!MAPTST(&im, ip))
+       continue;
+      if (!MAPTST(&installedm, ip))
+       continue;
+      if (MAPTST(&userinstalled, ip))
+       continue;
+      MAPCLR(&im, ip);
+      s = pool->solvables + ip;
+#ifdef CLEANDEPSDEBUG
+      printf("hello %s\n", solvable2str(pool, s));
+#endif
+      if (s->requires)
+       {
+         reqp = s->repo->idarraydata + s->requires;
+         while ((req = *reqp++) != 0)
+           {
+             if (req == SOLVABLE_PREREQMARKER)
+               continue;
+#if 0
+             /* count number of installed packages that match */
+             count = 0;
+             FOR_PROVIDES(p, pp, req)
+               if (MAPTST(&installedm, p))
+                 count++;
+             if (count > 1)
+               continue;
+#endif
+             FOR_PROVIDES(p, pp, req)
+               {
+                 if (MAPTST(&im, p))
+                   {
+#ifdef CLEANDEPSDEBUG
+                     printf("%s requires %s\n", solvid2str(pool, ip), solvid2str(pool, p));
+#endif
+                     queue_push(&iq, p);
+                   }
+               }
+           }
+       }
+      if (s->recommends)
+       {
+         reqp = s->repo->idarraydata + s->recommends;
+         while ((req = *reqp++) != 0)
+           {
+#if 0
+             count = 0;
+             FOR_PROVIDES(p, pp, req)
+               if (MAPTST(&installedm, p))
+                 count++;
+             if (count > 1)
+               continue;
+#endif
+             FOR_PROVIDES(p, pp, req)
+               {
+                 if (MAPTST(&im, p))
+                   {
+#ifdef CLEANDEPSDEBUG
+                     printf("%s recommends %s\n", solvid2str(pool, ip), solvid2str(pool, p));
+#endif
+                     queue_push(&iq, p);
+                   }
+               }
+           }
+       }
+      if (!iq.count)
+       {
+         /* supplements pass */
+         for (ip = solv->installed->start; ip < solv->installed->end; ip++)
+           {
+             if (!MAPTST(&installedm, ip))
+               continue;
+             s = pool->solvables + ip;
+             if (!s->supplements)
+               continue;
+             if (!MAPTST(&im, ip))
+               continue;
+             supp = s->repo->idarraydata + s->supplements;
+             while ((sup = *supp++) != 0)
+               if (!dep_possible(solv, sup, &im) && dep_possible(solv, sup, &installedm))
+                 break;
+             /* no longer supplemented, also erase */
+             if (sup)
+               {
+#ifdef CLEANDEPSDEBUG
+                 printf("%s supplemented\n", solvid2str(pool, ip));
+#endif
+                 queue_push(&iq, ip);
+               }
+           }
+       }
+    }
+
+  /* turn userinstalled into remove set for pruning */
+  map_empty(&userinstalled);
+  for (rid = solv->jobrules; rid < solv->jobrules_end; rid++)
+    {
+      r = solv->rules + rid;
+      if (r->p >= 0 || r->d != 0)
+       continue;       /* disabled or not erase */
+      p = -r->p;
+      MAPCLR(&im, p);
+      if (pool->solvables[p].repo == installed)
+        MAPSET(&userinstalled, p - installed->start);
+    }
+  for (p = installed->start; p < installed->end; p++)
+    if (MAPTST(&im, p))
+      queue_push(&iq, p);
+  for (rid = solv->jobrules; rid < solv->jobrules_end; rid++)
+    {
+      r = solv->rules + rid;
+      if (r->d < 0)
+       continue;
+      FOR_RULELITERALS(p, jp, r)
+       if (p > 0)
+          queue_push(&iq, p);
+    }
+  while (iq.count)
+    {
+      ip = queue_shift(&iq);
+      s = pool->solvables + ip;
+#ifdef CLEANDEPSDEBUG
+      printf("bye %s\n", solvable2str(pool, s));
+#endif
+      if (s->requires)
+       {
+         reqp = s->repo->idarraydata + s->requires;
+         while ((req = *reqp++) != 0)
+           {
+             FOR_PROVIDES(p, pp, req)
+               {
+                 if (!MAPTST(&im, p) && MAPTST(&installedm, p))
+                   {
+                     if (p == ip)
+                       continue;
+#ifdef CLEANDEPSDEBUG
+                     printf("%s requires %s\n", solvid2str(pool, ip), solvid2str(pool, p));
+#endif
+                     MAPSET(&im, p);
+                     queue_push(&iq, p);
+                   }
+               }
+           }
+       }
+      if (s->recommends)
+       {
+         reqp = s->repo->idarraydata + s->recommends;
+         while ((req = *reqp++) != 0)
+           {
+             FOR_PROVIDES(p, pp, req)
+               {
+                 if (!MAPTST(&im, p) && MAPTST(&installedm, p))
+                   {
+                     if (p == ip)
+                       continue;
+                     if (MAPTST(&userinstalled, p - installed->start))
+                       continue;
+#ifdef CLEANDEPSDEBUG
+                     printf("%s recommends %s\n", solvid2str(pool, ip), solvid2str(pool, p));
+#endif
+                     MAPSET(&im, p);
+                     queue_push(&iq, p);
+                   }
+               }
+           }
+       }
+      if (!iq.count)
+       {
+         /* supplements pass */
+         for (ip = installed->start; ip < installed->end; ip++)
+           {
+             if (!MAPTST(&installedm, ip))
+               continue;
+             if (MAPTST(&userinstalled, ip - installed->start))
+               continue;
+             s = pool->solvables + ip;
+             if (!s->supplements)
+               continue;
+             if (MAPTST(&im, ip) || !MAPTST(&installedm, ip))
+               continue;
+             supp = s->repo->idarraydata + s->supplements;
+             while ((sup = *supp++) != 0)
+               if (dep_possible(solv, sup, &im))
+                 break;
+             if (sup)
+               {
+#ifdef CLEANDEPSDEBUG
+                 printf("%s supplemented\n", solvid2str(pool, ip));
+#endif
+                 MAPSET(&im, ip);
+                 queue_push(&iq, ip);
+               }
+           }
+       }
+    }
+    
+  queue_free(&iq);
+  for (p = installed->start; p < installed->end; p++)
+    {
+      if (pool->solvables[p].repo != installed)
+       continue;
+      if (!MAPTST(&im, p))
+        MAPSET(&solv->cleandepsmap, p - installed->start);
+    }
+  map_free(&im);
+  map_free(&installedm);
+  map_free(&userinstalled);
+}
+
+
 /* EOF */
index e56c20f..e4effa1 100644 (file)
@@ -1296,6 +1296,7 @@ solver_free(Solver *solv)
   map_free(&solv->dupmap);
   map_free(&solv->dupinvolvedmap);
   map_free(&solv->droporphanedmap);
+  map_free(&solv->cleandepsmap);
 
   sat_free(solv->decisionmap);
   sat_free(solv->rules);
@@ -1548,8 +1549,16 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
                  if (solv->decisionmap[i] == 0)
                    {
                      olevel = level;
-                     POOL_DEBUG(SAT_DEBUG_POLICY, "keeping %s\n", solvid2str(pool, i));
-                     level = setpropagatelearn(solv, level, i, disablerules, r - solv->rules);
+                     if (solv->cleandepsmap.size && MAPTST(&solv->cleandepsmap, i - installed->start))
+                       {
+                         POOL_DEBUG(SAT_DEBUG_POLICY, "cleandeps erasing %s\n", solvid2str(pool, i));
+                         level = setpropagatelearn(solv, level, -i, disablerules, 0);
+                       }
+                     else
+                       {
+                         POOL_DEBUG(SAT_DEBUG_POLICY, "keeping %s\n", solvid2str(pool, i));
+                         level = setpropagatelearn(solv, level, i, disablerules, r - solv->rules);
+                       }
                      if (level == 0)
                        {
                          queue_free(&dq);
@@ -2421,6 +2430,18 @@ solver_calculate_noobsmap(Pool *pool, Queue *job, Map *noobsmap)
 }
 
 /*
+ * add a rule created by a job, record job number and weak flag
+ */
+static inline void
+solver_addjobrule(Solver *solv, Id p, Id d, Id job, int weak)
+{
+  solver_addrule(solv, p, d);
+  queue_push(&solv->ruletojob, job);
+  if (weak)
+    queue_push(&solv->weakruleq, solv->nrules - 1);
+}
+
+/*
  *
  * solve job queue
  *
@@ -2730,18 +2751,18 @@ solver_solve(Solver *solv, Queue *job)
              p = queue_shift(&q);      /* get first candidate */
              d = !q.count ? 0 : pool_queuetowhatprovides(pool, &q);    /* internalize */
            }
-         solver_addrule(solv, p, d);           /* add install rule */
-         queue_push(&solv->ruletojob, i);
-         if (weak)
-           queue_push(&solv->weakruleq, solv->nrules - 1);
+         solver_addjobrule(solv, p, d, i, weak);
          break;
        case SOLVER_ERASE:
-         POOL_DEBUG(SAT_DEBUG_JOB, "job: %serase %s\n", weak ? "weak " : "", solver_select2str(solv, select, what));
+         POOL_DEBUG(SAT_DEBUG_JOB, "job: %s%serase %s\n", weak ? "weak " : "", how & SOLVER_CLEANDEPS ? "clean deps " : "", solver_select2str(solv, select, what));
+         if ((how & SOLVER_CLEANDEPS) != 0 && !solv->cleandepsmap.size && solv->installed)
+           map_grow(&solv->cleandepsmap, solv->installed->end - solv->installed->start);
           if (select == SOLVER_SOLVABLE && solv->installed && pool->solvables[what].repo == solv->installed)
            {
              /* special case for "erase a specific solvable": we also
                * erase all other solvables with that name, so that they
                * don't get picked up as replacement */
+             /* XXX: look also at packages that obsolete this package? */
              name = pool->solvables[what].name;
              FOR_PROVIDES(p, pp, name)
                {
@@ -2756,19 +2777,11 @@ solver_solve(Solver *solv, Queue *job)
                  /* keep installcandidates of other jobs */
                  if (MAPTST(&installcandidatemap, p))
                    continue;
-                 solver_addrule(solv, -p, 0);                  /* remove by Id */
-                 queue_push(&solv->ruletojob, i);
-                 if (weak)
-                   queue_push(&solv->weakruleq, solv->nrules - 1);
+                 solver_addjobrule(solv, -p, 0, i, weak);      /* remove by id */
                }
            }
          FOR_JOB_SELECT(p, pp, select, what)
-           {
-             solver_addrule(solv, -p, 0);
-             queue_push(&solv->ruletojob, i);
-             if (weak)
-               queue_push(&solv->weakruleq, solv->nrules - 1);
-           }
+           solver_addjobrule(solv, -p, 0, i, weak);
          break;
 
        case SOLVER_UPDATE:
@@ -2801,13 +2814,7 @@ solver_solve(Solver *solv, Queue *job)
          FOR_JOB_SELECT(p, pp, select, what)
            {
              s = pool->solvables + p;
-             if (installed && s->repo == installed)
-               solver_addrule(solv, p, 0);
-             else
-               solver_addrule(solv, -p, 0);
-             queue_push(&solv->ruletojob, i);
-             if (weak)
-               queue_push(&solv->weakruleq, solv->nrules - 1);
+             solver_addjobrule(solv, installed && s->repo == installed ? p : -p, 0, i, weak);
            }
          break;
        case SOLVER_DISTUPGRADE:
@@ -2825,6 +2832,9 @@ solver_solve(Solver *solv, Queue *job)
              MAPSET(&solv->droporphanedmap, p - installed->start);
            }
          break;
+       case SOLVER_USERINSTALLED:
+         POOL_DEBUG(SAT_DEBUG_JOB, "job: user installed %s\n", solver_select2str(solv, select, what));
+         break;
        default:
          POOL_DEBUG(SAT_DEBUG_JOB, "job: unknown job\n");
          break;
@@ -2993,237 +3003,3 @@ solver_trivial_installable(Solver *solv, Queue *pkgs, Queue *res)
   map_free(&installedmap);
 }
 
-
-#if 0
-#define FIND_INVOLVED_DEBUG 0
-void
-solver_find_involved(Solver *solv, Queue *installedq, Solvable *ts, Queue *q)
-{
-  Pool *pool = solv->pool;
-  Map im;
-  Map installedm;
-  Solvable *s;
-  Queue iq;
-  Queue installedq_internal;
-  Id tp, ip, p, pp, req, *reqp, sup, *supp;
-  int i, count;
-
-  tp = ts - pool->solvables;
-  queue_init(&iq);
-  queue_init(&installedq_internal);
-  map_init(&im, pool->nsolvables);
-  map_init(&installedm, pool->nsolvables);
-
-  if (!installedq)
-    {
-      installedq = &installedq_internal;
-      if (solv->installed)
-       {
-         for (ip = solv->installed->start; ip < solv->installed->end; ip++)
-           {
-             s = pool->solvables + ip;
-             if (s->repo != solv->installed)
-               continue;
-             queue_push(installedq, ip);
-           }
-       }
-    }
-  for (i = 0; i < installedq->count; i++)
-    {
-      ip = installedq->elements[i];
-      MAPSET(&installedm, ip);
-      MAPSET(&im, ip);
-    }
-
-  queue_push(&iq, ts - pool->solvables);
-  while (iq.count)
-    {
-      ip = queue_shift(&iq);
-      if (!MAPTST(&im, ip))
-       continue;
-      if (!MAPTST(&installedm, ip))
-       continue;
-      MAPCLR(&im, ip);
-      s = pool->solvables + ip;
-#if FIND_INVOLVED_DEBUG
-      printf("hello %s\n", solvable2str(pool, s));
-#endif
-      if (s->requires)
-       {
-         reqp = s->repo->idarraydata + s->requires;
-         while ((req = *reqp++) != 0)
-           {
-             if (req == SOLVABLE_PREREQMARKER)
-               continue;
-             /* count number of installed packages that match */
-             count = 0;
-             FOR_PROVIDES(p, pp, req)
-               if (MAPTST(&installedm, p))
-                 count++;
-             if (count > 1)
-               continue;
-             FOR_PROVIDES(p, pp, req)
-               {
-                 if (MAPTST(&im, p))
-                   {
-#if FIND_INVOLVED_DEBUG
-                     printf("%s requires %s\n", solvid2str(pool, ip), solvid2str(pool, p));
-#endif
-                     queue_push(&iq, p);
-                   }
-               }
-           }
-       }
-      if (s->recommends)
-       {
-         reqp = s->repo->idarraydata + s->recommends;
-         while ((req = *reqp++) != 0)
-           {
-             count = 0;
-             FOR_PROVIDES(p, pp, req)
-               if (MAPTST(&installedm, p))
-                 count++;
-             if (count > 1)
-               continue;
-             FOR_PROVIDES(p, pp, req)
-               {
-                 if (MAPTST(&im, p))
-                   {
-#if FIND_INVOLVED_DEBUG
-                     printf("%s recommends %s\n", solvid2str(pool, ip), solvid2str(pool, p));
-#endif
-                     queue_push(&iq, p);
-                   }
-               }
-           }
-       }
-      if (!iq.count)
-       {
-         /* supplements pass */
-         for (i = 0; i < installedq->count; i++)
-           {
-             ip = installedq->elements[i];
-             s = pool->solvables + ip;
-             if (!s->supplements)
-               continue;
-             if (!MAPTST(&im, ip))
-               continue;
-             supp = s->repo->idarraydata + s->supplements;
-             while ((sup = *supp++) != 0)
-               if (!dep_possible(solv, sup, &im) && dep_possible(solv, sup, &installedm))
-                 break;
-             /* no longer supplemented, also erase */
-             if (sup)
-               {
-#if FIND_INVOLVED_DEBUG
-                 printf("%s supplemented\n", solvid2str(pool, ip));
-#endif
-                 queue_push(&iq, ip);
-               }
-           }
-       }
-    }
-
-  for (i = 0; i < installedq->count; i++)
-    {
-      ip = installedq->elements[i];
-      if (MAPTST(&im, ip))
-       queue_push(&iq, ip);
-    }
-
-  while (iq.count)
-    {
-      ip = queue_shift(&iq);
-      if (!MAPTST(&installedm, ip))
-       continue;
-      s = pool->solvables + ip;
-#if FIND_INVOLVED_DEBUG
-      printf("bye %s\n", solvable2str(pool, s));
-#endif
-      if (s->requires)
-       {
-         reqp = s->repo->idarraydata + s->requires;
-         while ((req = *reqp++) != 0)
-           {
-             FOR_PROVIDES(p, pp, req)
-               {
-                 if (!MAPTST(&im, p))
-                   {
-                     if (p == tp)
-                       continue;
-#if FIND_INVOLVED_DEBUG
-                     printf("%s requires %s\n", solvid2str(pool, ip), solvid2str(pool, p));
-#endif
-                     MAPSET(&im, p);
-                     queue_push(&iq, p);
-                   }
-               }
-           }
-       }
-      if (s->recommends)
-       {
-         reqp = s->repo->idarraydata + s->recommends;
-         while ((req = *reqp++) != 0)
-           {
-             FOR_PROVIDES(p, pp, req)
-               {
-                 if (!MAPTST(&im, p))
-                   {
-                     if (p == tp)
-                       continue;
-#if FIND_INVOLVED_DEBUG
-                     printf("%s recommends %s\n", solvid2str(pool, ip), solvid2str(pool, p));
-#endif
-                     MAPSET(&im, p);
-                     queue_push(&iq, p);
-                   }
-               }
-           }
-       }
-      if (!iq.count)
-       {
-         /* supplements pass */
-         for (i = 0; i < installedq->count; i++)
-           {
-             ip = installedq->elements[i];
-             if (ip == tp)
-               continue;
-             s = pool->solvables + ip;
-             if (!s->supplements)
-               continue;
-             if (MAPTST(&im, ip))
-               continue;
-             supp = s->repo->idarraydata + s->supplements;
-             while ((sup = *supp++) != 0)
-               if (dep_possible(solv, sup, &im))
-                 break;
-             if (sup)
-               {
-#if FIND_INVOLVED_DEBUG
-                 printf("%s supplemented\n", solvid2str(pool, ip));
-#endif
-                 MAPSET(&im, ip);
-                 queue_push(&iq, ip);
-               }
-           }
-       }
-    }
-    
-  queue_free(&iq);
-
-  /* convert map into result */
-  for (i = 0; i < installedq->count; i++)
-    {
-      ip = installedq->elements[i];
-      if (MAPTST(&im, ip))
-       continue;
-      if (ip == ts - pool->solvables)
-       continue;
-      queue_push(q, ip);
-    }
-  map_free(&im);
-  map_free(&installedm);
-  queue_free(&installedq_internal);
-}
-#endif
-
index e8ce937..7e2d4d4 100644 (file)
@@ -205,6 +205,7 @@ typedef struct _Solver {
   Map dupmap;                          /* packages from dup repos */
   Map dupinvolvedmap;                  /* packages involved in dup process */
   Map droporphanedmap;                 /* packages to drop in dup mode */
+  Map cleandepsmap;                    /* try to drop those packages as of cleandeps erases */
 
   Queue *ruleinfoq;                    /* tmp space for solver_ruleinfo() */
 } Solver;
@@ -231,11 +232,13 @@ typedef struct _Solver {
 #define SOLVER_DISTUPGRADE             0x0700
 #define SOLVER_VERIFY                  0x0800
 #define SOLVER_DROP_ORPHANED           0x0900
+#define SOLVER_USERINSTALLED            0x0a00
 
 #define SOLVER_JOBMASK                 0xff00
 
 #define SOLVER_WEAK                    0x010000
 #define SOLVER_ESSENTIAL               0x020000
+#define SOLVER_CLEANDEPS                0x040000
 
 /* old API compatibility, do not use in new code */
 #if 1