- create transaction as solver result
authorMichael Schroeder <mls@suse.de>
Thu, 16 Apr 2009 16:59:46 +0000 (18:59 +0200)
committerMichael Schroeder <mls@suse.de>
Thu, 16 Apr 2009 16:59:46 +0000 (18:59 +0200)
src/repodata.c
src/solver.c
src/solver.h
src/solverdebug.c
tools/repo_rpmmd.c

index 1e54ff6..fc7798c 100644 (file)
@@ -1265,7 +1265,7 @@ dataiterator_step(Dataiterator *di)
              continue;
            }
          if (!datamatcher_match(&di->matcher, di->kv.str))
-         continue;
+           continue;
        }
       /* found something! */
       return 1;
index a2e82f4..2d64b66 100644 (file)
@@ -2603,6 +2603,8 @@ solver_create(Pool *pool)
   solv->pool = pool;
   solv->installed = pool->installed;
 
+  queue_init(&solv->transaction);
+  queue_init(&solv->transaction_info);
   queue_init(&solv->ruletojob);
   queue_init(&solv->decisionq);
   queue_init(&solv->decisionq_why);
@@ -2639,6 +2641,8 @@ solver_create(Pool *pool)
 void
 solver_free(Solver *solv)
 {
+  queue_free(&solv->transaction);
+  queue_free(&solv->transaction_info);
   queue_free(&solv->job);
   queue_free(&solv->ruletojob);
   queue_free(&solv->decisionq);
@@ -4588,6 +4592,241 @@ findrecommendedsuggested(Solver *solv)
   map_free(&obsmap);
 }
 
+
+Solver *obsq_sortcmp_data;
+
+static int
+obsq_sortcmp(const void *ap, const void *bp)
+{
+  Id a, b, oa, ob;
+  Solver *solv = obsq_sortcmp_data;
+  Pool *pool = solv->pool;
+  Solvable *s, *oas, *obs;
+  int r;
+
+  a = ((Id *)ap)[0];
+  oa = ((Id *)ap)[1];
+  b = ((Id *)bp)[0];
+  ob = ((Id *)bp)[1];
+  if (a != b)
+    return a - b;
+  if (oa == ob)
+    return 0;
+  s = pool->solvables + a;
+  oas = pool->solvables + oa;
+  obs = pool->solvables + ob;
+  if (oas->name != obs->name)
+    {
+      if (oas->name == s->name)
+        return -1;
+      if (obs->name == s->name)
+        return 1;
+      return strcmp(id2str(pool, oas->name), id2str(pool, obs->name));
+    }
+  r = evrcmp(pool, oas->evr, obs->evr, EVRCMP_COMPARE);
+  if (r)
+    return -r; /* highest version first */
+  return oa - ob;
+}
+
+void
+solver_transaction_info(Solver *solv, Id p, Queue *out)
+{
+  Pool *pool = solv->pool;
+  Solvable *s = pool->solvables + p;
+  Queue *ti = &solv->transaction_info;
+  int i;
+
+  queue_empty(out);
+  if (p <= 0 || !s->repo)
+    return;
+  if (s->repo == solv->installed)
+    {
+      /* find which packages obsolete us */
+      for (i = 0; i < ti->count; i += 2)
+       if (ti->elements[i + 1] == p)
+         {
+           queue_push(out, p);
+           queue_push(out, ti->elements[i]);
+         }
+      if (out->count > 2)
+       {
+         /* sort obsoleters */
+         obsq_sortcmp_data = solv;
+         qsort(out->elements, out->count / 2, 2 * sizeof(Id), obsq_sortcmp);
+       }
+      for (i = 0; i < out->count; i += 2)
+       out->elements[i] = out->elements[i / 2 + 1];
+      out->count /= 2;
+    }
+  else
+    {
+      /* find the packages we obsolete */
+      for (i = 0; i < ti->count; i += 2)
+       {
+         if (ti->elements[i] == p)
+           queue_push(out, ti->elements[i + 1]);
+         else if (out->count)
+           break;
+       }
+    }
+}
+
+Id
+solver_transaction_pkg(Solver *solv, Id p)
+{
+  Queue ti;
+  Id tibuf[5];
+
+  queue_init_buffer(&ti, tibuf, sizeof(tibuf)/sizeof(*tibuf));
+  solver_transaction_info(solv, p, &ti);
+  p = ti.count ? ti.elements[0] : 0;
+  queue_free(&ti);
+  return p;
+}
+
+static void
+create_transaction(Solver *solv)
+{
+  Pool *pool = solv->pool;
+  Repo *installed = solv->installed;
+  Queue *ti = &solv->transaction_info;
+  int i, j, r, noobs;
+  Id p, p2, pp2;
+  Solvable *s, *s2;
+
+  queue_empty(&solv->transaction);
+  queue_empty(ti);
+
+  /* first create obsoletes index */
+  if (installed)
+    {
+      for (i = 0; i < solv->decisionq.count; i++)
+       {
+         p = solv->decisionq.elements[i];
+         if (p <= 0 || p == SYSTEMSOLVABLE)
+           continue;
+         s = pool->solvables + p;
+         if (s->repo == installed)
+           continue;
+         noobs = solv->noobsoletes.size && MAPTST(&solv->noobsoletes, p);
+         FOR_PROVIDES(p2, pp2, s->name)
+           {
+             if (solv->decisionmap[p2] > 0)
+               continue;
+             s2 = pool->solvables + p2;
+             if (s2->repo != installed)
+               continue;
+             if (noobs && (s->name != s2->name || s->evr != s2->evr || s->arch != s2->arch))
+               continue;
+             if (!solv->implicitobsoleteusesprovides && s->name != s2->name)
+               continue;
+             queue_push(ti, p);
+             queue_push(ti, p2);
+           }
+         if (s->obsoletes && !noobs)
+           {
+             Id obs, *obsp = s->repo->idarraydata + s->obsoletes;
+             while ((obs = *obsp++) != 0)
+               {
+                 FOR_PROVIDES(p2, pp2, obs)
+                   {
+                     s2 = pool->solvables + p2;
+                     if (s2->repo != installed)
+                       continue;
+                     if (!solv->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + p2, obs))
+                       continue;
+                     queue_push(ti, p);
+                     queue_push(ti, p2);
+                   }
+               }
+           }
+       }
+      obsq_sortcmp_data = solv;
+      qsort(ti->elements, ti->count / 2, 2 * sizeof(Id), obsq_sortcmp);
+      /* now unify */
+      for (i = j = 0; i < ti->count; i += 2)
+       {
+         if (j && ti->elements[i] == ti->elements[j - 2] && ti->elements[i + 1] == ti->elements[j - 1])
+           continue;
+         ti->elements[j++] = ti->elements[i];
+         ti->elements[j++] = ti->elements[i + 1];
+       }
+      ti->count = j;
+    }
+
+  if (installed)
+    {
+      FOR_REPO_SOLVABLES(installed, p, s)
+       {
+         if (solv->decisionmap[p] > 0)
+           continue;
+         p2 = solver_transaction_pkg(solv, p);
+         if (!p2)
+           queue_push(&solv->transaction, SOLVER_TRANSACTION_ERASE);
+         else
+           {
+             s2 = pool->solvables + p2;
+             if (s->name == s2->name)
+               {
+                 if (s->evr == s2->evr && solvable_identical(s, s2))
+                   queue_push(&solv->transaction, SOLVER_TRANSACTION_REINSTALLED);
+                 else
+                   {
+                     r = evrcmp(pool, s->evr, s2->evr, EVRCMP_COMPARE);
+                     if (r < 0)
+                       queue_push(&solv->transaction, SOLVER_TRANSACTION_UPGRADED);
+                     else if (r > 0)
+                       queue_push(&solv->transaction, SOLVER_TRANSACTION_DOWNGRADED);
+                     else
+                       queue_push(&solv->transaction, SOLVER_TRANSACTION_CHANGED);
+                   }
+               }
+             else
+               queue_push(&solv->transaction, SOLVER_TRANSACTION_OBSOLETED);
+           }
+         queue_push(&solv->transaction, p);
+       }
+    }
+  for (i = 0; i < solv->decisionq.count; i++)
+    {
+      p = solv->decisionq.elements[i];
+      if (p < 0 || p == SYSTEMSOLVABLE)
+       continue;
+      s = pool->solvables + p;
+      if (solv->installed && s->repo == solv->installed)
+       continue;
+      noobs = solv->noobsoletes.size && MAPTST(&solv->noobsoletes, p);
+      p2 = solver_transaction_pkg(solv, p);
+      if (noobs)
+       queue_push(&solv->transaction, p2 ? SOLVER_TRANSACTION_MULTIREINSTALL : SOLVER_TRANSACTION_MULTIINSTALL);
+      else if (!p2)
+       queue_push(&solv->transaction, SOLVER_TRANSACTION_INSTALL);
+      else
+       {
+         s2 = pool->solvables + p2;
+         if (s->name == s2->name)
+           {
+             if (s->evr == s2->evr && solvable_identical(s, s2))
+               queue_push(&solv->transaction, SOLVER_TRANSACTION_REINSTALL);
+             else
+               {
+                 r = evrcmp(pool, s->evr, s2->evr, EVRCMP_COMPARE);
+                 if (r > 0)
+                   queue_push(&solv->transaction, SOLVER_TRANSACTION_UPGRADE);
+                 else if (r < 0)
+                   queue_push(&solv->transaction, SOLVER_TRANSACTION_DOWNGRADE);
+                 else
+                   queue_push(&solv->transaction, SOLVER_TRANSACTION_CHANGE);
+               }
+           }
+         else
+           queue_push(&solv->transaction, SOLVER_TRANSACTION_RENAME);
+       }
+      queue_push(&solv->transaction, p);
+    }
+}
+
 /*
  *
  * solve job queue
@@ -5097,6 +5336,12 @@ solver_solve(Solver *solv, Queue *job)
        }
       solv->problems.count = j;
     }
+
+  /*
+   * finally prepare transaction info
+   */
+  create_transaction(solv);
+
   POOL_DEBUG(SAT_DEBUG_STATS, "final solver statistics: %d problems, %d learned rules, %d unsolvable\n", solv->problems.count / 2, solv->stats_learned, solv->stats_unsolvable);
   POOL_DEBUG(SAT_DEBUG_STATS, "solver_solve took %d ms\n", sat_timems(solve_start));
 }
index 2731306..c271591 100644 (file)
@@ -63,6 +63,9 @@ typedef struct solver {
   Pool *pool;
   Queue job;                           /* copy of the job we're solving */
 
+  Queue transaction;                   /* solver result */
+  Queue transaction_info;              /* transaction obsoletes info */
+
   Repo *installed;                     /* copy of pool->installed */
   
   /* list of rules, ordered
@@ -325,9 +328,30 @@ typedef enum {
 #define SOLVER_SOLUTION_DISTUPGRADE    (-1)
 #define SOLVER_SOLUTION_INFARCH                (-2)
 
+#define SOLVER_TRANSACTION_ERASE               0x10
+#define SOLVER_TRANSACTION_REINSTALLED         0x11
+#define SOLVER_TRANSACTION_DOWNGRADED          0x12
+#define SOLVER_TRANSACTION_CHANGED             0x13
+#define SOLVER_TRANSACTION_UPGRADED            0x14
+#define SOLVER_TRANSACTION_OBSOLETED           0x15
+
+#define SOLVER_TRANSACTION_INSTALL             0x20
+#define SOLVER_TRANSACTION_REINSTALL           0x21
+#define SOLVER_TRANSACTION_DOWNGRADE           0x22
+#define SOLVER_TRANSACTION_CHANGE              0x23
+#define SOLVER_TRANSACTION_UPGRADE             0x24
+#define SOLVER_TRANSACTION_RENAME              0x25
+
+#define SOLVER_TRANSACTION_MULTIINSTALL                0x30
+#define SOLVER_TRANSACTION_MULTIREINSTALL      0x31
+
+
 extern Solver *solver_create(Pool *pool);
 extern void solver_free(Solver *solv);
 extern void solver_solve(Solver *solv, Queue *job);
+extern void solver_transaction_info(Solver *solv, Id p, Queue *info);
+extern Id solver_transaction_pkg(Solver *solv, Id p);
+
 extern int solver_dep_installed(Solver *solv, Id dep);
 extern int solver_splitprovides(Solver *solv, Id dep);
 
index 3da35d8..c63a280 100644 (file)
@@ -253,9 +253,10 @@ solver_printdecisions(Solver *solv)
 {
   Pool *pool = solv->pool;
   Repo *installed = solv->installed;
-  Id p, *obsoletesmap = solver_create_decisions_obsoletesmap(solv);
-  int i;
+  Id p;
+  int i, j;
   Solvable *s;
+  Queue iq;
 
   IF_POOLDEBUG (SAT_DEBUG_SCHUBI)
     {
@@ -271,64 +272,68 @@ solver_printdecisions(Solver *solv)
   POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
   POOL_DEBUG(SAT_DEBUG_RESULT, "transaction:\n");
 
-  /* print solvables to be erased */
-
-  if (installed)
-    {
-      FOR_REPO_SOLVABLES(installed, p, s)
-       {
-         if (solv->decisionmap[p] > 0)
-           continue;
-         if (obsoletesmap[p])
-           continue;
-         POOL_DEBUG(SAT_DEBUG_RESULT, "  erase     %s\n", solvable2str(pool, s));
-       }
-    }
-
-  /* print solvables to be installed */
-
-  for (i = 0; i < solv->decisionq.count; i++)
+  queue_init(&iq);
+  for (i = 0; i < solv->transaction.count; i += 2)
     {
-      int j;
-      p = solv->decisionq.elements[i];
-      if (p < 0)
-       continue;
-      if (p == SYSTEMSOLVABLE)
-       continue;
-      s = pool->solvables + p;
-      if (installed && s->repo == installed)
-       continue;
-
-      if (!obsoletesmap[p])
+      s = pool->solvables + solv->transaction.elements[i + 1];
+      switch(solv->transaction.elements[i])
         {
+       case SOLVER_TRANSACTION_MULTI_INSTALL:
+          POOL_DEBUG(SAT_DEBUG_RESULT, "  multi install %s", solvable2str(pool, s));
+         break;
+       case SOLVER_TRANSACTION_MULTI_REINSTALL:
+          POOL_DEBUG(SAT_DEBUG_RESULT, "  multi reinstall %s", solvable2str(pool, s));
+         break;
+       case SOLVER_TRANSACTION_INSTALL:
           POOL_DEBUG(SAT_DEBUG_RESULT, "  install   %s", solvable2str(pool, s));
+         break;
+       case SOLVER_TRANSACTION_REINSTALL:
+          POOL_DEBUG(SAT_DEBUG_RESULT, "  reinstall %s", solvable2str(pool, s));
+         break;
+       case SOLVER_TRANSACTION_DOWNGRADE:
+          POOL_DEBUG(SAT_DEBUG_RESULT, "  downgrade %s", solvable2str(pool, s));
+         break;
+       case SOLVER_TRANSACTION_CHANGE:
+          POOL_DEBUG(SAT_DEBUG_RESULT, "  change    %s", solvable2str(pool, s));
+         break;
+       case SOLVER_TRANSACTION_UPGRADE:
+       case SOLVER_TRANSACTION_RENAME:
+          POOL_DEBUG(SAT_DEBUG_RESULT, "  upgrade   %s", solvable2str(pool, s));
+         break;
+       case SOLVER_TRANSACTION_ERASE:
+          POOL_DEBUG(SAT_DEBUG_RESULT, "  erase     %s", solvable2str(pool, s));
+         break;
+       default:
+         break;
         }
-      else
-       {
-         Id xp, xpp;
-         FOR_PROVIDES(xp, xpp, s->name)
+      switch(solv->transaction.elements[i])
+        {
+       case SOLVER_TRANSACTION_INSTALL:
+       case SOLVER_TRANSACTION_ERASE:
+         POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
+         break;
+       case SOLVER_TRANSACTION_REINSTALL:
+       case SOLVER_TRANSACTION_DOWNGRADE:
+       case SOLVER_TRANSACTION_CHANGE:
+       case SOLVER_TRANSACTION_UPGRADE:
+       case SOLVER_TRANSACTION_RENAME:
+         solver_transaction_info(solv, solv->transaction.elements[i + 1], &iq);
+         if (iq.count)
            {
-             Solvable *s2 = pool->solvables + xp;
-             if (s2->name != s->name)
-               continue;
-             if (evrcmp(pool, s->evr, s2->evr, EVRCMP_MATCH_RELEASE) < 0)
-               break;
+             POOL_DEBUG(SAT_DEBUG_RESULT, "  (obsoletes");
+             for (j = 0; j < iq.count; j++)
+               POOL_DEBUG(SAT_DEBUG_RESULT, " %s", solvable2str(pool, pool->solvables + iq.elements[j]));
+             POOL_DEBUG(SAT_DEBUG_RESULT, ")");
            }
-         if (xp)
-           POOL_DEBUG(SAT_DEBUG_RESULT, "  downgrade %s", solvable2str(pool, s));
-         else
-           POOL_DEBUG(SAT_DEBUG_RESULT, "  upgrade   %s", solvable2str(pool, s));
-          POOL_DEBUG(SAT_DEBUG_RESULT, "  (obsoletes");
-         for (j = installed->start; j < installed->end; j++)
-           if (obsoletesmap[j] == p)
-             POOL_DEBUG(SAT_DEBUG_RESULT, " %s", solvable2str(pool, pool->solvables + j));
-         POOL_DEBUG(SAT_DEBUG_RESULT, ")");
+         POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
+         break;
+       default:
+         break;
        }
-      POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
     }
-  POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
+  queue_free(&iq);
 
-  sat_free(obsoletesmap);
+  POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
 
   if (solv->recommendations.count)
     {
index c72aba5..027c723 100644 (file)
@@ -586,18 +586,18 @@ set_sourcerpm(Repodata *data, Solvable *s, Id handle, char *sourcerpm)
     return;
   sevr = p + 1;
   pool = s->repo->pool;
-  name = id2str(pool, s->name);
-  evr = id2str(pool, s->evr);
   if (!strcmp(sarch, "src.rpm"))
     repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, ARCH_SRC);
   else if (!strcmp(sarch, "nosrc.rpm"))
     repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, ARCH_NOSRC);
   else
     repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, strn2id(pool, sarch, strlen(sarch) - 4, 1));
+  evr = id2str(pool, s->evr);
   if (evr && !strncmp(sevr, evr, sarch - sevr - 1) && evr[sarch - sevr - 1] == 0)
     repodata_set_void(data, handle, SOLVABLE_SOURCEEVR);
   else
     repodata_set_id(data, handle, SOLVABLE_SOURCEEVR, strn2id(pool, sevr, sarch - sevr - 1, 1));
+  name = id2str(pool, s->name);
   if (name && !strncmp(sourcerpm, name, sevr - sourcerpm - 1) && name[sevr - sourcerpm - 1] == 0)
     repodata_set_void(data, handle, SOLVABLE_SOURCENAME);
   else