Hello community,

here is the log from the commit of package libsolv for openSUSE:Factory checked 
in at 2019-02-08 12:07:05
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libsolv (Old)
 and      /work/SRC/openSUSE:Factory/.libsolv.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libsolv"

Fri Feb  8 12:07:05 2019 rev:69 rq:670424 version:0.7.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/libsolv/libsolv.changes  2018-12-19 
13:48:44.639340887 +0100
+++ /work/SRC/openSUSE:Factory/.libsolv.new.28833/libsolv.changes       
2019-02-08 12:07:07.905610433 +0100
@@ -1,0 +2,11 @@
+Wed Jan 30 15:51:36 CET 2019 - [email protected]
+
+- fixed a couple of null pointer derefs
+  [bnc#1120629] [bnc#1120630] [bnc#1120631]
+- do favor evaluation before pruning allowing to (dis)favor
+  specific package versions
+- no longer disable infarch rules when they don't conflict with
+  the job
+- bump version to 0.7.3
+
+-------------------------------------------------------------------

Old:
----
  libsolv-0.7.2.tar.bz2

New:
----
  libsolv-0.7.3.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libsolv.spec ++++++
--- /var/tmp/diff_new_pack.BLZPYh/_old  2019-02-08 12:07:08.565610185 +0100
+++ /var/tmp/diff_new_pack.BLZPYh/_new  2019-02-08 12:07:08.573610182 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package libsolv
 #
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -52,7 +52,7 @@
 %bcond_with zypp
 
 Name:           libsolv
-Version:        0.7.2
+Version:        0.7.3
 Release:        0
 Summary:        Package dependency solver using a satisfiability algorithm
 License:        BSD-3-Clause
@@ -221,7 +221,7 @@
 CMAKE_FLAGS="-DSUSE=1"
 %endif
 
-cmake  $CMAKE_FLAGS \
+cmake . $CMAKE_FLAGS \
        -DCMAKE_INSTALL_PREFIX=%{_prefix} \
        -DLIB=%{_lib} \
        -DCMAKE_VERBOSE_MAKEFILE=TRUE \

++++++ libsolv-0.7.2.tar.bz2 -> libsolv-0.7.3.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/NEWS new/libsolv-0.7.3/NEWS
--- old/libsolv-0.7.2/NEWS      2018-12-07 15:20:15.000000000 +0100
+++ new/libsolv-0.7.3/NEWS      2019-01-30 16:11:58.000000000 +0100
@@ -2,6 +2,18 @@
 This file contains the major changes between
 libsolv versions:
 
+Version 0.7.3
+- selected bug fixes:
+  * fixed a couple of null pointer derefs and potential memory
+    leaks
+  * made disfavoring recommended packages work if strong recommends
+    is enabled
+  * no longer disable infarch rules when they don't conflict with
+    the job
+- new features:
+  * do favor evaluation before pruning allowing to (dis)favor
+    specific package versions
+
 Version 0.7.2
 - bug fixes:
   * do not autouninstall packages because of forcebest updates
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/VERSION.cmake 
new/libsolv-0.7.3/VERSION.cmake
--- old/libsolv-0.7.2/VERSION.cmake     2018-12-07 15:20:15.000000000 +0100
+++ new/libsolv-0.7.3/VERSION.cmake     2019-01-30 16:11:58.000000000 +0100
@@ -49,5 +49,5 @@
 
 SET(LIBSOLV_MAJOR "0")
 SET(LIBSOLV_MINOR "7")
-SET(LIBSOLV_PATCH "2")
+SET(LIBSOLV_PATCH "3")
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/bindings/solv.i 
new/libsolv-0.7.3/bindings/solv.i
--- old/libsolv-0.7.2/bindings/solv.i   2018-12-07 15:10:23.000000000 +0100
+++ new/libsolv-0.7.3/bindings/solv.i   2018-12-18 16:44:45.000000000 +0100
@@ -3454,6 +3454,7 @@
   static const int SOLVER_FLAG_FOCUS_BEST = SOLVER_FLAG_FOCUS_BEST;
   static const int SOLVER_FLAG_STRONG_RECOMMENDS = 
SOLVER_FLAG_STRONG_RECOMMENDS;
   static const int SOLVER_FLAG_INSTALL_ALSO_UPDATES = 
SOLVER_FLAG_INSTALL_ALSO_UPDATES;
+  static const int SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED = 
SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED;
 
   static const int SOLVER_REASON_UNRELATED = SOLVER_REASON_UNRELATED;
   static const int SOLVER_REASON_UNIT_RULE = SOLVER_REASON_UNIT_RULE;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/examples/solv/fastestmirror.c 
new/libsolv-0.7.3/examples/solv/fastestmirror.c
--- old/libsolv-0.7.2/examples/solv/fastestmirror.c     2018-10-01 
11:09:18.000000000 +0200
+++ new/libsolv-0.7.3/examples/solv/fastestmirror.c     2018-12-11 
13:59:34.000000000 +0100
@@ -68,7 +68,11 @@
          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)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/ext/pool_fileconflicts.c 
new/libsolv-0.7.3/ext/pool_fileconflicts.c
--- old/libsolv-0.7.2/ext/pool_fileconflicts.c  2018-10-01 11:09:18.000000000 
+0200
+++ new/libsolv-0.7.3/ext/pool_fileconflicts.c  2018-12-11 13:59:34.000000000 
+0100
@@ -590,7 +590,6 @@
 
   if (!info->dirlen)
     return;
-  dp = fn + info->dirlen;
   if (info->diridx != cbdata->lastdiridx)
     {
       cbdata->lastdiridx = info->diridx;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/ext/repo_appdata.c 
new/libsolv-0.7.3/ext/repo_appdata.c
--- old/libsolv-0.7.2/ext/repo_appdata.c        2018-11-22 12:59:31.000000000 
+0100
+++ new/libsolv-0.7.3/ext/repo_appdata.c        2018-12-11 13:59:34.000000000 
+0100
@@ -103,7 +103,7 @@
 {
   struct parsedata *pd = xmlp->userdata;
   Pool *pool = pd->pool;
-  Solvable *s = pd->solvable;
+  Solvable *s;
   const char *type;
 
   /* ignore all language tags */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/ext/repo_autopattern.c 
new/libsolv-0.7.3/ext/repo_autopattern.c
--- old/libsolv-0.7.2/ext/repo_autopattern.c    2018-10-31 13:56:02.000000000 
+0100
+++ new/libsolv-0.7.3/ext/repo_autopattern.c    2019-01-15 14:14:06.000000000 
+0100
@@ -131,8 +131,8 @@
   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);
 
   queue_init(&categorykeys);
   FOR_REPO_SOLVABLES(repo, p, s)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/ext/repo_comps.c 
new/libsolv-0.7.3/ext/repo_comps.c
--- old/libsolv-0.7.2/ext/repo_comps.c  2018-11-22 12:59:31.000000000 +0100
+++ new/libsolv-0.7.3/ext/repo_comps.c  2018-12-11 13:59:34.000000000 +0100
@@ -107,7 +107,7 @@
 {
   struct parsedata *pd = xmlp->userdata;
   Pool *pool = pd->pool;
-  Solvable *s = pd->solvable;
+  Solvable *s;
 
   switch(state)
     {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/ext/repo_repomdxml.c 
new/libsolv-0.7.3/ext/repo_repomdxml.c
--- old/libsolv-0.7.2/ext/repo_repomdxml.c      2018-11-22 12:59:31.000000000 
+0100
+++ new/libsolv-0.7.3/ext/repo_repomdxml.c      2018-12-11 13:59:34.000000000 
+0100
@@ -181,7 +181,7 @@
             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);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/ext/repo_rpmdb.c 
new/libsolv-0.7.3/ext/repo_rpmdb.c
--- old/libsolv-0.7.2/ext/repo_rpmdb.c  2018-11-22 12:59:31.000000000 +0100
+++ new/libsolv-0.7.3/ext/repo_rpmdb.c  2018-12-11 14:29:32.000000000 +0100
@@ -1896,6 +1896,8 @@
   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;
     }
@@ -1908,12 +1910,16 @@
   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;
     }
@@ -1922,6 +1928,8 @@
   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;
     }
@@ -1932,6 +1940,8 @@
     {
       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;
        }
@@ -1971,6 +1981,8 @@
          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;
            }
@@ -1991,6 +2003,7 @@
   if (fread(lead, 16, 1, fp) != 1)
     {
       pool_error(pool, -1, "%s: unexpected EOF", rpm);
+      solv_chksum_free(chksumh, 0);
       fclose(fp);
       return 0;
     }
@@ -1999,6 +2012,7 @@
   if (getu32(lead) != 0x8eade801)
     {
       pool_error(pool, -1, "%s: bad header", rpm);
+      solv_chksum_free(chksumh, 0);
       fclose(fp);
       return 0;
     }
@@ -2007,6 +2021,7 @@
   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;
     }
@@ -2014,6 +2029,7 @@
 
   if (!headfromfp(&state, rpm, fp, lead, sigcnt, sigdsize, 0, chksumh, 0))
     {
+      solv_chksum_free(chksumh, 0);
       fclose(fp);
       return 0;
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/ext/solv_zchunk.c 
new/libsolv-0.7.3/ext/solv_zchunk.c
--- old/libsolv-0.7.2/ext/solv_zchunk.c 2018-10-01 11:09:18.000000000 +0200
+++ new/libsolv-0.7.3/ext/solv_zchunk.c 2019-01-24 16:32:12.000000000 +0100
@@ -300,10 +300,28 @@
 #endif
   if ((p = getuint(p, zck->hdr_end, &zck->flags)) == 0)
     return open_error(zck);
-  if ((zck->flags & ~(1)) != 0)
+  if ((zck->flags & ~(3)) != 0)
     return open_error(zck);
   if ((p = getuint(p, zck->hdr_end, &zck->comp)) == 0 || (zck->comp != 0 && 
zck->comp != 2))
     return open_error(zck);    /* only uncompressed + zstd supported */
+  /* skip all optional elements if present */
+  if ((zck->flags & 2) != 0)
+    {
+      unsigned int nopt, lopt;
+      if ((p = getuint(p, zck->hdr_end, &nopt)) == 0)
+        return open_error(zck);
+      for (; nopt != 0; nopt--)
+       {
+         if ((p = getuint(p, zck->hdr_end, &lopt)) == 0)
+            return open_error(zck);
+         if ((p = getuint(p, zck->hdr_end, &lopt)) == 0)
+            return open_error(zck);
+         if (p + lopt > zck->hdr_end)
+           return open_error(zck);
+         p += lopt;
+       }
+    }
+
   preface_size = p - (zck->hdr + lead_size);
 
   /* parse index: index size, index chksum type, num chunks, chunk data  */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/ext/testcase.c 
new/libsolv-0.7.3/ext/testcase.c
--- old/libsolv-0.7.2/ext/testcase.c    2018-11-26 12:59:35.000000000 +0100
+++ new/libsolv-0.7.3/ext/testcase.c    2018-12-20 17:35:49.000000000 +0100
@@ -576,6 +576,8 @@
   Id flags, id, id2, namespaceid = 0;
   struct oplist *op;
 
+  if (!s)
+    return 0;
   while (*s == ' ' || *s == '\t')
     s++;
   if (!strncmp(s, "namespace:", 10))
@@ -964,11 +966,101 @@
   return jobflags;
 }
 
+static Id
+testcase_str2jobsel(Pool *pool, const char *caller, char **pieces, int 
npieces, Id *whatp)
+{
+  Id job, what;
+  if (!strcmp(pieces[0], "pkg") && npieces == 2)
+    {
+      job = SOLVER_SOLVABLE;
+      what = testcase_str2solvid(pool, pieces[1]);
+      if (!what)
+       return pool_error(pool, -1, "%s: unknown package '%s'", caller, 
pieces[1]);
+    }
+  else if (!strcmp(pieces[0], "name") || !strcmp(pieces[0], "provides"))
+    {
+      /* join em again for dep2str... */
+      char *sp;
+      for (sp = pieces[1]; sp < pieces[npieces - 1]; sp++)
+       if (*sp == 0)
+         *sp = ' ';
+      what = 0;
+      if (pieces[0][0] == 'p' && strncmp(pieces[1], "namespace:", 10) == 0)
+       {
+         char *spe = strchr(pieces[1], '(');
+         int l = strlen(pieces[1]);
+         if (spe && pieces[1][l - 1] == ')')
+           {
+             /* special namespace provides */
+             if (strcmp(spe, "(<NULL>)") != 0)
+               {
+                 pieces[1][l - 1] = 0;
+                 what = testcase_str2dep(pool, spe + 1);
+                 pieces[1][l - 1] = ')';
+               }
+             what = pool_rel2id(pool, pool_strn2id(pool, pieces[1], spe - 
pieces[1], 1), what, REL_NAMESPACE, 1);
+           }
+       }
+      if (!what)
+        what = testcase_str2dep(pool, pieces[1]);
+      if (pieces[0][0] == 'n')
+       job = SOLVER_SOLVABLE_NAME;
+      else
+       job = SOLVER_SOLVABLE_PROVIDES;
+    }
+  else if (!strcmp(pieces[0], "oneof"))
+    {
+      Queue q;
+      job = SOLVER_SOLVABLE_ONE_OF;
+      queue_init(&q);
+      if (npieces > 1 && strcmp(pieces[1], "nothing") != 0)
+       {
+         int i;
+         for (i = 1; i < npieces; i++)
+           {
+             Id p = testcase_str2solvid(pool, pieces[i]);
+             if (!p)
+               {
+                 queue_free(&q);
+                 return pool_error(pool, -1, "%s: unknown package '%s'", 
caller, pieces[i]);
+               }
+             queue_push(&q, p);
+           }
+       }
+      what = pool_queuetowhatprovides(pool, &q);
+      queue_free(&q);
+    }
+  else if (!strcmp(pieces[0], "repo") && npieces == 2)
+    {
+      Repo *repo = testcase_str2repo(pool, pieces[1]);
+      if (!repo)
+       return pool_error(pool, -1, "%s: unknown repo '%s'", caller, pieces[1]);
+      job = SOLVER_SOLVABLE_REPO;
+      what = repo->repoid;
+    }
+  else if (!strcmp(pieces[0], "all") && npieces == 2 && !strcmp(pieces[1], 
"packages"))
+    {
+      job = SOLVER_SOLVABLE_ALL;
+      what = 0;
+    }
+  else
+    {
+      /* join em again for the error message... */
+      char *sp;
+      for (sp = pieces[0]; sp < pieces[npieces - 1]; sp++)
+       if (*sp == 0)
+         *sp = ' ';
+      return pool_error(pool, -1, "%s: bad line '%s'", caller, pieces[0]);
+    }
+  *whatp = what;
+  return job;
+}
+
 Id
 testcase_str2job(Pool *pool, const char *str, Id *whatp)
 {
   int i;
-  Id job;
+  Id job, jobsel;
   Id what;
   char *s;
   char **pieces = 0;
@@ -1020,116 +1112,12 @@
          job |= str2jobflags(pool, flags);
        }
     }
-  if (!strcmp(pieces[1], "pkg"))
-    {
-      if (npieces != 3)
-       {
-         pool_error(pool, -1, "str2job: bad pkg selector in '%s'", str);
-         solv_free(pieces);
-         return -1;
-       }
-      job |= SOLVER_SOLVABLE;
-      what = testcase_str2solvid(pool, pieces[2]);
-      if (!what)
-       {
-         pool_error(pool, -1, "str2job: unknown package '%s'", pieces[2]);
-         solv_free(pieces);
-         return -1;
-       }
-    }
-  else if (!strcmp(pieces[1], "name") || !strcmp(pieces[1], "provides"))
-    {
-      /* join em again for dep2str... */
-      char *sp;
-      for (sp = pieces[2]; sp < pieces[npieces - 1]; sp++)
-       if (*sp == 0)
-         *sp = ' ';
-      what = 0;
-      if (pieces[1][0] == 'p' && strncmp(pieces[2], "namespace:", 10) == 0)
-       {
-         char *spe = strchr(pieces[2], '(');
-         int l = strlen(pieces[2]);
-         if (spe && pieces[2][l - 1] == ')')
-           {
-             /* special namespace provides */
-             if (strcmp(spe, "(<NULL>)") != 0)
-               {
-                 pieces[2][l - 1] = 0;
-                 what = testcase_str2dep(pool, spe + 1);
-                 pieces[2][l - 1] = ')';
-               }
-             what = pool_rel2id(pool, pool_strn2id(pool, pieces[2], spe - 
pieces[2], 1), what, REL_NAMESPACE, 1);
-           }
-       }
-      if (!what)
-        what = testcase_str2dep(pool, pieces[2]);
-      if (pieces[1][0] == 'n')
-       job |= SOLVER_SOLVABLE_NAME;
-      else
-       job |= SOLVER_SOLVABLE_PROVIDES;
-    }
-  else if (!strcmp(pieces[1], "oneof"))
-    {
-      Queue q;
-      job |= SOLVER_SOLVABLE_ONE_OF;
-      queue_init(&q);
-      if (npieces > 2 && strcmp(pieces[2], "nothing") != 0)
-       {
-         for (i = 2; i < npieces; i++)
-           {
-             Id p = testcase_str2solvid(pool, pieces[i]);
-             if (!p)
-               {
-                 pool_error(pool, -1, "str2job: unknown package '%s'", 
pieces[i]);
-                 queue_free(&q);
-                 solv_free(pieces);
-                 return -1;
-               }
-             queue_push(&q, p);
-           }
-       }
-      what = pool_queuetowhatprovides(pool, &q);
-      queue_free(&q);
-    }
-  else if (!strcmp(pieces[1], "repo"))
-    {
-      Repo *repo;
-      if (npieces != 3)
-       {
-         pool_error(pool, -1, "str2job: bad line '%s'", str);
-         solv_free(pieces);
-         return -1;
-       }
-      repo = testcase_str2repo(pool, pieces[2]);
-      if (!repo)
-       {
-         pool_error(pool, -1, "str2job: unknown repo '%s'", pieces[2]);
-         solv_free(pieces);
-         return -1;
-       }
-      job |= SOLVER_SOLVABLE_REPO;
-      what = repo->repoid;
-    }
-  else if (!strcmp(pieces[1], "all"))
-    {
-      if (npieces != 3 && strcmp(pieces[2], "packages") != 0)
-       {
-         pool_error(pool, -1, "str2job: bad line '%s'", str);
-         solv_free(pieces);
-         return -1;
-       }
-      job |= SOLVER_SOLVABLE_ALL;
-      what = 0;
-    }
-  else
-    {
-      pool_error(pool, -1, "str2job: unknown selection in '%s'", str);
-      solv_free(pieces);
-      return -1;
-    }
-  *whatp = what;
+  jobsel = testcase_str2jobsel(pool, "str2job", pieces + 1, npieces - 1, 
&what);
   solv_free(pieces);
-  return job;
+  if (jobsel == -1)
+    return -1;
+  *whatp = what;
+  return job | jobsel;
 }
 
 #define SELECTIONJOB_MATCHDEPS         1
@@ -1816,6 +1804,7 @@
   { SOLVER_RULE_LEARNT, "learnt" },
   { SOLVER_RULE_BEST, "best" },
   { SOLVER_RULE_YUMOBS, "yumobs" },
+  { SOLVER_RULE_RECOMMENDS, "recommends" },
   { 0, 0 }
 };
 
@@ -2023,6 +2012,8 @@
              /* map choice rules back to pkg rules */
              if (solver_ruleclass(solv, id) == SOLVER_RULE_CHOICE)
                id = solver_rule2pkgrule(solv, id);
+             if (solver_ruleclass(solv, id) == SOLVER_RULE_RECOMMENDS)
+               id = solver_rule2pkgrule(solv, id);
              solver_allruleinfos(solv, id, &rq);
              for (i = 0; i < rq.count; i += 4)
                {
@@ -2187,7 +2178,7 @@
   Id lowscore;
   FILE *fp;
   Strqueue sq;
-  char *cmd, *out;
+  char *cmd, *out, *result;
   const char *s;
 
   if (!testcasename)
@@ -2322,7 +2313,6 @@
 
   if ((resultflags & ~TESTCASE_RESULT_REUSE_SOLVER) != 0)
     {
-      char *result;
       cmd = 0;
       for (i = 0; resultflags2str[i].str; i++)
        if ((resultflags & resultflags2str[i].flag) != 0)
@@ -2333,7 +2323,6 @@
       result = testcase_solverresult(solv, resultflags);
       if (!strcmp(resultname, "<inline>"))
        {
-         int i;
          Strqueue rsq;
          strqueue_init(&rsq);
          strqueue_split(&rsq, result);
@@ -2365,6 +2354,7 @@
          if (fclose(fp))
            {
              pool_error(solv->pool, 0, "testcase_write: write error");
+             solv_free(result);
              strqueue_free(&sq);
              return 0;
            }
@@ -2372,29 +2362,29 @@
       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;
 }
 
@@ -2789,7 +2779,7 @@
        {
          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]);
            }
@@ -2877,12 +2867,7 @@
        }
       else if (!strcmp(pieces[0], "disable") && npieces == 3)
        {
-         Id p;
-         if (strcmp(pieces[1], "pkg"))
-           {
-             pool_error(pool, 0, "testcase_read: bad disable type '%s'", 
pieces[1]);
-             continue;
-           }
+         Id p, pp, jobsel, what = 0;
          if (!prepared)
            pool_createwhatprovides(pool);
          prepared = -1;
@@ -2892,11 +2877,20 @@
              map_init(pool->considered, pool->nsolvables);
              map_setall(pool->considered);
            }
-         p = testcase_str2solvid(pool, pieces[2]);
-         if (p)
+         jobsel = testcase_str2jobsel(pool, "disable", pieces + 1, npieces - 
1, &what);
+         if (jobsel < 0)
+           continue;
+         if (jobsel == SOLVER_SOLVABLE_ALL)
+           map_empty(pool->considered);
+         else if (jobsel == SOLVER_SOLVABLE_REPO)
+           {
+             Repo *repo = pool_id2repo(pool, what);
+             Solvable *s;
+             FOR_REPO_SOLVABLES(repo, p, s)
+               MAPCLR(pool->considered, p);
+           }
+         FOR_JOB_SELECT(p, pp, jobsel, what)
            MAPCLR(pool->considered, p);
-         else
-           pool_error(pool, 0, "disable: unknown package '%s'", pieces[2]);
        }
       else if (!strcmp(pieces[0], "feature"))
        {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/package/libsolv.changes 
new/libsolv-0.7.3/package/libsolv.changes
--- old/libsolv-0.7.2/package/libsolv.changes   2018-12-07 15:20:15.000000000 
+0100
+++ new/libsolv-0.7.3/package/libsolv.changes   2019-01-30 16:11:58.000000000 
+0100
@@ -1,4 +1,15 @@
 -------------------------------------------------------------------
+Wed Jan 30 15:51:36 CET 2019 - [email protected]
+
+- fixed a couple of null pointer derefs
+  [bnc#1120629] [bnc#1120630] [bnc#1120631]
+- do favor evaluation before pruning allowing to (dis)favor
+  specific package versions
+- no longer disable infarch rules when they don't conflict with
+  the job
+- bump version to 0.7.3
+
+-------------------------------------------------------------------
 Fri Dec  7 15:10:46 CET 2018 - [email protected]
 
 - do not autouninstall packages because of forcebest updates
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/package/libsolv.spec.in 
new/libsolv-0.7.3/package/libsolv.spec.in
--- old/libsolv-0.7.2/package/libsolv.spec.in   2018-10-01 11:09:18.000000000 
+0200
+++ new/libsolv-0.7.3/package/libsolv.spec.in   2019-01-30 15:47:03.000000000 
+0100
@@ -221,7 +221,7 @@
 CMAKE_FLAGS="-DSUSE=1"
 %endif
 
-cmake  $CMAKE_FLAGS \
+cmake . $CMAKE_FLAGS \
        -DCMAKE_INSTALL_PREFIX=%{_prefix} \
        -DLIB=%{_lib} \
        -DCMAKE_VERBOSE_MAKEFILE=TRUE \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/src/cleandeps.c 
new/libsolv-0.7.3/src/cleandeps.c
--- old/libsolv-0.7.2/src/cleandeps.c   2018-10-01 11:09:18.000000000 +0200
+++ new/libsolv-0.7.3/src/cleandeps.c   2018-12-19 14:30:15.000000000 +0100
@@ -748,7 +748,6 @@
            continue;
          if (strncmp(pool_id2str(pool, s->name), "pattern:", 8) != 0)
            continue;
-         dp = s->repo->idarraydata + s->requires;
          for (dp = s->repo->idarraydata + s->requires; *dp; dp++)
            FOR_PROVIDES(p, pp, *dp)
              if (pool->solvables[p].repo == installed)
@@ -1368,11 +1367,11 @@
          if (!r->p || r == fr || cleandeps_rule_is_true(solv, r))
            {
              /* update rule is true, check best rules */
-             if (!solv->bestrules_pkg)
+             if (!solv->bestrules_info)
                continue;
              nj = solv->bestrules_end - solv->bestrules;
-             for (j = 0; j < nj; j++)
-               if (solv->bestrules_pkg[j] == i)
+             for (j = solv->bestrules_up - solv->bestrules; j < nj; j++)
+               if (solv->bestrules_info[j] == i)
                  {
                    r = solv->rules + solv->bestrules + j;
                    if (!cleandeps_rule_is_true(solv, r))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/src/dirpool.c 
new/libsolv-0.7.3/src/dirpool.c
--- old/libsolv-0.7.2/src/dirpool.c     2018-10-01 11:09:18.000000000 +0200
+++ new/libsolv-0.7.3/src/dirpool.c     2018-12-11 13:59:34.000000000 +0100
@@ -85,7 +85,7 @@
     return;
   dp->dirs = solv_extend_resize(dp->dirs, dp->ndirs, sizeof(Id), DIR_BLOCK);
   dirtraverse = solv_calloc_block(dp->ndirs, sizeof(Id), DIR_BLOCK);
-  for (parent = 0, i = 0; i < dp->ndirs; i++)
+  for (i = 0; i < dp->ndirs; i++)
     {
       if (dp->dirs[i] > 0)
        continue;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/src/order.c 
new/libsolv-0.7.3/src/order.c
--- old/libsolv-0.7.2/src/order.c       2018-10-22 15:37:12.000000000 +0200
+++ new/libsolv-0.7.3/src/order.c       2018-12-11 13:59:34.000000000 +0100
@@ -1066,7 +1066,6 @@
 #if 0
 printf("do %s [%d]\n", pool_solvid2str(pool, te->p), temedianr[i]);
 #endif
-      s = pool->solvables + te->p;
       for (j = te->edges; od.invedgedata[j]; j++)
        {
          struct s_TransactionElement *te2 = od.tes + od.invedgedata[j];
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/src/pool.c new/libsolv-0.7.3/src/pool.c
--- old/libsolv-0.7.2/src/pool.c        2018-10-22 15:37:12.000000000 +0200
+++ new/libsolv-0.7.3/src/pool.c        2018-12-11 13:59:34.000000000 +0100
@@ -1536,6 +1536,7 @@
         vprintf(format, args);
       else
         vfprintf(stderr, format, args);
+      va_end(args);
       return;
     }
   vsnprintf(buf, sizeof(buf), format, args);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/src/problems.c 
new/libsolv-0.7.3/src/problems.c
--- old/libsolv-0.7.2/src/problems.c    2018-11-30 15:09:39.000000000 +0100
+++ new/libsolv-0.7.3/src/problems.c    2018-12-19 14:30:15.000000000 +0100
@@ -64,12 +64,12 @@
     }
   v = -(v + 1);
   jp = solv->ruletojob.elements;
-  if (solv->bestrules_pkg)
+  if (solv->bestrules_info)
     {
       int ni = solv->bestrules_up - solv->bestrules;
       for (i = 0; i < ni; i++)
        {
-         int j = solv->bestrules_pkg[i];
+         int j = solv->bestrules_info[i];
          if (j < 0 && jp[-j - solv->jobrules] == v)
            solver_disablerule(solv, solv->rules + solv->bestrules + i);
        }
@@ -131,12 +131,12 @@
     }
   v = -(v + 1);
   jp = solv->ruletojob.elements;
-  if (solv->bestrules_pkg)
+  if (solv->bestrules_info)
     {
       int ni = solv->bestrules_up - solv->bestrules;
       for (i = 0; i < ni; i++)
        {
-         int j = solv->bestrules_pkg[i];
+         int j = solv->bestrules_info[i];
          if (j < 0 && jp[-j - solv->jobrules] == v)
            solver_enablerule(solv, solv->rules + solv->bestrules + i);
        }
@@ -155,8 +155,8 @@
 {
   if (rid >= solv->jobrules && rid < solv->jobrules_end)
     rid = -(solv->ruletojob.elements[rid - solv->jobrules] + 1);
-  else if (rid >= solv->bestrules && rid < solv->bestrules_up && 
solv->bestrules_pkg[rid - solv->bestrules] < 0)
-    rid = -(solv->ruletojob.elements[-solv->bestrules_pkg[rid - 
solv->bestrules] - solv->jobrules] + 1);
+  else if (rid >= solv->bestrules && rid < solv->bestrules_up && 
solv->bestrules_info[rid - solv->bestrules] < 0)
+    rid = -(solv->ruletojob.elements[-solv->bestrules_info[rid - 
solv->bestrules] - solv->jobrules] + 1);
   else if (rid > solv->infarchrules && rid < solv->infarchrules_end)
     {
       Pool *pool = solv->pool;
@@ -252,13 +252,13 @@
            continue;
          if (pool->considered && !MAPTST(pool->considered, p))
            continue;   /* do not uninstalled disabled packages */
-         if (solv->bestrules_pkg && solv->bestrules_end > solv->bestrules)
+         if (solv->bestrules_info && 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)
+                 if (vv >= solv->bestrules && vv < solv->bestrules_end && 
solv->bestrules_info[vv - solv->bestrules] == p)
                    break;
                }
              if (j < solv->problems.count - 1)
@@ -678,7 +678,7 @@
        if (p > 0 && solv->decisionmap[p] > 0)
          return;       /* false alarm */
       /* check update/feature rule */
-      p = solv->bestrules_pkg[why - solv->bestrules];
+      p = solv->bestrules_info[why - solv->bestrules];
       if (p < 0)
        {
          /* install job */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/src/repopage.c 
new/libsolv-0.7.3/src/repopage.c
--- old/libsolv-0.7.2/src/repopage.c    2018-10-01 11:09:18.000000000 +0200
+++ new/libsolv-0.7.3/src/repopage.c    2018-12-11 13:59:34.000000000 +0100
@@ -399,7 +399,6 @@
              litlen -= 32;
            }
        }
-      litofs = 0;
     }
   return oo;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/src/rules.c 
new/libsolv-0.7.3/src/rules.c
--- old/libsolv-0.7.2/src/rules.c       2018-10-01 11:09:18.000000000 +0200
+++ new/libsolv-0.7.3/src/rules.c       2019-01-24 16:32:12.000000000 +0100
@@ -1463,12 +1463,12 @@
   r = solv->rules + solv->featurerules + (p - solv->installed->start);
   if (r->p && r->d >= 0)
     solver_disablerule(solv, r);
-  if (solv->bestrules_pkg)
+  if (solv->bestrules_info)
     {
       int i, ni;
       ni = solv->bestrules_end - solv->bestrules;
       for (i = solv->bestrules_up - solv->bestrules; i < ni; i++)
-       if (solv->bestrules_pkg[i] == p)
+       if (solv->bestrules_info[i] == p)
          solver_disablerule(solv, solv->rules + solv->bestrules + i);
     }
 }
@@ -1506,12 +1506,12 @@
            }
        }
     }
-  if (solv->bestrules_pkg)
+  if (solv->bestrules_info)
     {
       int i, ni;
       ni = solv->bestrules_end - solv->bestrules;
       for (i = solv->bestrules_up - solv->bestrules; i < ni; i++)
-       if (solv->bestrules_pkg[i] == p)
+       if (solv->bestrules_info[i] == p)
          solver_enablerule(solv, solv->rules + solv->bestrules + i);
     }
 }
@@ -1674,11 +1674,15 @@
                }
              if (installed && pool->solvables[p].repo == installed && 
!haveinstalled)
                continue;       /* installed package not in lock-step */
+             if (lsq.count < 2)
+               solver_addrule(solv, -p, lsq.count ? lsq.elements[0] : 0, 0);
+             else
+               solver_addrule(solv, -p, 0, pool_queuetowhatprovides(pool, 
&lsq));
            }
-         if (lsq.count < 2)
-           solver_addrule(solv, -p, lsq.count ? lsq.elements[0] : 0, 0);
          else
-           solver_addrule(solv, -p, 0, pool_queuetowhatprovides(pool, &lsq));
+           {
+             solver_addrule(solv, -p, 0, 0);
+           }
        }
     }
   queue_free(&lsq);
@@ -2126,7 +2130,13 @@
       if ((set & SOLVER_SETARCH) != 0 && solv->infarchrules != 
solv->infarchrules_end)
        {
          if (select == SOLVER_SOLVABLE)
-           queue_push2(q, DISABLE_INFARCH, pool->solvables[what].name);
+           {
+             for (i = solv->infarchrules; i < solv->infarchrules_end; i++)
+               if (solv->rules[i].p == -what)
+                 break;
+             if (i < solv->infarchrules_end)
+               queue_push2(q, DISABLE_INFARCH, pool->solvables[what].name);
+           }
          else
            {
              int qcnt = q->count;
@@ -2140,8 +2150,12 @@
                    if (q->elements[i + 1] == s->name)
                      break;
                  if (i < q->count)
-                   continue;
-                 queue_push2(q, DISABLE_INFARCH, s->name);
+                   continue;           /* already have that DISABLE_INFARCH 
element */
+                 for (i = solv->infarchrules; i < solv->infarchrules_end; i++)
+                   if (solv->rules[i].p == -p)
+                     break;
+                 if (i < solv->infarchrules_end)
+                   queue_push2(q, DISABLE_INFARCH, s->name);
                }
            }
        }
@@ -2719,8 +2733,8 @@
     }
   if (rid >= solv->bestrules && rid < solv->bestrules_end)
     {
-      if (fromp && solv->bestrules_pkg[rid - solv->bestrules] > 0)
-       *fromp = solv->bestrules_pkg[rid - solv->bestrules];
+      if (fromp && solv->bestrules_info[rid - solv->bestrules] > 0)
+       *fromp = solv->bestrules_info[rid - solv->bestrules];
       return SOLVER_RULE_BEST;
     }
   if (rid >= solv->yumobsrules && rid < solv->yumobsrules_end)
@@ -2740,13 +2754,11 @@
       return SOLVER_RULE_YUMOBS;
     }
   if (rid >= solv->choicerules && rid < solv->choicerules_end)
-    {
-      return SOLVER_RULE_CHOICE;
-    }
+    return SOLVER_RULE_CHOICE;
+  if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end)
+    return SOLVER_RULE_RECOMMENDS;
   if (rid >= solv->learntrules)
-    {
-      return SOLVER_RULE_LEARNT;
-    }
+    return SOLVER_RULE_LEARNT;
   return SOLVER_RULE_UNKNOWN;
 }
 
@@ -2773,6 +2785,8 @@
     return SOLVER_RULE_YUMOBS;
   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->learntrules && rid < solv->nrules)
     return SOLVER_RULE_LEARNT;
   return SOLVER_RULE_UNKNOWN;
@@ -2834,7 +2848,9 @@
 solver_rule2pkgrule(Solver *solv, Id rid)
 {
   if (rid >= solv->choicerules && rid < solv->choicerules_end)
-    return solv->choicerules_ref[rid - solv->choicerules];
+    return solv->choicerules_info[rid - solv->choicerules];
+  if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end)
+    return solv->recommendsrules_info[rid - solv->recommendsrules];
   return 0;
 }
 
@@ -2950,7 +2966,7 @@
   Pool *pool = solv->pool;
   Map m, mneg;
   Rule *r;
-  Queue q, qi, qcheck;
+  Queue q, qi, qcheck, infoq;
   int i, j, rid, havechoice;
   Id p, d, pp;
   Id p2, pp2;
@@ -2966,10 +2982,11 @@
       return;
     }
   now = solv_timems(0);
-  solv->choicerules_ref = solv_calloc(solv->pkgrules_end, sizeof(Id));
+  solv->choicerules_info = solv_calloc(solv->pkgrules_end, sizeof(Id));
   queue_init(&q);
   queue_init(&qi);
   queue_init(&qcheck);
+  queue_init(&infoq);
   map_init(&m, pool->nsolvables);
   map_init(&mneg, pool->nsolvables);
   /* set up negative assertion map from infarch and dup rules */
@@ -3158,7 +3175,7 @@
 
       solver_addrule(solv, r->p, 0, d);
       queue_push(&solv->weakruleq, solv->nrules - 1);
-      solv->choicerules_ref[solv->nrules - 1 - solv->choicerules] = rid;
+      queue_push(&infoq, rid);
 #if 0
       printf("OLD ");
       solver_printrule(solv, SOLV_DEBUG_RESULT, solv->rules + rid);
@@ -3166,20 +3183,21 @@
       solver_printrule(solv, SOLV_DEBUG_RESULT, solv->rules + solv->nrules - 
1);
 #endif
     }
+  if (infoq.count)
+    solv->choicerules_info = solv_memdup2(infoq.elements, infoq.count, 
sizeof(Id));
   queue_free(&q);
   queue_free(&qi);
   queue_free(&qcheck);
+  queue_free(&infoq);
   map_free(&m);
   map_free(&mneg);
   solv->choicerules_end = solv->nrules;
-  /* shrink choicerules_ref */
-  solv->choicerules_ref = solv_realloc2(solv->choicerules_ref, 
solv->choicerules_end - solv->choicerules, sizeof(Id));
   POOL_DEBUG(SOLV_DEBUG_STATS, "choice rule creation took %d ms\n", 
solv_timems(now));
 }
 
-/* called when a choice rule is disabled by analyze_unsolvable. We also
- * have to disable all other choice rules so that the best packages get
- * picked */
+/* called when a choice rule needs to be disabled by analyze_unsolvable.
+ * We also have to disable all other choice rules so that the best packages
+ * get picked */
 void
 solver_disablechoicerules(Solver *solv, Rule *r)
 {
@@ -3188,7 +3206,8 @@
   Map m;
   Rule *or;
 
-  or = solv->rules + solv->choicerules_ref[(r - solv->rules) - 
solv->choicerules];
+  solver_disablerule(solv, r);
+  or = solv->rules + solv->choicerules_info[(r - solv->rules) - 
solv->choicerules];
   map_init(&m, pool->nsolvables);
   FOR_RULELITERALS(p, pp, or)
     if (p > 0)
@@ -3201,7 +3220,7 @@
       r = solv->rules + rid;
       if (r->d < 0)
        continue;
-      or = solv->rules + solv->choicerules_ref[(r - solv->rules) - 
solv->choicerules];
+      or = solv->rules + solv->choicerules_info[rid - solv->choicerules];
       FOR_RULELITERALS(p, pp, or)
         if (p > 0 && MAPTST(&m, p))
          break;
@@ -3250,13 +3269,13 @@
   Repo *installed = solv->installed;
   Queue q, q2;
   Rule *r;
-  Queue r2pkg;
+  Queue infoq;
   int i, oldcnt;
 
   solv->bestrules = solv->nrules;
   queue_init(&q);
   queue_init(&q2);
-  queue_init(&r2pkg);
+  queue_init(&infoq);
 
   if (havebestinstalljobs)
     {
@@ -3297,7 +3316,7 @@
                    solver_addrule(solv, p2, 0, pool_queuetowhatprovides(pool, 
&q));
                  if ((how & SOLVER_WEAK) != 0)
                    queue_push(&solv->weakruleq, solv->nrules - 1);
-                 queue_push(&r2pkg, -(solv->jobrules + j));
+                 queue_push(&infoq, -(solv->jobrules + j));
                }
            }
        }
@@ -3387,7 +3406,7 @@
                    solver_addrule(solv, -p2, d, 0);
                  else
                    solver_addrule(solv, -p2, 0, -d);
-                 queue_push(&r2pkg, p);
+                 queue_push(&infoq, p);
                }
              for (i = 0; i < q.count; i++)
                MAPCLR(&m, q.elements[i]);
@@ -3398,16 +3417,16 @@
            solver_addrule(solv, p2, q.count ? q.elements[0] : 0, 0);
          else
            solver_addrule(solv, p2, 0, pool_queuetowhatprovides(pool, &q));
-         queue_push(&r2pkg, p);
+         queue_push(&infoq, p);
        }
       map_free(&m);
     }
-  if (r2pkg.count)
-    solv->bestrules_pkg = solv_memdup2(r2pkg.elements, r2pkg.count, 
sizeof(Id));
+  if (infoq.count)
+    solv->bestrules_info = solv_memdup2(infoq.elements, infoq.count, 
sizeof(Id));
   solv->bestrules_end = solv->nrules;
   queue_free(&q);
   queue_free(&q2);
-  queue_free(&r2pkg);
+  queue_free(&infoq);
 }
 
 
@@ -3442,7 +3461,7 @@
            continue;
          if ((pool->obsoleteusescolors || pool->implicitobsoleteusescolors) && 
!pool_colormatch(pool, s2, os))
            continue;
-         obsp2 = os->repo->idarraydata + os->obsoletes; 
+         obsp2 = os->repo->idarraydata + os->obsoletes;
          while ((obs2 = *obsp2++) != 0)
            if (obs2 == obs)
              break;
@@ -3460,7 +3479,7 @@
            continue;
          if ((pool->obsoleteusescolors || pool->implicitobsoleteusescolors) && 
!pool_colormatch(pool, s2, os))
            continue;
-         obsp2 = os->repo->idarraydata + os->obsoletes; 
+         obsp2 = os->repo->idarraydata + os->obsoletes;
          while ((obs2 = *obsp2++) != 0)
            if (obs2 == obs)
              break;
@@ -3524,7 +3543,7 @@
   Repo *installed = solv->installed;
   Id p, op, *opp;
   Solvable *s;
-  Queue qo, qq, yumobsinfoq;
+  Queue qo, qq, infoq;
   int i, j, k;
   unsigned int now;
 
@@ -3570,7 +3589,7 @@
       queue_free(&qo);
       return;
     }
-  queue_init(&yumobsinfoq);
+  queue_init(&infoq);
   queue_init(&qq);
   for (i = 0; i < qo.count; i++)
     {
@@ -3588,7 +3607,7 @@
   else
     printf("%s\n", pool_solvid2str(pool, qq.elements[j]));
 #endif
-  
+
       if (!qq.count)
        continue;
       /* at least two goups, build rules */
@@ -3617,22 +3636,70 @@
                    solver_addrule(solv, -p, qq.elements[groupstart], 0);
                  else
                    solver_addrule(solv, -p, 0, pool_ids2whatprovides(pool, 
qq.elements + groupstart, k - groupstart));
-                 queue_push(&yumobsinfoq, qo.elements[i]);
+                 queue_push(&infoq, qo.elements[i]);
                }
              groupstart = k + 1;
              groupk++;
            }
        }
     }
-  if (yumobsinfoq.count)
-    solv->yumobsrules_info = solv_memdup2(yumobsinfoq.elements, 
yumobsinfoq.count, sizeof(Id));
-  queue_free(&yumobsinfoq);
+  if (infoq.count)
+    solv->yumobsrules_info = solv_memdup2(infoq.elements, infoq.count, 
sizeof(Id));
+  queue_free(&infoq);
   queue_free(&qq);
   queue_free(&qo);
   solv->yumobsrules_end = solv->nrules;
   POOL_DEBUG(SOLV_DEBUG_STATS, "yumobs rule creation took %d ms\n", 
solv_timems(now));
 }
 
+/* recommendsrules are a copy of some recommends package rule but
+ * with some disfavored literals removed */
+void
+solver_addrecommendsrules(Solver *solv)
+{
+  Pool *pool = solv->pool;
+  int i, havedis, havepos;
+  Id p, pp;
+  Queue q, infoq;
+
+  solv->recommendsrules = solv->nrules;
+  queue_init(&q);
+  queue_init(&infoq);
+  for (i = 0; i < solv->recommendsruleq->count; i++)
+    {
+      int rid = solv->recommendsruleq->elements[i];
+      Rule *r = solv->rules + rid;
+      queue_empty(&q);
+      havedis = havepos = 0;
+      FOR_RULELITERALS(p, pp, r)
+       {
+         if (p > 0 && solv->favormap[p] < 0)
+           havedis = 1;
+         else
+           {
+             if (p > 0)
+               havepos = 1;
+             queue_push(&q, p);
+           }
+       }
+      if (!havedis)
+       continue;
+      solver_disablerule(solv, r);
+      if (!havepos || q.count < 2)
+       continue;
+      if (q.count == 2)
+       solver_addrule(solv, q.elements[0], q.elements[1], 0);
+      else
+       solver_addrule(solv, q.elements[0], 0, pool_ids2whatprovides(pool, 
q.elements + 1, q.count - 1));
+      queue_push(&infoq, rid);
+    }
+  if (infoq.count)
+    solv->recommendsrules_info = solv_memdup2(infoq.elements, infoq.count, 
sizeof(Id));
+  queue_free(&infoq);
+  queue_free(&q);
+  solv->recommendsrules_end = solv->nrules;
+}
+
 void
 solver_breakorphans(Solver *solv)
 {
@@ -3696,7 +3763,7 @@
   Pool *pool = solv->pool;
   int i;
   Id l, pp;
-  
+
   queue_empty(dq);
   if (!solv->brokenorphanrules)
     return;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/src/rules.h 
new/libsolv-0.7.3/src/rules.h
--- old/libsolv-0.7.2/src/rules.h       2018-10-22 15:37:12.000000000 +0200
+++ new/libsolv-0.7.3/src/rules.h       2018-12-18 16:44:45.000000000 +0100
@@ -71,7 +71,8 @@
   SOLVER_RULE_CHOICE = 0x700,
   SOLVER_RULE_LEARNT = 0x800,
   SOLVER_RULE_BEST = 0x900,
-  SOLVER_RULE_YUMOBS = 0xa00
+  SOLVER_RULE_YUMOBS = 0xa00,
+  SOLVER_RULE_RECOMMENDS = 0xb00
 } SolverRuleinfo;
 
 #define SOLVER_RULE_TYPEMASK    0xff00
@@ -133,6 +134,9 @@
 /* yumobs rules */
 extern void solver_addyumobsrules(struct s_Solver *solv);
 
+/* recommends rules */
+extern void solver_addrecommendsrules(struct s_Solver *solv);
+
 /* policy rule disabling/reenabling */
 extern void solver_disablepolicyrules(struct s_Solver *solv);
 extern void solver_reenablepolicyrules(struct s_Solver *solv, int jobidx);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/src/solver.c 
new/libsolv-0.7.3/src/solver.c
--- old/libsolv-0.7.2/src/solver.c      2018-12-10 15:09:56.000000000 +0100
+++ new/libsolv-0.7.3/src/solver.c      2018-12-20 17:35:49.000000000 +0100
@@ -845,18 +845,19 @@
 disable_recommendsrules(Solver *solv, Queue *weakq)
 {
   Pool *pool = solv->pool;
-  int i;
+  int i, rid;
   for (i = 0; i < weakq->count; i++)
     {
-      Rule *r;
-      if (!queue_contains(solv->recommendsruleq, weakq->elements[i]))
-       continue;
-      r = solv->rules + weakq->elements[i];
-      if (r->d >= 0)
+      rid = weakq->elements[i];
+      if ((rid >= solv->recommendsrules && rid < solv->recommendsrules_end) || 
queue_contains(solv->recommendsruleq, rid))
        {
-         POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "disabling ");
-         solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, r);
-         solver_disablerule(solv, r);
+         Rule *r = solv->rules + rid;
+         if (r->d >= 0)
+           {
+             POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "disabling ");
+             solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, r);
+             solver_disablerule(solv, r);
+           }
        }
     }
 }
@@ -894,6 +895,41 @@
     solver_recordproblem(solv, why);
 }
 
+/* fix a problem by disabling one or more weak rules */
+static void
+disable_weakrules(Solver *solv, Queue *weakq)
+{
+  Pool *pool = solv->pool;
+  int i;
+  Id lastweak = 0;
+  for (i = 0; i < weakq->count; i++)
+    if (weakq->elements[i] > lastweak)
+      lastweak = weakq->elements[i];
+  if (lastweak >= solv->recommendsrules && lastweak < 
solv->recommendsrules_end)
+    {
+      lastweak = 0;
+      for (i = 0; i < weakq->count; i++)
+       if (weakq->elements[i] < solv->recommendsrules && weakq->elements[i] > 
lastweak)
+         lastweak = weakq->elements[i];
+      if (lastweak < solv->pkgrules_end)
+       {
+         disable_recommendsrules(solv, weakq);
+         return;
+       }
+    }
+  if (lastweak < solv->pkgrules_end && solv->strongrecommends && 
solv->recommendsruleq && queue_contains(solv->recommendsruleq, lastweak))
+    {
+      disable_recommendsrules(solv, weakq);
+      return;
+    }
+  POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "disabling ");
+  solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, solv->rules + lastweak);
+  /* choice rules need special handling */
+  if (lastweak >= solv->choicerules && lastweak < solv->choicerules_end)
+    solver_disablechoicerules(solv, solv->rules + lastweak);
+  else
+    solver_fixproblem(solv, lastweak);
+}
 
 /*-------------------------------------------------------------------
  *
@@ -924,7 +960,7 @@
   Map rseen;
   Queue weakq;
   Id pp, v, vv, why;
-  int i, idx;
+  int idx;
   Id *decisionmap = solv->decisionmap;
   int oldproblemcount;
   int oldlearntpoolcount;
@@ -981,28 +1017,12 @@
 
   if (weakq.count)
     {
-      Id lastweak;
       /* revert problems */
       solv->problems.count = oldproblemcount;
       solv->learnt_pool.count = oldlearntpoolcount;
-      /* find last weak */
-      lastweak = 0;
-      for (i = 0; i < weakq.count; i++)
-       if (weakq.elements[i] > lastweak)
-         lastweak = weakq.elements[i];
-      if (lastweak < solv->pkgrules_end && solv->strongrecommends && 
solv->recommendsruleq && queue_contains(solv->recommendsruleq, lastweak))
-       {
-         disable_recommendsrules(solv, &weakq);
-         queue_free(&weakq);
-         solver_reset(solv);
-         return 0;
-       }
+      /* disable some weak rules */
+      disable_weakrules(solv, &weakq);
       queue_free(&weakq);
-      POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "disabling ");
-      solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, solv->rules + 
lastweak);
-      if (lastweak >= solv->choicerules && lastweak < solv->choicerules_end)
-       solver_disablechoicerules(solv, solv->rules + lastweak);
-      solver_fixproblem(solv, lastweak);
       solver_reset(solv);
       return 0;
     }
@@ -1160,6 +1180,15 @@
 /*-------------------------------------------------------------------
  *
  * branch handling
+ *
+ * format is:
+ *   [ -p1 p2 p3 .. pn  opt_pkg opt_data size level ]
+ *
+ * pkgs are negative if we tried them (to prevent inifinite recursion)
+ * opt_pkg:  recommends: package with the recommends
+ *           rule: 0
+ * opt_data: recommends: depid
+ *           rule: ruleid
  */
 
 static void
@@ -1378,9 +1407,10 @@
   solv_free(solv->obsoletes);
   solv_free(solv->obsoletes_data);
   solv_free(solv->specialupdaters);
-  solv_free(solv->choicerules_ref);
-  solv_free(solv->bestrules_pkg);
+  solv_free(solv->choicerules_info);
+  solv_free(solv->bestrules_info);
   solv_free(solv->yumobsrules_info);
+  solv_free(solv->recommendsrules_info);
   solv_free(solv->instbuddy);
   solv_free(solv);
 }
@@ -2345,7 +2375,7 @@
            policy_filter_unwanted(solv, dq, POLICY_MODE_CHOOSE);
          /* if we have multiple candidates we open a branch */
          if (dq->count > 1)
-             createbranch(solv, level, dq, s - pool->solvables, rec);
+           createbranch(solv, level, dq, s - pool->solvables, rec);
          p = dq->elements[0];
          POOL_DEBUG(SOLV_DEBUG_POLICY, "installing recommended %s\n", 
pool_solvid2str(pool, p));
          olevel = level;
@@ -2452,6 +2482,7 @@
                break;
            }
          *rerunp = 1;
+         return level;
        }
     }
   return level;
@@ -2705,7 +2736,7 @@
              if (lastsi >= 0)
                {
                  /* we have a recommended package that could not be installed 
*/
-                 /* take it if our current selection is not recommended */
+                 /* find current selection and take new one if it is not 
recommended */
                  for (i = starti; i < endi - 4; i++)
                    {
                      p = -solv->branches.elements[i];
@@ -3113,10 +3144,6 @@
   for (; i < pool->nsolvables; i++)
     if (MAPTST(addedmap, i))
       queue_push(&solv->addedmap_deduceq, i);
-  j = 0;
-  for (i = 2; i < pool->nsolvables; i++)
-    if (MAPTST(addedmap, i))
-      j++;
 }
 
 static void
@@ -3266,9 +3293,10 @@
   queuep_free(&solv->update_targets);
   queuep_free(&solv->cleandeps_updatepkgs);
   queue_empty(&solv->ruleassertions);
-  solv->bestrules_pkg = solv_free(solv->bestrules_pkg);
+  solv->bestrules_info = solv_free(solv->bestrules_info);
   solv->yumobsrules_info = solv_free(solv->yumobsrules_info);
-  solv->choicerules_ref = solv_free(solv->choicerules_ref);
+  solv->recommendsrules_info = solv_free(solv->recommendsrules_info);
+  solv->choicerules_info = solv_free(solv->choicerules_info);
   if (solv->noupdate.size)
     map_empty(&solv->noupdate);
   map_zerosize(&solv->multiversion);
@@ -3338,9 +3366,9 @@
    */
   initialnrules = solv->pkgrules_end ? solv->pkgrules_end : 1;
   if (initialnrules > 1)
-    deduceq2addedmap(solv, &addedmap);
+    deduceq2addedmap(solv, &addedmap);         /* also enables all pkg rules */
   if (solv->nrules != initialnrules)
-    solver_shrinkrules(solv, initialnrules);
+    solver_shrinkrules(solv, initialnrules);   /* shrink to just pkg rules */
   solv->lastpkgrule = 0;
   solv->pkgrules_end = 0;
 
@@ -3892,16 +3920,16 @@
   else
     solv->yumobsrules = solv->yumobsrules_end = solv->nrules;
 
+  if (solv->havedisfavored && solv->strongrecommends)
+    solver_addrecommendsrules(solv);
+  else
+    solv->recommendsrules = solv->recommendsrules_end = solv->nrules;
+
   if (1)
     solver_addchoicerules(solv);
   else
     solv->choicerules = solv->choicerules_end = solv->nrules;
 
-  if (0)
-    {
-      for (i = solv->featurerules; i < solv->nrules; i++)
-        solver_printruleclass(solv, SOLV_DEBUG_RESULT, solv->rules + i);
-    }
   /* all rules created
    * --------------------------------------------------------------
    * prepare for solving
@@ -4761,6 +4789,8 @@
       char buf[64];
       if (solver_ruleclass(solv, id) == SOLVER_RULE_CHOICE)
        id = solver_rule2pkgrule(solv, id);
+      if (solver_ruleclass(solv, id) == SOLVER_RULE_RECOMMENDS)
+       id = solver_rule2pkgrule(solv, id);
       rtype = solver_ruleinfo(solv, id, &depfrom, &depto, &dep);
       if ((rtype & SOLVER_RULE_TYPEMASK) == SOLVER_RULE_JOB)
        {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/src/solver.h 
new/libsolv-0.7.3/src/solver.h
--- old/libsolv-0.7.2/src/solver.h      2018-12-10 15:09:56.000000000 +0100
+++ new/libsolv-0.7.3/src/solver.h      2018-12-19 14:30:15.000000000 +0100
@@ -70,7 +70,7 @@
   Id bestrules;                                /* rules from SOLVER_FORCEBEST 
*/
   Id bestrules_up;                     /* update rule part starts here*/
   Id bestrules_end;
-  Id *bestrules_pkg;
+  Id *bestrules_info;                  /* < 0 : install rule, > 0 : pkg that 
needs to be updated */
 
   Id yumobsrules;                      /* rules from yum obsoletes handling */
   Id yumobsrules_end;
@@ -78,7 +78,11 @@
 
   Id choicerules;                      /* choice rules (always weak) */
   Id choicerules_end;
-  Id *choicerules_ref;
+  Id *choicerules_info;                        /* the rule we used to generate 
the choice rule */
+
+  Id recommendsrules;                  /* rules from recommends pkg rules with 
disfavored literals */
+  Id recommendsrules_end;
+  Id *recommendsrules_info;            /* the original pkg rule rule */
 
   Id learntrules;                      /* learnt rules, (end == nrules) */
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/src/solverdebug.c 
new/libsolv-0.7.3/src/solverdebug.c
--- old/libsolv-0.7.2/src/solverdebug.c 2018-10-01 11:09:18.000000000 +0200
+++ new/libsolv-0.7.3/src/solverdebug.c 2018-12-18 16:44:45.000000000 +0100
@@ -128,6 +128,8 @@
     POOL_DEBUG(type, "FEATURE ");
   else if (p >= solv->yumobsrules && p < solv->yumobsrules_end)
     POOL_DEBUG(type, "YUMOBS ");
+  else if (p >= solv->recommendsrules && p < solv->recommendsrules_end)
+    POOL_DEBUG(type, "RECOMMENDS ");
   solver_printrule(solv, type, r);
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libsolv-0.7.2/test/testcases/lockstep/infarch_install_best.t 
new/libsolv-0.7.3/test/testcases/lockstep/infarch_install_best.t
--- old/libsolv-0.7.2/test/testcases/lockstep/infarch_install_best.t    
1970-01-01 01:00:00.000000000 +0100
+++ new/libsolv-0.7.3/test/testcases/lockstep/infarch_install_best.t    
2019-01-15 14:14:06.000000000 +0100
@@ -0,0 +1,20 @@
+# test for issue 292
+repo system 0 testtags <inline>
+#>=Pkg: nss 3.39.0 2.fc29 x86_64
+#>=Pkg: nss-sysinit 3.39.0 2.fc29 x86_64
+#>=Req: nss = 3.39.0-2.fc29
+repo available 0 testtags <inline>
+#>=Pkg: nss 3.39.0 2.fc29 i686
+#>=Pkg: nss 3.41.0 1.fc29 x86_64
+#>=Pkg: nss-sysinit 3.41.0 1.fc29 x86_64
+#>=Req: nss = 3.41.0-1.fc29
+
+system x86_64 rpm system
+
+poolflags implicitobsoleteusescolors
+solverflags allowvendorchange keepexplicitobsoletes bestobeypolicy keeporphans 
yumobsoletes
+
+job install oneof nss-3.41.0-1.fc29.x86_64@available [setevr,setarch]
+result transaction,problems <inline>
+#>upgrade nss-3.39.0-2.fc29.x86_64@system nss-3.41.0-1.fc29.x86_64@available
+#>upgrade nss-sysinit-3.39.0-2.fc29.x86_64@system 
nss-sysinit-3.41.0-1.fc29.x86_64@available
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libsolv-0.7.2/test/testcases/strongrecommends/disfavored.t 
new/libsolv-0.7.3/test/testcases/strongrecommends/disfavored.t
--- old/libsolv-0.7.2/test/testcases/strongrecommends/disfavored.t      
1970-01-01 01:00:00.000000000 +0100
+++ new/libsolv-0.7.3/test/testcases/strongrecommends/disfavored.t      
2018-12-18 17:00:05.000000000 +0100
@@ -0,0 +1,34 @@
+# test strong recommends
+#
+# with normal recommends, the solver will
+# not backtrack to fulfill them.
+#
+repo system 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Con: C
+#>=Pkg: A2 1 1 noarch
+#>=Con: C2
+repo available 0 testtags <inline>
+#>=Pkg: A 1 2 noarch
+#>=Pkg: B 1 1 noarch
+#>=Rec: C
+#>=Pkg: C 1 1 noarch
+#>=Pkg: B2 1 1 noarch
+#>=Rec: C2
+#>=Pkg: C2 1 1 noarch
+#>=Pkg: D 1 1 noarch
+#>=Prv: C
+#>=Pkg: E 1 1 noarch
+#>=Prv: C
+system i686 rpm system
+solverflags strongrecommends
+job install name B
+job install name B2
+job disfavor name C
+result transaction,problems,alternatives <inline>
+#>alternative 6b91d100  1 + D-1-1.noarch@available
+#>alternative 6b91d100  2   E-1-1.noarch@available
+#>install B-1-1.noarch@available
+#>install B2-1-1.noarch@available
+#>install D-1-1.noarch@available
+#>upgrade A-1-1.noarch@system A-1-2.noarch@available
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libsolv-0.7.2/tools/repo2solv.c 
new/libsolv-0.7.3/tools/repo2solv.c
--- old/libsolv-0.7.2/tools/repo2solv.c 2018-10-01 11:09:18.000000000 +0200
+++ new/libsolv-0.7.3/tools/repo2solv.c 2019-01-22 09:59:48.000000000 +0100
@@ -169,9 +169,9 @@
          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 @@
        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)
     {


Reply via email to