Imported Upstream version 0.7.6 upstream/0.7.6
authorDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 10 Sep 2019 06:38:59 +0000 (15:38 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 10 Sep 2019 06:38:59 +0000 (15:38 +0900)
16 files changed:
CMakeLists.txt
NEWS
TODO_1.0
VERSION.cmake
bindings/solv.i
doc/gen/libsolv-bindings.3
doc/libsolv-bindings.txt
ext/CMakeLists.txt
ext/pool_parserpmrichdep.c
package/libsolv.changes
package/libsolv.spec.in
src/CMakeLists.txt
src/pool.c
src/repodata.c
src/solver.c
tools/repo2solv.c

index e331318..b39fd99 100644 (file)
@@ -126,6 +126,8 @@ SET (ENABLE_HAIKU ON)
 SET (have_system ${have_system}x)
 ENDIF (HAIKU)
 
+SET (CMAKE_MACOSX_RPATH ON)
+
 IF (${have_system} STREQUAL x)
     MESSAGE (STATUS "Building for no system")
 ENDIF (${have_system} STREQUAL x)
diff --git a/NEWS b/NEWS
index ede4a0e..d0bf75f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,16 @@
 This file contains the major changes between
 libsolv versions:
 
+Version 0.7.6
+- selected bug fixes:
+  * fix repository priority handling for multiversion packages
+  * better support of inverval deps in pool_match_dep()
+  * support src rpms that have non-empty provides
+- new features
+  * bindings: add get_disabled_list() and set_disabled_list()
+  * bindings: add whatcontainsdep()
+  * bindings: make the selection filters return the self object
+
 Version 0.7.5
 - selected bug fixes:
   * fix favorq leaking between solver runs if the solver is reused
index 3e243d3..9166930 100644 (file)
--- a/TODO_1.0
+++ b/TODO_1.0
@@ -9,6 +9,10 @@
 
 - write more manpages
 
+- forcebest pruning is not optimal: it should keep multiple packages
+  with the same version instead of reducing to just one package for
+  each name
+
 IDEAS:
 
 drop SEARCH_FILES and add SEARCH_BASENAME instead?
index 5c228a3..0811e42 100644 (file)
@@ -49,5 +49,5 @@ SET(LIBSOLVEXT_SOVERSION "1")
 
 SET(LIBSOLV_MAJOR "0")
 SET(LIBSOLV_MINOR "7")
-SET(LIBSOLV_PATCH "5")
+SET(LIBSOLV_PATCH "6")
 
index 107192f..48d3f1f 100644 (file)
@@ -629,10 +629,8 @@ SWIG_AsValDepId(void *obj, int *val) {
 %typemap(out) disown_helper {
 #if defined(SWIGRUBY)
   SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_Pool, SWIG_POINTER_DISOWN |  0 );
-#elif defined(SWIGPYTHON) && SWIG_VERSION < 0x040000
-  SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Pool, SWIG_POINTER_DISOWN |  0 );
 #elif defined(SWIGPYTHON)
-  SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Pool, SWIG_POINTER_DISOWN |  0 );
+  SWIG_ConvertPtr($self, &argp1,SWIGTYPE_p_Pool, SWIG_POINTER_DISOWN |  0 );
 #elif defined(SWIGPERL)
   SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_Pool, SWIG_POINTER_DISOWN |  0 );
 #elif defined(SWIGTCL)
@@ -650,6 +648,33 @@ SWIG_AsValDepId(void *obj, int *val) {
 
 
 /**
+ ** return $self
+ **/
+
+%define returnself(func)
+#if defined(SWIGPYTHON)
+%typemap(out) void func {
+  $result = $self;
+  Py_INCREF($result);
+}
+#elif defined(SWIGPERL)
+%typemap(out) void func {
+  $result = sv_2mortal(SvREFCNT_inc(ST(0)));argvi++;
+}
+#elif defined(SWIGRUBY)
+%typemap(ret) void func {
+  return self;
+}
+#elif defined(SWIGTCL)
+%typemap(out) void func {
+  Tcl_IncrRefCount(objv[1]);
+  Tcl_SetObjResult(interp, objv[1]);
+}
+#endif
+%enddef
+
+
+/**
  ** misc stuff
  **/
 
@@ -1362,12 +1387,14 @@ typedef struct {
     s->flags = $self->flags;
     return s;
   }
+returnself(filter)
   void filter(Selection *lsel) {
     if ($self->pool != lsel->pool)
       queue_empty(&$self->q);
     else
       selection_filter($self->pool, &$self->q, &lsel->q);
   }
+returnself(add)
   void add(Selection *lsel) {
     if ($self->pool == lsel->pool)
       {
@@ -1375,29 +1402,35 @@ typedef struct {
         $self->flags |= lsel->flags;
       }
   }
+returnself(add_raw)
   void add_raw(Id how, Id what) {
     queue_push2(&$self->q, how, what);
   }
+returnself(subtract)
   void subtract(Selection *lsel) {
     if ($self->pool == lsel->pool)
       selection_subtract($self->pool, &$self->q, &lsel->q);
   }
 
+returnself(select)
   void select(const char *name, int flags) {
     if ((flags & SELECTION_MODEBITS) == 0)
       flags |= SELECTION_FILTER | SELECTION_WITH_ALL;
     $self->flags = selection_make($self->pool, &$self->q, name, flags);
   }
+returnself(matchdeps)
   void matchdeps(const char *name, int flags, Id keyname, Id marker = -1) {
     if ((flags & SELECTION_MODEBITS) == 0)
       flags |= SELECTION_FILTER | SELECTION_WITH_ALL;
     $self->flags = selection_make_matchdeps($self->pool, &$self->q, name, flags, keyname, marker);
   }
+returnself(matchdepid)
   void matchdepid(DepId dep, int flags, Id keyname, Id marker = -1) {
     if ((flags & SELECTION_MODEBITS) == 0)
       flags |= SELECTION_FILTER | SELECTION_WITH_ALL;
     $self->flags = selection_make_matchdepid($self->pool, &$self->q, dep, flags, keyname, marker);
   }
+returnself(matchsolvable)
   void matchsolvable(XSolvable *solvable, int flags, Id keyname, Id marker = -1) {
     if ((flags & SELECTION_MODEBITS) == 0)
       flags |= SELECTION_FILTER | SELECTION_WITH_ALL;
@@ -1976,6 +2009,14 @@ typedef struct {
     pool_flush_namespaceproviders($self, ns, evr);
   }
 
+  %typemap(out) Queue whatcontainsdep Queue2Array(XSolvable *, 1, new_XSolvable(arg1, id));
+  %newobject whatcontainsdep;
+  Queue whatcontainsdep(Id keyname, DepId dep, Id marker = -1) {
+    Queue q;
+    queue_init(&q);
+    pool_whatcontainsdep($self, keyname, dep, &q, marker);
+    return q;
+  }
 
   %typemap(out) Queue whatmatchesdep Queue2Array(XSolvable *, 1, new_XSolvable(arg1, id));
   %newobject whatmatchesdep;
@@ -2057,9 +2098,18 @@ typedef struct {
     queue_init(&q);
     int i;
     for (i = 2; i < $self->nsolvables; i++) {
-      if (!$self->solvables[i].repo)
-        continue;
-      if (!$self->considered || MAPTST($self->considered, i))
+      if ($self->solvables[i].repo && (!$self->considered || MAPTST($self->considered, i)))
+        queue_push(&q, i);
+    }
+    return q;
+  }
+
+  Queue get_disabled_list() {
+    Queue q;
+    queue_init(&q);
+    int i;
+    for (i = 2; i < $self->nsolvables; i++) {
+      if ($self->solvables[i].repo && ($self->considered && !MAPTST($self->considered, i)))
         queue_push(&q, i);
     }
     return q;
@@ -2081,6 +2131,28 @@ typedef struct {
     }
   }
 
+  void set_disabled_list(Queue q) {
+    int i;
+    Id p;
+    if (!q.count) {
+      if ($self->considered) {
+        map_free($self->considered);
+        $self->considered = solv_free($self->considered);
+      }
+      return;
+    }
+    if (!$self->considered) {
+      $self->considered = solv_calloc(1, sizeof(Map));
+      map_init($self->considered, $self->nsolvables);
+    }
+    map_setall($self->considered);
+    for (i = 0; i < q.count; i++) {
+      p = q.elements[i];
+      if (p > 0 && p < $self->nsolvables)
+        MAPCLR($self->considered, p);
+    }
+  }
+
   void setpooljobs(Queue solvejobs) {
     queue_free(&$self->pooljobs);
     queue_init_clone(&$self->pooljobs, &solvejobs);
index 88ab97d..ab9403f 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: Libsolv-Bindings
 .\"    Author: [see the "Author" section]
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 03/16/2019
+.\"      Date: 07/01/2019
 .\"    Manual: LIBSOLV
 .\"    Source: libsolv
 .\"  Language: English
 .\"
-.TH "LIBSOLV\-BINDINGS" "3" "03/16/2019" "libsolv" "LIBSOLV"
+.TH "LIBSOLV\-BINDINGS" "3" "07/01/2019" "libsolv" "LIBSOLV"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -1129,6 +1129,62 @@ Set the callback function called when repository metadata needs to be loaded on
 .\}
 .sp
 Decrement the reference count of the appdata object\&. This can be used to break circular references (e\&.g\&. if the pool\(cqs appdata value points to some meta data structure that contains a pool handle)\&. If used incorrectly, this method can lead to application crashes, so beware\&. (This method is a no\-op for ruby and tcl\&.)
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+\fBId *get_considered_list()\fR
+my \fI@ids\fR \fB=\fR \fI$pool\fR\fB\->get_considered_list()\fR;
+\fIids\fR \fB=\fR \fIpool\fR\fB\&.get_considered_list()\fR
+\fIids\fR \fB=\fR \fIpool\fR\fB\&.get_considered_list()\fR
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+\fBvoid set_considered_list(Id *\fR\fIids\fR\fB)\fR
+\fI$pool\fR\fB\->set_considered_list(\e\fR\fI@ids\fR\fB)\fR;
+\fIpool\fR\fB\&.set_considered_list(\fR\fIids\fR\fB)\fR
+\fIpool\fR\fB\&.set_considered_list(\fR\fIids\fR\fB)\fR
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+Get/set the list of solvables that are eligible for installation\&. Note that you need to recreate the whatprovides hash after changing the list\&.
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+\fBId *get_disabled_list()\fR
+my \fI@ids\fR \fB=\fR \fI$pool\fR\fB\->get_disabled_list()\fR;
+\fIids\fR \fB=\fR \fIpool\fR\fB\&.get_disabled_list()\fR
+\fIids\fR \fB=\fR \fIpool\fR\fB\&.get_disabled_list()\fR
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+\fBvoid set_disabled_list(Id *\fR\fIids\fR\fB)\fR
+\fI$pool\fR\fB\->set_disabled_list(\e\fR\fI@ids\fR\fB)\fR;
+\fIpool\fR\fB\&.set_disabled_list(\fR\fIids\fR\fB)\fR
+\fIpool\fR\fB\&.set_disabled_list(\fR\fIids\fR\fB)\fR
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+Get/set the list of solvables that are not eligible for installation\&. This is basically the inverse of the \(lqconsidered\(rq methods above, i\&.e\&. calling \(lqset_disabled_list()\(rq with an empty list will make all solvables eligible for installation\&. Note you need to recreate the whatprovides hash after changing the list\&.
 .SS "DATA RETRIEVAL METHODS"
 .sp
 In the following functions, the \fIkeyname\fR argument describes what to retrieve\&. For the standard cases you can use the available Id constants\&. For example,
index 7b4f505..ac112cf 100644 (file)
@@ -495,6 +495,20 @@ a Dep object or a simple Id as argument.
 
 Filter list of solvables by repo priority, architecture and version.
 
+       Solvable *whatcontainsdep(Id keyname, DepId dep, Id marker = -1)
+       my @solvables = $pool->whatcontainsdep($keyname, $dep)
+       solvables = pool.whatcontainsdep(keyname, dep)
+       solvables = pool.whatcontainsdep(keyname, dep)
+
+Return all solvables for which keyname contains the dependency.
+
+       Solvable *whatmatchesdep(Id keyname, DepId dep, Id marker = -1)
+       my @solvables = $pool->whatmatchesdep($keyname, $sdep)
+       solvables = pool.whatmatchesdep(keyname, dep)
+       solvables = pool.whatmatchesdep(keyname, dep)
+
+Return all solvables that have dependencies in keyname that match the dependency.
+
        Solvable *whatmatchessolvable(Id keyname, Solvable solvable, Id marker = -1)
        my @solvables = $pool->whatmatchessolvable($keyname, $solvable)
        solvables = pool.whatmatchessolvable(keyname, solvable)
@@ -645,6 +659,35 @@ circular references (e.g. if the pool's appdata value points to some meta data
 structure that contains a pool handle). If used incorrectly, this method can
 lead to application crashes, so beware. (This method is a no-op for ruby and tcl.)
 
+       Id *get_considered_list()
+       my @ids = $pool->get_considered_list();
+       ids = pool.get_considered_list()
+       ids = pool.get_considered_list()
+
+       void set_considered_list(Id *ids)
+       $pool->set_considered_list(\@ids);
+       pool.set_considered_list(ids)
+       pool.set_considered_list(ids)
+
+Get/set the list of solvables that are eligible for installation. Note that
+you need to recreate the whatprovides hash after changing the list.
+
+       Id *get_disabled_list()
+       my @ids = $pool->get_disabled_list();
+       ids = pool.get_disabled_list()
+       ids = pool.get_disabled_list()
+
+       void set_disabled_list(Id *ids)
+       $pool->set_disabled_list(\@ids);
+       pool.set_disabled_list(ids)
+       pool.set_disabled_list(ids)
+
+Get/set the list of solvables that are not eligible for installation. This is
+basically the inverse of the ``considered'' methods above, i.e. calling
+``set_disabled_list()'' with an empty list will make all solvables eligible for
+installation. Note you need to recreate the whatprovides hash after changing the
+list.
+
 === DATA RETRIEVAL METHODS ===
 
 In the following functions, the _keyname_ argument describes what to retrieve.
@@ -807,7 +850,7 @@ Back reference to the pool this dependency belongs to.
 
 The id of this dependency.
 
-== Methods ==
+=== METHODS ===
 
        Dep Rel(int flags, DepId evrid, bool create = 1)
        my $reldep = $dep->Rel($flags, $evrdep);
index 7c25535..f01c023 100644 (file)
@@ -163,7 +163,6 @@ ENDIF ()
 
 SET_TARGET_PROPERTIES(libsolvext PROPERTIES OUTPUT_NAME "solvext")
 SET_TARGET_PROPERTIES(libsolvext PROPERTIES SOVERSION ${LIBSOLVEXT_SOVERSION})
-SET_TARGET_PROPERTIES(libsolvext PROPERTIES INSTALL_NAME_DIR ${CMAKE_INSTALL_LIBDIR})
 
 INSTALL (FILES ${libsolvext_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/solv")
 INSTALL (TARGETS libsolvext LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
index 93d77f8..bf6cbef 100644 (file)
@@ -27,13 +27,23 @@ static struct RichOpComp {
   { NULL, 0, 0},
 };
 
+static inline const char *
+skipnonwhite(const char *p)
+{
+  int bl = 0;
+  while (*p && !(*p == ' ' || *p == ',' || (*p == ')' && bl-- <= 0)))
+    if (*p++ == '(')
+      bl++;
+  return p;
+}
+
 static Id
 parseRichDep(Pool *pool, const char **depp, Id chainfl)
 {
   const char *p = *depp;
   const char *n;
   Id id, evr;
-  int fl, bl;
+  int fl;
   struct RichOpComp *op;
 
   if (!chainfl && *p++ != '(')
@@ -51,10 +61,7 @@ parseRichDep(Pool *pool, const char **depp, Id chainfl)
   else
     {
       n = p;
-      bl = 0;
-      while (*p && !(*p == ' ' || *p == ',' || (*p == ')' && bl-- <= 0)))
-       if (*p++ == '(')
-         bl++;
+      p = skipnonwhite(p);
       if (n == p)
        return 0;
       id = pool_strn2id(pool, n, p - n, 1);
@@ -79,10 +86,7 @@ parseRichDep(Pool *pool, const char **depp, Id chainfl)
              while (*p == ' ')
                p++;
              n = p;
-             bl = 0;
-             while (*p && !(*p == ' ' || *p == ',' || (*p == ')' && bl-- <= 0)))
-               if (*p++ == '(')
-                 bl++;
+             p = skipnonwhite(p);
              if (p - n > 2 && n[0] == '0' && n[1] == ':')
                n += 2;         /* strip zero epoch */
              if (n == p)
index 6393734..aee75cd 100644 (file)
@@ -1,4 +1,25 @@
 -------------------------------------------------------------------
+Wed Aug 28 14:49:19 CEST 2019 - mls@suse.de
+
+- Fix repository priority handling for multiversion packages
+- Make code compatible with swig 4.0, remove obj0 instances
+- repo2solv: support zchunk compressed data
+- bump version to 0.7.6
+
+-------------------------------------------------------------------
+Wed Jul 10 07:48:10 UTC 2019 - Martin Liška <mliska@suse.cz>
+
+- Add -ffat-lto-objects to $optflags as the package provides
+  static libraries
+- Remove NO_BRP_STRIP_DEBUG=true as brp-15-strip-debug will
+  not strip debug info for archives
+
+-------------------------------------------------------------------
+Thu Jun 13 16:15:39 CEST 2019 - mls@suse.de
+
+- make cleandeps jobs on patterns work [bnc#1137977]
+
+-------------------------------------------------------------------
 Wed Jun 12 13:22:40 CEST 2019 - mls@suse.de
 
 - fix favorq leaking between solver runs if the solver is reused
index 40d266a..b8985d5 100644 (file)
@@ -207,6 +207,7 @@ Perl bindings for libsolv.
 %setup -q
 
 %build
+%global _lto_cflags %{_lto_cflags} -ffat-lto-objects
 export CFLAGS="%{optflags}"
 export CXXFLAGS="$CFLAGS"
 
@@ -257,10 +258,6 @@ ln -s repo2solv %{buildroot}/%{_bindir}/repo2solv.sh
 %py3_compile %{buildroot}/%{python3_sitearch}
 %endif
 %endif
-%if %{with static}
-# we want to leave the .a file untouched
-export NO_BRP_STRIP_DEBUG=true
-%endif
 
 %check
 make ARGS=--output-on-failure test
index f91c9c0..6abb3ad 100644 (file)
@@ -55,7 +55,6 @@ ENDIF (DISABLE_SHARED)
 
 SET_TARGET_PROPERTIES(libsolv PROPERTIES OUTPUT_NAME "solv")
 SET_TARGET_PROPERTIES(libsolv PROPERTIES SOVERSION ${LIBSOLV_SOVERSION})
-SET_TARGET_PROPERTIES(libsolv PROPERTIES INSTALL_NAME_DIR ${CMAKE_INSTALL_LIBDIR})
 
 INSTALL (FILES ${libsolv_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/solv")
 INSTALL (TARGETS libsolv LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
index a554453..4b63727 100644 (file)
@@ -814,6 +814,23 @@ pool_intersect_evrs(Pool *pool, int pflags, Id pevr, int flags, Id evr)
   return pool_match_flags_evr(pool, pflags, pevr, flags, evr);
 }
 
+
+static int
+is_interval_dep(Pool *pool, Id d1, Id d2)
+{
+  Reldep *rd1, *rd2;
+  if (!ISRELDEP(d1) || !ISRELDEP(d2))
+    return 0;
+  rd1 = GETRELDEP(pool, d1);
+  rd2 = GETRELDEP(pool, d2);
+  if (rd1->name != rd2->name || rd1->flags >= 8 || rd2->flags >= 8)
+    return 0;
+  if (((rd1->flags ^ rd2->flags) & (REL_LT|REL_GT)) != (REL_LT|REL_GT))
+    return 0;
+  return 1;
+}
+
+
 /* match two dependencies (d1 = provider) */
 
 int
@@ -830,6 +847,8 @@ pool_match_dep(Pool *pool, Id d1, Id d2)
       rd1 = GETRELDEP(pool, d1);
       if (rd1->flags == REL_AND || rd1->flags == REL_OR || rd1->flags == REL_WITH || rd1->flags == REL_WITHOUT || rd1->flags == REL_COND || rd1->flags == REL_UNLESS)
        {
+         if (rd1->flags == REL_WITH && is_interval_dep(pool, rd1->name, rd1->evr))
+           return pool_match_dep(pool, rd1->name, d2) && pool_match_dep(pool, rd1->evr, d2);
          if (pool_match_dep(pool, rd1->name, d2))
            return 1;
          if ((rd1->flags == REL_COND || rd1->flags == REL_UNLESS) && ISRELDEP(rd1->evr))
@@ -849,6 +868,8 @@ pool_match_dep(Pool *pool, Id d1, Id d2)
       rd2 = GETRELDEP(pool, d2);
       if (rd2->flags == REL_AND || rd2->flags == REL_OR || rd2->flags == REL_WITH || rd2->flags == REL_WITHOUT || rd2->flags == REL_COND || rd2->flags == REL_UNLESS)
        {
+         if (rd2->flags == REL_WITH && is_interval_dep(pool, rd2->name, rd2->evr))
+           return pool_match_dep(pool, d1, rd2->name) && pool_match_dep(pool, d1, rd2->evr);
          if (pool_match_dep(pool, d1, rd2->name))
            return 1;
          if ((rd2->flags == REL_COND || rd2->flags == REL_UNLESS) && ISRELDEP(rd2->evr))
@@ -1355,9 +1376,9 @@ pool_addrelproviders(Pool *pool, Id d)
                  continue;
                }
            }
-         if (!s->provides)
+         if (!s->provides || s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
            {
-             /* no provides - check nevr */
+             /* no provides or src rpm - check nevr */
              if (pool_match_nevr_rel(pool, s, MAKERELDEP(d)))
                queue_push(&plist, p);
              continue;
index 0c7a51f..3cae0fe 100644 (file)
@@ -211,11 +211,13 @@ repodata_schema2id(Repodata *data, Id *schema, int create)
   cid = schematahash[h];
   if (cid)
     {
-      if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
+      if ((data->schemata[cid] + len <= data->schemadatalen) &&
+                         !memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
         return cid;
       /* cache conflict, do a slow search */
       for (cid = 1; cid < data->nschemata; cid++)
-        if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
+        if ((data->schemata[cid] + len <= data->schemadatalen) &&
+                               !memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
           return cid;
     }
   /* a new one */
index e7a9dc0..5453b39 100644 (file)
@@ -1720,12 +1720,27 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq)
            {
              if (specialupdaters && (d = specialupdaters[i - installed->start]) != 0)
                {
+                 int j;
                  /* special multiversion handling, make sure best version is chosen */
                  if (rr->p == i && solv->decisionmap[i] >= 0)
                    queue_push(dq, i);
                  while ((p = pool->whatprovidesdata[d++]) != 0)
                    if (solv->decisionmap[p] >= 0)
                      queue_push(dq, p);
+                 for (j = 0; j < dq->count; j++)
+                   {
+                     Id p2 = dq->elements[j];
+                     if (pool->solvables[p2].repo != installed)
+                       continue;
+                     d = specialupdaters[i - installed->start];
+                     while ((p = pool->whatprovidesdata[d++]) != 0)
+                       {
+                         if (solv->decisionmap[p] >= 0 || pool->solvables[p].repo == installed)
+                           continue;
+                         if (solvable_identical(pool->solvables + p, pool->solvables + p2))
+                           queue_push(dq, p);  /* identical to installed, put it on the list so we have a repo prio */
+                       }
+                   }
                  if (dq->count && solv->update_targets && solv->update_targets->elements[i - installed->start])
                    prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[i - installed->start], dq);
                  if (dq->count)
@@ -3858,6 +3873,10 @@ solver_solve(Solver *solv, Queue *job)
                  name_s = s;
                }
              solver_addjobrule(solv, -p, 0, 0, i, weak);
+#ifdef ENABLE_LINKED_PKGS
+             if (solv->instbuddy && installed && s->repo == installed && solv->instbuddy[p - installed->start] > 1)
+               solver_addjobrule(solv, -solv->instbuddy[p - installed->start], 0, 0, i, weak);
+#endif
            }
          /* special case for "erase a specific solvable": we also
           * erase all other solvables with that name, so that they
@@ -3925,7 +3944,14 @@ solver_solve(Solver *solv, Queue *job)
                }
            }
          FOR_JOB_SELECT(p, pp, select, what)
-           solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, 0, i, weak);
+           {
+             s = pool->solvables + p;
+             solver_addjobrule(solv, installed && s->repo == installed ? p : -p, 0, 0, i, weak);
+#ifdef ENABLE_LINKED_PKGS
+             if (solv->instbuddy && installed && s->repo == installed && solv->instbuddy[p - installed->start] > 1)
+               solver_addjobrule(solv, solv->instbuddy[p - installed->start], 0, 0, i, weak);
+#endif
+           }
          if (solv->nrules != oldnrules)
            haslockjob = 1;
          break;
index 776b94f..03491a6 100644 (file)
@@ -504,13 +504,42 @@ read_susetags_repo(Repo *repo, const char *dir)
 
 #ifdef ENABLE_RPMMD
 
+# ifdef ENABLE_ZCHUNK_COMPRESSION
+
+static int
+repomd_exists(const char *dir, const char *filename)
+{
+  char *path;
+  struct stat stb;
+  int r;
+  
+  if (!filename)
+    return 0;
+  path = solv_dupjoin(dir, "/", filename);
+  r = stat(path, &stb) == 0;
+  solv_free(path);
+  return r;
+}
+
+# endif
+
 static const char *
-repomd_find(Repo *repo, const char *what)
+repomd_find(Repo *repo, const char *dir, const char *what, int findzchunk)
 {
   Pool *pool = repo->pool;
   Dataiterator di;
   const char *filename;
 
+# ifdef ENABLE_ZCHUNK_COMPRESSION
+  if (findzchunk)
+    {
+      char *what_zck = solv_dupjoin(what, "_zck", 0);
+      filename = repomd_find(repo, dir, what_zck, 0);
+      solv_free(what_zck);
+      if (filename && repomd_exists(dir, filename))
+       return filename;
+    }
+# endif
   filename = 0;
   dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_REPOMD_TYPE, what, SEARCH_STRING);
   dataiterator_prepend_keyname(&di, REPOSITORY_REPOMD);
@@ -555,7 +584,7 @@ repomd_extend(Repo *repo, const char *dir, const char *what, const char *languag
   FILE *fp;
   char *tmp;
 
-  filename = repomd_find(repo, what);
+  filename = repomd_find(repo, dir, what, 1);
   if (!filename)
     return;
   fp = repomd_open(dir, filename, &tmp, missingok);
@@ -581,8 +610,20 @@ repomd_extend_languages(Repo *repo, const char *dir, int missingok)
   dataiterator_prepend_keyname(&di, REPOSITORY_REPOMD);
   while (dataiterator_step(&di))
     {
+      char *str = solv_strdup(di.kv.str);
+      size_t l = strlen(str);
+      if (l > 4 && !strcmp(str + l - 4, "_zck"))
+       str[l - 4] = 0;
+      for (i = 0; i < nsusedatas; i++)
+        if (!strcmp(susedatas[i], str))
+         break;
+      if (i < nsusedatas)
+       {
+         solv_free(str);
+         continue;     /* already have that entry */
+       }
       susedatas = solv_extend(susedatas, nsusedatas, 1, sizeof(char *), 15);
-      susedatas[nsusedatas++] = solv_strdup(di.kv.str);
+      susedatas[nsusedatas++] = str;
     }
   dataiterator_free(&di);
   for (i = 0; i < nsusedatas; i++)
@@ -628,7 +669,7 @@ read_rpmmd_repo(Repo *repo, const char *dir)
     }
   fclose(fp);
   tmp = solv_free(tmp);
-  filename = repomd_find(repo, "suseinfo");
+  filename = repomd_find(repo, dir, "suseinfo", 0);
   if (filename && (fp = repomd_open(dir, filename, &tmp, 0)) != 0)
     {
       if (repo_add_repomdxml(repo, fp, REPO_REUSE_REPODATA))
@@ -641,7 +682,7 @@ read_rpmmd_repo(Repo *repo, const char *dir)
     }
   
   /* first all primary packages */
-  filename = repomd_find(repo, "primary");
+  filename = repomd_find(repo, dir, "primary", 1);
   if (filename)
     {
       add_rpmmd_file(repo, dir, filename, 0);
@@ -654,16 +695,16 @@ read_rpmmd_repo(Repo *repo, const char *dir)
     }
 
   /* some legacy stuff */
-  filename = repomd_find(repo, "products");
+  filename = repomd_find(repo, dir, "products", 0);
   if (!filename)
-    filename = repomd_find(repo, "product");
+    filename = repomd_find(repo, dir, "product", 0);
   if (filename)
     add_rpmmd_file(repo, dir, filename, 1);
-  filename = repomd_find(repo, "patterns");
+  filename = repomd_find(repo, dir, "patterns", 0);
     add_rpmmd_file(repo, dir, filename, 1);
   
   /* updateinfo */
-  filename = repomd_find(repo, "updateinfo");
+  filename = repomd_find(repo, dir, "updateinfo", 1);
   if (filename && (fp = repomd_open(dir, filename, &tmp, 0)) != 0)
     {
       if (repo_add_updateinfoxml(repo, fp, 0))
@@ -676,9 +717,9 @@ read_rpmmd_repo(Repo *repo, const char *dir)
     }
 
   /* deltainfo */
-  filename = repomd_find(repo, "deltainfo");
+  filename = repomd_find(repo, dir, "deltainfo", 1);
   if (!filename)
-    filename = repomd_find(repo, "prestodelta");
+    filename = repomd_find(repo, dir, "prestodelta", 1);
   if (filename && (fp = repomd_open(dir, filename, &tmp, 1)) != 0)
     {
       if (repo_add_deltainfoxml(repo, fp, 0))
@@ -692,7 +733,7 @@ read_rpmmd_repo(Repo *repo, const char *dir)
 
 #ifdef ENABLE_APPDATA
   /* appdata */
-  filename = add_appdata ? repomd_find(repo, "appdata") : 0;
+  filename = add_appdata ? repomd_find(repo, dir, "appdata", 1) : 0;
   if (filename && (fp = repomd_open(dir, filename, &tmp, 1)) != 0)
     {
       if (repo_add_appdata(repo, fp, 0))