From 51a3a2ac14ea0b18ccbe47ce771d5c962aa0800a Mon Sep 17 00:00:00 2001 From: DongHun Kwak Date: Fri, 30 Nov 2018 12:40:15 +0900 Subject: [PATCH] Imported Upstream version 0.6.25 Change-Id: I4c41182d0968927b2dc78980b41c0b7c2e931a4a Signed-off-by: DongHun Kwak --- CMakeLists.txt | 11 +++++- NEWS | 8 ++++ VERSION.cmake | 2 +- bindings/solv.i | 51 ++++++++++++++++++++++++ doc/libsolv-bindings.3 | 56 ++++++++++++++++++++++---- doc/libsolv-bindings.txt | 44 ++++++++++++++++++--- examples/solv/repoinfo.c | 14 +++++++ examples/solv/solv.c | 21 +++------- ext/repo_rpmdb.c | 21 ++++++---- ext/testcase.c | 2 + package/libsolv.changes | 15 +++++++ src/dirpool.c | 7 ++-- src/policy.c | 22 +---------- src/pool.c | 10 ++++- src/pool.h | 2 +- src/problems.c | 7 ++++ src/repo_solv.c | 19 ++++++--- src/repo_write.c | 4 ++ src/repodata.c | 10 ++--- src/rules.c | 101 +++++++++++++++++++++++++++++++++++++++-------- src/rules.h | 1 + src/solvable.c | 3 ++ src/solver.c | 53 ++++++++++++++++++------- src/solver.h | 7 ++++ src/suse.c | 7 ++-- 25 files changed, 388 insertions(+), 110 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 82034e0..12b9b32 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 --- 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 diff --git a/VERSION.cmake b/VERSION.cmake index ffa5bd0..3d93005 100644 --- a/VERSION.cmake +++ b/VERSION.cmake @@ -49,5 +49,5 @@ SET(LIBSOLVEXT_SOVERSION "0") SET(LIBSOLV_MAJOR "0") SET(LIBSOLV_MINOR "6") -SET(LIBSOLV_PATCH "24") +SET(LIBSOLV_PATCH "25") diff --git a/bindings/solv.i b/bindings/solv.i index 64f51d0..61dc640 100644 --- a/bindings/solv.i +++ b/bindings/solv.i @@ -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 { diff --git a/doc/libsolv-bindings.3 b/doc/libsolv-bindings.3 index 6b57ebf..477a6e4 100644 --- a/doc/libsolv-bindings.3 +++ b/doc/libsolv-bindings.3 @@ -2,12 +2,12 @@ .\" Title: Libsolv-Bindings .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets v1.78.1 -.\" 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:\(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: diff --git a/doc/libsolv-bindings.txt b/doc/libsolv-bindings.txt index 79f4c2c..e44d53a 100644 --- a/doc/libsolv-bindings.txt +++ b/doc/libsolv-bindings.txt @@ -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 ``:'' 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*:: diff --git a/examples/solv/repoinfo.c b/examples/solv/repoinfo.c index e08d160..91f7c28 100644 --- a/examples/solv/repoinfo.c +++ b/examples/solv/repoinfo.c @@ -10,6 +10,10 @@ #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); diff --git a/examples/solv/solv.c b/examples/solv/solv.c index 814f7e1..3301126 100644 --- a/examples/solv/solv.c +++ b/examples/solv/solv.c @@ -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) diff --git a/ext/repo_rpmdb.c b/ext/repo_rpmdb.c index 034198c..fe05bec 100644 --- a/ext/repo_rpmdb.c +++ b/ext/repo_rpmdb.c @@ -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) diff --git a/ext/testcase.c b/ext/testcase.c index a56c4db..ccfcb61 100644 --- a/ext/testcase.c +++ b/ext/testcase.c @@ -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 } }; diff --git a/package/libsolv.changes b/package/libsolv.changes index fd351c3..d32694e 100644 --- a/package/libsolv.changes +++ b/package/libsolv.changes @@ -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 diff --git a/src/dirpool.c b/src/dirpool.c index 5f08361..afb26ea 100644 --- a/src/dirpool.c +++ b/src/dirpool.c @@ -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 diff --git a/src/policy.c b/src/policy.c index 7ed52d9..8b4c2e4 100644 --- a/src/policy.c +++ b/src/policy.c @@ -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 */ diff --git a/src/pool.c b/src/pool.c index 72e22f8..1adf70e 100644 --- a/src/pool.c +++ b/src/pool.c @@ -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) { diff --git a/src/pool.h b/src/pool.h index 86d49aa..1ae3b11 100644 --- a/src/pool.h +++ b/src/pool.h @@ -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 */ diff --git a/src/problems.c b/src/problems.c index 063d47b..a9bbdce 100644 --- a/src/problems.c +++ b/src/problems.c @@ -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); diff --git a/src/repo_solv.c b/src/repo_solv.c index 86c851c..2460e30 100644 --- a/src/repo_solv.c +++ b/src/repo_solv.c @@ -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"); } } diff --git a/src/repo_write.c b/src/repo_write.c index 210636c..396cd42 100644 --- a/src/repo_write.c +++ b/src/repo_write.c @@ -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; diff --git a/src/repodata.c b/src/repodata.c index b611afc..027c24c 100644 --- a/src/repodata.c +++ b/src/repodata.c @@ -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) diff --git a/src/rules.c b/src/rules.c index 67f10d8..33f5350 100644 --- a/src/rules.c +++ b/src/rules.c @@ -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; diff --git a/src/rules.h b/src/rules.h index 29325ea..db52199 100644 --- a/src/rules.h +++ b/src/rules.h @@ -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, diff --git a/src/solvable.c b/src/solvable.c index 2570e4f..6f6ba1d 100644 --- a/src/solvable.c +++ b/src/solvable.c @@ -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++) diff --git a/src/solver.c b/src/solver.c index efe3342..c759746 100644 --- a/src/solver.c +++ b/src/solver.c @@ -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 */ diff --git a/src/solver.h b/src/solver.h index be240c9..15fdf3f 100644 --- a/src/solver.h +++ b/src/solver.h @@ -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 */ diff --git a/src/suse.c b/src/suse.c index 6106f3f..9537a33 100644 --- a/src/suse.c +++ b/src/suse.c @@ -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; -- 2.7.4