Imported Upstream version 0.7.7
[platform/upstream/libsolv.git] / src / order.c
index d560865..b8d4b82 100644 (file)
 #include "repo.h"
 #include "util.h"
 
-struct _TransactionElement {
+struct s_TransactionElement {
   Id p;                /* solvable id */
   Id edges;    /* pointer into edges data */
   Id mark;
 };
 
-struct _TransactionOrderdata {
-  struct _TransactionElement *tes;
+struct s_TransactionOrderdata {
+  struct s_TransactionElement *tes;
   int ntes;
   Id *invedgedata;
   int ninvedgedata;
@@ -43,8 +43,11 @@ struct _TransactionOrderdata {
 #define TYPE_REQ_P     (1<<2)
 #define TYPE_PREREQ_P  (1<<3)
 
-#define TYPE_REQ       (1<<4)
-#define TYPE_PREREQ    (1<<5)
+#define TYPE_SUG       (1<<4)
+#define TYPE_REC       (1<<5)
+
+#define TYPE_REQ       (1<<6)
+#define TYPE_PREREQ    (1<<7)
 
 #define TYPE_CYCLETAIL  (1<<16)
 #define TYPE_CYCLEHEAD  (1<<17)
@@ -54,7 +57,7 @@ struct _TransactionOrderdata {
 void
 transaction_clone_orderdata(Transaction *trans, Transaction *srctrans)
 {
-  struct _TransactionOrderdata *od = srctrans->orderdata;
+  struct s_TransactionOrderdata *od = srctrans->orderdata;
   if (!od)
     return;
   trans->orderdata = solv_calloc(1, sizeof(*trans->orderdata));
@@ -74,7 +77,7 @@ transaction_free_orderdata(Transaction *trans)
 {
   if (trans->orderdata)
     {
-      struct _TransactionOrderdata *od = trans->orderdata;
+      struct s_TransactionOrderdata *od = trans->orderdata;
       od->tes = solv_free(od->tes);
       od->invedgedata = solv_free(od->invedgedata);
       if (od->cycles)
@@ -88,7 +91,7 @@ transaction_free_orderdata(Transaction *trans)
 
 struct orderdata {
   Transaction *trans;
-  struct _TransactionElement *tes;
+  struct s_TransactionElement *tes;
   int ntes;
   Id *edgedata;
   int nedgedata;
@@ -103,7 +106,7 @@ static int
 addteedge(struct orderdata *od, int from, int to, int type)
 {
   int i;
-  struct _TransactionElement *te;
+  struct s_TransactionElement *te;
 
   if (from == to)
     return 0;
@@ -151,7 +154,7 @@ addedge(struct orderdata *od, Id from, Id to, int type)
   Transaction *trans = od->trans;
   Pool *pool = trans->pool;
   Solvable *s;
-  struct _TransactionElement *te;
+  struct s_TransactionElement *te;
   int i;
 
   /* printf("addedge %d %d type %d\n", from, to, type); */
@@ -245,21 +248,21 @@ addsolvableedges(struct orderdata *od, Solvable *s)
 {
   Transaction *trans = od->trans;
   Pool *pool = trans->pool;
-  Id req, *reqp, con, *conp;
   Id p, p2, pp2;
   int i, j, pre, numins;
   Repo *installed = pool->installed;
   Solvable *s2;
-  Queue reqq;
+  Queue depq;
   int provbyinst;
 
 #if 0
   printf("addsolvableedges %s\n", pool_solvable2str(pool, s));
 #endif
   p = s - pool->solvables;
-  queue_init(&reqq);
+  queue_init(&depq);
   if (s->requires)
     {
+      Id req, *reqp;
       reqp = s->repo->idarraydata + s->requires;
       pre = TYPE_REQ;
       while ((req = *reqp++) != 0)
@@ -269,15 +272,7 @@ addsolvableedges(struct orderdata *od, Solvable *s)
              pre = TYPE_PREREQ;
              continue;
            }
-#if 0
-         if (pre != TYPE_PREREQ && installed && s->repo == installed)
-           {
-             /* ignore normal requires if we're getting obsoleted */
-             if (trans->transaction_installed[p - pool->installed->start])
-               continue;
-           }
-#endif
-         queue_empty(&reqq);
+         queue_empty(&depq);
          numins = 0;   /* number of packages to be installed providing it */
          provbyinst = 0;       /* provided by kept package */
          FOR_PROVIDES(p2, pp2, req)
@@ -285,19 +280,13 @@ addsolvableedges(struct orderdata *od, Solvable *s)
              s2 = pool->solvables + p2;
              if (p2 == p)
                {
-                 reqq.count = 0;       /* self provides */
+                 depq.count = 0;       /* self provides */
                  break;
                }
              if (s2->repo == installed && !MAPTST(&trans->transactsmap, p2))
                {
                  provbyinst = 1;
-#if 0
-                 printf("IGNORE inst provides %s by %s\n", pool_dep2str(pool, req), pool_solvable2str(pool, s2));
-                 reqq.count = 0;       /* provided by package that stays installed */
-                 break;
-#else
                  continue;
-#endif
                }
              if (s2->repo != installed && !MAPTST(&trans->transactsmap, p2))
                continue;               /* package stays uninstalled */
@@ -305,7 +294,7 @@ addsolvableedges(struct orderdata *od, Solvable *s)
              if (s->repo == installed)
                {
                  /* s gets uninstalled */
-                 queue_pushunique(&reqq, p2);
+                 queue_pushunique(&depq, p2);
                  if (s2->repo != installed)
                    numins++;
                }
@@ -313,55 +302,53 @@ addsolvableedges(struct orderdata *od, Solvable *s)
                {
                  if (s2->repo == installed)
                    continue;   /* s2 gets uninstalled */
-                 queue_pushunique(&reqq, p2);
+                 queue_pushunique(&depq, p2);
                }
            }
          if (provbyinst)
            {
              /* prune to harmless ->inst edges */
-             for (i = j = 0; i < reqq.count; i++)
-               if (pool->solvables[reqq.elements[i]].repo != installed)
-                 reqq.elements[j++] = reqq.elements[i];
-             reqq.count = j;
+             for (i = j = 0; i < depq.count; i++)
+               if (pool->solvables[depq.elements[i]].repo != installed)
+                 depq.elements[j++] = depq.elements[i];
+             depq.count = j;
            }
 
-         if (numins && reqq.count)
+         if (numins && depq.count)
            {
              if (s->repo == installed)
                {
-                 for (i = 0; i < reqq.count; i++)
+                 for (i = 0; i < depq.count; i++)
                    {
-                     if (pool->solvables[reqq.elements[i]].repo == installed)
+                     if (pool->solvables[depq.elements[i]].repo == installed)
                        {
-                         for (j = 0; j < reqq.count; j++)
+                         for (j = 0; j < depq.count; j++)
                            {
-                             if (pool->solvables[reqq.elements[j]].repo != installed)
+                             if (pool->solvables[depq.elements[j]].repo != installed)
                                {
-                                 if (trans->transaction_installed[reqq.elements[i] - pool->installed->start] == reqq.elements[j])
+                                 if (trans->transaction_installed[depq.elements[i] - pool->installed->start] == depq.elements[j])
                                    continue;   /* no self edge */
 #if 0
-                                 printf("add interrreq uninst->inst edge (%s -> %s -> %s)\n", pool_solvid2str(pool, reqq.elements[i]), pool_dep2str(pool, req), pool_solvid2str(pool, reqq.elements[j]));
+                                 printf("add interrreq uninst->inst edge (%s -> %s -> %s)\n", pool_solvid2str(pool, depq.elements[i]), pool_dep2str(pool, req), pool_solvid2str(pool, depq.elements[j]));
 #endif
-                                 addedge(od, reqq.elements[i], reqq.elements[j], pre == TYPE_PREREQ ? TYPE_PREREQ_P : TYPE_REQ_P);
+                                 addedge(od, depq.elements[i], depq.elements[j], pre == TYPE_PREREQ ? TYPE_PREREQ_P : TYPE_REQ_P);
                                }
                            }
                        }
                    }
                }
              /* no mixed types, remove all deps on uninstalls */
-             for (i = j = 0; i < reqq.count; i++)
-               if (pool->solvables[reqq.elements[i]].repo != installed)
-                 reqq.elements[j++] = reqq.elements[i];
-             reqq.count = j;
+             for (i = j = 0; i < depq.count; i++)
+               if (pool->solvables[depq.elements[i]].repo != installed)
+                 depq.elements[j++] = depq.elements[i];
+             depq.count = j;
            }
-          if (!reqq.count)
-           continue;
-          for (i = 0; i < reqq.count; i++)
+          for (i = 0; i < depq.count; i++)
            {
-             p2 = reqq.elements[i];
+             p2 = depq.elements[i];
              if (pool->solvables[p2].repo != installed)
                {
-                 /* all elements of reqq are installs, thus have different TEs */
+                 /* all elements of depq are installs, thus have different TEs */
                  if (pool->solvables[p].repo != installed)
                    {
 #if 0
@@ -399,6 +386,7 @@ addsolvableedges(struct orderdata *od, Solvable *s)
     }
   if (s->conflicts)
     {
+      Id con, *conp;
       conp = s->repo->idarraydata + s->conflicts;
       while ((con = *conp++) != 0)
        {
@@ -435,13 +423,83 @@ addsolvableedges(struct orderdata *od, Solvable *s)
            }
        }
     }
-  if (s->repo == installed && solvable_lookup_idarray(s, SOLVABLE_TRIGGERS, &reqq) && reqq.count)
+  if (s->recommends && s->repo != installed)
+    {
+      Id rec, *recp;
+      recp = s->repo->idarraydata + s->recommends;
+      while ((rec = *recp++) != 0)
+       {
+         queue_empty(&depq);
+         FOR_PROVIDES(p2, pp2, rec)
+           {
+             s2 = pool->solvables + p2;
+             if (p2 == p)
+               {
+                 depq.count = 0;       /* self provides */
+                 break;
+               }
+             if (s2->repo == installed && !MAPTST(&trans->transactsmap, p2))
+               continue;
+             if (s2->repo != installed && !MAPTST(&trans->transactsmap, p2))
+               continue;               /* package stays uninstalled */
+             if (s2->repo != installed)
+               queue_pushunique(&depq, p2);
+           }
+          for (i = 0; i < depq.count; i++)
+           {
+             p2 = depq.elements[i];
+             if (pool->solvables[p2].repo != installed)
+               {
+#if 0
+                 printf("add recommends inst->inst edge (%s -> %s -> %s)\n", pool_solvid2str(pool, p), pool_dep2str(pool, rec), pool_solvid2str(pool, p2));
+#endif
+                 addedge(od, p, p2, TYPE_REC);
+               }
+           }
+       }
+    }
+  if (s->suggests && s->repo != installed)
+    {
+      Id sug, *sugp;
+      sugp = s->repo->idarraydata + s->suggests;
+      while ((sug = *sugp++) != 0)
+       {
+         queue_empty(&depq);
+         FOR_PROVIDES(p2, pp2, sug)
+           {
+             s2 = pool->solvables + p2;
+             if (p2 == p)
+               {
+                 depq.count = 0;       /* self provides */
+                 break;
+               }
+             if (s2->repo == installed && !MAPTST(&trans->transactsmap, p2))
+               continue;
+             if (s2->repo != installed && !MAPTST(&trans->transactsmap, p2))
+               continue;               /* package stays uninstalled */
+             if (s2->repo != installed)
+               queue_pushunique(&depq, p2);
+           }
+          for (i = 0; i < depq.count; i++)
+           {
+             p2 = depq.elements[i];
+             if (pool->solvables[p2].repo != installed)
+               {
+#if 0
+                 printf("add suggests inst->inst edge (%s -> %s -> %s)\n", pool_solvid2str(pool, p), pool_dep2str(pool, sug), pool_solvid2str(pool, p2));
+#endif
+                 addedge(od, p, p2, TYPE_SUG);
+               }
+           }
+       }
+    }
+  if (s->repo == installed && solvable_lookup_idarray(s, SOLVABLE_TRIGGERS, &depq) && depq.count)
     {
       /* we're getting deinstalled/updated. Try to do this before our
        * triggers are hit */
-      for (i = 0; i < reqq.count; i++)
+      for (i = 0; i < depq.count; i++)
        {
-         Id tri = reqq.elements[i];
+         Id tri = depq.elements[i];
          FOR_PROVIDES(p2, pp2, tri)
            {
              if (p2 == p)
@@ -462,7 +520,7 @@ addsolvableedges(struct orderdata *od, Solvable *s)
            }
        }
     }
-  queue_free(&reqq);
+  queue_free(&depq);
 }
 
 
@@ -473,7 +531,7 @@ breakcycle(struct orderdata *od, Id *cycle)
   Pool *pool = od->trans->pool;
   Id ddegmin, ddegmax, ddeg;
   int k, l;
-  struct _TransactionElement *te;
+  struct s_TransactionElement *te;
 
   l = 0;
   ddegmin = ddegmax = 0;
@@ -540,13 +598,14 @@ breakcycle(struct orderdata *od, Id *cycle)
   POOL_DEBUG(SOLV_DEBUG_STATS, "\n");
 }
 
+#if 0
 static inline void
 dump_tes(struct orderdata *od)
 {
   Pool *pool = od->trans->pool;
   int i, j;
   Queue obsq;
-  struct _TransactionElement *te, *te2;
+  struct s_TransactionElement *te, *te2;
 
   queue_init(&obsq);
   for (i = 1, te = od->tes + i; i < od->ntes; i++, te++)
@@ -570,11 +629,12 @@ dump_tes(struct orderdata *od)
        }
     }
 }
+#endif
 
 static void
 reachable(struct orderdata *od, Id i)
 {
-  struct _TransactionElement *te = od->tes + i;
+  struct s_TransactionElement *te = od->tes + i;
   int j, k;
 
   if (te->mark != 0)
@@ -602,7 +662,7 @@ addcycleedges(struct orderdata *od, Id *cycle, Queue *todo)
   Transaction *trans = od->trans;
   Pool *pool = trans->pool;
 #endif
-  struct _TransactionElement *te;
+  struct s_TransactionElement *te;
   int i, j, k, tail;
   int head;
 
@@ -722,7 +782,7 @@ transaction_order(Transaction *trans, int flags)
   Solvable *s;
   int i, j, k, numte, numedge;
   struct orderdata od;
-  struct _TransactionElement *te;
+  struct s_TransactionElement *te;
   Queue todo, obsq, samerepoq, uninstq;
   int cycstart, cycel;
   Id *cycle;
@@ -737,7 +797,7 @@ transaction_order(Transaction *trans, int flags)
   /* free old data if present */
   if (trans->orderdata)
     {
-      struct _TransactionOrderdata *od = trans->orderdata;
+      struct s_TransactionOrderdata *od = trans->orderdata;
       od->tes = solv_free(od->tes);
       od->invedgedata = solv_free(od->invedgedata);
       trans->orderdata = solv_free(trans->orderdata);
@@ -1008,10 +1068,9 @@ transaction_order(Transaction *trans, int flags)
 #if 0
 printf("do %s [%d]\n", pool_solvid2str(pool, te->p), temedianr[i]);
 #endif
-      s = pool->solvables + te->p;
       for (j = te->edges; od.invedgedata[j]; j++)
        {
-         struct _TransactionElement *te2 = od.tes + od.invedgedata[j];
+         struct s_TransactionElement *te2 = od.tes + od.invedgedata[j];
          assert(te2->mark > 0);
          if (--te2->mark == 0)
            {
@@ -1045,7 +1104,7 @@ printf("free %s [%d]\n", pool_solvid2str(pool, te2->p), temedianr[od.invedgedata
 
   if ((flags & (SOLVER_TRANSACTION_KEEP_ORDERDATA | SOLVER_TRANSACTION_KEEP_ORDERCYCLES)) != 0)
     {
-      struct _TransactionOrderdata *tod;
+      struct s_TransactionOrderdata *tod;
       trans->orderdata = tod = solv_calloc(1, sizeof(*trans->orderdata));
       if ((flags & SOLVER_TRANSACTION_KEEP_ORDERCYCLES) != 0)
        {
@@ -1079,8 +1138,8 @@ int
 transaction_order_add_choices(Transaction *trans, Id chosen, Queue *choices)
 {
   int i, j;
-  struct _TransactionOrderdata *od = trans->orderdata;
-  struct _TransactionElement *te;
+  struct s_TransactionOrderdata *od = trans->orderdata;
+  struct s_TransactionElement *te;
 
   if (!od)
      return choices->count;
@@ -1262,8 +1321,10 @@ transaction_check_order(Transaction *trans)
   map_init(&ins, pool->nsolvables);
   map_init(&seen, pool->nsolvables);
   if (pool->installed)
-    FOR_REPO_SOLVABLES(pool->installed, p, s)
-      MAPSET(&ins, p);
+    {
+      FOR_REPO_SOLVABLES(pool->installed, p, s)
+        MAPSET(&ins, p);
+    }
   lastins = 0;
   for (i = 0; i < trans->steps.count; i++)
     {
@@ -1289,7 +1350,7 @@ transaction_check_order(Transaction *trans)
 void
 transaction_order_get_cycleids(Transaction *trans, Queue *q, int minseverity)
 {
-  struct _TransactionOrderdata *od = trans->orderdata;
+  struct s_TransactionOrderdata *od = trans->orderdata;
   Queue *cq;
   int i, cid, ncycles;
 
@@ -1317,7 +1378,7 @@ transaction_order_get_cycleids(Transaction *trans, Queue *q, int minseverity)
 int
 transaction_order_get_cycle(Transaction *trans, Id cid, Queue *q)
 {
-  struct _TransactionOrderdata *od = trans->orderdata;
+  struct s_TransactionOrderdata *od = trans->orderdata;
   Queue *cq;
   int cmin, cmax, severity;
   int ncycles;