implement special install/erase namespace provides hack
authorMichael Schroeder <mls@suse.de>
Mon, 10 Dec 2012 18:18:31 +0000 (19:18 +0100)
committerMichael Schroeder <mls@suse.de>
Mon, 10 Dec 2012 18:18:31 +0000 (19:18 +0100)
bindings/solv.i
examples/solv.c
src/rules.c
src/rules.h
src/solver.c
src/solver.h
src/solverdebug.c
tools/installcheck.c
tools/patchcheck.c

index 654ea86..3273b34 100644 (file)
@@ -2459,6 +2459,7 @@ typedef struct {
   static const int SOLVER_RULE_FEATURE = SOLVER_RULE_FEATURE;
   static const int SOLVER_RULE_JOB = SOLVER_RULE_JOB;
   static const int SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP = SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP;
+  static const int SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM = SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM;
   static const int SOLVER_RULE_DISTUPGRADE = SOLVER_RULE_DISTUPGRADE;
   static const int SOLVER_RULE_INFARCH = SOLVER_RULE_INFARCH;
   static const int SOLVER_RULE_CHOICE = SOLVER_RULE_CHOICE;
index 3d690f1..6218e64 100644 (file)
@@ -2214,6 +2214,19 @@ nscallback(Pool *pool, void *data, Id name, Id evr)
         }
       return bestp;
     }
+#if 0
+  if (name == NAMESPACE_LANGUAGE)
+    {
+      if (!strcmp(pool_id2str(pool, evr), "ja"))
+       return 1;
+      if (!strcmp(pool_id2str(pool, evr), "de"))
+       return 1;
+      if (!strcmp(pool_id2str(pool, evr), "en"))
+       return 1;
+      if (!strcmp(pool_id2str(pool, evr), "en_US"))
+       return 1;
+    }
+#endif
   return 0;
 }
 
@@ -2808,6 +2821,10 @@ main(int argc, char **argv)
   // queue_push2(&job, SOLVER_NOOBSOLETES|SOLVER_SOLVABLE_NAME, pool_str2id(pool, "kernel-pae", 1));
   // queue_push2(&job, SOLVER_NOOBSOLETES|SOLVER_SOLVABLE_NAME, pool_str2id(pool, "kernel-pae-base", 1));
   // queue_push2(&job, SOLVER_NOOBSOLETES|SOLVER_SOLVABLE_NAME, pool_str2id(pool, "kernel-pae-extra", 1));
+#if 0
+  queue_push2(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, NAMESPACE_LANGUAGE, 0, REL_NAMESPACE, 1));
+  queue_push2(&job, SOLVER_ERASE|SOLVER_CLEANDEPS|SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, NAMESPACE_LANGUAGE, 0, REL_NAMESPACE, 1));
+#endif
 
 #ifdef SOFTLOCKS_PATH
   addsoftlocks(pool, &job);
index 4a9459d..9b9b8aa 100644 (file)
@@ -35,8 +35,8 @@ static void solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unnee
 /*-------------------------------------------------------------------
  * Check if dependency is possible
  * 
- * mirrors solver_dep_fulfilled but uses map m instead of the decisionmap
- * used in solver_addrpmrulesforweak and solver_createcleandepsmap
+ * mirrors solver_dep_fulfilled but uses map m instead of the decisionmap.
+ * used in solver_addrpmrulesforweak and solver_createcleandepsmap.
  */
 
 static inline int
@@ -2132,10 +2132,14 @@ solver_ruleinfo(Solver *solv, Id rid, Id *fromp, Id *top, Id *depp)
        *depp = solv->job.elements[jidx + 1];
       if ((r->d == 0 || r->d == -1) && r->w2 == 0 && r->p == -SYSTEMSOLVABLE)
        {
-         if ((solv->job.elements[jidx] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_NAME)
+         if ((solv->job.elements[jidx] & (SOLVER_JOBMASK|SOLVER_SELECTMASK)) == (SOLVER_INSTALL|SOLVER_SOLVABLE_NAME))
            return SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP;
-         if ((solv->job.elements[jidx] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_PROVIDES)
+         if ((solv->job.elements[jidx] & (SOLVER_JOBMASK|SOLVER_SELECTMASK)) == (SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES))
            return SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP;
+         if ((solv->job.elements[jidx] & (SOLVER_JOBMASK|SOLVER_SELECTMASK)) == (SOLVER_ERASE|SOLVER_SOLVABLE_NAME))
+           return SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM;
+         if ((solv->job.elements[jidx] & (SOLVER_JOBMASK|SOLVER_SELECTMASK)) == (SOLVER_ERASE|SOLVER_SOLVABLE_PROVIDES))
+           return SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM;
        }
       return SOLVER_RULE_JOB;
     }
@@ -2671,6 +2675,59 @@ dep_pkgcheck(Solver *solv, Id dep, Map *m, Queue *q)
       queue_push(q, p);
 }
 
+static int
+check_xsupp(Solver *solv, Queue *depq, Id dep)
+{
+  Pool *pool = solv->pool;
+  Id p, pp;
+
+  if (ISRELDEP(dep))
+    {
+      Reldep *rd = GETRELDEP(pool, dep);
+      if (rd->flags >= 8)
+       {
+         if (rd->flags == REL_AND)
+           {
+             if (!check_xsupp(solv, depq, rd->name))
+               return 0;
+             return check_xsupp(solv, depq, rd->evr);
+           }
+         if (rd->flags == REL_OR)
+           {
+             if (check_xsupp(solv, depq, rd->name))
+               return 1;
+             return check_xsupp(solv, depq, rd->evr);
+           }
+         if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
+           return solver_splitprovides(solv, rd->evr);
+         if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
+           return solver_dep_installed(solv, rd->evr);
+       }
+      if (depq && rd->flags == REL_NAMESPACE)
+       {
+         int i;
+         for (i = 0; i < depq->count; i++)
+           if (depq->elements[i] == dep || depq->elements[i] == rd->name)
+            return 1;
+       }
+    }
+  FOR_PROVIDES(p, pp, dep)
+    if (p == SYSTEMSOLVABLE || pool->solvables[p].repo == solv->installed)
+      return 1;
+  return 0;
+}
+
+static inline int
+queue_contains(Queue *q, Id id)
+{
+  int i;
+  for (i = 0; i < q->count; i++)
+    if (q->elements[i] == id)
+      return 1;
+  return 0;
+}
+
+
 /*
  * Find all installed packages that are no longer
  * needed regarding the current solver job.
@@ -2707,7 +2764,7 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded)
   Id p, pp, ip, jp;
   Id req, *reqp, sup, *supp;
   Solvable *s;
-  Queue iq, iqcopy;
+  Queue iq, iqcopy, xsuppq;
   int i;
 
   map_empty(cleandepsmap);
@@ -2717,6 +2774,7 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded)
   map_init(&im, pool->nsolvables);
   map_init(&installedm, pool->nsolvables);
   queue_init(&iq);
+  queue_init(&xsuppq);
 
   for (i = 0; i < job->count; i += 2)
     {
@@ -2732,6 +2790,50 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded)
            if (pool->solvables[p].repo == installed)
              MAPSET(&userinstalled, p - installed->start);
        }
+      if ((how & (SOLVER_JOBMASK | SOLVER_SELECTMASK)) == (SOLVER_ERASE | SOLVER_SOLVABLE_PROVIDES))
+       {
+         what = job->elements[i + 1];
+         if (ISRELDEP(what))
+           {
+             Reldep *rd = GETRELDEP(pool, what);
+             if (rd->flags != REL_NAMESPACE)
+               continue;
+             if (rd->evr == 0)
+               {
+                 queue_pushunique(&iq, rd->name);
+                 continue;
+               }
+             FOR_PROVIDES(p, pp, what)
+               if (p)
+                 break;
+             if (p)
+               continue;
+             queue_pushunique(&iq, what);
+           }
+       }
+    }
+
+  /* have special namespace cleandeps erases */
+  if (iq.count)
+    {
+      for (ip = solv->installed->start; ip < solv->installed->end; ip++)
+       {
+         s = pool->solvables + ip;
+         if (s->repo != installed)
+           continue;
+         if (!s->supplements)
+           continue;
+         supp = s->repo->idarraydata + s->supplements;
+         while ((sup = *supp++) != 0)
+           if (check_xsupp(solv, &iq, sup) && !check_xsupp(solv, 0, sup))
+             {
+#ifdef CLEANDEPSDEBUG
+               printf("xsupp %s from %s\n", pool_dep2str(pool, sup), pool_solvid2str(pool, ip));
+#endif
+               queue_pushunique(&xsuppq, sup);
+             }
+       }
+      queue_empty(&iq);
     }
 
   /* also add visible patterns to userinstalled for openSUSE */
@@ -2904,6 +3006,8 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded)
        continue;
       MAPSET(&im, p);
     }
+  MAPSET(&installedm, SYSTEMSOLVABLE);
+  MAPSET(&im, SYSTEMSOLVABLE);
 
 #ifdef CLEANDEPSDEBUG
   printf("REMOVE PASS\n");
@@ -2916,7 +3020,7 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded)
          if (unneeded)
            break;
          /* supplements pass */
-         for (ip = solv->installed->start; ip < solv->installed->end; ip++)
+         for (ip = installed->start; ip < installed->end; ip++)
            {
              if (!MAPTST(&installedm, ip))
                continue;
@@ -2935,7 +3039,7 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded)
                {
                  supp = s->repo->idarraydata + s->supplements;
                  while ((sup = *supp++) != 0)
-                   if (dep_possible(solv, sup, &installedm))
+                   if (dep_possible(solv, sup, &installedm) || (xsuppq.count && queue_contains(&xsuppq, sup)))
                      {
                        /* no longer supplemented, also erase */
                        int iqcount = iq.count;
@@ -2949,14 +3053,14 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded)
                          }
                        queue_truncate(&iq, iqcount);
 #ifdef CLEANDEPSDEBUG
-                       printf("%s supplemented\n", pool_solvid2str(pool, ip));
+                       printf("%s supplemented [%s]\n", pool_solvid2str(pool, ip), pool_dep2str(pool, sup));
 #endif
                        queue_push(&iq, ip);
                      }
                }
            }
          if (!iq.count)
-           break;
+           break;      /* no supplementing package found, we're done */
        }
       ip = queue_shift(&iq);
       s = pool->solvables + ip;
@@ -2988,7 +3092,7 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded)
 #endif
              FOR_PROVIDES(p, pp, req)
                {
-                 if (MAPTST(&im, p))
+                 if (p != SYSTEMSOLVABLE && MAPTST(&im, p))
                    {
 #ifdef CLEANDEPSDEBUG
                      printf("%s requires %s\n", pool_solvid2str(pool, ip), pool_solvid2str(pool, p));
@@ -3013,7 +3117,7 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded)
 #endif
              FOR_PROVIDES(p, pp, req)
                {
-                 if (MAPTST(&im, p))
+                 if (p != SYSTEMSOLVABLE && MAPTST(&im, p))
                    {
 #ifdef CLEANDEPSDEBUG
                      printf("%s recommends %s\n", pool_solvid2str(pool, ip), pool_solvid2str(pool, p));
@@ -3037,6 +3141,7 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded)
       if (pool->solvables[p].repo == installed)
         MAPSET(&userinstalled, p - installed->start);
     }
+  MAPSET(&im, SYSTEMSOLVABLE); /* in case we cleared it above */
   for (p = installed->start; p < installed->end; p++)
     if (MAPTST(&im, p))
       queue_push(&iq, p);
@@ -3109,6 +3214,11 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded)
          while ((req = *reqp++) != 0)
            {
              FOR_PROVIDES(p, pp, req)
+               if (MAPTST(&im, p))
+                 break;
+             if (p)
+               continue;
+             FOR_PROVIDES(p, pp, req)
                {
                  if (!MAPTST(&im, p) && MAPTST(&installedm, p))
                    {
@@ -3131,6 +3241,11 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded)
          while ((req = *reqp++) != 0)
            {
              FOR_PROVIDES(p, pp, req)
+               if (MAPTST(&im, p))
+                 break;
+             if (p)
+               continue;
+             FOR_PROVIDES(p, pp, req)
                {
                  if (!MAPTST(&im, p) && MAPTST(&installedm, p))
                    {
@@ -3171,6 +3286,7 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded)
   map_free(&im);
   map_free(&installedm);
   map_free(&userinstalled);
+  queue_free(&xsuppq);
 #ifdef CLEANDEPSDEBUG
   printf("=== final cleandeps map:\n");
   for (p = installed->start; p < installed->end; p++)
index d42b22b..144b683 100644 (file)
@@ -62,6 +62,7 @@ typedef enum {
   SOLVER_RULE_FEATURE = 0x300,
   SOLVER_RULE_JOB = 0x400,
   SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP,
+  SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM,
   SOLVER_RULE_DISTUPGRADE = 0x500,
   SOLVER_RULE_INFARCH = 0x600,
   SOLVER_RULE_CHOICE = 0x700,
index 8b6140c..76680ce 100644 (file)
@@ -103,6 +103,64 @@ solver_dep_installed(Solver *solv, Id dep)
   return 0;
 }
 
+/* mirrors solver_dep_installed, but returns 2 if a
+ * dependency listed in solv->installsuppdepq was involved */
+static int
+solver_check_installsuppdepq_dep(Solver *solv, Id dep)
+{
+  Pool *pool = solv->pool;
+  Id p, pp;
+  Queue *q;
+
+  if (ISRELDEP(dep))
+    {
+      Reldep *rd = GETRELDEP(pool, dep);
+      if (rd->flags == REL_AND)
+        {
+         int r2, r1 = solver_check_installsuppdepq_dep(solv, rd->name);
+          if (!r1)
+            return 0;
+         r2 = solver_check_installsuppdepq_dep(solv, rd->evr);
+         if (!r2)
+           return 0;
+          return r1 == 2 || r2 == 2 ? 2 : 1;
+        }
+      if (rd->flags == REL_OR)
+       {
+         int r2, r1 = solver_check_installsuppdepq_dep(solv, rd->name);
+         r2 = solver_check_installsuppdepq_dep(solv, rd->evr);
+         if (!r1 && !r2)
+           return 0;
+          return r1 == 2 || r2 == 2 ? 2 : 1;
+       }
+      if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
+        return solver_splitprovides(solv, rd->evr);
+      if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
+        return solver_dep_installed(solv, rd->evr);
+      if (rd->flags == REL_NAMESPACE && (q = solv->installsuppdepq) != 0)
+       {
+         int i;
+         for (i = 0; i < q->count; i++)
+           if (q->elements[i] == dep || q->elements[i] == rd->name)
+             return 2;
+       }
+    }
+  FOR_PROVIDES(p, pp, dep)
+    if (solv->decisionmap[p] > 0)
+      return 1;
+  return 0;
+}
+
+static int
+solver_check_installsuppdepq(Solver *solv, Solvable *s)
+{
+  Id sup, *supp;
+  supp = s->repo->idarraydata + s->supplements;
+  while ((sup = *supp++) != 0)
+    if (solver_check_installsuppdepq_dep(solv, sup) == 2)
+      return 1;
+  return 0;
+}
 
 static Id
 autouninstall(Solver *solv, Id *problem)
@@ -1430,6 +1488,11 @@ solver_free(Solver *solv)
       queue_free(solv->update_targets);
       solv->update_targets = solv_free(solv->update_targets);
     }
+  if (solv->installsuppdepq)
+    {
+      queue_free(solv->installsuppdepq);
+      solv->installsuppdepq = solv_free(solv->installsuppdepq);
+    }
 
   map_free(&solv->recommendsmap);
   map_free(&solv->suggestsmap);
@@ -2151,6 +2214,8 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
                    continue;
                  if (!solver_is_supplementing(solv, s))
                    dqs.elements[j++] = p;
+                 else if (s->supplements && solv->installsuppdepq && solver_check_installsuppdepq(solv, s))
+                   dqs.elements[j++] = p;
                }
              dqs.count = j;
              /* undo turning off */
@@ -3140,6 +3205,21 @@ solver_solve(Solver *solv, Queue *job)
              p = queue_shift(&q);      /* get first candidate */
              d = !q.count ? 0 : pool_queuetowhatprovides(pool, &q);    /* internalize */
            }
+         /* force install of namespace supplements hack */
+         if (select == SOLVER_SOLVABLE_PROVIDES && !d && (p == SYSTEMSOLVABLE || p == -SYSTEMSOLVABLE) && ISRELDEP(what))
+           {
+             Reldep *rd = GETRELDEP(pool, what);
+             if (rd->flags == REL_NAMESPACE)
+               {
+                 p = SYSTEMSOLVABLE;
+                 if (!solv->installsuppdepq)
+                   {
+                     solv->installsuppdepq = solv_calloc(1, sizeof(Queue));
+                     queue_init(solv->installsuppdepq);
+                   }
+                 queue_pushunique(solv->installsuppdepq, rd->evr == 0 ? rd->name : what);
+               }
+           }
          solver_addjobrule(solv, p, d, i, weak);
           if (how & SOLVER_FORCEBEST)
            hasbestinstalljob = 1;
index fac1a17..dc7377f 100644 (file)
@@ -225,6 +225,8 @@ struct _Solver {
   Queue *cleandeps_mistakes;           /* mistakes we made */
 
   Queue *update_targets;               /* update to specific packages */
+
+  Queue *installsuppdepq;              /* deps from the install namespace provides hack */
 #endif /* LIBSOLV_INTERNAL */
 };
 
index a755da3..58785f7 100644 (file)
@@ -569,6 +569,9 @@ solver_printproblemruleinfo(Solver *solv, Id probr)
     case SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP:
       POOL_DEBUG(SOLV_DEBUG_RESULT, "nothing provides requested %s\n", pool_dep2str(pool, dep));
       return;
+    case SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM:
+      POOL_DEBUG(SOLV_DEBUG_RESULT, "%s is provided by the system\n", pool_dep2str(pool, dep));
+      return;
     case SOLVER_RULE_RPM:
       POOL_DEBUG(SOLV_DEBUG_RESULT, "some dependency problem\n");
       return;
@@ -996,6 +999,8 @@ solver_problemruleinfo2str(Solver *solv, SolverRuleinfo type, Id source, Id targ
       return "conflicting requests";
     case SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP:
       return pool_tmpjoin(pool, "nothing provides requested ", pool_dep2str(pool, dep), 0);
+    case SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM:
+      return pool_tmpjoin(pool, pool_dep2str(pool, dep), " is provided by the system", 0);
     case SOLVER_RULE_RPM:
       return "some dependency problem";
     case SOLVER_RULE_RPM_NOT_INSTALLABLE:
index 3721682..4859bc2 100644 (file)
@@ -379,6 +379,7 @@ main(int argc, char **argv)
                          printf("  %s can not be updated\n", pool_solvable2str(pool, s));
                          break;
                        case SOLVER_RULE_JOB:
+                       case SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM:
                          break;
                        case SOLVER_RULE_RPM:
                          printf("  some dependency problem\n");
index 7c91974..6edc51f 100644 (file)
@@ -93,6 +93,7 @@ showproblems(Solver *solv, Solvable *s, Queue *cand, Queue *badguys)
                      }
                  break;
                case SOLVER_RULE_JOB:
+               case SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM:
                  break;
                case SOLVER_RULE_RPM:
                  printf("  some dependency problem\n");