Imported Upstream version 0.6.25 95/194195/1 upstream/0.6.25
authorDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 30 Nov 2018 03:40:15 +0000 (12:40 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 30 Nov 2018 03:40:16 +0000 (12:40 +0900)
Change-Id: I4c41182d0968927b2dc78980b41c0b7c2e931a4a
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
25 files changed:
CMakeLists.txt
NEWS
VERSION.cmake
bindings/solv.i
doc/libsolv-bindings.3
doc/libsolv-bindings.txt
examples/solv/repoinfo.c
examples/solv/solv.c
ext/repo_rpmdb.c
ext/testcase.c
package/libsolv.changes
src/dirpool.c
src/policy.c
src/pool.c
src/pool.h
src/problems.c
src/repo_solv.c
src/repo_write.c
src/repodata.c
src/rules.c
src/rules.h
src/solvable.c
src/solver.c
src/solver.h
src/suse.c

index 82034e0..12b9b32 100644 (file)
@@ -58,12 +58,17 @@ else (DEFINED INCLUDE)
 ENDIF (DEFINED  INCLUDE)
 MESSAGE (STATUS "Header files will be installed in ${INCLUDE_INSTALL_DIR}")
 SET (BIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/bin")
+IF (NOT MAN_INSTALL_DIR)
 SET (MAN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/man")
 IF (IS_DIRECTORY "${CMAKE_INSTALL_PREFIX}/man"  AND NOT IS_DIRECTORY "${CMAKE_INSTALL_PREFIX}/share/man")
   SET (MAN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/man")
 ENDIF (IS_DIRECTORY "${CMAKE_INSTALL_PREFIX}/man"  AND NOT IS_DIRECTORY "${CMAKE_INSTALL_PREFIX}/share/man")
+ENDIF (NOT MAN_INSTALL_DIR)
 MESSAGE(STATUS "Man pages will be installed in ${MAN_INSTALL_DIR}")
 
+IF (NOT PKGCONFIG_INSTALL_DIR)
+  SET (PKGCONFIG_INSTALL_DIR ${LIB_INSTALL_DIR}/pkgconfig)
+ENDIF (NOT PKGCONFIG_INSTALL_DIR)
 ####################################################################
 # CONFIGURATION                                                    #
 ####################################################################
@@ -153,6 +158,7 @@ SET (ENABLE_LZMA_COMPRESSION ON)
 ENDIF (ENABLE_ARCHREPO)
 
 FIND_PACKAGE (EXPAT REQUIRED)
+INCLUDE_DIRECTORIES (${EXPAT_INCLUDE_DIRS})
 FIND_PACKAGE (ZLIB REQUIRED)
 IF (ENABLE_LZMA_COMPRESSION)
 FIND_PACKAGE (LZMA REQUIRED)
@@ -206,6 +212,9 @@ IF (ENABLE_RPMDB)
     IF (DB_LIBRARY)
       SET (RPMDB_LIBRARY ${DB_LIBRARY} ${RPMDB_LIBRARY})
     ENDIF (DB_LIBRARY)
+    IF (DB_INCLUDE_DIR)
+      INCLUDE_DIRECTORIES (${DB_INCLUDE_DIR})
+    ENDIF (DB_INCLUDE_DIR)
   ENDIF (NOT HAVE_RPM_DB_H)
   INCLUDE (CheckLibraryExists)
   CHECK_LIBRARY_EXISTS(rpmio pgpDigGetParams "" HAVE_PGPDIGGETPARAMS)
@@ -386,7 +395,7 @@ ENDMACRO (SPECFILE)
 MACRO (PCFILE)
   MESSAGE (STATUS "Writing pkg-config file...")
   CONFIGURE_FILE (${CMAKE_SOURCE_DIR}/libsolv.pc.in ${CMAKE_BINARY_DIR}/libsolv.pc @ONLY)
-  INSTALL( FILES ${CMAKE_BINARY_DIR}/libsolv.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig )
+  INSTALL( FILES ${CMAKE_BINARY_DIR}/libsolv.pc DESTINATION ${PKGCONFIG_INSTALL_DIR} )
 ENDMACRO (PCFILE)
 
 SPECFILE ()
diff --git a/NEWS b/NEWS
index 79e18dc..abb9bda 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,14 @@
 This file contains the major changes between
 libsolv versions:
 
+Version 0.6.25
+- new features:
+  * new SOLVER_FLAG_STRONG_RECOMMENDS flag
+  * new SOLVER_FLAG_INSTALL_ALSO_UPDATES flag
+  * new matchesdep() method in bindings
+  * SOLVABLE_NAME selects nevr matching for
+    pool_whatmatchesdep and solvable_matchesdep
 Version 0.6.24
 - new features:
   * new SOLVER_FLAG_FOCUS_BEST flag
index ffa5bd0..3d93005 100644 (file)
@@ -49,5 +49,5 @@ SET(LIBSOLVEXT_SOVERSION "0")
 
 SET(LIBSOLV_MAJOR "0")
 SET(LIBSOLV_MINOR "6")
-SET(LIBSOLV_PATCH "24")
+SET(LIBSOLV_PATCH "25")
 
index 64f51d0..61dc640 100644 (file)
@@ -2188,6 +2188,34 @@ rb_eval_string(
   }
 #endif
 
+  Repo *createshadow(const char *name) {
+    Repo *repo = repo_create($self->pool, name);
+    if ($self->idarraysize) {
+      repo_reserve_ids(repo, 0, $self->idarraysize);
+      memcpy(repo->idarraydata, $self->idarraydata, sizeof(Id) * $self->idarraysize);
+      repo->idarraysize = $self->idarraysize;
+    }
+    repo->start = $self->start;
+    repo->end = $self->end;
+    repo->nsolvables = $self->nsolvables;
+    return repo;
+  }
+
+  void moveshadow(Queue q) {
+    Pool *pool = $self->pool;
+    int i;
+    for (i = 0; i < q.count; i++) {
+      Solvable *s;
+      Id p = q.elements[i];
+      if (p < $self->start || p >= $self->end)
+        continue;
+      s = pool->solvables + p;
+      if ($self->idarraysize != s->repo->idarraysize)
+        continue;
+      s->repo = $self;
+    }
+  }
+
 #if defined(SWIGTCL)
   %rename("==") __eq__;
 #endif
@@ -2963,6 +2991,12 @@ rb_eval_string(
   int evrcmp(XSolvable *s2) {
     return pool_evrcmp($self->pool, $self->pool->solvables[$self->id].evr, s2->pool->solvables[s2->id].evr, EVRCMP_COMPARE);
   }
+#ifdef SWIGRUBY
+  %rename("matchesdep?") matchesdep;
+#endif
+  bool matchesdep(Id keyname, DepId id, Id marker = -1) {
+    return solvable_matchesdep($self->pool->solvables + $self->id, keyname, id, marker);
+  }
 
 #if defined(SWIGTCL)
   %rename("==") __eq__;
@@ -3281,6 +3315,8 @@ rb_eval_string(
   static const int SOLVER_FLAG_YUM_OBSOLETES = SOLVER_FLAG_YUM_OBSOLETES;
   static const int SOLVER_FLAG_NEED_UPDATEPROVIDE = SOLVER_FLAG_NEED_UPDATEPROVIDE;
   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_REASON_UNRELATED = SOLVER_REASON_UNRELATED;
   static const int SOLVER_REASON_UNIT_RULE = SOLVER_REASON_UNIT_RULE;
@@ -3451,6 +3487,21 @@ rb_eval_string(
   bool write_testcase(const char *dir) {
     return testcase_write($self, dir, TESTCASE_RESULT_TRANSACTION | TESTCASE_RESULT_PROBLEMS, 0, 0);
   }
+
+  Queue raw_decisions(int filter=0) {
+    Queue q;
+    queue_init(&q);
+    solver_get_decisionqueue($self, &q);
+    if (filter) {
+      int i, j;
+      for (i = j = 0; i < q.count; i++)
+        if ((filter > 0 && q.elements[i] > 1) ||
+            (filter < 0 && q.elements[i] < 0))
+          q.elements[j++] = q.elements[i];
+      queue_truncate(&q, j);
+    }
+    return q;
+  }
 }
 
 %extend Transaction {
index 6b57ebf..477a6e4 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: Libsolv-Bindings
 .\"    Author: [see the "Author" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 05/03/2016
+.\"      Date: 12/14/2016
 .\"    Manual: LIBSOLV
 .\"    Source: libsolv
 .\"  Language: English
 .\"
-.TH "LIBSOLV\-BINDINGS" "3" "05/03/2016" "libsolv" "LIBSOLV"
+.TH "LIBSOLV\-BINDINGS" "3" "12/14/2016" "libsolv" "LIBSOLV"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -2514,8 +2514,8 @@ Return true if the solvable is installed on the system\&.
 .nf
 \fBbool identical(Solvable *\fR\fIother\fR\fB)\fR
 \fI$solvable\fR\fB\->identical(\fR\fI$other\fR\fB)\fR
-\fI$solvable\fR\fB\&.identical(\fR\fIother\fR\fB)\fR
-\fI$solvable\fR\fB\&.identical?(\fR\fIother\fR\fB)\fR
+\fIsolvable\fR\fB\&.identical(\fR\fIother\fR\fB)\fR
+\fIsolvable\fR\fB\&.identical?(\fR\fIother\fR\fB)\fR
 .fi
 .if n \{\
 .RE
@@ -2528,9 +2528,9 @@ Return true if the two solvables are identical\&.
 .\}
 .nf
 \fBint evrcmp(Solvable *\fR\fIother\fR\fB)\fR
-\fI$solvable\fR\fB\->evrcmp(\fR\fIother\fR\fB)\fR
-\fI$solvable\fR\fB\&.evrcmp(\fR\fIother\fR\fB)\fR
-\fI$solvable\fR\fB\&.evrcmp(\fR\fIother\fR\fB)\fR
+\fI$solvable\fR\fB\->evrcmp(\fR\fI$other\fR\fB)\fR
+\fIsolvable\fR\fB\&.evrcmp(\fR\fIother\fR\fB)\fR
+\fIsolvable\fR\fB\&.evrcmp(\fR\fIother\fR\fB)\fR
 .fi
 .if n \{\
 .RE
@@ -2542,6 +2542,21 @@ Returns \-1 if the epoch/version/release of the solvable is less than the one fr
 .RS 4
 .\}
 .nf
+\fBint matchesdep(Id\fR \fIkeyname\fR\fB, DepId\fR \fIid\fR\fB, Id\fR \fImarker\fR \fB= \-1)\fR
+\fI$solvable\fR\fB\->matchesdep(\fR\fI$keyname\fR\fB,\fR \fI$dep\fR\fB)\fR
+\fIsolvable\fR\fB\&.matchesdep(\fR\fIkeyname\fR\fB,\fR \fIdep\fR\fB)\fR
+\fIsolvable\fR\fB\&.matchesdep?(\fR\fIkeyname\fR\fB,\fR \fIdep\fR\fB)\fR
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+Return true if the dependencies stored in keyname match the specified dependeny\&.
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
 \fBSelection Selection(int\fR \fIsetflags\fR \fB= 0)\fR
 my \fI$sel\fR \fB=\fR \fI$solvable\fR\fB\->Selection()\fR;
 \fIsel\fR \fB=\fR \fIsolvable\fR\fB\&.Selection()\fR
@@ -3529,6 +3544,11 @@ Like SOLVER_FLAG_ALLOW_NAMECHANGE, but used in distupgrade mode\&.
 If multiple packages obsolete an installed package, the solver checks the provides of every such package and ignores all packages that do not provide the installed package name\&. Thus, you can have an official update candidate that provides the old name, and other packages that also obsolete the package but are not considered for updating\&. If you cannot use this feature, you can turn it off by setting this flag\&.
 .RE
 .PP
+\fBSOLVER_FLAG_NEED_UPDATEPROVIDE\fR
+.RS 4
+This is somewhat the opposite of SOLVER_FLAG_NO_UPDATEPROVIDE: Only packages that provied the installed package names are considered for updating\&.
+.RE
+.PP
 \fBSOLVER_FLAG_SPLITPROVIDES\fR
 .RS 4
 Make the solver aware of special provides of the form \(lq<packagename>:<path>\(rq used in SUSE systems to support package splits\&.
@@ -3571,7 +3591,27 @@ Ignore dependencies of orphaned packages that get in the way of resolving non\-o
 .PP
 \fBSOLVER_FLAG_FOCUS_INSTALLED\fR
 .RS 4
-Resolve installed packages before resolving the given job\&. Setting this flag means that the solver will prefer picking a package version that fits the other installed packages over updating installed packages\&.
+Resolve installed packages before resolving the given jobs\&. Setting this flag means that the solver will prefer picking a package version that fits the other installed packages over updating installed packages\&.
+.RE
+.PP
+\fBSOLVER_FLAG_FOCUS_BEST\fR
+.RS 4
+First resolve the given jobs, then the dependencies of the resulting packages, then resolve all already installed packages\&. This will result in more packages being updated as when the flag is not used\&.
+.RE
+.PP
+\fBSOLVER_FLAG_INSTALL_ALSO_UPDATES\fR
+.RS 4
+Update the package if a job is already fulfilled by an installed package\&.
+.RE
+.PP
+\fBSOLVER_FLAG_YUM_OBSOLETES\fR
+.RS 4
+Turn on yum\-like package split handling\&. See the yum documentation for more details\&.
+.RE
+.PP
+\fBSOLVER_FLAG_URPM_REORDER\fR
+.RS 4
+Turn on urpm like package reordering for kernel packages\&. See the urpm documentation for more details\&.
 .RE
 .sp
 Basic rule types:
index 79f4c2c..e44d53a 100644 (file)
@@ -1400,20 +1400,27 @@ Return true if the solvable is installed on the system.
 
        bool identical(Solvable *other)
        $solvable->identical($other)
-       $solvable.identical(other)
-       $solvable.identical?(other)
+       solvable.identical(other)
+       solvable.identical?(other)
 
 Return true if the two solvables are identical.
 
        int evrcmp(Solvable *other)
-       $solvable->evrcmp(other)
-       $solvable.evrcmp(other)
-       $solvable.evrcmp(other)
+       $solvable->evrcmp($other)
+       solvable.evrcmp(other)
+       solvable.evrcmp(other)
 
 Returns -1 if the epoch/version/release of the solvable is less than the
 one from the other solvable, 1 if it is greater, and 0 if they are equal.
 Note that "equal" does not mean that the evr is identical.
 
+       int matchesdep(Id keyname, DepId id, Id marker = -1)
+       $solvable->matchesdep($keyname, $dep)
+       solvable.matchesdep(keyname, dep)
+       solvable.matchesdep?(keyname, dep)
+
+Return true if the dependencies stored in keyname match the specified dependeny.
+
        Selection Selection(int setflags = 0)
        my $sel = $solvable->Selection();
        sel = solvable.Selection()
@@ -2120,6 +2127,11 @@ packages that also obsolete the package but are not considered for
 updating. If you cannot use this feature, you can turn it off
 by setting this flag.
 
+*SOLVER_FLAG_NEED_UPDATEPROVIDE*::
+This is somewhat the opposite of SOLVER_FLAG_NO_UPDATEPROVIDE: Only
+packages that provied the installed package names are considered
+for updating.
+
 *SOLVER_FLAG_SPLITPROVIDES*::
 Make the solver aware of special provides of the form
 ``<packagename>:<path>'' used in SUSE systems to support package
@@ -2162,11 +2174,31 @@ of resolving non-orphaned ones. Setting the flag might result
 in no longer working packages in case they are orphaned.
 
 *SOLVER_FLAG_FOCUS_INSTALLED*::
-Resolve installed packages before resolving the given job.
+Resolve installed packages before resolving the given jobs.
 Setting this flag means that the solver will prefer picking
 a package version that fits the other installed packages
 over updating installed packages.
 
+*SOLVER_FLAG_FOCUS_BEST*::
+First resolve the given jobs, then the dependencies of the
+resulting packages, then resolve all already installed
+packages. This will result in more packages being updated
+as when the flag is not used.
+
+*SOLVER_FLAG_INSTALL_ALSO_UPDATES*::
+Update the package if a job is already fulfilled by an installed
+package.
+
+*SOLVER_FLAG_YUM_OBSOLETES*::
+Turn on yum-like package split handling. See the yum documentation
+for more details.
+
+*SOLVER_FLAG_URPM_REORDER*::
+Turn on urpm like package reordering for kernel packages. See
+the urpm documentation for more details.
+
+
+
 Basic rule types:
 
 *SOLVER_RULE_UNKNOWN*::
index e08d160..91f7c28 100644 (file)
 #if defined(ENABLE_DEBIAN) && defined(DEBIAN)
 #include "repo_deb.h"
 #endif
+#ifdef SUSE
+#include "repo_autopattern.h"
+#endif
+
 
 #include "repoinfo.h"
 #include "repoinfo_cache.h"
@@ -110,6 +114,9 @@ read_installed_repo(struct repoinfo *cinfo, Pool *pool)
 #if defined(ENABLE_DEBIAN) && defined(DEBIAN)
   r = read_installed_debian(cinfo);
 #endif
+#ifdef SUSE
+  repo_add_autopattern(cinfo->repo, 0);
+#endif
   pool_set_installed(pool, cinfo->repo);
   return r;
 }
@@ -235,6 +242,9 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos)
 
       if ((!cinfo->autorefresh || cinfo->metadata_expire) && usecachedrepo(cinfo, 0, 0))
        {
+#ifdef SUSE
+         repo_add_autopattern(cinfo->repo, 0);
+#endif
          printf("repo '%s':", cinfo->alias);
          printf(" cached\n");
          continue;
@@ -268,6 +278,10 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos)
          cinfo->repo = 0;
          break;
        }
+#ifdef SUSE
+      if (cinfo->repo)
+        repo_add_autopattern(cinfo->repo, 0);
+#endif
     }
   if (sigpool)
     pool_free(sigpool);
index 814f7e1..3301126 100644 (file)
@@ -116,17 +116,6 @@ nscallback(Pool *pool, void *data, Id name, Id evr)
 
 #ifdef SUSE
 static void
-add_autopackages(Pool *pool)
-{
-  int i;
-  Repo *repo;
-  FOR_REPOS(i, repo)
-    repo_add_autopattern(repo, 0);
-}
-#endif
-
-#ifdef SUSE
-static void
 showdiskusagechanges(Transaction *trans)
 {
   DUChanges duc[4];
@@ -500,16 +489,18 @@ main(int argc, char **argv)
          commandlinepkgs[i] = p;
        }
       if (commandlinerepo)
-       repo_internalize(commandlinerepo);
+       {
+         repo_internalize(commandlinerepo);
+#ifdef SUSE
+         repo_add_autopattern(commandlinerepo, 0);
+#endif
+       }
     }
 
 #if defined(ENABLE_RPMDB)
   if (pool->disttype == DISTTYPE_RPM)
     addfileprovides(pool);
 #endif
-#ifdef SUSE
-  add_autopackages(pool);
-#endif
   pool_createwhatprovides(pool);
 
   if (keyname)
index 034198c..fe05bec 100644 (file)
@@ -765,16 +765,15 @@ adddudata(Repodata *data, Id handle, RpmHead *rpmhead, char **dn, unsigned int *
     {
       if (!fn[i])
        continue;
-      if (!*dn[i])
+      did = repodata_str2dir(data, dn[i], 1);
+      if (!did)
        {
-         Solvable *s = data->repo->pool->solvables + handle;
+          Solvable *s = data->repo->pool->solvables + handle;
           if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
            did = repodata_str2dir(data, "/usr/src", 1);
          else
            continue;   /* work around rpm bug */
        }
-      else
-        did = repodata_str2dir(data, dn[i], 1);
       repodata_add_dirnumnum(data, handle, SOLVABLE_DISKUSAGE, did, fkb[i], fn[i]);
     }
   solv_free(fn);
@@ -1575,7 +1574,7 @@ static Id copydir_complex(Pool *pool, Repodata *data, Repodata *fromdata, Id did
 static inline Id
 copydir(Pool *pool, Repodata *data, Repodata *fromdata, Id did, Id *cache)
 {
-  if (cache && cache[did & 255] == did)
+  if (cache && did && cache[did & 255] == did)
     return cache[(did & 255) + 256];
   return copydir_complex(pool, data, fromdata, did, cache);
 }
@@ -1583,8 +1582,16 @@ copydir(Pool *pool, Repodata *data, Repodata *fromdata, Id did, Id *cache)
 static Id
 copydir_complex(Pool *pool, Repodata *data, Repodata *fromdata, Id did, Id *cache)
 {
-  Id parent = dirpool_parent(&fromdata->dirpool, did);
-  Id compid = dirpool_compid(&fromdata->dirpool, did);
+  Id parent, compid;
+  if (!did)
+    {
+      /* make sure that the dirpool has an entry */
+      if (!data->dirpool.ndirs)
+        dirpool_add_dir(&data->dirpool, 0, 0, 1);
+      return 0;
+    }
+  parent = dirpool_parent(&fromdata->dirpool, did);
+  compid = dirpool_compid(&fromdata->dirpool, did);
   if (parent)
     parent = copydir(pool, data, fromdata, parent, cache);
   if (data->localpool || fromdata->localpool)
index a56c4db..ccfcb61 100644 (file)
@@ -116,6 +116,8 @@ static struct solverflags2str {
   { SOLVER_FLAG_NEED_UPDATEPROVIDE,         "needupdateprovide", 0 },
   { SOLVER_FLAG_URPM_REORDER,               "urpmreorder", 0 },
   { SOLVER_FLAG_FOCUS_BEST,                 "focusbest", 0 },
+  { SOLVER_FLAG_STRONG_RECOMMENDS,          "strongrecommends", 0 },
+  { SOLVER_FLAG_INSTALL_ALSO_UPDATES,       "installalsoupdates", 0 },
   { 0, 0, 0 }
 };
 
index fd351c3..d32694e 100644 (file)
@@ -1,4 +1,19 @@
 -------------------------------------------------------------------
+Tue Feb  7 13:13:01 CET 2017 - mls@suse.de
+
+- add SOLVABLE_NAME hack for pool_whatmatchesdep and
+  solvable_matchesdep
+- add SOLVER_FLAG_STRONG_RECOMMENDS option
+- add SOLVER_FLAG_INSTALL_ALSO_UPDATES option
+- do not special case release-less provides in sort_by_common_dep
+- solver_problemruleinfo2str: return reason why a package is not
+  installable
+- guard against dirpool_add_dir being called with an illegal
+  component id
+- reject solv files with bad directories
+- bump version to 0.6.25
+
+-------------------------------------------------------------------
 Thu Nov 10 15:09:25 CET 2016 - mls@suse.de
 
 - make testcase_str2solvid work with ignored packages
index 5f08361..afb26ea 100644 (file)
@@ -99,7 +99,7 @@ dirpool_make_dirtraverse(Dirpool *dp)
 Id
 dirpool_add_dir(Dirpool *dp, Id parent, Id comp, int create)
 {
-  Id did, d, ds, *dirtraverse;
+  Id did, d, ds;
 
   if (!dp->ndirs)
     {
@@ -110,14 +110,15 @@ dirpool_add_dir(Dirpool *dp, Id parent, Id comp, int create)
       dp->dirs[0] = 0;
       dp->dirs[1] = 1; /* "" */
     }
+  if (comp <= 0)
+    return 0;
   if (parent == 0 && comp == 1)
     return 1;
   if (!dp->dirtraverse)
     dirpool_make_dirtraverse(dp);
   /* check all entries with this parent if we
    * already have this component */
-  dirtraverse = dp->dirtraverse;
-  ds = dirtraverse[parent];
+  ds = dp->dirtraverse[parent];
   while (ds)
     {
       /* ds: first component in this block
index 7ed52d9..8b4c2e4 100644 (file)
@@ -981,23 +981,7 @@ sort_by_name_evr_sortcmp(const void *ap, const void *bp, void *dp)
     return 0;
   a = aa[2] < 0 ? -aa[2] : aa[2];
   b = bb[2] < 0 ? -bb[2] : bb[2];
-  if (pool->disttype != DISTTYPE_DEB && a != b)
-    {
-      /* treat release-less versions different */
-      const char *as = pool_id2str(pool, a);
-      const char *bs = pool_id2str(pool, b);
-      if (strchr(as, '-'))
-       {
-         if (!strchr(bs, '-'))
-           return -2;
-       }
-      else
-       {
-         if (strchr(bs, '-'))
-           return 2;
-       }
-    }
-  r = pool_evrcmp(pool, b, a, EVRCMP_COMPARE);
+  r = pool_evrcmp(pool, b, a, pool->disttype != DISTTYPE_DEB ? EVRCMP_MATCH_RELEASE : EVRCMP_COMPARE);
   if (!r && (aa[2] < 0 || bb[2] < 0))
     {
       if (bb[2] >= 0)
@@ -1005,9 +989,7 @@ sort_by_name_evr_sortcmp(const void *ap, const void *bp, void *dp)
       if (aa[2] >= 0)
        return -1;
     }
-  if (r)
-    return r < 0 ? -1 : 1;
-  return 0;
+  return r;
 }
 
 /* common end of sort_by_srcversion and sort_by_common_dep */
index 72e22f8..1adf70e 100644 (file)
@@ -799,7 +799,7 @@ pool_match_flags_evr_rel_compat(Pool *pool, Reldep *range, int flags, int evr)
 
 /* public (i.e. not inlined) version of pool_match_flags_evr */
 int
-pool_intersect_evrs(Pool *pool, int pflags, Id pevr, int flags, int evr)
+pool_intersect_evrs(Pool *pool, int pflags, Id pevr, int flags, Id evr)
 {
   return pool_match_flags_evr(pool, pflags, pevr, flags, evr);
 }
@@ -1335,6 +1335,14 @@ pool_whatmatchesdep(Pool *pool, Id keyname, Id dep, Queue *q, int marker)
   int i;
 
   queue_empty(q);
+  if (keyname == SOLVABLE_NAME)
+    {
+      Id pp;
+      FOR_PROVIDES(p, pp, dep)
+        if (pool_match_dep(pool, p, dep))
+         queue_push(q, p);
+      return;
+    }
   queue_init(&qq);
   FOR_POOL_SOLVABLES(p)
     {
index 86d49aa..1ae3b11 100644 (file)
@@ -289,7 +289,7 @@ static inline const char *pool_solvid2str(Pool *pool, Id p)
 void pool_set_languages(Pool *pool, const char **languages, int nlanguages);
 Id pool_id2langid(Pool *pool, Id id, const char *lang, int create);
 
-int pool_intersect_evrs(Pool *pool, int pflags, Id pevr, int flags, int evr);
+int pool_intersect_evrs(Pool *pool, int pflags, Id pevr, int flags, Id evr);
 int pool_match_dep(Pool *pool, Id d1, Id d2);
 
 /* semi private, used in pool_match_nevr */
index 063d47b..a9bbdce 100644 (file)
@@ -1089,6 +1089,7 @@ solver_problemruleinfo2str(Solver *solv, SolverRuleinfo type, Id source, Id targ
 {
   Pool *pool = solv->pool;
   char *s;
+  Solvable *ss;
   switch (type)
     {
     case SOLVER_RULE_DISTUPGRADE:
@@ -1114,6 +1115,12 @@ solver_problemruleinfo2str(Solver *solv, SolverRuleinfo type, Id source, Id targ
         return pool_tmpjoin(pool, "cannot install the best update candidate for package ", pool_solvid2str(pool, source), 0);
      return "cannot install the best candidate for the job";
     case SOLVER_RULE_PKG_NOT_INSTALLABLE:
+      ss = pool->solvables + source;
+      if (pool_disabled_solvable(pool, ss))
+        return pool_tmpjoin(pool, "package ", pool_solvid2str(pool, source), " is disabled");
+      if (ss->arch && ss->arch != ARCH_SRC && ss->arch != ARCH_NOSRC &&
+          pool->id2arch && (ss->arch > pool->lastarch || !pool->id2arch[ss->arch]))
+        return pool_tmpjoin(pool, "package ", pool_solvid2str(pool, source), " does not have a compatible architecture");
       return pool_tmpjoin(pool, "package ", pool_solvid2str(pool, source), " is not installable");
     case SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP:
       s = pool_tmpjoin(pool, "nothing provides ", pool_dep2str(pool, dep), 0);
index 86c851c..2460e30 100644 (file)
@@ -873,11 +873,20 @@ repo_add_solv(Repo *repo, FILE *fp, int flags)
        {
          id = read_id(&data, i + numid);
          if (id >= numid)
-           data.dirpool.dirs[i] = -(id - numid);
-         else if (idmap)
-           data.dirpool.dirs[i] = idmap[id];
-         else
-           data.dirpool.dirs[i] = id;
+           {
+             data.dirpool.dirs[i++] = -(id - numid);
+             if (i >= numdir)
+               {
+                 data.error = pool_error(pool, SOLV_ERROR_CORRUPT, "last dir entry is not a component");
+                 break;
+               }
+             id = read_id(&data, numid);
+           }
+         if (idmap)
+           id = idmap[id];
+         data.dirpool.dirs[i] = id;
+         if (id <= 0)
+            data.error = pool_error(pool, SOLV_ERROR_CORRUPT, "bad dir component");
        }
     }
 
index 210636c..396cd42 100644 (file)
@@ -955,6 +955,10 @@ traverse_dirs(Dirpool *dp, Id *dirmap, Id n, Id dir, Id *used)
       dirmap[n++] = sib;
     }
 
+  /* check if our block has some content */
+  if (parent == n)
+    return n - 1;      /* nope, drop parent id again */
+
   /* now go through all the siblings we just added and
    * do recursive calls on them */
   lastn = n;
index b611afc..027c24c 100644 (file)
@@ -268,17 +268,13 @@ repodata_str2dir(Repodata *data, const char *dir, int create)
 #endif
   const char *dire;
 
-  parent = 0;
   if (!*dir)
-    return 0;
+    return data->dirpool.ndirs ? 0 : dirpool_add_dir(&data->dirpool, 0, 0, create);
   while (*dir == '/' && dir[1] == '/')
     dir++;
   if (*dir == '/' && !dir[1])
-    {
-      if (data->dirpool.ndirs)
-        return 1;
-      return dirpool_add_dir(&data->dirpool, 0, 1, create);
-    }
+    return data->dirpool.ndirs ? 1 : dirpool_add_dir(&data->dirpool, 0, 1, create);
+  parent = 0;
 #ifdef DIRCACHE_SIZE
   dirs = dir;
   if (data->dircache)
index 67f10d8..33f5350 100644 (file)
@@ -114,24 +114,27 @@ unifyrules_sortcmp(const void *ap, const void *bp, void *dp)
 
   x = a->p - b->p;
   if (x)
-    return x;                         /* p differs */
+    return x;                          /* p differs */
 
   /* identical p */
-  if (a->d == 0 && b->d == 0)
-    return a->w2 - b->w2;             /* assertion: return w2 diff */
+  if (a->d == 0 && b->d == 0)          /* both assertions or binary */
+    return a->w2 - b->w2;
 
-  if (a->d == 0)                      /* a is assertion, b not */
+  if (a->d == 0)                       /* a is assertion or binary, b not */
     {
       x = a->w2 - pool->whatprovidesdata[b->d];
       return x ? x : -1;
     }
 
-  if (b->d == 0)                      /* b is assertion, a not */
+  if (b->d == 0)                       /* b is assertion or binary, a not */
     {
       x = pool->whatprovidesdata[a->d] - b->w2;
       return x ? x : 1;
     }
 
+  if (a->d == b->d)
+    return 0;
+
   /* compare whatprovidesdata */
   ad = pool->whatprovidesdata + a->d;
   bd = pool->whatprovidesdata + b->d;
@@ -161,22 +164,31 @@ solver_unifyrules(Solver *solv)
   int i, j;
   Rule *ir, *jr;
 
-  if (solv->nrules <= 2)              /* nothing to unify */
+  if (solv->nrules <= 2)               /* nothing to unify */
     return;
 
+  if (solv->recommendsruleq)
+    {
+      /* mis-use n2 as recommends rule marker */
+      for (i = 1, ir = solv->rules + i; i < solv->nrules; i++, ir++)
+       ir->n2 = 0;
+      for (i = 0; i < solv->recommendsruleq->count; i++)
+       solv->rules[solv->recommendsruleq->elements[i]].n2 = 1;
+    }
+
   /* sort rules first */
   solv_sort(solv->rules + 1, solv->nrules - 1, sizeof(Rule), unifyrules_sortcmp, solv->pool);
 
-  /* prune rules
-   * i = unpruned
-   * j = pruned
-   */
+  /* prune rules */
   jr = 0;
   for (i = j = 1, ir = solv->rules + i; i < solv->nrules; i++, ir++)
     {
       if (jr && !unifyrules_sortcmp(ir, jr, pool))
-       continue;                      /* prune! */
-      jr = solv->rules + j++;         /* keep! */
+       {
+         jr->n2 &= ir->n2;             /* bitwise-and recommends marker */
+         continue;                     /* prune! */
+       }
+      jr = solv->rules + j++;          /* keep! */
       if (ir != jr)
         *jr = *ir;
     }
@@ -185,8 +197,19 @@ solver_unifyrules(Solver *solv)
   POOL_DEBUG(SOLV_DEBUG_STATS, "pruned rules from %d to %d\n", solv->nrules, j);
 
   /* adapt rule buffer */
-  solv->nrules = j;
-  solv->rules = solv_extend_resize(solv->rules, solv->nrules, sizeof(Rule), RULES_BLOCK);
+  solver_shrinkrules(solv, j);
+
+  if (solv->recommendsruleq)
+    {
+      /* rebuild recommendsruleq */
+      queue_empty(solv->recommendsruleq);
+      for (i = 1, ir = solv->rules + i; i < solv->nrules; i++, ir++)
+       if (ir->n2)
+         {
+           ir->n2 = 0;
+           queue_push(solv->recommendsruleq, i);
+         }
+    }
 
   /*
    * debug: log rule statistics
@@ -300,7 +323,7 @@ solver_addrule(Solver *solv, Id p, Id p2, Id d)
    * the work for unifyrules a bit easier */
   if (!solv->pkgrules_end)             /* we add pkg rules */
     {
-      r = solv->rules + solv->nrules - 1;
+      r = solv->rules + solv->lastpkgrule;
       if (d)
        {
          Id *dp;
@@ -335,6 +358,7 @@ solver_addrule(Solver *solv, Id p, Id p2, Id d)
          if (p == -p2)
            return 0;                   /* rule is self-fulfilling */
        }
+      solv->lastpkgrule = solv->nrules;
     }
 
   solv->rules = solv_extend(solv->rules, solv->nrules, 1, sizeof(Rule), RULES_BLOCK);
@@ -359,6 +383,7 @@ solver_shrinkrules(Solver *solv, int nrules)
 {
   solv->nrules = nrules;
   solv->rules = solv_extend_resize(solv->rules, solv->nrules, sizeof(Rule), RULES_BLOCK);
+  solv->lastpkgrule = 0;
 }
 
 /******************************************************************************
@@ -572,13 +597,15 @@ add_complex_deprules(Solver *solv, Id p, Id dep, int type, int dontfix, Queue *w
              if (!dp[j])
                continue;
            }
+         if (type == SOLVER_RULE_PKG_RECOMMENDS && !*dp)
+           continue;
          /* check if the rule contains both p and -p */
          for (j = 0; dp[j] != 0; j++)
            if (dp[j] == p)
              break;
          if (dp[j])
            continue;
-         addpkgrule(solv, -p, 0, dp - pool->whatprovidesdata, SOLVER_RULE_PKG_REQUIRES, dep);
+         addpkgrule(solv, -p, 0, dp - pool->whatprovidesdata, type, dep);
          /* push all non-visited providers on the work queue */
          if (m)
            for (; *dp; dp++)
@@ -858,6 +885,48 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m)
            }
        }
 
+      if (s->recommends && solv->strongrecommends)
+       {
+         int start = solv->nrules;
+         solv->lastpkgrule = 0;
+         reqp = s->repo->idarraydata + s->recommends;
+         while ((req = *reqp++) != 0)            /* go through all recommends */
+           {
+#ifdef ENABLE_COMPLEX_DEPS
+             if (pool_is_complex_dep(pool, req))
+               {
+                 /* we have AND/COND deps, normalize */
+                 add_complex_deprules(solv, n, req, SOLVER_RULE_PKG_RECOMMENDS, dontfix, &workq, m);
+                 continue;
+               }
+#endif
+             dp = pool_whatprovides_ptr(pool, req);
+             if (*dp == SYSTEMSOLVABLE || !*dp)          /* always installed or not installable */
+               continue;
+             for (i = 0; dp[i] != 0; i++)
+               if (n == dp[i])
+                 break;
+             if (dp[i])
+               continue;               /* provided by itself, no need to add rule */
+             addpkgrule(solv, -n, 0, dp - pool->whatprovidesdata, SOLVER_RULE_PKG_RECOMMENDS, req);
+             if (m)
+               for (; *dp; dp++)
+                 if (!MAPTST(m, *dp))
+                   queue_push(&workq, *dp);
+           }
+         if (!solv->ruleinfoq && start < solv->nrules)
+           {
+             if (!solv->recommendsruleq)
+               {
+                 solv->recommendsruleq = solv_calloc(1, sizeof(Queue));
+                 queue_init(solv->recommendsruleq);
+               }
+             for (i = start; i < solv->nrules; i++)
+               queue_push(solv->recommendsruleq, i);
+             solv->lastpkgrule = 0;
+           }
+       }
+
       /* that's all we check for src packages */
       if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
        continue;
index 29325ea..db52199 100644 (file)
@@ -58,6 +58,7 @@ typedef enum {
   SOLVER_RULE_PKG_OBSOLETES,
   SOLVER_RULE_PKG_IMPLICIT_OBSOLETES,
   SOLVER_RULE_PKG_INSTALLED_OBSOLETES,
+  SOLVER_RULE_PKG_RECOMMENDS,
   SOLVER_RULE_UPDATE = 0x200,
   SOLVER_RULE_FEATURE = 0x300,
   SOLVER_RULE_JOB = 0x400,
index 2570e4f..6f6ba1d 100644 (file)
@@ -601,6 +601,9 @@ solvable_matchesdep(Solvable *s, Id keyname, Id dep, int marker)
   int i;
   Pool *pool = s->repo->pool;
   Queue q;
+
+  if (keyname == SOLVABLE_NAME)
+    return pool_match_nevr(pool, s, dep) ? 1 : 0;      /* nevr match hack */
   queue_init(&q);
   solvable_lookup_deparray(s, keyname, &q, marker);
   for (i = 0; i < q.count; i++)
index efe3342..c759746 100644 (file)
@@ -1624,6 +1624,7 @@ solver_free(Solver *solv)
   queuep_free(&solv->suggestscplxq);
   queuep_free(&solv->brokenorphanrules);
   queuep_free(&solv->favorq);
+  queuep_free(&solv->recommendsruleq);
 
   map_free(&solv->recommendsmap);
   map_free(&solv->suggestsmap);
@@ -1708,6 +1709,10 @@ solver_get_flag(Solver *solv, int flag)
     return solv->needupdateprovide;
   case SOLVER_FLAG_URPM_REORDER:
     return solv->urpmreorder;
+  case SOLVER_FLAG_STRONG_RECOMMENDS:
+    return solv->strongrecommends;
+  case SOLVER_FLAG_INSTALL_ALSO_UPDATES:
+    return solv->install_also_updates;
   default:
     break;
   }
@@ -1792,6 +1797,12 @@ solver_set_flag(Solver *solv, int flag, int value)
   case SOLVER_FLAG_URPM_REORDER:
     solv->urpmreorder = value;
     break;
+  case SOLVER_FLAG_STRONG_RECOMMENDS:
+    solv->strongrecommends = value;
+    break;
+  case SOLVER_FLAG_INSTALL_ALSO_UPDATES:
+    solv->install_also_updates = value;
+    break;
   default:
     break;
   }
@@ -1832,24 +1843,26 @@ resolve_jobrules(Solver *solv, int level, int disablerules, Queue *dq)
        continue;
       /* prune to installed if not updating */
       if (dq->count > 1 && solv->installed && !solv->updatemap_all &&
+         !solv->install_also_updates &&
          !(solv->job.elements[solv->ruletojob.elements[i - solv->jobrules]] & SOLVER_ORUPDATE))
        {
-         int j, k;
-         for (j = k = 0; j < dq->count; j++)
+         int j = dq->count, k;
+         if (solv->updatemap.size)
            {
-             Solvable *s = pool->solvables + dq->elements[j];
-             if (s->repo == solv->installed)
-               {
-                 dq->elements[k++] = dq->elements[j];
-                 if (solv->updatemap.size && MAPTST(&solv->updatemap, dq->elements[j] - solv->installed->start))
-                   {
-                     k = 0;    /* package wants to be updated, do not prune */
-                     break;
-                   }
-               }
+             /* do not prune if an installed package wants to be updated */
+             for (j = 0; j < dq->count; j++)
+               if (pool->solvables[dq->elements[j]].repo == solv->installed
+                   && MAPTST(&solv->updatemap, dq->elements[j] - solv->installed->start))
+                 break;
+           }
+         if (j == dq->count)
+           {
+             for (j = k = 0; j < dq->count; j++)
+               if (pool->solvables[dq->elements[j]].repo == solv->installed)
+                 dq->elements[k++] = dq->elements[j];
+             if (k)
+               dq->count = k;
            }
-         if (k)
-           dq->count = k;
        }
       olevel = level;
       level = selectandinstall(solv, level, dq, disablerules, i, SOLVER_REASON_RESOLVE_JOB);
@@ -3627,6 +3640,7 @@ solver_solve(Solver *solv, Queue *job)
   if (solv->nrules != initialnrules)
     solver_shrinkrules(solv, initialnrules);
   solv->nrules = initialnrules;
+  solv->lastpkgrule = 0;
   solv->pkgrules_end = 0;
 
   if (installed)
@@ -3840,6 +3854,7 @@ solver_solve(Solver *solv, Queue *job)
   if (solv->nrules > initialnrules)
     solver_unifyrules(solv);                   /* remove duplicate pkg rules */
   solv->pkgrules_end = solv->nrules;           /* mark end of pkg rules */
+  solv->lastpkgrule = 0;
 
   if (solv->nrules > initialnrules)
     addedmap2deduceq(solv, &addedmap);         /* so that we can recreate the addedmap */
@@ -4215,7 +4230,7 @@ solver_solve(Solver *solv, Queue *job)
   POOL_DEBUG(SOLV_DEBUG_STATS, "overall rule memory used: %d K\n", solv->nrules * (int)sizeof(Rule) / 1024);
 
   /* create weak map */
-  if (solv->weakruleq.count)
+  if (solv->weakruleq.count || solv->recommendsruleq)
     {
       map_grow(&solv->weakrulemap, solv->nrules);
       for (i = 0; i < solv->weakruleq.count; i++)
@@ -4223,6 +4238,14 @@ solver_solve(Solver *solv, Queue *job)
          p = solv->weakruleq.elements[i];
          MAPSET(&solv->weakrulemap, p);
        }
+      if (solv->recommendsruleq)
+       {
+         for (i = 0; i < solv->recommendsruleq->count; i++)
+           {
+             p = solv->recommendsruleq->elements[i];
+             MAPSET(&solv->weakrulemap, p);
+           }
+       }
     }
 
   /* enable cleandepsmap creation if we have updatepkgs */
index be240c9..15fdf3f 100644 (file)
@@ -44,6 +44,7 @@ struct _Solver {
    */
   Rule *rules;                         /* all rules */
   Id nrules;                           /* [Offset] index of the last rule */
+  Id lastpkgrule;                      /* last package rule we added */
 
   Queue ruleassertions;                        /* Queue of all assertion rules */
 
@@ -163,6 +164,8 @@ struct _Solver {
   int focus_best;                      /* true: resolve job dependencies first */
   int do_yum_obsoletes;                        /* true: add special yumobs rules */
   int urpmreorder;                     /* true: do special urpm package reordering */
+  int strongrecommends;                        /* true: create weak rules for recommends */
+  int install_also_updates;            /* true: do not prune install job rules to installed packages */
 
   Map dupmap;                          /* dup these packages*/
   int dupmap_all;                      /* dup all packages */
@@ -201,6 +204,8 @@ struct _Solver {
 
   int installedpos;                    /* for resolve_installed */
   int do_extra_reordering;             /* reorder for future installed packages */
+
+  Queue *recommendsruleq;              /* pkg rules comming from recommends */
 #endif /* LIBSOLV_INTERNAL */
 };
 
@@ -308,6 +313,8 @@ typedef struct _Solver Solver;
 #define SOLVER_FLAG_NEED_UPDATEPROVIDE         22
 #define SOLVER_FLAG_URPM_REORDER               23
 #define SOLVER_FLAG_FOCUS_BEST                 24
+#define SOLVER_FLAG_STRONG_RECOMMENDS          25
+#define SOLVER_FLAG_INSTALL_ALSO_UPDATES       26
 
 #define GET_USERINSTALLED_NAMES                        (1 << 0)        /* package names instead of ids */
 #define GET_USERINSTALLED_INVERTED             (1 << 1)        /* autoinstalled */
index 6106f3f..9537a33 100644 (file)
@@ -211,7 +211,7 @@ repo_fix_supplements(Repo *repo, Offset provides, Offset supplements, Offset fre
 Offset
 repo_fix_conflicts(Repo *repo, Offset conflicts)
 {
-  char buf[1024], *p, *dep;
+  char buf[1024], *dep;
   Pool *pool = repo->pool;
   Id id;
   int i;
@@ -224,11 +224,10 @@ repo_fix_conflicts(Repo *repo, Offset conflicts)
       if (ISRELDEP(id))
        continue;
       dep = (char *)pool_id2str(pool, id);
-      if (!strncmp(dep, "otherproviders(", 15) && strlen(dep) < sizeof(buf) - 2)
+      if (!strncmp(dep, "otherproviders(", 15) && dep[15] && strlen(dep) < sizeof(buf) - 2)
        {
          strcpy(buf, dep + 15);
-         if ((p = strchr(buf, ')')) != 0)
-           *p = 0;
+         buf[strlen(buf) - 1] = 0;
          id = pool_str2id(pool, buf, 1);
          id = pool_rel2id(pool, NAMESPACE_OTHERPROVIDERS, id, REL_NAMESPACE, 1);
          repo->idarraydata[i] = id;