- add SOLVER_SET bits to tell solver which properties of a job are intended by the...
authorMichael Schroeder <mls@suse.de>
Fri, 28 May 2010 14:17:06 +0000 (16:17 +0200)
committerMichael Schroeder <mls@suse.de>
Fri, 28 May 2010 14:17:06 +0000 (16:17 +0200)
- add policy_is_illegal check function
- rework solv package select function to use new SET bits

examples/solv.c
src/evr.c
src/evr.h
src/policy.c
src/policy.h
src/rules.c
src/solver.c
src/solver.h
src/solverdebug.c
src/solverdebug.h

index 887fe88..437ed9d 100644 (file)
@@ -924,9 +924,11 @@ usecachedrepo(Repo *repo, const char *repoext, unsigned char *cookie, int mark)
 
   flags = 0;
   if (repoext)
-    flags = REPO_USE_LOADING|REPO_EXTEND_SOLVABLES;
-  if (repoext && strcmp(repoext, "DL") != 0)
-    flags |= REPO_LOCALPOOL;   /* no local pool for DL so that we can compare IDs */
+    {
+      flags = REPO_USE_LOADING|REPO_EXTEND_SOLVABLES;
+      if (strcmp(repoext, "DL") != 0)
+        flags |= REPO_LOCALPOOL;       /* no local pool for DL so that we can compare IDs */
+    }
 
   if (repo_add_solv_flags(repo, fp, flags))
     {
@@ -1590,8 +1592,13 @@ str2archid(Pool *pool, char *arch)
   return id;
 }
 
+
+#define DEPGLOB_NAME     1
+#define DEPGLOB_DEP      2
+#define DEPGLOB_NAMEDEP  3
+
 int
-depglob(Pool *pool, char *name, Queue *job)
+depglob(Pool *pool, char *name, Queue *job, int what)
 {
   Id p, pp;
   Id id = str2id(pool, name, 0);
@@ -1603,7 +1610,7 @@ depglob(Pool *pool, char *name, Queue *job)
        {
          Solvable *s = pool->solvables + p;
          match = 1;
-         if (s->name == id)
+         if (s->name == id && (what & DEPGLOB_NAME) != 0)
            {
              queue_push2(job, SOLVER_SOLVABLE_NAME, id);
              return 1;
@@ -1611,7 +1618,8 @@ depglob(Pool *pool, char *name, Queue *job)
        }
       if (match)
        {
-         printf("[using capability match for '%s']\n", name);
+         if (what == DEPGLOB_NAMEDEP)
+           printf("[using capability match for '%s']\n", name);
          queue_push2(job, SOLVER_SOLVABLE_PROVIDES, id);
          return 1;
        }
@@ -1620,40 +1628,46 @@ depglob(Pool *pool, char *name, Queue *job)
   if (strpbrk(name, "[*?") == 0)
     return 0;
 
-  /* looks like a name glob. hard work. */
-  for (p = 1; p < pool->nsolvables; p++)
+  if ((what & DEPGLOB_NAME) != 0)
     {
-      Solvable *s = pool->solvables + p;
-      if (!s->repo || !pool_installable(pool, s))
-       continue;
-      id = s->name;
-      if (fnmatch(name, id2str(pool, id), 0) == 0)
+      /* looks like a name glob. hard work. */
+      for (p = 1; p < pool->nsolvables; p++)
        {
-         for (i = 0; i < job->count; i += 2)
-           if (job->elements[i] == SOLVER_SOLVABLE_NAME && job->elements[i + 1] == id)
-             break;
-         if (i == job->count)
-           queue_push2(job, SOLVER_SOLVABLE_NAME, id);
-         match = 1;
+         Solvable *s = pool->solvables + p;
+         if (!s->repo || !pool_installable(pool, s))
+           continue;
+         id = s->name;
+         if (fnmatch(name, id2str(pool, id), 0) == 0)
+           {
+             for (i = 0; i < job->count; i += 2)
+               if (job->elements[i] == SOLVER_SOLVABLE_NAME && job->elements[i + 1] == id)
+                 break;
+             if (i == job->count)
+               queue_push2(job, SOLVER_SOLVABLE_NAME, id);
+             match = 1;
+           }
        }
+      if (match)
+       return 1;
     }
-  if (match)
-    return 1;
-  /* looks like a dep glob. really hard work. */
-  for (id = 1; id < pool->ss.nstrings; id++)
+  if ((what & DEPGLOB_DEP))
     {
-      if (!pool->whatprovides[id])
-       continue;
-      if (fnmatch(name, id2str(pool, id), 0) == 0)
+      /* looks like a dep glob. really hard work. */
+      for (id = 1; id < pool->ss.nstrings; id++)
        {
-         if (!match)
-           printf("[using capability match for '%s']\n", name);
-         for (i = 0; i < job->count; i += 2)
-           if (job->elements[i] == SOLVER_SOLVABLE_PROVIDES && job->elements[i + 1] == id)
-             break;
-         if (i == job->count)
-           queue_push2(job, SOLVER_SOLVABLE_PROVIDES, id);
-         match = 1;
+         if (!pool->whatprovides[id])
+           continue;
+         if (fnmatch(name, id2str(pool, id), 0) == 0)
+           {
+             if (!match && what == DEPGLOB_NAMEDEP)
+               printf("[using capability match for '%s']\n", name);
+             for (i = 0; i < job->count; i += 2)
+               if (job->elements[i] == SOLVER_SOLVABLE_PROVIDES && job->elements[i + 1] == id)
+                 break;
+             if (i == job->count)
+               queue_push2(job, SOLVER_SOLVABLE_PROVIDES, id);
+             match = 1;
+           }
        }
     }
   if (match)
@@ -1664,98 +1678,53 @@ depglob(Pool *pool, char *name, Queue *job)
 void
 addrelation(Pool *pool, Queue *job, int flags, Id evr)
 {
-  int i;
+  int i, match;
+  Id p, pp;
   for (i = 0; i < job->count; i += 2)
     {
-      if (job->elements[i] != SOLVER_SOLVABLE_NAME && job->elements[i] != SOLVER_SOLVABLE_PROVIDES)
+      Id select = job->elements[i] & SOLVER_SELECTMASK;
+      if (select != SOLVER_SOLVABLE_NAME && select != SOLVER_SOLVABLE_PROVIDES)
        continue;
       job->elements[i + 1] = rel2id(pool, job->elements[i + 1], evr, flags, 1);
-    }
-}
-
-int
-limitevr(Pool *pool, char *evr, Queue *job, Id archid)
-{
-  Queue mq;
-  Id p, pp, evrid;
-  int matched = 0;
-  int i, j;
-  Solvable *s;
-  const char *sevr;
-
-  queue_init(&mq);
-  for (i = 0; i < job->count; i += 2)
-    {
-      queue_empty(&mq);
-      FOR_JOB_SELECT(p, pp, job->elements[i], job->elements[i + 1])
+      if (flags == REL_ARCH)
+       job->elements[i] |= SOLVER_SETARCH;
+      if (flags == REL_EQ && select == SOLVER_SOLVABLE_NAME && job->elements[i])
        {
-         s = pool_id2solvable(pool, p);
-         if (archid && s->arch != archid)
-           continue;
-          sevr = id2str(pool, s->evr);
-          if (!strchr(evr, ':') && strchr(sevr, ':'))
-           sevr = strchr(sevr, ':') + 1;
-         if (evrcmp_str(pool, sevr, evr, EVRCMP_MATCH) == 0)
-            queue_push(&mq, p);
+         const char *evrstr = id2str(pool, evr);
+         if (strchr(evrstr, '-'))
+           job->elements[i] |= SOLVER_SETEVR;
+         else
+           job->elements[i] |= SOLVER_SETEV;
        }
-      if (mq.count)
+      /* make sure we still have matches */
+      match = 0;
+      FOR_JOB_SELECT(p, pp, job->elements[i], job->elements[i + 1])
        {
-         if (!matched && i)
-           {
-             queue_deleten(job, 0, i);
-             i = 0;
-           }
-         matched = 1;
-         /* if all solvables have the same evr */
-         s = pool_id2solvable(pool, mq.elements[0]);
-         evrid = s->evr;
-         for (j = 0; j < mq.count; j++)
-           {
-             s = pool_id2solvable(pool, mq.elements[j]);
-             if (s->evr != evrid)
-               break;
-           }
-         if (j == mq.count && j > 1)
-           {
-             prune_to_best_arch(pool, &mq);
-             // prune_to_highest_prio(pool, &mq);
-             mq.count = 1;
-           }
-         if (mq.count > 1)
-           {
-             job->elements[i] = SOLVER_SOLVABLE_ONE_OF;
-             job->elements[i + 1] = pool_queuetowhatprovides(pool, &mq);
-           }
-         else
-           {
-             job->elements[i] = SOLVER_SOLVABLE;
-             job->elements[i + 1] = mq.elements[0];
-           }
+         match = 1;
+         break;
        }
-      else if (matched)
+      if (!match)
        {
-         queue_deleten(job, i, 2);
-         i -= 2;
+         fprintf(stderr, "nothing matches %s\n", solver_select2str(pool, job->elements[i] & SOLVER_SELECTMASK, job->elements[i + 1]));
+         exit(1);
        }
     }
-  queue_free(&mq);
-  if (matched)
-    return 1;
-  if (!archid)
+}
+
+void
+addrelation_arch(Pool *pool, Queue *job, int flags, char *evr)
+{
+  char *r;
+  Id archid;
+  if ((r = strrchr(evr, '.')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0)
     {
-      char *r;
-      if ((r = strrchr(evr, '.')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0)
-       {
-         *r = 0;
-         if (limitevr(pool, evr, job, archid))
-           {
-             *r = '.';
-             return 1;
-           }
-         *r = '.';
-       }
+      *r = 0;
+      addrelation(pool, job, REL_ARCH, archid);
+      addrelation(pool, job, flags, str2id(pool, evr, 1));
+      *r = '.';
     }
-  return 0;
+  else
+    addrelation(pool, job, flags, str2id(pool, evr, 1));
 }
 
 int
@@ -1785,16 +1754,9 @@ limitrepo(Pool *pool, Id repofilter, Queue *job)
              i = 0;
            }
          matched = 1;
-         if (mq.count > 1)
-           {
-             job->elements[i] = SOLVER_SOLVABLE_ONE_OF;
-             job->elements[i + 1] = pool_queuetowhatprovides(pool, &mq);
-           }
-         else
-           {
-             job->elements[i] = SOLVER_SOLVABLE;
-             job->elements[i + 1] = mq.elements[0];
-           }
+         /* here we assume that repo == vendor */
+         job->elements[i] = SOLVER_SOLVABLE_ONE_OF | (job->elements[i] & SOLVER_SETMASK) | SOLVER_SETVENDOR | SOLVER_SETREPO;
+         job->elements[i + 1] = pool_queuetowhatprovides(pool, &mq);
        }
       else if (matched)
        {
@@ -1816,7 +1778,6 @@ mkselect(Pool *pool, int mode, char *name, Queue *job)
     {
       Dataiterator di;
       Queue q;
-      int match = 0;
 
       queue_init(&q);
       dataiterator_init(&di, pool, mode == SOLVER_ERASE ? pool->installed : 0, 0, SOLVABLE_FILELIST, name, SEARCH_STRING|SEARCH_FILES|SEARCH_COMPLETE_FILELIST);
@@ -1832,21 +1793,19 @@ mkselect(Pool *pool, int mode, char *name, Queue *job)
       if (q.count)
        {
          printf("[using file list match for '%s']\n", name);
-         match = 1;
          if (q.count > 1)
            queue_push2(job, SOLVER_SOLVABLE_ONE_OF, pool_queuetowhatprovides(pool, &q));
          else
            queue_push2(job, SOLVER_SOLVABLE, q.elements[0]);
+         queue_free(&q);
+         return;
        }
-      queue_free(&q);
-      if (match)
-       return;
     }
   if ((r = strpbrk(name, "<=>")) != 0)
     {
       /* relation case, support:
        * depglob rel
-       * depglob.rpm rel
+       * depglob.arch rel
        */
       int rflags = 0;
       int nend = r - name;
@@ -1871,7 +1830,7 @@ mkselect(Pool *pool, int mode, char *name, Queue *job)
          fprintf(stderr, "bad relation\n");
          exit(1);
        }
-      if (depglob(pool, name, job))
+      if (depglob(pool, name, job, DEPGLOB_NAMEDEP))
        {
          addrelation(pool, job, rflags, str2id(pool, r, 1));
          return;
@@ -1879,7 +1838,7 @@ mkselect(Pool *pool, int mode, char *name, Queue *job)
       if ((r2 = strrchr(name, '.')) != 0 && r2[1] && (archid = str2archid(pool, r2 + 1)) != 0)
        {
          *r2 = 0;
-         if (depglob(pool, name, job))
+         if (depglob(pool, name, job, DEPGLOB_NAMEDEP))
            {
              *r2 = '.';
              addrelation(pool, job, REL_ARCH, archid);
@@ -1894,16 +1853,17 @@ mkselect(Pool *pool, int mode, char *name, Queue *job)
       /* no relation case, support:
        * depglob
        * depglob.arch
-       * depglob-version-release
-       * depglob-version-release.arch
+       * nameglob-version
+       * nameglob-version.arch
+       * nameglob-version-release
+       * nameglob-version-release.arch
        */
-      if (depglob(pool, name, job))
+      if (depglob(pool, name, job, DEPGLOB_NAMEDEP))
        return;
-      archid = 0;
       if ((r = strrchr(name, '.')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0)
        {
          *r = 0;
-         if (depglob(pool, name, job))
+         if (depglob(pool, name, job, DEPGLOB_NAMEDEP))
            {
              *r = '.';
              addrelation(pool, job, REL_ARCH, archid);
@@ -1914,24 +1874,25 @@ mkselect(Pool *pool, int mode, char *name, Queue *job)
       if ((r = strrchr(name, '-')) != 0)
        {
          *r = 0;
-         if (depglob(pool, name, job))
+         if (depglob(pool, name, job, DEPGLOB_NAME))
            {
              /* have just the version */
+             addrelation_arch(pool, job, REL_EQ, r + 1);
              *r = '-';
-             if (limitevr(pool, r + 1, job, 0))
-               return;
+             return;
            }
          if ((r2 = strrchr(name, '-')) != 0)
            {
              *r = '-';
              *r2 = 0;
-             if (depglob(pool, name, job))
+             r = r2;
+             if (depglob(pool, name, job, DEPGLOB_NAME))
                {
-                 *r2 = '-';
-                 if (limitevr(pool, r2 + 1, job, 0))
-                   return;
+                 /* have version-release */
+                 addrelation_arch(pool, job, REL_EQ, r + 1);
+                 *r = '-';
+                 return;
                }
-             *r2 = '-';
            }
          *r = '-';
        }
index 4d6318f..a20c7b7 100644 (file)
--- a/src/evr.c
+++ b/src/evr.c
@@ -215,6 +215,8 @@ evrcmp_str(const Pool *pool, const char *evr1, const char *evr2, int mode)
       if (r1 && !r2)
        return 1;
     }
+  if (mode == EVRCMP_COMPARE_EVONLY)
+    return 0;
   if (r1 && r2)
     {
       if (s1 != ++r1 && s2 != ++r2)
index c45cf81..e9a96f4 100644 (file)
--- a/src/evr.h
+++ b/src/evr.h
@@ -19,9 +19,10 @@ extern "C" {
 
 #include "pooltypes.h"
 
-#define EVRCMP_COMPARE                  0
-#define EVRCMP_MATCH_RELEASE            1
-#define EVRCMP_MATCH                    2
+#define EVRCMP_COMPARE                 0
+#define EVRCMP_MATCH_RELEASE           1
+#define EVRCMP_MATCH                   2
+#define EVRCMP_COMPARE_EVONLY          3
 
 extern int vercmp(const char *s1, const char *q1, const char *s2, const char *q2);
 extern int evrcmp_str(const Pool *pool, const char *evr1, const char *evr2, int mode);
index 168400b..0dc3df8 100644 (file)
@@ -441,6 +441,31 @@ policy_illegal_vendorchange(Solver *solv, Solvable *s1, Solvable *s2)
   return 1;    /* no class matches */
 }
 
+/* check if it is illegal to replace installed
+ * package "is" with package "s" (which must obsolete "is")
+ */
+int
+policy_is_illegal(Solver *solv, Solvable *is, Solvable *s, int ignore)
+{
+  Pool *pool = solv->pool;
+  int ret = 0;
+  if (!(ignore & POLICY_ILLEGAL_DOWNGRADE) && !solv->allowdowngrade)
+    {
+      if (is->name == s->name && evrcmp(pool, is->evr, s->evr, EVRCMP_COMPARE) > 0)
+       ret |= POLICY_ILLEGAL_DOWNGRADE;
+    }
+  if (!(ignore & POLICY_ILLEGAL_ARCHCHANGE) && !solv->allowarchchange)
+    {
+      if (is->arch != s->arch && policy_illegal_archchange(solv, s, is))
+       ret |= POLICY_ILLEGAL_ARCHCHANGE;
+    }
+  if (!(ignore & POLICY_ILLEGAL_VENDORCHANGE) && !solv->allowvendorchange)
+    {
+      if (is->vendor != s->vendor && policy_illegal_vendorchange(solv, s, is))
+       ret |= POLICY_ILLEGAL_VENDORCHANGE;
+    }
+  return ret;
+}
 
 /*-------------------------------------------------------------------
  * 
index e52f4f8..b072929 100644 (file)
@@ -56,9 +56,15 @@ extern void prune_to_best_version(Pool *pool, Queue *plist);
  *     candidates : List of candidates (This list depends on other
  *                  restrictions like architecture and vendor policies too)
  */   
+
+#define POLICY_ILLEGAL_DOWNGRADE       1
+#define POLICY_ILLEGAL_ARCHCHANGE      2
+#define POLICY_ILLEGAL_VENDORCHANGE    4
+
 extern void policy_filter_unwanted(Solver *solv, Queue *plist, int mode);
 extern int  policy_illegal_archchange(Solver *solv, Solvable *s1, Solvable *s2);
 extern int  policy_illegal_vendorchange(Solver *solv, Solvable *s1, Solvable *s2);
+extern int  policy_is_illegal(Solver *solv, Solvable *s1, Solvable *s2, int ignore);
 extern void policy_findupdatepackages(Solver *solv,
                                      Solvable *s,
                                      Queue *qs,
index 783ce6c..635bb55 100644 (file)
@@ -22,6 +22,7 @@
 #include "pool.h"
 #include "poolarch.h"
 #include "util.h"
+#include "evr.h"
 #include "policy.h"
 #include "solverdebug.h"
 
@@ -1338,17 +1339,44 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
   Id select, p, pp;
   Repo *installed;
   Solvable *s;
-  int i;
+  int i, j, set, qstart, pass;
+  Map omap;
 
   installed = solv->installed;
   select = how & SOLVER_SELECTMASK;
   switch (how & SOLVER_JOBMASK)
     {
     case SOLVER_INSTALL:
-      if ((select == SOLVER_SOLVABLE_NAME || select == SOLVER_SOLVABLE_PROVIDES) && solv->infarchrules != solv->infarchrules_end && ISRELDEP(what))
+      set = how & SOLVER_SETMASK;
+      if (select == SOLVER_SOLVABLE)
+       set |= SOLVER_SETARCH | SOLVER_SETVENDOR | SOLVER_SETREPO | SOLVER_SETEVR;
+      else if ((select == SOLVER_SOLVABLE_NAME || select == SOLVER_SOLVABLE_PROVIDES) && ISRELDEP(what))
        {
          Reldep *rd = GETRELDEP(pool, what);
+         if (rd->flags == REL_EQ && select == SOLVER_SOLVABLE_NAME)
+           {
+#if !defined(DEBIAN_SEMANTICS)
+             const char *evr = id2str(pool, rd->evr);
+             if (strchr(evr, '-'))
+               set |= SOLVER_SETEVR;
+             else
+               set |= SOLVER_SETEV;
+#else
+             set |= SOLVER_SETEVR;
+#endif
+           }
+         if (rd->flags <= 7 && ISRELDEP(rd->name))
+           rd = GETRELDEP(pool, rd->name);
          if (rd->flags == REL_ARCH)
+           set |= SOLVER_SETARCH;
+       }
+      if (!set)
+       return;
+      if ((set & SOLVER_SETARCH) != 0 && solv->infarchrules != solv->infarchrules_end)
+       {
+         if (select == SOLVER_SOLVABLE)
+           queue_push2(q, DISABLE_INFARCH, pool->solvables[what].name);
+         else
            {
              int qcnt = q->count;
              FOR_JOB_SELECT(p, pp, select, what)
@@ -1364,55 +1392,143 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
                }
            }
        }
-      if (select != SOLVER_SOLVABLE)
-       break;
-      s = pool->solvables + what;
-      if (solv->infarchrules != solv->infarchrules_end)
-       queue_push2(q, DISABLE_INFARCH, s->name);
-      if (solv->duprules != solv->duprules_end)
-       queue_push2(q, DISABLE_DUP, s->name);
-      if (!installed)
-       return;
-      if (solv->noobsoletes.size && MAPTST(&solv->noobsoletes, what))
+      if ((set & SOLVER_SETREPO) != 0 && solv->duprules != solv->duprules_end)
        {
-         /* XXX: remove if we always do distupgrade with DUP rules */
-         if (solv->dupmap_all && s->repo == installed)
-           queue_push2(q, DISABLE_UPDATE, what);
-         return;
+         if (select == SOLVER_SOLVABLE)
+           queue_push2(q, DISABLE_DUP, pool->solvables[what].name);
+         else
+           {
+             int qcnt = q->count;
+             FOR_JOB_SELECT(p, pp, select, what)
+               {
+                 s = pool->solvables + p;
+                 /* unify names */
+                 for (i = qcnt; i < q->count; i += 2)
+                   if (q->elements[i + 1] == s->name)
+                     break;
+                 if (i < q->count)
+                   continue;
+                 queue_push2(q, DISABLE_DUP, s->name);
+               }
+           }
        }
-      if (s->repo == installed)
+      if (!installed)
+       return;
+      /* now the hard part: disable some update rules */
+
+      /* first check if we have noobs or installed packages in the job */
+      FOR_JOB_SELECT(p, pp, select, what)
        {
-         queue_push2(q, DISABLE_UPDATE, what);
-         return;
+         if (pool->solvables[p].repo == installed)
+           {
+             if (select == SOLVER_SOLVABLE)
+               queue_push2(q, DISABLE_UPDATE, what);
+             return;
+           }
+         if (solv->noobsoletes.size && MAPTST(&solv->noobsoletes, p))
+           return;
        }
-      if (s->obsoletes)
+
+      /* all job packages obsolete */
+      qstart = q->count;
+      pass = 0;
+      memset(&omap, 0, sizeof(omap));
+      FOR_JOB_SELECT(p, pp, select, what)
        {
-         Id obs, *obsp;
-         obsp = s->repo->idarraydata + s->obsoletes;
-         while ((obs = *obsp++) != 0)
-           FOR_PROVIDES(p, pp, obs)
-             {
-               Solvable *ps = pool->solvables + p;
-               if (ps->repo != installed)
-                 continue;
-               if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs))
-                 continue;
-               if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
-                 continue;
-               queue_push2(q, DISABLE_UPDATE, p);
-             }
+         Id p2, pp2;
+
+         if (pass == 1)
+           map_grow(&omap, installed->end - installed->start);
+         s = pool->solvables + p;
+         if (s->obsoletes)
+           {
+             Id obs, *obsp;
+             obsp = s->repo->idarraydata + s->obsoletes;
+             while ((obs = *obsp++) != 0)
+               FOR_PROVIDES(p2, pp2, obs)
+                 {
+                   Solvable *ps = pool->solvables + p2;
+                   if (ps->repo != installed)
+                     continue;
+                   if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs))
+                     continue;
+                   if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
+                     continue;
+                   if (pass)
+                     MAPSET(&omap, p2 - installed->start);
+                   else
+                     queue_push2(q, DISABLE_UPDATE, p2);
+                 }
+           }
+         FOR_PROVIDES(p2, pp2, s->name)
+           {
+             Solvable *ps = pool->solvables + p2;
+             if (ps->repo != installed)
+               continue;
+             if (!pool->implicitobsoleteusesprovides && ps->name != s->name)
+               continue;
+             if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
+               continue;
+             if (pass)
+               MAPSET(&omap, p2 - installed->start);
+              else
+               queue_push2(q, DISABLE_UPDATE, p2);
+           }
+         if (pass)
+           {
+             for (i = j = qstart; i < q->count; i += 2)
+               {
+                 if (MAPTST(&omap, q->elements[i + 1] - installed->start))
+                   {
+                     MAPCLR(&omap, q->elements[i + 1] - installed->start);
+                     q->elements[j + 1] = q->elements[i + 1];
+                     j += 2;
+                   }
+               }
+             queue_truncate(q, j);
+           }
+         if (q->count == qstart)
+           break;
+         pass++;
        }
-      FOR_PROVIDES(p, pp, s->name)
+      if (omap.size)
+        map_free(&omap);
+      if (select == SOLVER_SOLVABLE || qstart == q->count)
+       return;         /* all done already */
+
+      /* now that we know which installed packages are obsoleted check each of them */
+      for (i = j = qstart; i < q->count; i += 2)
        {
-         Solvable *ps = pool->solvables + p;
-         if (ps->repo != installed)
-           continue;
-         if (!pool->implicitobsoleteusesprovides && ps->name != s->name)
-           continue;
-         if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
-           continue;
-         queue_push2(q, DISABLE_UPDATE, p);
+         Solvable *is = pool->solvables + q->elements[i + 1];
+         FOR_JOB_SELECT(p, pp, select, what)
+           {
+             int illegal = 0;
+             s = pool->solvables + p;
+             if ((set & SOLVER_SETEVR) != 0)
+               illegal |= POLICY_ILLEGAL_DOWNGRADE;    /* ignore */
+             if ((set & SOLVER_SETARCH) != 0)
+               illegal |= POLICY_ILLEGAL_ARCHCHANGE;   /* ignore */
+             if ((set & SOLVER_SETVENDOR) != 0)
+               illegal |= POLICY_ILLEGAL_VENDORCHANGE; /* ignore */
+             illegal = policy_is_illegal(solv, is, s, illegal);
+             if (illegal && illegal == POLICY_ILLEGAL_DOWNGRADE && (set & SOLVER_SETEV) != 0)
+               {
+                 /* it's ok if the EV is different */
+                 if (evrcmp(pool, is->evr, s->evr, EVRCMP_COMPARE_EVONLY) != 0)
+                   illegal = 0;
+               }
+             if (illegal)
+               break;
+           }
+         if (!p)
+           {   
+             /* no package conflicts with the update rule */
+             /* thus keep the DISABLE_UPDATE */
+             q->elements[j + 1] = q->elements[i + 1];
+             j += 2;
+           }
        }
+      queue_truncate(q, j);
       return;
     case SOLVER_ERASE:
       if (!installed)
@@ -1871,12 +1987,10 @@ solver_addchoicerules(Solver *solv)
          if (p2)
            {
              /* found installed package p2 that we can update to p */
-             if (!solv->allowarchchange && s->arch != s2->arch && policy_illegal_archchange(solv, s, s2))
-               continue;
-             if (!solv->allowvendorchange && s->vendor != s2->vendor && policy_illegal_vendorchange(solv, s, s2))
-               continue;
              if (MAPTST(&mneg, p))
                continue;
+             if (policy_is_illegal(solv, s2, s, 0))
+               continue;
              queue_push(&qi, p2);
              queue_push(&q, p);
              continue;
@@ -1904,12 +2018,10 @@ solver_addchoicerules(Solver *solv)
              if (obs)
                {
                  /* found installed package p2 that we can update to p */
-                 if (!solv->allowarchchange && s->arch != s2->arch && policy_illegal_archchange(solv, s, s2))
-                   continue;
-                 if (!solv->allowvendorchange && s->vendor != s2->vendor && policy_illegal_vendorchange(solv, s, s2))
-                   continue;
                  if (MAPTST(&mneg, p))
                    continue;
+                 if (policy_is_illegal(solv, s2, s, 0))
+                   continue;
                  queue_push(&qi, p2);
                  queue_push(&q, p);
                  continue;
index 1ffe5bf..7cefd1a 100644 (file)
@@ -2764,7 +2764,7 @@ solver_solve(Solver *solv, Queue *job)
       switch (how & SOLVER_JOBMASK)
        {
        case SOLVER_INSTALL:
-         POOL_DEBUG(SAT_DEBUG_JOB, "job: %sinstall %s\n", weak ? "weak " : "", solver_select2str(solv, select, what));
+         POOL_DEBUG(SAT_DEBUG_JOB, "job: %sinstall %s\n", weak ? "weak " : "", solver_select2str(pool, select, what));
          if (select == SOLVER_SOLVABLE)
            {
              p = what;
@@ -2786,7 +2786,7 @@ solver_solve(Solver *solv, Queue *job)
          solver_addjobrule(solv, p, d, i, weak);
          break;
        case SOLVER_ERASE:
-         POOL_DEBUG(SAT_DEBUG_JOB, "job: %s%serase %s\n", weak ? "weak " : "", how & SOLVER_CLEANDEPS ? "clean deps " : "", solver_select2str(solv, select, what));
+         POOL_DEBUG(SAT_DEBUG_JOB, "job: %s%serase %s\n", weak ? "weak " : "", how & SOLVER_CLEANDEPS ? "clean deps " : "", solver_select2str(pool, 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)
@@ -2817,23 +2817,23 @@ solver_solve(Solver *solv, Queue *job)
          break;
 
        case SOLVER_UPDATE:
-         POOL_DEBUG(SAT_DEBUG_JOB, "job: %supdate %s\n", weak ? "weak " : "", solver_select2str(solv, select, what));
+         POOL_DEBUG(SAT_DEBUG_JOB, "job: %supdate %s\n", weak ? "weak " : "", solver_select2str(pool, select, what));
          break;
        case SOLVER_VERIFY:
-         POOL_DEBUG(SAT_DEBUG_JOB, "job: %sverify %s\n", weak ? "weak " : "", solver_select2str(solv, select, what));
+         POOL_DEBUG(SAT_DEBUG_JOB, "job: %sverify %s\n", weak ? "weak " : "", solver_select2str(pool, select, what));
          break;
        case SOLVER_WEAKENDEPS:
-         POOL_DEBUG(SAT_DEBUG_JOB, "job: %sweaken deps %s\n", weak ? "weak " : "", solver_select2str(solv, select, what));
+         POOL_DEBUG(SAT_DEBUG_JOB, "job: %sweaken deps %s\n", weak ? "weak " : "", solver_select2str(pool, select, what));
          if (select != SOLVER_SOLVABLE)
            break;
          s = pool->solvables + what;
          weaken_solvable_deps(solv, what);
          break;
        case SOLVER_NOOBSOLETES:
-         POOL_DEBUG(SAT_DEBUG_JOB, "job: %sno obsolete %s\n", weak ? "weak " : "", solver_select2str(solv, select, what));
+         POOL_DEBUG(SAT_DEBUG_JOB, "job: %sno obsolete %s\n", weak ? "weak " : "", solver_select2str(pool, select, what));
          break;
        case SOLVER_LOCK:
-         POOL_DEBUG(SAT_DEBUG_JOB, "job: %slock %s\n", weak ? "weak " : "", solver_select2str(solv, select, what));
+         POOL_DEBUG(SAT_DEBUG_JOB, "job: %slock %s\n", weak ? "weak " : "", solver_select2str(pool, select, what));
          FOR_JOB_SELECT(p, pp, select, what)
            {
              s = pool->solvables + p;
@@ -2841,10 +2841,10 @@ solver_solve(Solver *solv, Queue *job)
            }
          break;
        case SOLVER_DISTUPGRADE:
-         POOL_DEBUG(SAT_DEBUG_JOB, "job: distupgrade %s\n", solver_select2str(solv, select, what));
+         POOL_DEBUG(SAT_DEBUG_JOB, "job: distupgrade %s\n", solver_select2str(pool, select, what));
          break;
        case SOLVER_DROP_ORPHANED:
-         POOL_DEBUG(SAT_DEBUG_JOB, "job: drop orphaned %s\n", solver_select2str(solv, select, what));
+         POOL_DEBUG(SAT_DEBUG_JOB, "job: drop orphaned %s\n", solver_select2str(pool, select, what));
          if (select == SOLVER_SOLVABLE_ALL)
            solv->droporphanedmap_all = 1;
          FOR_JOB_SELECT(p, pp, select, what)
@@ -2858,7 +2858,7 @@ solver_solve(Solver *solv, Queue *job)
            }
          break;
        case SOLVER_USERINSTALLED:
-         POOL_DEBUG(SAT_DEBUG_JOB, "job: user installed %s\n", solver_select2str(solv, select, what));
+         POOL_DEBUG(SAT_DEBUG_JOB, "job: user installed %s\n", solver_select2str(pool, select, what));
          break;
        default:
          POOL_DEBUG(SAT_DEBUG_JOB, "job: unknown job\n");
index c4de09b..1b09522 100644 (file)
@@ -247,6 +247,14 @@ typedef struct _Solver {
 #define SOLVER_ESSENTIAL               0x020000
 #define SOLVER_CLEANDEPS                0x040000
 
+#define SOLVER_SETEV                   0x01000000
+#define SOLVER_SETEVR                  0x02000000
+#define SOLVER_SETARCH                 0x04000000
+#define SOLVER_SETVENDOR               0x08000000
+#define SOLVER_SETREPO                 0x10000000
+
+#define SOLVER_SETMASK                 0x1f000000
+
 /* old API compatibility, do not use in new code */
 #if 1
 #define SOLVER_INSTALL_SOLVABLE (SOLVER_INSTALL|SOLVER_SOLVABLE)
index e5bf519..0d8ad24 100644 (file)
@@ -661,23 +661,23 @@ solver_printsolution(Solver *solv, Id problem, Id solution)
              if (select == SOLVER_SOLVABLE && solv->installed && pool->solvables[what].repo == solv->installed)
                POOL_DEBUG(SAT_DEBUG_RESULT, "  - do not keep %s installed\n", solvid2str(pool, what));
              else if (select == SOLVER_SOLVABLE_PROVIDES)
-               POOL_DEBUG(SAT_DEBUG_RESULT, "  - do not install a solvable %s\n", solver_select2str(solv, select, what));
+               POOL_DEBUG(SAT_DEBUG_RESULT, "  - do not install a solvable %s\n", solver_select2str(pool, select, what));
              else
-               POOL_DEBUG(SAT_DEBUG_RESULT, "  - do not install %s\n", solver_select2str(solv, select, what));
+               POOL_DEBUG(SAT_DEBUG_RESULT, "  - do not install %s\n", solver_select2str(pool, select, what));
              break;
            case SOLVER_ERASE:
              if (select == SOLVER_SOLVABLE && !(solv->installed && pool->solvables[what].repo == solv->installed))
                POOL_DEBUG(SAT_DEBUG_RESULT, "  - do not forbid installation of %s\n", solvid2str(pool, what));
              else if (select == SOLVER_SOLVABLE_PROVIDES)
-               POOL_DEBUG(SAT_DEBUG_RESULT, "  - do not deinstall all solvables %s\n", solver_select2str(solv, select, what));
+               POOL_DEBUG(SAT_DEBUG_RESULT, "  - do not deinstall all solvables %s\n", solver_select2str(pool, select, what));
              else
-               POOL_DEBUG(SAT_DEBUG_RESULT, "  - do not deinstall %s\n", solver_select2str(solv, select, what));
+               POOL_DEBUG(SAT_DEBUG_RESULT, "  - do not deinstall %s\n", solver_select2str(pool, select, what));
              break;
            case SOLVER_UPDATE:
-             POOL_DEBUG(SAT_DEBUG_RESULT, "  - do not install most recent version of %s\n", solver_select2str(solv, select, what));
+             POOL_DEBUG(SAT_DEBUG_RESULT, "  - do not install most recent version of %s\n", solver_select2str(pool, select, what));
              break;
            case SOLVER_LOCK:
-             POOL_DEBUG(SAT_DEBUG_RESULT, "  - do not lock %s\n", solver_select2str(solv, select, what));
+             POOL_DEBUG(SAT_DEBUG_RESULT, "  - do not lock %s\n", solver_select2str(pool, select, what));
              break;
            default:
              POOL_DEBUG(SAT_DEBUG_RESULT, "  - do something different\n");
@@ -707,26 +707,19 @@ solver_printsolution(Solver *solv, Id problem, Id solution)
          sd = rp ? pool->solvables + rp : 0;
          if (sd)
            {
-             int gotone = 0;
-             if (!solv->allowdowngrade && evrcmp(pool, s->evr, sd->evr, EVRCMP_MATCH_RELEASE) > 0)
-               {
-                 POOL_DEBUG(SAT_DEBUG_RESULT, "  - allow downgrade of %s to %s\n", solvable2str(pool, s), solvable2str(pool, sd));
-                 gotone = 1;
-               }
-             if (!solv->allowarchchange && s->name == sd->name && s->arch != sd->arch && policy_illegal_archchange(solv, s, sd))
-               {
-                 POOL_DEBUG(SAT_DEBUG_RESULT, "  - allow architecture change of %s to %s\n", solvable2str(pool, s), solvable2str(pool, sd));
-                 gotone = 1;
-               }
-             if (!solv->allowvendorchange && s->name == sd->name && s->vendor != sd->vendor && policy_illegal_vendorchange(solv, s, sd))
+             int illegal = policy_is_illegal(solv, s, sd, 0);
+             if ((illegal & POLICY_ILLEGAL_DOWNGRADE) != 0)
+               POOL_DEBUG(SAT_DEBUG_RESULT, "  - allow downgrade of %s to %s\n", solvable2str(pool, s), solvable2str(pool, sd));
+             if ((illegal & POLICY_ILLEGAL_ARCHCHANGE) != 0)
+               POOL_DEBUG(SAT_DEBUG_RESULT, "  - allow architecture change of %s to %s\n", solvable2str(pool, s), solvable2str(pool, sd));
+             if ((illegal & POLICY_ILLEGAL_VENDORCHANGE) != 0)
                {
                  if (sd->vendor)
                    POOL_DEBUG(SAT_DEBUG_RESULT, "  - allow vendor change from '%s' (%s) to '%s' (%s)\n", id2str(pool, s->vendor), solvable2str(pool, s), id2str(pool, sd->vendor), solvable2str(pool, sd));
                  else
                    POOL_DEBUG(SAT_DEBUG_RESULT, "  - allow vendor change from '%s' (%s) to no vendor (%s)\n", id2str(pool, s->vendor), solvable2str(pool, s), solvable2str(pool, sd));
-                 gotone = 1;
                }
-             if (!gotone)
+             if (!illegal)
                POOL_DEBUG(SAT_DEBUG_RESULT, "  - allow replacement of %s with %s\n", solvable2str(pool, s), solvable2str(pool, sd));
            }
          else
@@ -801,9 +794,8 @@ solver_printtrivial(Solver *solv)
 }
 
 const char *
-solver_select2str(Solver *solv, Id select, Id what)
+solver_select2str(Pool *pool, Id select, Id what)
 {
-  Pool *pool = solv->pool;
   const char *s;
   char *b;
   if (select == SOLVER_SOLVABLE)
index e1033e7..7be568d 100644 (file)
@@ -31,7 +31,8 @@ extern void solver_printcompleteprobleminfo(Solver *solv, Id problem);
 extern void solver_printsolution(Solver *solv, Id problem, Id solution);
 extern void solver_printallsolutions(Solver *solv);
 extern void solver_printtrivial(Solver *solv);
-extern const char *solver_select2str(Solver *solv, Id select, Id what);
+
+extern const char *solver_select2str(Pool *pool, Id select, Id what);
 
 
 #endif /* SATSOLVER_SOLVERDEBUG_H */