Imported Upstream version 0.7.8 upstream/0.7.8
authorDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 27 Nov 2020 05:44:21 +0000 (14:44 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 27 Nov 2020 05:44:21 +0000 (14:44 +0900)
27 files changed:
NEWS
VERSION.cmake
ext/libsolvext.ver
ext/repo_rpmdb.c
ext/repo_rpmdb_bdb.h
ext/repo_rpmdb_librpm.h
ext/repo_updateinfoxml.c
ext/repo_updateinfoxml.h
ext/testcase.c
package/libsolv.changes
src/knownid.h
src/libsolv.ver
src/pool.c
src/problems.c
src/problems.h
src/rules.c
src/rules.h
src/selection.c
src/solvable.c
src/solvable.h
src/solver.c
src/solver.h
src/solverdebug.c
src/transaction.c
test/testcases/blacklist/ptf [new file with mode: 0644]
test/testcases/blacklist/retracted [new file with mode: 0644]
tools/repo2solv.c

diff --git a/NEWS b/NEWS
index 19caab7..467547b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,19 @@
 This file contains the major changes between
 libsolv versions:
 
+Version 0.7.8
+- selected bug fixes:
+  * support arch<->noarch package changes when creating patch
+    conflicts from the updateinfo data
+  * also support other rpm database types
+- new features:
+  * support for SOLVER_BLACKLIST jobs that block the installation
+    of matched packages unless they are directly selected by an
+    SOLVER_INSTALL job
+  * libsolv now also parses the patch status in the updateinfo
+    parser
+  * new solvable_matchessolvable() function
+
 Version 0.7.7
 - selected bug fixes:
   * fix updating of too many packages in focusbest mode
index 87c236c..491723a 100644 (file)
@@ -49,5 +49,5 @@ SET(LIBSOLVEXT_SOVERSION "1")
 
 SET(LIBSOLV_MAJOR "0")
 SET(LIBSOLV_MINOR "7")
-SET(LIBSOLV_PATCH "7")
+SET(LIBSOLV_PATCH "8")
 
index ef028f0..02cf6d1 100644 (file)
@@ -42,6 +42,7 @@ SOLV_1.0 {
                repo_add_zyppdb_products;
                repo_find_all_pubkeys;
                repo_find_pubkey;
+               repo_mark_retracted_packages;
                repo_verify_sigdata;
                rpm_byfp;
                rpm_byrpmdbid;
index fb1491b..e49188d 100644 (file)
@@ -1605,7 +1605,7 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags)
     }
 
   /* XXX: should get ro lock of Packages database! */
-  if (stat_database(&state, "Packages", &packagesstat, 1))
+  if (stat_database(&state, &packagesstat))
     {
       freestate(&state);
       return -1;
index ae477f7..574e9a8 100644 (file)
@@ -57,7 +57,7 @@ struct rpmdbstate {
 
 
 static int
-stat_database(struct rpmdbstate *state, char *dbname, struct stat *statbuf, int seterror)
+stat_database_name(struct rpmdbstate *state, char *dbname, struct stat *statbuf, int seterror)
 {
   char *dbpath;
   dbpath = solv_dupjoin(state->rootdir, state->is_ostree ? "/usr/share/rpm/" : "/var/lib/rpm/", dbname);
@@ -72,6 +72,13 @@ stat_database(struct rpmdbstate *state, char *dbname, struct stat *statbuf, int
   return 0;
 }
 
+static int
+stat_database(struct rpmdbstate *state, struct stat *statbuf)
+{
+  return stat_database_name(state, "Packages", statbuf, 1);
+}
+
+
 static inline Id
 db2rpmdbid(unsigned char *db, int byteswapped)
 {
@@ -426,7 +433,7 @@ count_headers(struct rpmdbstate *state)
   DBT dbkey;
   DBT dbdata;
 
-  if (stat_database(state, "Name", &statbuf, 0))
+  if (stat_database_name(state, "Name", &statbuf, 0))
     return 0;
   memset(&dbkey, 0, sizeof(dbkey));
   memset(&dbdata, 0, sizeof(dbdata));
index 79983d3..6fdcfb0 100644 (file)
@@ -31,18 +31,34 @@ struct rpmdbstate {
 };
 
 static int
-stat_database(struct rpmdbstate *state, char *dbname, struct stat *statbuf, int seterror)
+stat_database(struct rpmdbstate *state, struct stat *statbuf)
 {
-  char *dbpath;
-  dbpath = solv_dupjoin(state->rootdir, state->is_ostree ? "/usr/share/rpm/" : "/var/lib/rpm/", dbname);
-  if (stat(dbpath, statbuf))
+  static const char *dbname[] = {
+    "Packages",
+    "Packages.db",
+    "rpmdb.sqlite",
+    "data.mdb",
+    "Packages",                /* for error reporting */
+    0,
+  };
+  int i;
+
+  for (i = 0; ; i++)
     {
-      if (seterror)
-        pool_error(state->pool, -1, "%s: %s", dbpath, strerror(errno));
-      free(dbpath);
-      return -1;
+      char *dbpath = solv_dupjoin(state->rootdir, state->is_ostree ? "/usr/share/rpm/" : "/var/lib/rpm/", dbname[i]);
+      if (!stat(dbpath, statbuf))
+       {
+         free(dbpath);
+         return 0;
+       }
+      if (errno != ENOENT || !dbname[i + 1])
+       {
+         pool_error(state->pool, -1, "%s: %s", dbpath, strerror(errno));
+         solv_free(dbpath);
+         return -1;
+       }
+      solv_free(dbpath);
     }
-  free(dbpath);
   return 0;
 }
 
index f375727..5b980a1 100644 (file)
@@ -220,7 +220,7 @@ startElement(struct solv_xmlparser *xmlp, int state, const char *name, const cha
        */
     case STATE_UPDATE:
       {
-       const char *from = 0, *type = 0, *version = 0;
+       const char *from = 0, *type = 0, *version = 0, *status = 0;
        for (; *atts; atts += 2)
          {
            if (!strcmp(*atts, "from"))
@@ -229,6 +229,8 @@ startElement(struct solv_xmlparser *xmlp, int state, const char *name, const cha
              type = atts[1];
            else if (!strcmp(*atts, "version"))
              version = atts[1];
+           else if (!strcmp(*atts, "status"))
+             status = atts[1];
          }
        solvable = pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo));
        pd->handle = pd->solvable - pool->solvables;
@@ -238,6 +240,8 @@ startElement(struct solv_xmlparser *xmlp, int state, const char *name, const cha
        solvable->arch = ARCH_NOARCH;
        if (type)
          repodata_set_str(pd->data, pd->handle, SOLVABLE_PATCHCATEGORY, type);
+       if (status)
+         repodata_set_poolstr(pd->data, pd->handle, UPDATE_STATUS, status);
         pd->buildtime = (time_t)0;
       }
       break;
@@ -294,8 +298,7 @@ startElement(struct solv_xmlparser *xmlp, int state, const char *name, const cha
       {
        const char *arch = 0, *name = 0;
        Id evr = makeevr_atts(pool, pd, atts); /* parse "epoch", "version", "release" */
-       Id n, a = 0;
-       Id rel_id;
+       Id n, a, id;
 
        for (; *atts; atts += 2)
          {
@@ -304,17 +307,24 @@ startElement(struct solv_xmlparser *xmlp, int state, const char *name, const cha
            else if (!strcmp(*atts, "name"))
              name = atts[1];
          }
-       /* generated Id for name */
-       n = pool_str2id(pool, name, 1);
-       rel_id = n;
-       if (arch)
+       n = name ? pool_str2id(pool, name, 1) : 0;
+       a = arch ? pool_str2id(pool, arch, 1) : 0;
+
+       /* generated conflicts for the package */
+       if (a && a != ARCH_NOARCH)
+         {
+           id = pool_rel2id(pool, n, a, REL_ARCH, 1);
+           id = pool_rel2id(pool, id, evr, REL_LT, 1);
+           solvable->conflicts = repo_addid_dep(pd->repo, solvable->conflicts, id, 0);
+           id = pool_rel2id(pool, n, ARCH_NOARCH, REL_ARCH, 1);
+           id = pool_rel2id(pool, id, evr, REL_LT, 1);
+           solvable->conflicts = repo_addid_dep(pd->repo, solvable->conflicts, id, 0);
+         }
+       else
          {
-           /*  generate Id for arch and combine with name */
-           a = pool_str2id(pool, arch, 1);
-           rel_id = pool_rel2id(pool, n, a, REL_ARCH, 1);
+           id = pool_rel2id(pool, n, evr, REL_LT, 1);
+           solvable->conflicts = repo_addid_dep(pd->repo, solvable->conflicts, id, 0);
          }
-       rel_id = pool_rel2id(pool, rel_id, evr, REL_LT, 1);
-       solvable->conflicts = repo_addid_dep(pd->repo, solvable->conflicts, rel_id, 0);
 
         /* who needs the collection anyway? */
         pd->collhandle = repodata_new_handle(pd->data);
@@ -486,3 +496,92 @@ repo_add_updateinfoxml(Repo *repo, FILE *fp, int flags)
   return pd.ret;
 }
 
+#ifdef SUSE
+
+static int
+repo_mark_retracted_packages_cmp(const void *ap, const void *bp, void *dp)
+{
+  Id *a = (Id *)ap;
+  Id *b = (Id *)bp;
+  if (a[1] != b[1])
+    return a[1] - b[1];
+  if (a[2] != b[2])
+    return a[2] - b[2];
+  if (a[0] != b[0])
+    return a[0] - b[0];
+  return 0;
+}
+
+
+void
+repo_mark_retracted_packages(Repo *repo, Id retractedmarker)
+{
+  Pool *pool = repo->pool;
+  int i, p;
+  Solvable *s;
+  Id con, *conp;
+  Id retractedname, retractedevr;
+
+  Queue q;
+  queue_init(&q);
+  for (p = 1; p < pool->nsolvables; p++)
+    {
+      const char *status;
+      s = pool->solvables + p;
+      if (strncmp(pool_id2str(pool, s->name), "patch:", 6) != 0)
+       {
+         if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
+           continue;
+         queue_push2(&q, p, s->name);
+         queue_push2(&q, s->evr, s->arch);
+         continue;
+       }
+      status = solvable_lookup_str(s, UPDATE_STATUS);
+      if (!status || strcmp(status, "retracted") != 0)
+       continue;
+      if (!s->conflicts)
+       continue;
+      conp = s->repo->idarraydata + s->conflicts;
+      while ((con = *conp++) != 0)
+       {
+         Reldep *rd;
+         Id name, evr, arch;
+         if (!ISRELDEP(con))
+           continue;
+         rd = GETRELDEP(pool, con);
+         if (rd->flags != REL_LT)
+           continue;
+         name = rd->name;
+         evr = rd->evr;
+         arch = 0;
+         if (ISRELDEP(name))
+           {
+             rd = GETRELDEP(pool, name);
+             name = rd->name;
+             if (rd->flags == REL_ARCH)
+               arch = rd->evr;
+           }
+         queue_push2(&q, 0, name);
+         queue_push2(&q, evr, arch);
+       }
+    }
+  if (q.count)
+    solv_sort(q.elements, q.count / 4, sizeof(Id) * 4, repo_mark_retracted_packages_cmp, repo->pool);
+  retractedname = retractedevr = 0;
+  for (i = 0; i < q.count; i += 4)
+    {
+      if (!q.elements[i])
+       {
+         retractedname = q.elements[i + 1];
+         retractedevr = q.elements[i + 2];
+       }
+      else if (q.elements[i + 1] == retractedname && q.elements[i + 2] == retractedevr)
+       {
+         s = pool->solvables + q.elements[i];
+         s->provides = repo_addid_dep(repo, s->provides, retractedmarker, 0);
+       }
+    }
+  queue_free(&q);
+}
+
+#endif
index bd0a61b..c3da0f6 100644 (file)
@@ -6,3 +6,6 @@
  */
 
 extern int repo_add_updateinfoxml(Repo *repo, FILE *fp, int flags);
+
+extern void repo_mark_retracted_packages(Repo *repo, Id retractedmarker);
+
index bd0643a..d6c4a57 100644 (file)
@@ -59,6 +59,7 @@ static struct job2str {
   { SOLVER_ALLOWUNINSTALL, "allowuninstall" },
   { SOLVER_FAVOR,          "favor" },
   { SOLVER_DISFAVOR,       "disfavor" },
+  { SOLVER_BLACKLIST,      "blacklist" },
   { 0, 0 }
 };
 
@@ -1190,6 +1191,7 @@ static struct rclass2str {
   { SOLVER_RULE_LEARNT, "learnt" },
   { SOLVER_RULE_BEST, "best" },
   { SOLVER_RULE_YUMOBS, "yumobs" },
+  { SOLVER_RULE_BLACK, "black" },
   { SOLVER_RULE_RECOMMENDS, "recommends" },
   { 0, 0 }
 };
index fbb4a72..e060b4d 100644 (file)
@@ -1,4 +1,17 @@
 -------------------------------------------------------------------
+Tue Nov 12 11:35:12 CET 2019 - mls@suse.de
+
+- support arch<->noarch package changes when creating patch
+  conflicts from the updateinfo data
+- support for SOLVER_BLACKLIST jobs that block the installation
+  of matched packages unless they are directly selected by an
+  SOLVER_INSTALL job
+- libsolv now also parses the patch status in the updateinfo
+  parser
+- new solvable_matchessolvable() function
+- bump version to 0.7.8
+
+-------------------------------------------------------------------
 Fri Oct 18 10:53:54 CEST 2019 - mls@suse.de
 
 - fix updating of too many packages in focusbest mode
index 9d7f157..3a88ee2 100644 (file)
@@ -261,6 +261,10 @@ KNOWNID(UPDATE_MODULE_ARCH,                "update:module:arch"),          /* architecture */
 KNOWNID(SOLVABLE_BUILDVERSION,         "solvable:buildversion"),       /* conda */
 KNOWNID(SOLVABLE_BUILDFLAVOR,          "solvable:buildflavor"),        /* conda */
 
+KNOWNID(UPDATE_STATUS,                 "update:status"),               /* "stable", "testing", ...*/
+
+KNOWNID(LIBSOLV_SELF_DESTRUCT_PKG,      "libsolv-self-destruct-pkg()"),        /* this package will self-destruct on installation */
+
 KNOWNID(ID_NUM_INTERNAL,               0)
 
 #ifdef KNOWNID_INITIALIZE
index eafe3e6..ee40d0a 100644 (file)
@@ -325,6 +325,7 @@ SOLV_1.0 {
                solvable_lookup_type;
                solvable_lookup_void;
                solvable_matchesdep;
+               solvable_matchessolvable;
                solvable_selfprovidedep;
                solvable_set_deparray;
                solvable_set_id;
index 76636a7..0b4b9dd 100644 (file)
@@ -1542,7 +1542,7 @@ pool_whatmatchessolvable(Pool *pool, Id keyname, Id solvid, Queue *q, int marker
        continue;
       if (s->repo != pool->installed && !pool_installable(pool, s))
        continue;
-      if (solvable_matchessolvable_int(s, keyname, marker, solvid, 0, &qq, &missc, reloff))
+      if (solvable_matchessolvable_int(s, keyname, marker, solvid, 0, &qq, &missc, reloff, 0))
         queue_push(q, p);
     }
   map_free(&missc);
index 6f2ad4b..b46d624 100644 (file)
@@ -719,6 +719,12 @@ convertsolution(Solver *solv, Id why, Queue *solutionq)
        }
       return;
     }
+  if (why >= solv->blackrules && why < solv->blackrules_end)
+    {
+      queue_push(solutionq, SOLVER_SOLUTION_BLACK);
+      assert(solv->rules[why].p < 0);
+      queue_push(solutionq, -solv->rules[why].p);
+    }
 }
 
 /*
@@ -981,6 +987,8 @@ solver_solutionelement_extrajobflags(Solver *solv, Id problem, Id solution)
  *    -> add (SOLVER_INSTALL|SOLVER_SOLVABLE, rp) to the job
  *    SOLVER_SOLUTION_BEST          pkgid
  *    -> add (SOLVER_INSTALL|SOLVER_SOLVABLE, rp) to the job
+ *    SOLVER_SOLUTION_BLACK         pkgid
+ *    -> add (SOLVER_INSTALL|SOLVER_SOLVABLE, rp) to the job
  *    SOLVER_SOLUTION_JOB           jobidx
  *    -> remove job (jobidx - 1, jobidx) from job queue
  *    SOLVER_SOLUTION_POOLJOB       jobidx
@@ -1331,6 +1339,8 @@ solver_problemruleinfo2str(Solver *solv, SolverRuleinfo type, Id source, Id targ
       s = pool_tmpjoin(pool, "both package ", pool_solvid2str(pool, source), " and ");
       s = pool_tmpjoin(pool, s, pool_solvid2str(pool, target), " obsolete ");
       return pool_tmpappend(pool, s, pool_dep2str(pool, dep), 0);
+    case SOLVER_RULE_BLACK:
+      return pool_tmpjoin(pool, "package ", pool_solvid2str(pool, source), " can only be installed by a direct request");
     default:
       return "bad problem rule type";
     }
@@ -1385,6 +1395,11 @@ solver_solutionelement2str(Solver *solv, Id p, Id rp)
       else
         return pool_tmpjoin(pool, "install ", pool_solvable2str(pool, s), " despite the old version");
     }
+  else if (p == SOLVER_SOLUTION_BLACK)
+    {
+      Solvable *s = pool->solvables + rp;
+      return pool_tmpjoin(pool, "install ", pool_solvable2str(pool, s), 0);
+    }
   else if (p > 0 && rp == 0)
     return pool_tmpjoin(pool, "allow deinstallation of ", pool_solvid2str(pool, p), 0);
   else if (p > 0 && rp > 0)
index 37021e1..45e4e7c 100644 (file)
@@ -22,11 +22,12 @@ extern "C" {
 
 struct s_Solver;
 
-#define SOLVER_SOLUTION_JOB             (0)
-#define SOLVER_SOLUTION_DISTUPGRADE     (-1)
-#define SOLVER_SOLUTION_INFARCH         (-2)
-#define SOLVER_SOLUTION_BEST            (-3)
-#define SOLVER_SOLUTION_POOLJOB         (-4)
+#define SOLVER_SOLUTION_JOB            (0)
+#define SOLVER_SOLUTION_DISTUPGRADE    (-1)
+#define SOLVER_SOLUTION_INFARCH                (-2)
+#define SOLVER_SOLUTION_BEST           (-3)
+#define SOLVER_SOLUTION_POOLJOB                (-4)
+#define SOLVER_SOLUTION_BLACK          (-5)
 
 void solver_recordproblem(struct s_Solver *solv, Id rid);
 void solver_fixproblem(struct s_Solver *solv, Id rid);
index 57895c0..cb8d17d 100644 (file)
@@ -498,6 +498,16 @@ add_package_link(Solver *solv, Solvable *s, Map *m, Queue *workq)
 
 #ifdef ENABLE_COMPLEX_DEPS
 
+#ifdef SUSE
+static inline int
+suse_isptf(Pool *pool, Solvable *s)
+{
+  if (!strncmp("ptf-", pool_id2str(pool, s->name), 4))
+    return 1;
+  return 0;
+}
+#endif
+
 static void
 add_complex_deprules(Solver *solv, Id p, Id dep, int type, int dontfix, Queue *workq, Map *m)
 {
@@ -511,6 +521,10 @@ add_complex_deprules(Solver *solv, Id p, Id dep, int type, int dontfix, Queue *w
   /* CNF expansion for requires, DNF + INVERT expansion for conflicts */
   if (type == SOLVER_RULE_PKG_CONFLICTS)
     flags |= CPLXDEPS_TODNF | CPLXDEPS_EXPAND | CPLXDEPS_INVERT;
+#ifdef SUSE
+  if (type == SOLVER_RULE_PKG_REQUIRES && suse_isptf(pool, pool->solvables + p))
+    flags |= CPLXDEPS_NAME;    /* do not match provides */
+#endif
 
   i = pool_normalize_complex_dep(pool, dep, &bq, flags);
   /* handle special cases */
@@ -2101,6 +2115,97 @@ reenableduprule(Solver *solv, Id name)
     }
 }
 
+/***********************************************************************
+ ***
+ ***  Black rule part
+ ***/
+
+static inline void
+disableblackrule(Solver *solv, Id p)
+{
+  Rule *r;
+  int i;
+  for (i = solv->blackrules, r = solv->rules + i; i < solv->blackrules_end; i++, r++)
+    if (r->p == -p)
+      solver_disablerule(solv, r);
+}
+
+static inline void
+reenableblackrule(Solver *solv, Id p)
+{
+  Pool *pool = solv->pool;
+  Rule *r;
+  int i;
+  for (i = solv->blackrules, r = solv->rules + i; i < solv->blackrules_end; i++, r++)
+    if (r->p == -p)
+      {
+       solver_enablerule(solv, r);
+       IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS)
+         {
+           POOL_DEBUG(SOLV_DEBUG_SOLUTIONS, "@@@ re-enabling ");
+           solver_printruleclass(solv, SOLV_DEBUG_SOLUTIONS, r);
+         }
+      }
+}
+
+void
+solver_addblackrules(Solver *solv)
+{
+  int i;
+  Id how, select, what, p, pp;
+  Queue *job = &solv->job;
+  Pool *pool = solv->pool;
+  Repo *installed = solv->installed;
+  Map updatemap;
+
+  map_init(&updatemap, 0);
+  solv->blackrules = solv->nrules;
+  if (installed)
+    {
+      for (i = 0; i < job->count; i += 2)
+       {
+         how = job->elements[i];
+         select = job->elements[i] & SOLVER_SELECTMASK;
+         what = job->elements[i + 1];
+         switch (how & SOLVER_JOBMASK)
+           {
+           case SOLVER_BLACKLIST:
+             FOR_JOB_SELECT(p, pp, select, what)
+               {
+                 Solvable *s = pool->solvables + p;
+                 if (s->repo != installed)
+                   continue;
+                 if (!updatemap.size)
+                   map_grow(&updatemap, pool->ss.nstrings);
+                 if (s->name > 0 && s->name < pool->ss.nstrings)
+                   MAPSET(&updatemap, s->name);
+               }
+           }
+       }
+    }
+  for (i = 0; i < job->count; i += 2)
+    {
+      how = job->elements[i];
+      select = job->elements[i] & SOLVER_SELECTMASK;
+      what = job->elements[i + 1];
+      switch (how & SOLVER_JOBMASK)
+       {
+       case SOLVER_BLACKLIST:
+         FOR_JOB_SELECT(p, pp, select, what)
+           {
+             Solvable *s = pool->solvables + p;
+             if (s->repo == installed)
+               continue;
+             if (updatemap.size && s->name > 0 && s->name < pool->ss.nstrings && MAPTST(&updatemap, s->name))
+               continue;       /* installed package with same name is already blacklisted */
+             solver_addrule(solv, -p, 0, 0);
+           }
+         break;
+       }
+    }
+  map_free(&updatemap);
+  solv->blackrules_end = solv->nrules;
+}
 
 /***********************************************************************
  ***
@@ -2114,6 +2219,7 @@ reenableduprule(Solver *solv, Id name)
 #define DISABLE_UPDATE 1
 #define DISABLE_INFARCH        2
 #define DISABLE_DUP    3
+#define DISABLE_BLACK  4
 
 static void
 jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
@@ -2213,6 +2319,16 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
                }
            }
        }
+      if ((set & SOLVER_SETEVR) != 0 && solv->blackrules != solv->blackrules_end)
+        {
+         if (select == SOLVER_SOLVABLE)
+           queue_push2(q, DISABLE_BLACK, what);
+         else
+           {
+             FOR_JOB_SELECT(p, pp, select, what)
+               queue_push2(q, DISABLE_BLACK, p);
+           }
+        }
       if (!installed || installed->end == installed->start)
        return;
       /* now the hard part: disable some update rules */
@@ -2386,6 +2502,9 @@ solver_disablepolicyrules(Solver *solv)
        case DISABLE_DUP:
          disableduprule(solv, arg);
          break;
+       case DISABLE_BLACK:
+         disableblackrule(solv, arg);
+         break;
        default:
          break;
        }
@@ -2489,6 +2608,9 @@ solver_reenablepolicyrules(Solver *solv, int jobidx)
        case DISABLE_DUP:
          reenableduprule(solv, arg);
          break;
+       case DISABLE_BLACK:
+         reenableblackrule(solv, arg);
+         break;
        }
     }
   queue_free(&q);
@@ -2815,6 +2937,12 @@ solver_ruleinfo(Solver *solv, Id rid, Id *fromp, Id *top, Id *depp)
        *depp = solv->yumobsrules_info[rid - solv->yumobsrules];
       return SOLVER_RULE_YUMOBS;
     }
+  if (rid >= solv->blackrules && rid < solv->blackrules_end)
+    {
+      if (fromp)
+       *fromp = -r->p;
+      return SOLVER_RULE_BLACK;
+    }
   if (rid >= solv->choicerules && rid < solv->choicerules_end)
     return SOLVER_RULE_CHOICE;
   if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end)
@@ -2845,10 +2973,14 @@ solver_ruleclass(Solver *solv, Id rid)
     return SOLVER_RULE_BEST;
   if (rid >= solv->yumobsrules && rid < solv->yumobsrules_end)
     return SOLVER_RULE_YUMOBS;
+  if (rid >= solv->blackrules && rid < solv->blackrules_end)
+    return SOLVER_RULE_BLACK;
   if (rid >= solv->choicerules && rid < solv->choicerules_end)
     return SOLVER_RULE_CHOICE;
   if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end)
     return SOLVER_RULE_RECOMMENDS;
+  if (rid >= solv->blackrules && rid < solv->blackrules_end)
+    return SOLVER_RULE_BLACK;
   if (rid >= solv->learntrules && rid < solv->nrules)
     return SOLVER_RULE_LEARNT;
   return SOLVER_RULE_UNKNOWN;
index 6b8511f..9286090 100644 (file)
@@ -72,7 +72,8 @@ typedef enum {
   SOLVER_RULE_LEARNT = 0x800,
   SOLVER_RULE_BEST = 0x900,
   SOLVER_RULE_YUMOBS = 0xa00,
-  SOLVER_RULE_RECOMMENDS = 0xb00
+  SOLVER_RULE_RECOMMENDS = 0xb00,
+  SOLVER_RULE_BLACK = 0xc00
 } SolverRuleinfo;
 
 #define SOLVER_RULE_TYPEMASK    0xff00
@@ -134,6 +135,9 @@ extern void solver_addbestrules(struct s_Solver *solv, int havebestinstalljobs,
 /* yumobs rules */
 extern void solver_addyumobsrules(struct s_Solver *solv);
 
+/* black rules */
+extern void solver_addblackrules(struct s_Solver *solv);
+
 /* recommends rules */
 extern void solver_addrecommendsrules(struct s_Solver *solv);
 
index e58d731..5f01e2b 100644 (file)
@@ -1502,7 +1502,7 @@ selection_make_matchsolvable_common(Pool *pool, Queue *selection, Queue *solvidq
        continue;
       if (!solvable_matches_selection_flags(pool, s, flags))
        continue;
-      if (solvable_matchessolvable_int(s, keyname, marker, solvid, solvidq ? &m : 0, &q, &missc, reloff))
+      if (solvable_matchessolvable_int(s, keyname, marker, solvid, solvidq ? &m : 0, &q, &missc, reloff, 0))
         queue_push(selection, p);
     }
   queue_free(&q);
index d3d2d31..474e6f5 100644 (file)
@@ -645,7 +645,7 @@ solvable_matchesdep(Solvable *s, Id keyname, Id dep, int marker)
 }
 
 int
-solvable_matchessolvable_int(Solvable *s, Id keyname, int marker, Id solvid, Map *solvidmap, Queue *depq, Map *missc, int reloff)
+solvable_matchessolvable_int(Solvable *s, Id keyname, int marker, Id solvid, Map *solvidmap, Queue *depq, Map *missc, int reloff, Queue *outdepq)
 {
   Pool *pool = s->repo->pool;
   int i, boff;
@@ -653,6 +653,8 @@ solvable_matchessolvable_int(Solvable *s, Id keyname, int marker, Id solvid, Map
 
   if (depq->count)
     queue_empty(depq);
+  if (outdepq && outdepq->count)
+    queue_empty(outdepq);
   solvable_lookup_deparray(s, keyname, depq, marker);
   for (i = 0; i < depq->count; i++)
     {
@@ -695,15 +697,46 @@ solvable_matchessolvable_int(Solvable *s, Id keyname, int marker, Id solvid, Map
        {
          for (; *wp; wp++)
            if (MAPTST(solvidmap, *wp))
-             return 1;
+             break;
        }
       else
        {
          for (; *wp; wp++)
            if (*wp == solvid)
-             return 1;
+             break;
+       }
+      if (*wp)
+       {
+         if (outdepq)
+           {
+             queue_pushunique(outdepq, dep);
+             continue;
+           }
+         return 1;
        }
       MAPSET(missc, boff);
     }
-  return 0;
+  return outdepq && outdepq->count ? 1 : 0;
+}
+
+int
+solvable_matchessolvable(Solvable *s, Id keyname, Id solvid, Queue *depq, int marker)
+{
+  Pool *pool = s->repo->pool;
+  Map missc;           /* cache for misses */
+  int res, reloff;
+  Queue qq;
+
+  if (depq && depq->count)
+    queue_empty(depq);
+  if (s - pool->solvables == solvid)
+    return 0;          /* no self-matches */
+
+  queue_init(&qq);
+  reloff = pool->ss.nstrings;
+  map_init(&missc, reloff + pool->nrels);
+  res = solvable_matchessolvable_int(s, keyname, marker, solvid, 0, &qq, &missc, reloff, depq);
+  map_free(&missc);
+  queue_free(&qq);
+  return res;
 }
index bf92a00..7788e7c 100644 (file)
@@ -81,9 +81,10 @@ int solvable_identical(Solvable *s1, Solvable *s2);
 Id solvable_selfprovidedep(Solvable *s);
 
 int solvable_matchesdep(Solvable *s, Id keyname, Id dep, int marker);
+int solvable_matchessolvable(Solvable *s, Id keyname, Id solvid, Queue *depq, int marker);
 
 /* internal */
-int solvable_matchessolvable_int(Solvable *s, Id keyname, int marker, Id solvid, Map *solvidmap, Queue *depq, Map *missc, int reloff);
+int solvable_matchessolvable_int(Solvable *s, Id keyname, int marker, Id solvid, Map *solvidmap, Queue *depq, Map *missc, int reloff, Queue *outdepq);
 
 
 /* weird suse stuff */
index 45f9dbf..6a9d66e 100644 (file)
@@ -3377,6 +3377,7 @@ solver_solve(Solver *solv, Queue *job)
   int hasbestinstalljob = 0;
   int hasfavorjob = 0;
   int haslockjob = 0;
+  int hasblacklistjob = 0;
 
   solve_start = solv_timems(0);
 
@@ -3987,6 +3988,10 @@ solver_solve(Solver *solv, Queue *job)
          POOL_DEBUG(SOLV_DEBUG_JOB, "job: %s %s\n", (how & SOLVER_JOBMASK) == SOLVER_FAVOR ? "favor" : "disfavor", solver_select2str(pool, select, what));
          hasfavorjob = 1;
          break;
+       case SOLVER_BLACKLIST:
+         POOL_DEBUG(SOLV_DEBUG_JOB, "job: blacklist %s\n", solver_select2str(pool, select, what));
+         hasblacklistjob = 1;
+         break;
        default:
          POOL_DEBUG(SOLV_DEBUG_JOB, "job: unknown job\n");
          break;
@@ -4040,6 +4045,11 @@ solver_solve(Solver *solv, Queue *job)
   else
     solv->yumobsrules = solv->yumobsrules_end = solv->nrules;
 
+  if (hasblacklistjob)
+    solver_addblackrules(solv);
+  else
+    solv->blackrules = solv->blackrules_end = solv->nrules;
+
   if (solv->havedisfavored && solv->strongrecommends && solv->recommendsruleq)
     solver_addrecommendsrules(solv);
   else
@@ -4851,6 +4861,9 @@ pool_job2str(Pool *pool, Id how, Id what, Id flagmask)
     case SOLVER_DISFAVOR:
       strstart = "disfavor ";
       break;
+    case SOLVER_BLACKLIST:
+      strstart = "blacklist ";
+      break;
     default:
       strstart = "unknown job ";
       break;
index daf4f63..2dec259 100644 (file)
@@ -76,6 +76,9 @@ struct s_Solver {
   Id yumobsrules_end;
   Id *yumobsrules_info;                        /* the dependency for each rule */
 
+  Id blackrules;                       /* rules from blacklisted packages */
+  Id blackrules_end;
+
   Id choicerules;                      /* choice rules (always weak) */
   Id choicerules_end;
   Id *choicerules_info;                        /* the rule we used to generate the choice rule */
@@ -244,6 +247,7 @@ typedef struct s_Solver Solver;
 #define SOLVER_ALLOWUNINSTALL          0x0b00
 #define SOLVER_FAVOR                   0x0c00
 #define SOLVER_DISFAVOR                        0x0d00
+#define SOLVER_BLACKLIST               0x0e00
 
 #define SOLVER_JOBMASK                 0xff00
 
index b1b55f4..0b2879b 100644 (file)
@@ -128,6 +128,8 @@ solver_printruleclass(Solver *solv, int type, Rule *r)
     POOL_DEBUG(type, "FEATURE ");
   else if (p >= solv->yumobsrules && p < solv->yumobsrules_end)
     POOL_DEBUG(type, "YUMOBS ");
+  else if (p >= solv->blackrules && p < solv->blackrules_end)
+    POOL_DEBUG(type, "BLACK ");
   else if (p >= solv->recommendsrules && p < solv->recommendsrules_end)
     POOL_DEBUG(type, "RECOMMENDS ");
   solver_printrule(solv, type, r);
index 4a4189e..fb2cc9a 100644 (file)
@@ -646,6 +646,8 @@ create_transaction_info(Transaction *trans, Queue *decisionq)
       s = pool->solvables + p;
       if (!s->repo || s->repo == installed)
        continue;
+      if (!MAPTST(&trans->transactsmap, p))
+       continue;
       multi = trans->multiversionmap.size && MAPTST(&trans->multiversionmap, p);
       FOR_PROVIDES(p2, pp2, s->name)
        {
@@ -726,9 +728,10 @@ transaction_create_decisionq(Pool *pool, Queue *decisionq, Map *multiversionmap)
 {
   Repo *installed = pool->installed;
   int i, needmulti;
-  Id p;
+  Id p, pp;
   Solvable *s;
   Transaction *trans;
+  Map selfdestructmap;
 
   trans = transaction_create(pool);
   if (multiversionmap && !multiversionmap->size)
@@ -736,6 +739,13 @@ transaction_create_decisionq(Pool *pool, Queue *decisionq, Map *multiversionmap)
   queue_empty(&trans->steps);
   map_init(&trans->transactsmap, pool->nsolvables);
   needmulti = 0;
+  map_init(&selfdestructmap, 0);
+  FOR_PROVIDES(p, pp, LIBSOLV_SELF_DESTRUCT_PKG)
+    {
+      if (!selfdestructmap.size)
+       map_grow(&selfdestructmap, pool->nsolvables);
+      MAPSET(&selfdestructmap, p);
+    }
   for (i = 0; i < decisionq->count; i++)
     {
       p = decisionq->elements[i];
@@ -746,11 +756,14 @@ transaction_create_decisionq(Pool *pool, Queue *decisionq, Map *multiversionmap)
        MAPSET(&trans->transactsmap, -p);
       if (!(installed && s->repo == installed) && p > 0)
        {
+         if (selfdestructmap.size && MAPTST(&selfdestructmap, p))
+           continue;
          MAPSET(&trans->transactsmap, p);
          if (multiversionmap && MAPTST(multiversionmap, p))
            needmulti = 1;
        }
     }
+  map_free(&selfdestructmap);
   MAPCLR(&trans->transactsmap, SYSTEMSOLVABLE);
   if (needmulti)
     map_init_clone(&trans->multiversionmap, multiversionmap);
diff --git a/test/testcases/blacklist/ptf b/test/testcases/blacklist/ptf
new file mode 100644 (file)
index 0000000..b8765d0
--- /dev/null
@@ -0,0 +1,52 @@
+repo system 0 testtags <inline>
+#>=Pkg: ptf-2 1 1 noarch
+#>=Prv: ptf-package()
+repo available 0 testtags <inline>
+#>=Pkg: ptf-1 1 1 noarch
+#>=Prv: ptf-package()
+#>=Pkg: ptf-2 2 1 noarch
+#>=Prv: ptf-package()
+#>=Pkg: A 1 1 noarch
+#>=Req: ptf-1
+
+system i686 * system
+
+#
+# test 1: a ptf package cannot be pulled in via a dependency
+#
+job blacklist provides ptf-package()
+job install name A
+result transaction,problems <inline>
+#>problem 78613afb info package A-1-1.noarch requires ptf-1, but none of the providers can be installed
+#>problem 78613afb solution 23f73f5b deljob install name A
+#>problem 78613afb solution b79aeb6f allow ptf-1-1-1.noarch@available
+
+#
+# test 2: a ptf package cannot be pulled in via a unspecific job
+#
+nextjob
+job blacklist provides ptf-package()
+job install name ptf-1
+result transaction,problems <inline>
+#>problem 021b17e2 info package ptf-1-1-1.noarch cannot only be installed by a direct request
+#>problem 021b17e2 solution 932a6c2f deljob install name ptf-1
+#>problem 021b17e2 solution b79aeb6f allow ptf-1-1-1.noarch@available
+
+#
+# test 3: a ptf package can be pulled in via a specific job
+#
+nextjob
+job blacklist provides ptf-package()
+job install name ptf-1 [setevr]
+result transaction,problems <inline>
+#>install ptf-1-1-1.noarch@available
+
+#
+# test 4: a ptf package can be updated
+#
+nextjob
+job blacklist provides ptf-package()
+job update all packages
+result transaction,problems <inline>
+#>upgrade ptf-2-1-1.noarch@system ptf-2-2-1.noarch@available
+
diff --git a/test/testcases/blacklist/retracted b/test/testcases/blacklist/retracted
new file mode 100644 (file)
index 0000000..d75f17d
--- /dev/null
@@ -0,0 +1,22 @@
+repo system 0 testtags <inline>
+#>=Pkg: B 1 1 noarch
+repo available 0 testtags <inline>
+#>=Pkg: patch 1 1 noarch
+#>=Con: B < 2-1
+#>=Pkg: B 2 1 noarch
+#>=Prv: retracted-patch-package()
+
+system i686 * system
+
+job blacklist provides retracted-patch-package()
+job install name patch
+#>problem 3a66200a info package patch-1-1.noarch conflicts with B < 2-1 provided by B-1-1.noarch
+#>problem 3a66200a solution 14805cf8 deljob install name patch
+#>problem 3a66200a solution 4a9277b8 allow B-2-1.noarch@available
+#>problem 3a66200a solution 718064ed erase B-1-1.noarch@system
+
+nextjob
+job blacklist provides retracted-patch-package()
+job install pkg B-2-1.noarch@available
+result transaction,problems <inline>
+#>upgrade B-1-1.noarch@system B-2-1.noarch@available
index 03491a6..b390743 100644 (file)
@@ -868,6 +868,7 @@ main(int argc, char **argv)
 #ifdef SUSE
   if (add_auto)
     repo_add_autopattern(repo, 0);
+  repo_mark_retracted_packages(repo, pool_str2id(pool, "retracted-patch-package()", 1));
 #endif
   tool_write(repo, stdout);
   pool_free(pool);