Imported Upstream version 0.6.36 upstream/0.6.36
authorDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 10 Sep 2019 06:37:46 +0000 (15:37 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 10 Sep 2019 06:37:46 +0000 (15:37 +0900)
26 files changed:
NEWS
VERSION.cmake
doc/rpmdb2solv.txt
examples/solv/fastestmirror.c
examples/solv/repoinfo_system_rpm.c
ext/repo_autopattern.c
ext/repo_repomdxml.c
ext/repo_rpmdb.c
ext/testcase.c
package/libsolv.changes
package/libsolv.spec.in
src/cleandeps.c
src/policy.c
src/pool.c
src/pool.h
src/problems.c
src/rules.c
src/selection.c
src/solver.c
src/strpool.c
test/testcases/allowuninstall/conflict.t [new file with mode: 0644]
test/testcases/allowuninstall/forcebest.t [new file with mode: 0644]
test/testcases/cleandeps/cleandeps_up3.t [new file with mode: 0644]
tools/repo2solv.c
tools/rpmdb2solv.c
tools/susetags2solv.c

diff --git a/NEWS b/NEWS
index abb211f..5b1a2af 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,18 @@
 This file contains the major changes between
 libsolv versions:
 
+Version 0.6.36
+- bug fixes:
+  * do not autouninstall packages because of forcebest updates
+  * fixed a couple of null pointer derefs and potential memory
+    leaks
+  * no longer disable infarch rules when they don't conflict with
+    the job
+  * fix cleandeps updates not updating all packages
+  * fix SOLVER_FLAG_FOCUS_BEST updateing packages without reason
+  * be more correct with multiversion packages that obsolete their
+    own name
+
 Version 0.6.35
 - new configuration options:
   * ENABLE_ZSTD_COMPRESSION: support zstd compression
index 991c920..d866276 100644 (file)
@@ -49,5 +49,5 @@ SET(LIBSOLVEXT_SOVERSION "0")
 
 SET(LIBSOLV_MAJOR "0")
 SET(LIBSOLV_MINOR "6")
-SET(LIBSOLV_PATCH "35")
+SET(LIBSOLV_PATCH "36")
 
index ad8314f..128e179 100644 (file)
@@ -47,6 +47,9 @@ standard directory is */etc/products.d*.
 Do not read any packages from the rpm database. This is useful
 together with *-p* to only convert SUSE products.
 
+*-C*::
+Include the package changelog in the generated solv file.
+
 *-X*::
 Autoexpand SUSE pattern and product provides into packages.
 
index d2ebd97..0ee4e73 100644 (file)
@@ -68,7 +68,11 @@ findfastest(char **urls, int nurls)
          socks[i] = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
          if (socks[i] >= 0)
            {
-             fcntl(socks[i], F_SETFL, O_NONBLOCK);
+             if (fcntl(socks[i], F_SETFL, O_NONBLOCK) == -1)
+            {
+                     close(socks[i]);
+                     socks[i] = -1;
+            }
              if (connect(socks[i], result->ai_addr, result->ai_addrlen) == -1)
                {
                  if (errno != EINPROGRESS)
index 4926ecd..b556afc 100644 (file)
@@ -17,6 +17,9 @@
 #if defined(ENABLE_APPDATA)
 #include "repo_appdata.h"
 #endif
+#ifdef SUSE
+#include "repo_autopattern.h"
+#endif
 #include "transaction.h"
 
 #include "repoinfo.h"
@@ -118,6 +121,9 @@ read_installed_rpm(struct repoinfo *cinfo)
   if (ofp)
     fclose(ofp);
   repo_internalize(repo);
+#ifdef SUSE
+  repo_add_autopattern(repo, 0);
+#endif
   writecachedrepo(cinfo, 0, 0);
   return 1;
 }
index f6e1004..7cef78c 100644 (file)
@@ -103,8 +103,8 @@ repo_add_autopattern(Repo *repo, int flags)
   if (repo == pool->installed)
     flags |= ADD_NO_AUTOPRODUCTS;      /* no auto products for installed repos */
 
-  pattern_id = pool_str2id(pool, "pattern()", 9);
-  product_id = pool_str2id(pool, "product()", 9);
+  pattern_id = pool_str2id(pool, "pattern()", 1);
+  product_id = pool_str2id(pool, "product()", 1);
   FOR_REPO_SOLVABLES(repo, p, s)
     {
       const char *n = pool_id2str(pool, s->name);
index 760d481..b2a5b8d 100644 (file)
@@ -181,7 +181,7 @@ startElement(struct solv_xmlparser *xmlp, int state, const char *name, const cha
             while (value)
              {
                char *p = strchr(value, ',');
-               if (*p)
+               if (p)
                  *p++ = 0;
                if (*value)
                  repodata_add_poolstr_array(pd->data, SOLVID_META, REPOSITORY_UPDATES, value);
index 75bb678..daf22e9 100644 (file)
@@ -1000,7 +1000,7 @@ addchangelog(Repodata *data, Id handle, RpmHead *rpmhead)
   char **cn;
   char **cx;
   uint32_t *ct;
-  int i, cnc, cxc, ctc;
+  int i, cnc, cxc, ctc = 0;
   Queue hq;
 
   ct = headint32array(rpmhead, TAG_CHANGELOGTIME, &ctc);
@@ -1939,6 +1939,8 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
   if (fread(lead, 96 + 16, 1, fp) != 1 || getu32(lead) != 0xedabeedb)
     {
       pool_error(pool, -1, "%s: not a rpm", rpm);
+      solv_chksum_free(leadsigchksumh, 0);
+      solv_chksum_free(chksumh, 0);
       fclose(fp);
       return 0;
     }
@@ -1951,12 +1953,16 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
   if (lead[78] != 0 || lead[79] != 5)
     {
       pool_error(pool, -1, "%s: not a rpm v5 header", rpm);
+      solv_chksum_free(leadsigchksumh, 0);
+      solv_chksum_free(chksumh, 0);
       fclose(fp);
       return 0;
     }
   if (getu32(lead + 96) != 0x8eade801)
     {
       pool_error(pool, -1, "%s: bad signature header", rpm);
+      solv_chksum_free(leadsigchksumh, 0);
+      solv_chksum_free(chksumh, 0);
       fclose(fp);
       return 0;
     }
@@ -1965,6 +1971,8 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
   if (sigcnt >= MAX_SIG_CNT || sigdsize >= MAX_SIG_DSIZE)
     {
       pool_error(pool, -1, "%s: bad signature header", rpm);
+      solv_chksum_free(leadsigchksumh, 0);
+      solv_chksum_free(chksumh, 0);
       fclose(fp);
       return 0;
     }
@@ -1975,6 +1983,8 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
     {
       if (!headfromfp(&state, rpm, fp, lead + 96, sigcnt, sigdsize, sigpad, chksumh, leadsigchksumh))
        {
+      solv_chksum_free(leadsigchksumh, 0);
+      solv_chksum_free(chksumh, 0);
          fclose(fp);
          return 0;
        }
@@ -2014,6 +2024,8 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
          if (fread(lead, l, 1, fp) != 1)
            {
              pool_error(pool, -1, "%s: unexpected EOF", rpm);
+             solv_chksum_free(leadsigchksumh, 0);
+             solv_chksum_free(chksumh, 0);
              fclose(fp);
              return 0;
            }
@@ -2034,6 +2046,7 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
   if (fread(lead, 16, 1, fp) != 1)
     {
       pool_error(pool, -1, "%s: unexpected EOF", rpm);
+      solv_chksum_free(chksumh, 0);
       fclose(fp);
       return 0;
     }
@@ -2042,6 +2055,7 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
   if (getu32(lead) != 0x8eade801)
     {
       pool_error(pool, -1, "%s: bad header", rpm);
+      solv_chksum_free(chksumh, 0);
       fclose(fp);
       return 0;
     }
@@ -2050,6 +2064,7 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
   if (sigcnt >= MAX_HDR_CNT || sigdsize >= MAX_HDR_DSIZE)
     {
       pool_error(pool, -1, "%s: bad header", rpm);
+      solv_chksum_free(chksumh, 0);
       fclose(fp);
       return 0;
     }
@@ -2057,6 +2072,7 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
 
   if (!headfromfp(&state, rpm, fp, lead, sigcnt, sigdsize, 0, chksumh, 0))
     {
+      solv_chksum_free(chksumh, 0);
       fclose(fp);
       return 0;
     }
index aa72a8d..0bac26b 100644 (file)
@@ -571,6 +571,8 @@ testcase_str2dep_complex(Pool *pool, const char **sp, int relop)
   Id flags, id, id2, namespaceid = 0;
   struct oplist *op;
 
+  if (!s)
+    return 0;
   while (*s == ' ' || *s == '\t')
     s++;
   if (!strncmp(s, "namespace:", 10))
@@ -1068,7 +1070,7 @@ testcase_str2job(Pool *pool, const char *str, Id *whatp)
       Queue q;
       job |= SOLVER_SOLVABLE_ONE_OF;
       queue_init(&q);
-      if (npieces > 3 && strcmp(pieces[2], "nothing") != 0)
+      if (npieces > 2 && strcmp(pieces[2], "nothing") != 0)
        {
          for (i = 2; i < npieces; i++)
            {
@@ -2013,7 +2015,7 @@ testcase_solverresult(Solver *solv, int resultflags)
                  if ((rtype & SOLVER_RULE_TYPEMASK) == SOLVER_RULE_JOB)
                    {
                      const char *js = testcase_job2str(pool, rq.elements[i + 2], rq.elements[i + 3]);
-                     char *s = pool_tmpjoin(pool, altprefix, num, " job ");
+                     char *s = pool_tmpjoin(pool, altprefix, num, "job ");
                      s = pool_tmpappend(pool, s, js, 0);
                      strqueue_push(&sq, s);
                    }
@@ -2023,6 +2025,13 @@ testcase_solverresult(Solver *solv, int resultflags)
                      s = pool_tmpappend(pool, s, " requires ", testcase_dep2str(pool, rq.elements[i + 3]));
                      strqueue_push(&sq, s);
                    }
+                 else if (rtype == SOLVER_RULE_UPDATE || rtype == SOLVER_RULE_FEATURE)
+                   {
+                     const char *js = testcase_solvid2str(pool, rq.elements[i + 1]);
+                     char *s = pool_tmpjoin(pool, altprefix, num, "update ");
+                     s = pool_tmpappend(pool, s, js, 0);
+                     strqueue_push(&sq, s);
+                   }
                }
            }
          for (i = 0; i < q.count; i++)
@@ -2170,7 +2179,7 @@ testcase_write_mangled(Solver *solv, const char *dir, int resultflags, const cha
   Id lowscore;
   FILE *fp;
   Strqueue sq;
-  char *cmd, *out;
+  char *cmd, *out, *result;
   const char *s;
 
   if (!testcasename)
@@ -2305,7 +2314,6 @@ testcase_write_mangled(Solver *solv, const char *dir, int resultflags, const cha
 
   if ((resultflags & ~TESTCASE_RESULT_REUSE_SOLVER) != 0)
     {
-      char *result;
       cmd = 0;
       for (i = 0; resultflags2str[i].str; i++)
        if ((resultflags & resultflags2str[i].flag) != 0)
@@ -2316,7 +2324,6 @@ testcase_write_mangled(Solver *solv, const char *dir, int resultflags, const cha
       result = testcase_solverresult(solv, resultflags);
       if (!strcmp(resultname, "<inline>"))
        {
-         int i;
          Strqueue rsq;
          strqueue_init(&rsq);
          strqueue_split(&rsq, result);
@@ -2348,6 +2355,7 @@ testcase_write_mangled(Solver *solv, const char *dir, int resultflags, const cha
          if (fclose(fp))
            {
              pool_error(solv->pool, 0, "testcase_write: write error");
+             solv_free(result);
              strqueue_free(&sq);
              return 0;
            }
@@ -2355,29 +2363,29 @@ testcase_write_mangled(Solver *solv, const char *dir, int resultflags, const cha
       solv_free(result);
     }
 
-  cmd = strqueue_join(&sq);
+  result = strqueue_join(&sq);
+  strqueue_free(&sq);
   out = pool_tmpjoin(pool, dir, "/", testcasename);
   if (!(fp = fopen(out, "w")))
     {
       pool_error(solv->pool, 0, "testcase_write: could not open '%s' for writing", out);
-      strqueue_free(&sq);
+      solv_free(result);
       return 0;
     }
-  if (*cmd && fwrite(cmd, strlen(cmd), 1, fp) != 1)
+  if (*result && fwrite(result, strlen(result), 1, fp) != 1)
     {
       pool_error(solv->pool, 0, "testcase_write: write error");
-      strqueue_free(&sq);
+      solv_free(result);
       fclose(fp);
       return 0;
     }
   if (fclose(fp))
     {
       pool_error(solv->pool, 0, "testcase_write: write error");
-      strqueue_free(&sq);
+      solv_free(result);
       return 0;
     }
-  solv_free(cmd);
-  strqueue_free(&sq);
+  solv_free(result);
   return 1;
 }
 
@@ -2766,7 +2774,7 @@ testcase_read(Pool *pool, FILE *fp, const char *testcase, Queue *job, char **res
        {
          int i = strlen(pieces[1]);
          s = strchr(pieces[1], '(');
-         if (!s && pieces[1][i - 1] != ')')
+         if (!s || pieces[1][i - 1] != ')')
            {
              pool_error(pool, 0, "testcase_read: bad namespace '%s'", pieces[1]);
            }
index 430e479..dcdbabd 100644 (file)
@@ -1,4 +1,22 @@
 -------------------------------------------------------------------
+Thu Jun 27 16:36:00 CEST 2019 - mls@suse.de
+
+- make cleandeps jobs on patterns work [bnc#1137977]
+- fix SOLVER_FLAG_FOCUS_BEST updateing packages without reason
+- be more correct with multiversion packages that obsolete their
+  own name [bnc#1127155]
+- always prefer to stay with the same package name if there are
+  multiple alternatives [bnc#1131823]
+- fix cleandeps updates not updating all packages
+- fixed a couple of null pointer derefs
+  [bnc#1120629] [bnc#1120630] [bnc#1120631]
+  [CVE-2018-20532] [CVE-2018-20533] [CVE-2018-20534]
+- no longer disable infarch rules when they don't conflict with
+  the job
+- do not autouninstall packages because of forcebest updates
+- bump version to 0.6.36
+
+-------------------------------------------------------------------
 Thu Aug  9 17:09:41 CEST 2018 - mls@suse.de
 
 - refactor arch handling
index ca649e8..63d8f38 100644 (file)
@@ -24,7 +24,7 @@
 %bcond_with bz2
 %bcond_with xz
 %endif
-%if 0%{?sle_version} >= 150000 || 0%{?suse_version} >= 1500
+%if 0%{?is_opensuse} && ( 0%{?sle_version} >= 150000 || 0%{?suse_version} >= 1500 )
 %bcond_without zstd
 %else
 %bcond_with zstd
index 1da28f6..ef9a528 100644 (file)
@@ -837,7 +837,7 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded)
                    if (MAPTST(&solv->multiversion, p))
                      break;
                  if (p)
-                   continue;
+                   continue;   /* found a multiversion package that will not obsolate anything */
                }
 
              om.size = 0;
index a38dea0..e1682f2 100644 (file)
@@ -866,6 +866,8 @@ move_installed_to_front(Pool *pool, Queue *plist)
   Solvable *s;
   Id p, pp;
 
+  if (!pool->installed)
+    return;
   for (i = j = 0; i < plist->count; i++)
     {
       s = pool->solvables + plist->elements[i];
@@ -924,9 +926,9 @@ prune_to_best_version(Pool *pool, Queue *plist)
     {
       s = pool->solvables + plist->elements[i];
 
-      POOL_DEBUG(SOLV_DEBUG_POLICY, "- %s[%s]\n",
-                pool_solvable2str(pool, s),
-                (pool->installed && s->repo == pool->installed) ? "installed" : "not installed");
+      POOL_DEBUG(SOLV_DEBUG_POLICY, "- %s [%d]%s\n",
+                pool_solvable2str(pool, s), plist->elements[i], 
+                (pool->installed && s->repo == pool->installed) ? "I" : "");
 
       if (!best)               /* if no best yet, the current is best */
         {
@@ -961,8 +963,6 @@ prune_to_best_version(Pool *pool, Queue *plist)
       else
         prune_obsoleted(pool, plist);
     }
-  if (plist->count > 1 && pool->installed)
-    move_installed_to_front(pool, plist);
 }
 
 
@@ -1236,7 +1236,7 @@ urpm_reorder(Solver *solv, Queue *plist)
                    {
                      char kn[256];
                      Id p, pp, knid;
-                     memcpy(kn, "kernel", 8);
+                     memcpy(kn, "kernel", 7);
                      memcpy(kn + 6, flavor, release - flavor + 1);
                      memcpy(kn + 6 + (release - flavor) + 1, sn, flavor - sn);
                      strcpy(kn + 6 + (release + 1 - sn), release);
@@ -1343,6 +1343,7 @@ policy_filter_unwanted(Solver *solv, Queue *plist, int mode)
 #endif
          dislike_old_versions(pool, plist);
          sort_by_common_dep(pool, plist);
+         move_installed_to_front(pool, plist);
          if (solv->urpmreorder)
            urpm_reorder(solv, plist);
          prefer_suggested(solv, plist);
@@ -1364,6 +1365,7 @@ pool_best_solvables(Pool *pool, Queue *plist, int flags)
     {
       dislike_old_versions(pool, plist);
       sort_by_common_dep(pool, plist);
+      move_installed_to_front(pool, plist);
     }
 }
 
index 60cc0f4..279359a 100644 (file)
@@ -1505,6 +1505,7 @@ pool_debug(Pool *pool, int type, const char *format, ...)
         vprintf(format, args);
       else
         vfprintf(stderr, format, args);
+      va_end(args);
       return;
     }
   vsnprintf(buf, sizeof(buf), format, args);
@@ -1566,7 +1567,7 @@ pool_setdebuglevel(Pool *pool, int level)
   if (level > 2)
     mask |= SOLV_DEBUG_PROPAGATE;
   if (level > 3)
-    mask |= SOLV_DEBUG_RULE_CREATION;
+    mask |= SOLV_DEBUG_RULE_CREATION | SOLV_DEBUG_WATCHES;
   mask |= pool->debugmask & SOLV_DEBUG_TO_STDERR;      /* keep bit */
   pool->debugmask = mask;
 }
index e6d1700..40e3777 100644 (file)
@@ -188,6 +188,7 @@ struct _Pool {
 #define SOLV_DEBUG_JOB                 (1<<11)
 #define SOLV_DEBUG_SOLVER              (1<<12)
 #define SOLV_DEBUG_TRANSACTION         (1<<13)
+#define SOLV_DEBUG_WATCHES             (1<<14)
 
 #define SOLV_DEBUG_TO_STDERR           (1<<30)
 
index df751c4..2b5cefd 100644 (file)
@@ -247,8 +247,23 @@ solver_autouninstall(Solver *solv, int start)
       if (v >= solv->updaterules && v < solv->updaterules_end)
        {
          Rule *r;
+         Id p = solv->installed->start + (v - solv->updaterules);
          if (m && !MAPTST(m, v - solv->updaterules))
            continue;
+         if (pool->considered && !MAPTST(pool->considered, p))
+           continue;   /* do not uninstalled disabled packages */
+         if (solv->bestrules_pkg && solv->bestrules_end > solv->bestrules)
+           {
+             int j;
+             for (j = start + 1; j < solv->problems.count - 1; j++)
+               {
+                 Id vv = solv->problems.elements[j];
+                 if (vv >= solv->bestrules && vv < solv->bestrules_end && solv->bestrules_pkg[vv - solv->bestrules] == p)
+                   break;
+               }
+             if (j < solv->problems.count - 1)
+               continue;       /* best rule involved, do not uninstall */
+           }
          /* check if identical to feature rule, we don't like that (except for orphans) */
          r = solv->rules + solv->featurerules + (v - solv->updaterules);
          if (!r->p)
@@ -260,7 +275,7 @@ solver_autouninstall(Solver *solv, int start)
              if (solv->keep_orphans)
                {
                  r = solv->rules + v;
-                 if (!r->d && !r->w2 && r->p == (solv->installed->start + (v - solv->updaterules)))
+                 if (!r->d && !r->w2 && r->p == p)
                    {
                      lastfeature = v;
                      lastupdate = 0;
index df32341..5901145 100644 (file)
@@ -1328,6 +1328,31 @@ solver_addfeaturerule(Solver *solv, Solvable *s)
     }
 }
 
+/* check if multiversion solvable s2 has an obsoletes for installed solvable s */
+static int
+is_multiversion_obsoleteed(Pool *pool, Solvable *s, Solvable *s2)
+{
+  Id *wp, obs, *obsp;
+
+  if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2))
+    return 0;
+  obsp = s2->repo->idarraydata + s2->obsoletes;
+  if (!pool->obsoleteusesprovides)
+    {
+      while ((obs = *obsp++) != 0)
+        if (pool_match_nevr(pool, s, obs))
+         return 1;
+    }
+  else
+    {
+      while ((obs = *obsp++) != 0)
+        for (wp = pool_whatprovides_ptr(pool, obs); *wp; wp++)
+         if (pool->solvables + *wp == s)
+           return 1;
+    }
+  return 0;
+}
+
 /*-------------------------------------------------------------------
  *
  * add rule for update
@@ -1389,9 +1414,8 @@ solver_addupdaterule(Solver *solv, Solvable *s)
              if (MAPTST(&solv->multiversion, qs.elements[i]))
                {
                  Solvable *ps = pool->solvables + qs.elements[i];
-                 /* if keepexplicitobsoletes is set and the name is different,
-                  * we assume that there is an obsoletes. XXX: not 100% correct */
-                 if (solv->keepexplicitobsoletes && ps->name != s->name)
+                 /* check if there is an explicit obsoletes */
+                 if (solv->keepexplicitobsoletes && ps->obsoletes && is_multiversion_obsoleteed(pool, s, ps))
                    {
                      qs.elements[j++] = qs.elements[i];
                      continue;
@@ -2175,7 +2199,7 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
          if (pool->solvables[p].repo == installed)
            return;
          if (solv->multiversion.size && MAPTST(&solv->multiversion, p) && !solv->keepexplicitobsoletes)
-           return;
+           return;             /* will not obsolete anything, so just return */
        }
       omap.size = 0;
       qstart = q->count;
index d44c482..0b36ea8 100644 (file)
@@ -1468,7 +1468,7 @@ selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char
          revr = pool_str2id(pool, r, 1);
          ret |= SELECTION_REL;
        }
-      if ((flags & SELECTION_GLOB) != 0 && !strpbrk(rname, "[*?") != 0)
+      if ((flags & SELECTION_GLOB) != 0 && strpbrk(rname, "[*?") == 0)
        flags &= ~SELECTION_GLOB;
 
       if ((flags & SELECTION_GLOB) == 0 && (flags & SELECTION_NOCASE) == 0 && (flags & SELECTION_MATCH_DEPSTR) == 0)
index 6405f4a..102d814 100644 (file)
@@ -431,7 +431,7 @@ propagate(Solver *solv, int level)
   Id *decisionmap = solv->decisionmap;
   Id *watches = solv->watches + pool->nsolvables;   /* place ptr in middle */
 
-  POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "----- propagate -----\n");
+  POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "----- propagate level %d -----\n", level);
 
   /* foreach non-propagated decision */
   while (solv->propagate_index < solv->decisionq.count)
@@ -444,7 +444,7 @@ propagate(Solver *solv, int level)
        
       IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE)
         {
-         POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "propagate for decision %d level %d\n", -pkg, level);
+         POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "propagate decision %d:", -pkg);
          solver_printruleelement(solv, SOLV_DEBUG_PROPAGATE, 0, -pkg);
         }
 
@@ -462,10 +462,10 @@ propagate(Solver *solv, int level)
              continue;
            }
 
-         IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE)
+         IF_POOLDEBUG (SOLV_DEBUG_WATCHES)
            {
-             POOL_DEBUG(SOLV_DEBUG_PROPAGATE,"  watch triggered ");
-             solver_printrule(solv, SOLV_DEBUG_PROPAGATE, r);
+             POOL_DEBUG(SOLV_DEBUG_WATCHES, "  watch triggered ");
+             solver_printrule(solv, SOLV_DEBUG_WATCHES, r);
            }
 
          /*
@@ -532,12 +532,12 @@ propagate(Solver *solv, int level)
                   * if we found some p that is UNDEF or TRUE, move
                   * watch to it
                   */
-                 IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE)
+                 IF_POOLDEBUG (SOLV_DEBUG_WATCHES)
                    {
                      if (p > 0)
-                       POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "    -> move w%d to %s\n", (pkg == r->w1 ? 1 : 2), pool_solvid2str(pool, p));
+                       POOL_DEBUG(SOLV_DEBUG_WATCHES, "    -> move w%d to %s\n", (pkg == r->w1 ? 1 : 2), pool_solvid2str(pool, p));
                      else
-                       POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "    -> move w%d to !%s\n", (pkg == r->w1 ? 1 : 2), pool_solvid2str(pool, -p));
+                       POOL_DEBUG(SOLV_DEBUG_WATCHES, "    -> move w%d to !%s\n", (pkg == r->w1 ? 1 : 2), pool_solvid2str(pool, -p));
                    }
 
                  *rp = *next_rp;
@@ -593,7 +593,7 @@ propagate(Solver *solv, int level)
        
     } /* while we have non-decided decisions */
 
-  POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "----- propagate end-----\n");
+  POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "----- propagate end -----\n");
 
   return 0;    /* all is well */
 }
@@ -1790,6 +1790,69 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq)
   return level;
 }
 
+/* one or more installed cleandeps packages in dq that are to be updated */
+/* we need to emulate the code in resolve_installed */
+static void
+do_cleandeps_update_filter(Solver *solv, Queue *dq)
+{
+  Pool *pool = solv->pool;
+  Repo *installed = solv->installed;
+  Id *specialupdaters = solv->specialupdaters;
+  Id p, p2, pp, d;
+  Queue q;
+  int i, j, k;
+
+  queue_init(&q);
+  for (i = 0; i < dq->count; i++)
+    {
+      Id p = dq->elements[i];
+      if (p < 0)
+       p = -p;
+      if (pool->solvables[p].repo != installed || !MAPTST(&solv->cleandepsmap, p - installed->start))
+       continue;
+      queue_empty(&q);
+      /* find updaters */
+      if (specialupdaters && (d = specialupdaters[p - installed->start]) != 0)
+       {
+         while ((p2 = pool->whatprovidesdata[d++]) != 0)
+           if (solv->decisionmap[p2] >= 0)
+             queue_push(&q, p2);
+       }
+      else
+       {
+         Rule *r = solv->rules + solv->updaterules + (p - installed->start);
+         if (r->p)
+           {
+             FOR_RULELITERALS(p2, pp, r)
+               if (solv->decisionmap[p2] >= 0)
+                 queue_push(&q, p2);
+           }
+       }
+      if (q.count && solv->update_targets && solv->update_targets->elements[p - installed->start])
+        prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[p - installed->start], &q);
+      /* mark all elements in dq that are in the updaters list */
+      dq->elements[i] = -p;
+      for (j = 0; j < dq->count; j++)
+       {
+          p = dq->elements[j];
+         if (p < 0)
+           continue;
+         for (k = 0; k < q.count; k++)
+           if (q.elements[k] == p)
+             {
+               dq->elements[j] = -p;
+               break;
+             }
+       }
+    }
+  /* now prune to marked elements */
+  for (i = j = 0; i < dq->count; i++)
+    if ((p = dq->elements[i]) < 0)
+      dq->elements[j++] = -p;
+  dq->count = j;
+  queue_free(&q);
+}
+
 static int
 resolve_dependencies(Solver *solv, int level, int disablerules, Queue *dq)
 {
@@ -1817,6 +1880,8 @@ resolve_dependencies(Solver *solv, int level, int disablerules, Queue *dq)
        }
       if (i == solv->nrules)
        i = 1;
+      if (solv->focus_best && solv->do_extra_reordering && i >= solv->featurerules)
+       continue;
       r = solv->rules + i;
       if (r->d < 0)            /* ignore disabled rules */
        continue;
@@ -1885,15 +1950,25 @@ resolve_dependencies(Solver *solv, int level, int disablerules, Queue *dq)
       /* prune to cleandeps packages */
       if (solv->cleandepsmap.size && solv->installed)
        {
+         int cleandeps_update = 0;
          Repo *installed = solv->installed;
          for (j = 0; j < dq->count; j++)
            if (pool->solvables[dq->elements[j]].repo == installed && MAPTST(&solv->cleandepsmap, dq->elements[j] - installed->start))
-             break;
+             {
+               if (solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, dq->elements[j] - installed->start)))
+                 {
+                   cleandeps_update = 1;               /* cleandeps package is marked for update */
+                   continue;
+                 }
+               break;
+             }
          if (j < dq->count)
            {
              dq->elements[0] = dq->elements[j];
              queue_truncate(dq, 1);
            }
+         else if (cleandeps_update)
+           do_cleandeps_update_filter(solv, dq);       /* special update filter */
        }
 
       if (dq->count > 1 && postponed >= 0)
@@ -3233,6 +3308,7 @@ solver_solve(Solver *solv, Queue *job)
   POOL_DEBUG(SOLV_DEBUG_STATS, "solver started\n");
   POOL_DEBUG(SOLV_DEBUG_STATS, "dosplitprovides=%d, noupdateprovide=%d, noinfarchcheck=%d\n", solv->dosplitprovides, solv->noupdateprovide, solv->noinfarchcheck);
   POOL_DEBUG(SOLV_DEBUG_STATS, "allowuninstall=%d, allowdowngrade=%d, allownamechange=%d, allowarchchange=%d, allowvendorchange=%d\n", solv->allowuninstall, solv->allowdowngrade, solv->allownamechange, solv->allowarchchange, solv->allowvendorchange);
+  POOL_DEBUG(SOLV_DEBUG_STATS, "dupallowdowngrade=%d, dupallownamechange=%d, dupallowarchchange=%d, dupallowvendorchange=%d\n", solv->dup_allowdowngrade, solv->dup_allownamechange, solv->dup_allowarchchange, solv->dup_allowvendorchange);
   POOL_DEBUG(SOLV_DEBUG_STATS, "promoteepoch=%d, forbidselfconflicts=%d\n", pool->promoteepoch, pool->forbidselfconflicts);
   POOL_DEBUG(SOLV_DEBUG_STATS, "obsoleteusesprovides=%d, implicitobsoleteusesprovides=%d, obsoleteusescolors=%d, implicitobsoleteusescolors=%d\n", pool->obsoleteusesprovides, pool->implicitobsoleteusesprovides, pool->obsoleteusescolors, pool->implicitobsoleteusescolors);
   POOL_DEBUG(SOLV_DEBUG_STATS, "dontinstallrecommended=%d, addalreadyrecommended=%d\n", solv->dontinstallrecommended, solv->addalreadyrecommended);
@@ -3736,6 +3812,10 @@ solver_solve(Solver *solv, Queue *job)
                  name_s = s;
                }
              solver_addjobrule(solv, -p, 0, 0, i, weak);
+#ifdef ENABLE_LINKED_PKGS
+             if (solv->instbuddy && installed && s->repo == installed && solv->instbuddy[p - installed->start] > 1)
+               solver_addjobrule(solv, -solv->instbuddy[p - installed->start], 0, 0, i, weak);
+#endif
            }
          /* special case for "erase a specific solvable": we also
           * erase all other solvables with that name, so that they
@@ -3803,7 +3883,14 @@ solver_solve(Solver *solv, Queue *job)
                }
            }
          FOR_JOB_SELECT(p, pp, select, what)
-           solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, 0, i, weak);
+           {
+             s = pool->solvables + p;
+             solver_addjobrule(solv, installed && s->repo == installed ? p : -p, 0, 0, i, weak);
+#ifdef ENABLE_LINKED_PKGS
+             if (solv->instbuddy && installed && s->repo == installed && solv->instbuddy[p - installed->start] > 1)
+               solver_addjobrule(solv, solv->instbuddy[p - installed->start], 0, 0, i, weak);
+#endif
+           }
          break;
        case SOLVER_DISTUPGRADE:
          POOL_DEBUG(SOLV_DEBUG_JOB, "job: distupgrade %s\n", solver_select2str(pool, select, what));
index 5e87918..b4a09a5 100644 (file)
@@ -56,11 +56,7 @@ stringpool_freehash(Stringpool *ss)
 void
 stringpool_init_empty(Stringpool *ss)
 {
-  const char *emptystrs[] = {
-    "<NULL>",
-    "",
-    0,
-  };
+  static const char *emptystrs[] = { "<NULL>", "", 0 };
   stringpool_init(ss, emptystrs);
 }
 
diff --git a/test/testcases/allowuninstall/conflict.t b/test/testcases/allowuninstall/conflict.t
new file mode 100644 (file)
index 0000000..a66d322
--- /dev/null
@@ -0,0 +1,14 @@
+repo system 0 testtags <inline>
+#>=Pkg: a 1 1 noarch
+#>=Con: b
+repo available 0 testtags <inline>
+#>=Pkg: b 1 1 noarch
+
+system x86_64 rpm system
+solverflags allowuninstall
+disable pkg a-1-1.noarch@system
+job install name b
+result transaction,problems <inline>
+#>problem a658cbaf info package a-1-1.noarch conflicts with b provided by b-1-1.noarch
+#>problem a658cbaf solution 567aa15d erase a-1-1.noarch@system
+#>problem a658cbaf solution e98e1a37 deljob install name b
diff --git a/test/testcases/allowuninstall/forcebest.t b/test/testcases/allowuninstall/forcebest.t
new file mode 100644 (file)
index 0000000..38ade6f
--- /dev/null
@@ -0,0 +1,19 @@
+repo system 0 testtags <inline>
+#>=Pkg: a 1 1 noarch
+#>=Req: b = 1-1
+#>=Pkg: b 1 1 noarch
+repo available 0 testtags <inline>
+#>=Pkg: a 2 1 noarch
+#>=Req: b = 2-1
+#>=Pkg: b 2 1 noarch
+
+system x86_64 rpm system
+disable pkg b-1-1.noarch@system
+disable pkg b-2-1.noarch@available
+job allowuninstall pkg a-1-1.noarch@system
+job allowuninstall pkg b-1-1.noarch@system
+job update name a [forcebest]
+result transaction,problems <inline>
+#>problem e6d3911d info nothing provides b = 2-1 needed by a-2-1.noarch
+#>problem e6d3911d solution 0011b04f allow a-1-1.noarch@system
+#>problem e6d3911d solution 44d189a0 erase a-1-1.noarch@system
diff --git a/test/testcases/cleandeps/cleandeps_up3.t b/test/testcases/cleandeps/cleandeps_up3.t
new file mode 100644 (file)
index 0000000..7a4bfbc
--- /dev/null
@@ -0,0 +1,23 @@
+repo system 0 testtags <inline>
+#>=Pkg: a 1 1 x86_64
+#>=Req: b
+#>=Pkg: b 1 1 x86_64
+repo available 0 testtags <inline>
+#>=Pkg: a 2 1 x86_64
+#>=Req: b
+#>=Pkg: b 2 1 x86_64
+#>=Pkg: c 2 1 x86_64
+#>=Prv: b = 4
+repo available2 0 testtags <inline>
+#>=Pkg: b 3 1 x86_64
+system x86_64 rpm system
+
+job update all packages [cleandeps]
+result transaction,problems <inline>
+#>upgrade a-1-1.x86_64@system a-2-1.x86_64@available
+#>upgrade b-1-1.x86_64@system b-3-1.x86_64@available2
+nextjob
+job update repo available [cleandeps]
+result transaction,problems <inline>
+#>upgrade a-1-1.x86_64@system a-2-1.x86_64@available
+#>upgrade b-1-1.x86_64@system b-2-1.x86_64@available
index e055e40..ece4225 100644 (file)
@@ -169,9 +169,9 @@ read_plaindir_repo(Repo *repo, const char *dir)
          close(fds[1]);
        }
       if (recursive)
-       execl("/usr/bin/find", ".", "-name", ".", "-o", "-name", ".*", "-prune", "-o", "-name", "*.delta.rpm", "-o", "-name", "*.patch.rpm", "-o", "-name", "*.rpm", "-a", "-type", "f", "-print0", (char *)0);
+       execl("/usr/bin/find", "/usr/bin/find", ".", "-name", ".", "-o", "-name", ".*", "-prune", "-o", "-name", "*.delta.rpm", "-o", "-name", "*.patch.rpm", "-o", "-name", "*.rpm", "-a", "-type", "f", "-print0", (char *)0);
       else
-       execl("/usr/bin/find", ".", "-maxdepth", "1", "-name", ".", "-o", "-name", ".*", "-prune", "-o", "-name", "*.delta.rpm", "-o", "-name", "*.patch.rpm", "-o", "-name", "*.rpm", "-a", "-type", "f", "-print0", (char *)0);
+       execl("/usr/bin/find", "/usr/bin/find", ".", "-maxdepth", "1", "-name", ".", "-o", "-name", ".*", "-prune", "-o", "-name", "*.delta.rpm", "-o", "-name", "*.patch.rpm", "-o", "-name", "*.rpm", "-a", "-type", "f", "-print0", (char *)0);
       perror("/usr/bin/find");
       _exit(1);
     }
@@ -208,6 +208,7 @@ read_plaindir_repo(Repo *repo, const char *dir)
        repodata_set_location(data, p, 0, 0, bp[0] == '.' && bp[1] == '/' ? bp + 2 : bp);
       solv_free(rpm);
     }
+  solv_free(buf);
   fclose(fp);
   while (waitpid(pid, &wstatus, 0) == -1)
     {
@@ -404,7 +405,7 @@ read_susetags_repo(Repo *repo, const char *dir)
   filename = susetags_find(files, nfiles, "packages");
   if (filename && (fp = susetags_open(ddir, filename, &tmp, 1)) != 0)
     {
-      if (repo_add_susetags(repo, fp, defvendor, 0, REPO_NO_INTERNALIZE|SUSETAGS_RECORD_SHARES))
+      if (repo_add_susetags(repo, fp, defvendor, 0, SUSETAGS_RECORD_SHARES))
        {
          fprintf(stderr, "%s: %s\n", tmp, pool_errstr(pool));
          exit(1);
index aa978d8..9fa8580 100644 (file)
@@ -41,12 +41,14 @@ static void
 usage(int status)
 {
   fprintf(stderr, "\nUsage:\n"
-         "rpmdb2solv [-n] [-b <basefile>] [-p <productsdir>] [-r <root>]\n"
+         "rpmdb2solv [-P] [-C] [-n] [-b <basefile>] [-p <productsdir>] [-r <root>]\n"
          " -n : No packages, do not read rpmdb, useful to only parse products\n"
          " -b <basefile> : Write .solv to <basefile>.solv instead of stdout\n"
          " -p <productsdir> : Scan <productsdir> for .prod files, representing installed products\n"
          " -r <root> : Prefix rpmdb path and <productsdir> with <root>\n"
          " -o <solv> : Write .solv to file instead of stdout\n"
+          " -P : print percentage done\n"
+          " -C : include the changelog\n"
         );
   exit(status);
 }
@@ -61,6 +63,7 @@ main(int argc, char **argv)
   Repodata *data;
   int c, percent = 0;
   int nopacks = 0;
+  int add_changelog = 0;
   const char *root = 0;
   const char *basefile = 0;
   const char *refname = 0;
@@ -82,7 +85,7 @@ main(int argc, char **argv)
    * parse arguments
    */
   
-  while ((c = getopt(argc, argv, "APhnkxXb:r:p:o:")) >= 0)
+  while ((c = getopt(argc, argv, "ACPhnkxXb:r:p:o:")) >= 0)
     switch (c)
       {
       case 'h':
@@ -126,6 +129,9 @@ main(int argc, char **argv)
         pubkeys = 1;
         break;
 #endif
+      case 'C':
+       add_changelog = 1;
+       break;
       default:
        usage(1);
       }
@@ -165,7 +171,12 @@ main(int argc, char **argv)
 
   if (!nopacks)
     {
-      if (repo_add_rpmdb_reffp(repo, reffp, REPO_USE_ROOTDIR | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE | (percent ? RPMDB_REPORT_PROGRESS : 0)))
+      int flags = REPO_USE_ROOTDIR | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE;
+      if (percent)
+       flags |= RPMDB_REPORT_PROGRESS;
+      if (add_changelog)
+       flags |= RPM_ADD_WITH_CHANGELOG;
+      if (repo_add_rpmdb_reffp(repo, reffp, flags))
        {
          fprintf(stderr, "rpmdb2solv: %s\n", pool_errstr(pool));
          exit(1);
index 19278db..ced614b 100644 (file)
@@ -197,7 +197,7 @@ main(int argc, char **argv)
                  perror(fn);
                  exit(1);
                }
-             if (repo_add_susetags(repo, fp, defvendor, 0, flags | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE))
+             if (repo_add_susetags(repo, fp, defvendor, 0, flags | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE | SUSETAGS_RECORD_SHARES))
                {
                  fprintf(stderr, "susetags2solv: %s: %s\n", fnp, pool_errstr(pool));
                  exit(1);