diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | NEWS | 10 | ||||
-rw-r--r-- | TODO_1.0 | 4 | ||||
-rw-r--r-- | VERSION.cmake | 2 | ||||
-rw-r--r-- | bindings/solv.i | 84 | ||||
-rw-r--r-- | doc/gen/libsolv-bindings.3 | 60 | ||||
-rw-r--r-- | doc/libsolv-bindings.txt | 45 | ||||
-rw-r--r-- | ext/CMakeLists.txt | 1 | ||||
-rw-r--r-- | ext/pool_parserpmrichdep.c | 22 | ||||
-rw-r--r-- | package/libsolv.changes | 21 | ||||
-rw-r--r-- | package/libsolv.spec.in | 5 | ||||
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/pool.c | 25 | ||||
-rw-r--r-- | src/repodata.c | 6 | ||||
-rw-r--r-- | src/solver.c | 28 | ||||
-rw-r--r-- | tools/repo2solv.c | 65 |
16 files changed, 339 insertions, 42 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index e331318..b39fd99 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) @@ -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 @@ -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? diff --git a/VERSION.cmake b/VERSION.cmake index 5c228a3..0811e42 100644 --- a/VERSION.cmake +++ b/VERSION.cmake @@ -49,5 +49,5 @@ SET(LIBSOLVEXT_SOVERSION "1") SET(LIBSOLV_MAJOR "0") SET(LIBSOLV_MINOR "7") -SET(LIBSOLV_PATCH "5") +SET(LIBSOLV_PATCH "6") diff --git a/bindings/solv.i b/bindings/solv.i index 107192f..48d3f1f 100644 --- a/bindings/solv.i +++ b/bindings/solv.i @@ -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); diff --git a/doc/gen/libsolv-bindings.3 b/doc/gen/libsolv-bindings.3 index 88ab97d..ab9403f 100644 --- a/doc/gen/libsolv-bindings.3 +++ b/doc/gen/libsolv-bindings.3 @@ -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, diff --git a/doc/libsolv-bindings.txt b/doc/libsolv-bindings.txt index 7b4f505..ac112cf 100644 --- a/doc/libsolv-bindings.txt +++ b/doc/libsolv-bindings.txt @@ -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); diff --git a/ext/CMakeLists.txt b/ext/CMakeLists.txt index 7c25535..f01c023 100644 --- a/ext/CMakeLists.txt +++ b/ext/CMakeLists.txt @@ -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}) diff --git a/ext/pool_parserpmrichdep.c b/ext/pool_parserpmrichdep.c index 93d77f8..bf6cbef 100644 --- a/ext/pool_parserpmrichdep.c +++ b/ext/pool_parserpmrichdep.c @@ -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) diff --git a/package/libsolv.changes b/package/libsolv.changes index 6393734..aee75cd 100644 --- a/package/libsolv.changes +++ b/package/libsolv.changes @@ -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 diff --git a/package/libsolv.spec.in b/package/libsolv.spec.in index 40d266a..b8985d5 100644 --- a/package/libsolv.spec.in +++ b/package/libsolv.spec.in @@ -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 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f91c9c0..6abb3ad 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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}) @@ -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; diff --git a/src/repodata.c b/src/repodata.c index 0c7a51f..3cae0fe 100644 --- a/src/repodata.c +++ b/src/repodata.c @@ -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 */ diff --git a/src/solver.c b/src/solver.c index e7a9dc0..5453b39 100644 --- a/src/solver.c +++ b/src/solver.c @@ -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; diff --git a/tools/repo2solv.c b/tools/repo2solv.c index 776b94f..03491a6 100644 --- a/tools/repo2solv.c +++ b/tools/repo2solv.c @@ -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)) |