diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 18 | ||||
-rw-r--r-- | src/chksum.c | 4 | ||||
-rw-r--r-- | src/cleandeps.c | 2 | ||||
-rw-r--r-- | src/conda.c | 242 | ||||
-rw-r--r-- | src/conda.h | 2 | ||||
-rw-r--r-- | src/knownid.h | 15 | ||||
-rw-r--r-- | src/libsolv.ver | 2 | ||||
-rw-r--r-- | src/policy.c | 30 | ||||
-rw-r--r-- | src/pool.c | 18 | ||||
-rw-r--r-- | src/qsort_r.c | 2 | ||||
-rw-r--r-- | src/repo.c | 13 | ||||
-rw-r--r-- | src/repo_solv.c | 2 | ||||
-rw-r--r-- | src/repodata.c | 32 | ||||
-rw-r--r-- | src/repopage.c | 19 | ||||
-rw-r--r-- | src/rules.c | 166 | ||||
-rw-r--r-- | src/rules.h | 2 | ||||
-rw-r--r-- | src/selection.c | 21 | ||||
-rw-r--r-- | src/solvable.c | 74 | ||||
-rw-r--r-- | src/solver.c | 78 | ||||
-rw-r--r-- | src/solver.h | 1 | ||||
-rw-r--r-- | src/util.c | 22 | ||||
-rw-r--r-- | src/util.h | 1 |
22 files changed, 636 insertions, 130 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index be487a7..f91c9c0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,10 +31,18 @@ SET (libsolv_HEADERS IF (ENABLE_CONDA) SET (libsolv_SRCS ${libsolv_SRCS} conda.c) + SET (libsolv_HEADERS ${libsolv_HEADERS} conda.h) ENDIF (ENABLE_CONDA) +IF (NOT MSVC) + SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") +ENDIF (NOT MSVC) + +IF (WIN32) + INCLUDE (${PROJECT_SOURCE_DIR}/win32/CMakeLists.txt) + LIST (APPEND libsolv_SRCS ${WIN32_COMPAT_SOURCES}) +ENDIF (WIN32) -SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") IF (HAVE_LINKER_VERSION_SCRIPT) SET (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINK_FLAGS} -Wl,--version-script=${CMAKE_SOURCE_DIR}/src/libsolv.ver") ENDIF (HAVE_LINKER_VERSION_SCRIPT) @@ -47,14 +55,14 @@ 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 ${LIB_INSTALL_DIR}) +SET_TARGET_PROPERTIES(libsolv PROPERTIES INSTALL_NAME_DIR ${CMAKE_INSTALL_LIBDIR}) -INSTALL (FILES ${libsolv_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}/solv") -INSTALL (TARGETS libsolv LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR} RUNTIME DESTINATION bin) +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}) IF (ENABLE_STATIC AND NOT DISABLE_SHARED) ADD_LIBRARY (libsolv_static STATIC ${libsolv_SRCS}) SET_TARGET_PROPERTIES(libsolv_static PROPERTIES OUTPUT_NAME "solv") SET_TARGET_PROPERTIES(libsolv_static PROPERTIES SOVERSION ${LIBSOLV_SOVERSION}) -INSTALL (TARGETS libsolv_static LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR}) +INSTALL (TARGETS libsolv_static LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) ENDIF (ENABLE_STATIC AND NOT DISABLE_SHARED) diff --git a/src/chksum.c b/src/chksum.c index df46145..1f8ab47 100644 --- a/src/chksum.c +++ b/src/chksum.c @@ -19,6 +19,10 @@ #include "sha1.h" #include "sha2.h" +#ifdef _WIN32 + #include "strfncs.h" +#endif + struct s_Chksum { Id type; int done; diff --git a/src/cleandeps.c b/src/cleandeps.c index 8ef6fd3..aa83c10 100644 --- a/src/cleandeps.c +++ b/src/cleandeps.c @@ -836,7 +836,7 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded) if (MAPTST(&solv->multiversion, p)) break; if (p) - continue; + continue; /* found a multiversion package that will not obsolate anything */ } om.size = 0; diff --git a/src/conda.c b/src/conda.c index 5b134dd..7f2538a 100644 --- a/src/conda.c +++ b/src/conda.c @@ -24,6 +24,10 @@ #include "util.h" #include "conda.h" +#ifdef _WIN32 +#include "strfncs.h" +#endif + static const char * endseg(const char *seg, const char *end) { @@ -226,7 +230,7 @@ pool_evrcmp_conda(const Pool *pool, const char *evr1, const char *evr2, int mode } static int -regexmatch(const char *evr, const char *version, size_t versionlen) +regexmatch(const char *evr, const char *version, size_t versionlen, int icase) { regex_t reg; char *buf = solv_malloc(versionlen + 1); @@ -234,15 +238,19 @@ regexmatch(const char *evr, const char *version, size_t versionlen) memcpy(buf, version, versionlen); buf[versionlen] = 0; - if (regcomp(®, buf, REG_EXTENDED | REG_NOSUB)) - return 0; + if (regcomp(®, buf, REG_EXTENDED | REG_NOSUB | (icase ? REG_ICASE : 0))) + { + solv_free(buf); + return 0; + } r = regexec(®, evr, 0, NULL, 0); regfree(®); + solv_free(buf); return r == 0; } static int -globmatch(const char *evr, const char *version, size_t versionlen) +globmatch(const char *evr, const char *version, size_t versionlen, int icase) { regex_t reg; char *buf = solv_malloc(2 * versionlen + 3); @@ -259,10 +267,14 @@ globmatch(const char *evr, const char *version, size_t versionlen) } buf[j++] = '$'; buf[j] = 0; - if (regcomp(®, buf, REG_EXTENDED | REG_NOSUB)) - return 0; + if (regcomp(®, buf, REG_EXTENDED | REG_NOSUB | (icase ? REG_ICASE : 0))) + { + solv_free(buf); + return 0; + } r = regexec(®, evr, 0, NULL, 0); regfree(®); + solv_free(buf); return r == 0; } @@ -279,7 +291,7 @@ solvable_conda_matchversion_single(Solvable *s, const char *version, size_t vers return 1; /* matches every version */ evr = pool_id2str(s->repo->pool, s->evr); if (versionlen >= 2 && version[0] == '^' && version[versionlen - 1] == '$') - return regexmatch(evr, version, versionlen); + return regexmatch(evr, version, versionlen, 0); if (version[0] == '=' || version[0] == '<' || version[0] == '>' || version[0] == '!' || version[0] == '~') { int flags = 0; @@ -361,7 +373,7 @@ solvable_conda_matchversion_single(Solvable *s, const char *version, size_t vers if (version[i] != '*') break; if (i < versionlen) - return globmatch(evr, version, versionlen); + return globmatch(evr, version, versionlen, 1); } if (versionlen > 1 && version[versionlen - 1] == '*') @@ -430,6 +442,26 @@ solvable_conda_matchversion_rec(Solvable *s, const char **versionp, const char * } } +static int +solvable_conda_matchbuild(Solvable *s, const char *build, const char *buildend) +{ + const char *bp; + const char *flavor = solvable_lookup_str(s, SOLVABLE_BUILDFLAVOR); + + if (!flavor) + flavor = ""; + if (build == buildend) + return *flavor ? 0 : 1; + if (build + 1 == buildend && *build == '*') + return 1; + if (*build == '^' && buildend[-1] == '$') + return regexmatch(flavor, build, buildend - build, 0); + for (bp = build; bp < buildend; bp++) + if (*bp == '*') + return globmatch(flavor, build, buildend - build, 0); + return strncmp(flavor, build, buildend - build) == 0 && flavor[buildend - build] == 0 ? 1 : 0; +} + /* return true if solvable s matches the version */ /* see conda/models/match_spec.py */ int @@ -449,6 +481,200 @@ solvable_conda_matchversion(Solvable *s, const char *version) r = solvable_conda_matchversion_rec(s, &version, versionend); if (r != 1 || version != versionend) return 0; + if (build && !solvable_conda_matchbuild(s, build, build + strlen(build))) + return 0; return r; } +static Id +pool_addrelproviders_conda_slow(Pool *pool, const char *namestr, Id evr, Queue *plist, int mode) +{ + size_t namestrlen = strlen(namestr); + const char *evrstr = evr == 0 || evr == 1 ? 0 : pool_id2str(pool, evr); + Id p; + + FOR_POOL_SOLVABLES(p) + { + Solvable *s = pool->solvables + p; + if (!pool_installable(pool, s)) + continue; + if (mode == 1 && !globmatch(pool_id2str(pool, s->name), namestr, namestrlen, 1)) + continue; + if (mode == 2 && !regexmatch(pool_id2str(pool, s->name), namestr, namestrlen, 1)) + continue; + if (!evrstr || solvable_conda_matchversion(s, evrstr)) + queue_push(plist, p); + } + return 0; +} + +/* called from pool_addrelproviders, plist is an empty queue + * it can either return an offset into the whatprovides array + * or fill the plist queue and return zero */ +Id +pool_addrelproviders_conda(Pool *pool, Id name, Id evr, Queue *plist) +{ + const char *namestr = pool_id2str(pool, name), *np; + size_t l, nuc = 0; + Id wp, p, *pp; + + /* is this a regex? */ + if (*namestr && *namestr == '^') + { + l = strlen(namestr); + if (namestr[l - 1] == '$') + return pool_addrelproviders_conda_slow(pool, namestr, evr, plist, 2); + } + /* is this '*'? */ + if (*namestr && *namestr == '*' && namestr[1] == 0) + return pool_addrelproviders_conda_slow(pool, namestr, evr, plist, 0); + /* does the string contain '*' or uppercase? */ + for (np = namestr; *np; np++) + { + if (*np == '*') + return pool_addrelproviders_conda_slow(pool, namestr, evr, plist, 1); + else if (*np >= 'A' && *np <= 'Z') + nuc++; + } + if (nuc) + { + char *nbuf = solv_strdup(namestr), *nbufp; + for (nbufp = nbuf; *nbufp; nbufp++) + *nbufp = *nbufp >= 'A' && *nbufp <= 'Z' ? *nbufp + ('a' - 'A') : *nbufp; + name = pool_str2id(pool, nbuf, 0); + wp = name ? pool_whatprovides(pool, name) : 0; + solv_free(nbuf); + } + else + wp = pool_whatprovides(pool, name); + if (wp && evr && evr != 1) + { + const char *evrstr = pool_id2str(pool, evr); + pp = pool->whatprovidesdata + wp; + while ((p = *pp++) != 0) + { + if (solvable_conda_matchversion(pool->solvables + p, evrstr)) + queue_push(plist, p); + else + wp = 0; + } + } + return wp; +} + +/* create a CONDA_REL relation from a matchspec */ +Id +pool_conda_matchspec(Pool *pool, const char *name) +{ + const char *p2; + char *name2; + char *p, *pp; + char *build, *buildend, *version, *versionend; + Id nameid, evrid; + int haveglob = 0; + + /* ignore channel and namespace for now */ + if ((p2 = strrchr(name, ':'))) + name = p2 + 1; + name2 = solv_strdup(name); + /* find end of name */ + for (p = name2; *p && *p != ' ' && *p != '=' && *p != '<' && *p != '>' && *p != '!' && *p != '~'; p++) + { + if (*p >= 'A' && *p <= 'Z') + *(char *)p += 'a' - 'A'; /* lower case the name */ + else if (*p == '*') + haveglob = 1; + } + if (p == name2) + { + solv_free(name2); + return 0; /* error: empty package name */ + } + nameid = pool_strn2id(pool, name2, p - name2, 1); + while (*p == ' ') + p++; + if (!*p) + { + if (*name2 != '^' && !haveglob) + { + solv_free(name2); + return nameid; /* return a simple dependency if no glob/regex */ + } + evrid = pool_str2id(pool, "*", 1); + solv_free(name2); + return pool_rel2id(pool, nameid, evrid, REL_CONDA, 1); + } + /* have version */ + version = p; + versionend = p + strlen(p); + while (versionend > version && versionend[-1] == ' ') + versionend--; + build = buildend = 0; + /* split of build */ + p = versionend; + for (;;) + { + while (p > version && p[-1] != ' ' && p[-1] != '-' && p[-1] != '=' && p[-1] != ',' && p[-1] != '|' && p[-1] != '<' && p[-1] != '>' && p[-1] != '~') + p--; + if (p <= version + 1 || (p[-1] != ' ' && p[-1] != '=')) + break; /* no build */ + /* check char before delimiter */ + if (p[-2] == '=' || p[-2] == '!' || p[-2] == '|' || p[-2] == ',' || p[-2] == '<' || p[-2] == '>' || p[-2] == '~') + { + /* illegal combination */ + if (p[-1] == ' ') + { + p--; + continue; /* special case space: it may be in the build */ + } + break; /* no build */ + } + if (p < versionend) + { + build = p; + buildend = versionend; + versionend = p - 1; + } + break; + } + /* do weird version translation */ + if (versionend > version && version[0] == '=') + { + if (versionend - version >= 2 && version[1] == '=') + { + if (!build) + version += 2; + } + else if (build) + version += 1; + else + { + for (p = version + 1; p < versionend; p++) + if (*p == '=' || *p == ',' || *p == '|') + break; + if (p == versionend) + { + memmove(version, version + 1, versionend - version - 1); + versionend[-1] = '*'; + } + } + } +#if 0 + printf("version: >%.*s<\n", (int)(versionend - version), version); + if (build) printf("build: >%.*s<\n", (int)(buildend - build), build); +#endif + /* strip spaces from version */ + for (p = pp = version; pp < versionend; pp++) + if (*pp != ' ') + *p++ = *pp; + if (build) + { + *p++ = ' '; + memcpy(p, build, buildend - build); + p += buildend - build; + } + evrid = pool_strn2id(pool, version, p - version, 1); + solv_free(name2); + return pool_rel2id(pool, nameid, evrid, REL_CONDA, 1); +} + diff --git a/src/conda.h b/src/conda.h index 7233f17..3bcfa2d 100644 --- a/src/conda.h +++ b/src/conda.h @@ -15,6 +15,8 @@ int pool_evrcmp_conda(const Pool *pool, const char *evr1, const char *evr2, int mode); int solvable_conda_matchversion(Solvable *s, const char *version); +Id pool_addrelproviders_conda(Pool *pool, Id name, Id evr, Queue *plist); +Id pool_conda_matchspec(Pool *pool, const char *name); #endif /* LIBSOLV_CONDA_H */ diff --git a/src/knownid.h b/src/knownid.h index b5b41d6..9d7f157 100644 --- a/src/knownid.h +++ b/src/knownid.h @@ -251,12 +251,15 @@ KNOWNID(SIGNATURE_EXPIRES, "signature:expires"), KNOWNID(SIGNATURE_DATA, "signature:data"), /* 'content' of patch, usually list of modules */ -KNOWNID(UPDATE_MODULE, "update:module"), /* "name stream version context arch" */ -KNOWNID(UPDATE_MODULE_NAME, "update:module:name"), /* name */ -KNOWNID(UPDATE_MODULE_STREAM, "update:module:stream"), /* stream */ -KNOWNID(UPDATE_MODULE_VERSION, "update:module:version"), /* version */ -KNOWNID(UPDATE_MODULE_CONTEXT, "update:module:context"), /* context */ -KNOWNID(UPDATE_MODULE_ARCH, "update:module:arch"), /* architecture */ +KNOWNID(UPDATE_MODULE, "update:module"), /* "name stream version context arch" */ +KNOWNID(UPDATE_MODULE_NAME, "update:module:name"), /* name */ +KNOWNID(UPDATE_MODULE_STREAM, "update:module:stream"), /* stream */ +KNOWNID(UPDATE_MODULE_VERSION, "update:module:version"), /* version */ +KNOWNID(UPDATE_MODULE_CONTEXT, "update:module:context"), /* context */ +KNOWNID(UPDATE_MODULE_ARCH, "update:module:arch"), /* architecture */ + +KNOWNID(SOLVABLE_BUILDVERSION, "solvable:buildversion"), /* conda */ +KNOWNID(SOLVABLE_BUILDFLAVOR, "solvable:buildflavor"), /* conda */ KNOWNID(ID_NUM_INTERNAL, 0) diff --git a/src/libsolv.ver b/src/libsolv.ver index f0e86ff..eafe3e6 100644 --- a/src/libsolv.ver +++ b/src/libsolv.ver @@ -448,4 +448,6 @@ SOLV_1.2 { SOLV_1.3 { repodata_set_kv; + solv_setcloexec; + pool_conda_matchspec; } SOLV_1.2; diff --git a/src/policy.c b/src/policy.c index 5f61115..823a008 100644 --- a/src/policy.c +++ b/src/policy.c @@ -798,6 +798,8 @@ move_installed_to_front(Pool *pool, Queue *plist) Solvable *s; Id p, pp; + if (!pool->installed) + return; for (i = j = 0; i < plist->count; i++) { s = pool->solvables + plist->elements[i]; @@ -831,6 +833,26 @@ move_installed_to_front(Pool *pool, Queue *plist) } } +static int +pool_buildversioncmp(Pool *pool, Solvable *s1, Solvable *s2) +{ + const char *bv1 = solvable_lookup_str(s1, SOLVABLE_BUILDVERSION); + const char *bv2 = solvable_lookup_str(s2, SOLVABLE_BUILDVERSION); + if (!bv1 && !bv2) + return 0; + return pool_evrcmp_str(pool, bv1 ? bv1 : "" , bv2 ? bv2 : "", EVRCMP_COMPARE); +} + +static int +pool_buildflavorcmp(Pool *pool, Solvable *s1, Solvable *s2) +{ + const char *f1 = solvable_lookup_str(s1, SOLVABLE_BUILDFLAVOR); + const char *f2 = solvable_lookup_str(s2, SOLVABLE_BUILDFLAVOR); + if (!f1 && !f2) + return 0; + return pool_evrcmp_str(pool, f1 ? f1 : "" , f2 ? f2 : "", EVRCMP_COMPARE); +} + /* * prune_to_best_version * @@ -878,6 +900,10 @@ prune_to_best_version(Pool *pool, Queue *plist) if (r == 0 && has_package_link(pool, s)) r = pool_link_evrcmp(pool, best, s); #endif + if (r == 0 && pool->disttype == DISTTYPE_CONDA) + r = pool_buildversioncmp(pool, best, s); + if (r == 0 && pool->disttype == DISTTYPE_CONDA) + r = pool_buildflavorcmp(pool, best, s); if (r < 0) best = s; } @@ -893,8 +919,6 @@ prune_to_best_version(Pool *pool, Queue *plist) else prune_obsoleted(pool, plist); } - if (plist->count > 1 && pool->installed) - move_installed_to_front(pool, plist); } @@ -1321,6 +1345,7 @@ policy_filter_unwanted(Solver *solv, Queue *plist, int mode) #endif dislike_old_versions(pool, plist); sort_by_common_dep(pool, plist); + move_installed_to_front(pool, plist); if (solv->urpmreorder) urpm_reorder(solv, plist); prefer_suggested(solv, plist); @@ -1342,6 +1367,7 @@ pool_best_solvables(Pool *pool, Queue *plist, int flags) { dislike_old_versions(pool, plist); sort_by_common_dep(pool, plist); + move_installed_to_front(pool, plist); } } @@ -1289,19 +1289,7 @@ pool_addrelproviders(Pool *pool, Id d) break; #ifdef ENABLE_CONDA case REL_CONDA: - wp = pool_whatprovides(pool, name); - if (evr) - { - const char *evrstr = pool_id2str(pool, evr); - pp = pool->whatprovidesdata + wp; - while ((p = *pp++) != 0) - { - if (solvable_conda_matchversion(pool->solvables + p, evrstr)) - queue_push(&plist, p); - else - wp = 0; - } - } + wp = pool_addrelproviders_conda(pool, name, evr, &plist); break; #endif default: @@ -1324,7 +1312,7 @@ pool_addrelproviders(Pool *pool, Id d) POOL_DEBUG(SOLV_DEBUG_STATS, "addrelproviders: what provides %s?\n", pool_dep2str(pool, name)); #endif pp = pool_whatprovides_ptr(pool, name); - if (!ISRELDEP(name) && name < pool->whatprovidesauxoff) + if (!ISRELDEP(name) && (Offset)name < pool->whatprovidesauxoff) ppaux = pool->whatprovidesaux[name] ? pool->whatprovidesauxdata + pool->whatprovidesaux[name] : 0; while (ISRELDEP(name)) { @@ -1938,7 +1926,7 @@ pool_set_whatprovides(Pool *pool, Id id, Id providers) else { pool->whatprovides[id] = providers; - if (id < pool->whatprovidesauxoff) + if ((Offset)id < pool->whatprovidesauxoff) pool->whatprovidesaux[id] = 0; /* sorry */ d = 1; } diff --git a/src/qsort_r.c b/src/qsort_r.c index d49049a..ffc09dc 100644 --- a/src/qsort_r.c +++ b/src/qsort_r.c @@ -37,7 +37,9 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)qsort.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ +#ifndef _WIN32 #include <sys/cdefs.h> +#endif /* $FreeBSD: src/lib/libc/stdlib/qsort.c,v 1.13.2.1.8.1 2010/12/21 17:10:29 kensmith Exp $ */ @@ -391,7 +391,7 @@ repo_addid_dep_hash(Repo *repo, Offset olddeps, Id id, Id marker, int size) if (repo->lastidhash_idarraysize != repo->idarraysize || (Hashval)size * 2 > repo->lastidhash_mask || repo->lastmarker != marker) { repo->lastmarkerpos = 0; - if (size * 2 > (Hashval)repo->lastidhash_mask) + if ((Hashval)size * 2 > repo->lastidhash_mask) { repo->lastidhash_mask = mkmask(size < REPO_ADDID_DEP_HASHMIN ? REPO_ADDID_DEP_HASHMIN : size); repo->lastidhash = solv_realloc2(repo->lastidhash, repo->lastidhash_mask + 1, sizeof(Id)); @@ -844,7 +844,7 @@ repo_search_md(Repo *repo, Id p, Id keyname, struct matchdata *md) case RPM_RPMDBID: if (repo->rpmdbid) { - kv.num = repo->rpmdbid[p - repo->start]; + kv.num = (unsigned int)repo->rpmdbid[p - repo->start]; kv.num2 = 0; repo_matchvalue(md, s, 0, repo_solvablekeys + (RPM_RPMDBID - SOLVABLE_NAME), &kv); } @@ -1097,7 +1097,7 @@ repo_lookup_num(Repo *repo, Id entry, Id keyname, unsigned long long notfound) if (keyname == RPM_RPMDBID) { if (repo->rpmdbid && entry >= repo->start && entry < repo->end) - return repo->rpmdbid[entry - repo->start]; + return (unsigned int)repo->rpmdbid[entry - repo->start]; return notfound; } } @@ -1250,7 +1250,10 @@ Id repo_lookup_type(Repo *repo, Id entry, Id keyname) { Id type; - Repodata *data = repo_lookup_repodata_opt(repo, entry, keyname); + Repodata *data; + if (keyname >= SOLVABLE_NAME && keyname <= RPM_RPMDBID) + return repo_solvablekeys[keyname - SOLVABLE_NAME].type; + data = repo_lookup_repodata_opt(repo, entry, keyname); if (data && (type = repodata_lookup_type(data, entry, keyname)) != 0 && type != REPOKEY_TYPE_DELETED) return type; return 0; @@ -1363,7 +1366,7 @@ repo_set_num(Repo *repo, Id p, Id keyname, unsigned long long num) { if (!repo->rpmdbid) repo->rpmdbid = repo_sidedata_create(repo, sizeof(Id)); - repo->rpmdbid[p - repo->start] = num; + repo->rpmdbid[p - repo->start] = (Id)num; return; } } diff --git a/src/repo_solv.c b/src/repo_solv.c index be33967..761d06e 100644 --- a/src/repo_solv.c +++ b/src/repo_solv.c @@ -1220,7 +1220,7 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key default: if (id == RPM_RPMDBID && s && keys[key].type == REPOKEY_TYPE_NUM) { - dp = data_read_id_max(dp, &id, 0, 0, &data); + dp = data_read_id(dp, &id); if (!repo->rpmdbid) repo->rpmdbid = repo_sidedata_create(repo, sizeof(Id)); repo->rpmdbid[(s - pool->solvables) - repo->start] = id; diff --git a/src/repodata.c b/src/repodata.c index ad5aaea..0c7a51f 100644 --- a/src/repodata.c +++ b/src/repodata.c @@ -34,6 +34,10 @@ #include "repopack.h" #include "repopage.h" +#ifdef _WIN32 + #include "strfncs.h" +#endif + #define REPODATA_BLOCK 255 static unsigned char *data_skip_key(Repodata *data, unsigned char *dp, Repokey *key); @@ -791,14 +795,28 @@ repodata_lookup_idarray(Repodata *data, Id solvid, Id keyname, Queue *q) queue_empty(q); dp = find_key_data(data, solvid, keyname, &key); - if (!dp || key->type != REPOKEY_TYPE_IDARRAY) + if (!dp) return 0; - for (;;) + switch (key->type) { - dp = data_read_ideof(dp, &id, &eof); + case REPOKEY_TYPE_CONSTANTID: + queue_push(q, key->size); + break; + case REPOKEY_TYPE_ID: + dp = data_read_id(dp, &id); queue_push(q, id); - if (eof) - break; + break; + case REPOKEY_TYPE_IDARRAY: + for (;;) + { + dp = data_read_ideof(dp, &id, &eof); + queue_push(q, id); + if (eof) + break; + } + break; + default: + return 0; } return 1; } @@ -1124,7 +1142,7 @@ repodata_search_array(Repodata *data, Id solvid, Id keyname, int flags, Repokey if (!dp || kv->entry != -1) return 0; - while (++kv->entry < kv->num) + while (++kv->entry < (int)kv->num) { if (kv->entry) dp = data_skip_schema(data, dp, schema); @@ -3142,7 +3160,7 @@ compact_attrdata(Repodata *data, int entry, int nentry) break; case REPOKEY_TYPE_DIRSTRARRAY: for (v = attrs[1]; data->attriddata[v] ; v += 2) - if (data->attriddata[v + 1] < attrdatastart) + if ((unsigned int)data->attriddata[v + 1] < attrdatastart) attrdatastart = data->attriddata[v + 1]; /* FALLTHROUGH */ case REPOKEY_TYPE_IDARRAY: diff --git a/src/repopage.c b/src/repopage.c index 85d53eb..9e9694f 100644 --- a/src/repopage.c +++ b/src/repopage.c @@ -30,6 +30,12 @@ #include <fcntl.h> #include <time.h> +#ifdef _WIN32 + #include <windows.h> + #include <fileapi.h> + #include <io.h> +#endif + #include "repo.h" #include "repopage.h" @@ -704,11 +710,22 @@ repopagestore_load_page_range(Repopagestore *store, unsigned int pstart, unsigne #ifdef DEBUG_PAGING fprintf(stderr, "PAGEIN: %d to %d", pnum, i); #endif +#ifndef _WIN32 if (pread(store->pagefd, compressed ? buf : dest, in_len, store->file_offset + p->page_offset) != in_len) { perror("mapping pread"); return 0; } +#else + DWORD read_len; + OVERLAPPED ovlp = {0}; + ovlp.Offset = store->file_offset + p->page_offset; + if (!ReadFile((HANDLE) _get_osfhandle(store->pagefd), compressed ? buf : dest, in_len, &read_len, &ovlp) || read_len != in_len) + { + perror("mapping ReadFile"); + return 0; + } +#endif if (compressed) { unsigned int out_len; @@ -785,7 +802,7 @@ repopagestore_read_or_setup_pages(Repopagestore *store, FILE *fp, unsigned int p if (store->pagefd == -1) can_seek = 0; else - fcntl(store->pagefd, F_SETFD, FD_CLOEXEC); + solv_setcloexec(store->pagefd, 1); #ifdef DEBUG_PAGING fprintf(stderr, "can %sseek\n", can_seek ? "" : "NOT "); diff --git a/src/rules.c b/src/rules.c index b6cd582..3aef6ee 100644 --- a/src/rules.c +++ b/src/rules.c @@ -1328,6 +1328,31 @@ solver_addfeaturerule(Solver *solv, Solvable *s) } } +/* check if multiversion solvable s2 has an obsoletes for installed solvable s */ +static int +is_multiversion_obsoleteed(Pool *pool, Solvable *s, Solvable *s2) +{ + Id *wp, obs, *obsp; + + if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2)) + return 0; + obsp = s2->repo->idarraydata + s2->obsoletes; + if (!pool->obsoleteusesprovides) + { + while ((obs = *obsp++) != 0) + if (pool_match_nevr(pool, s, obs)) + return 1; + } + else + { + while ((obs = *obsp++) != 0) + for (wp = pool_whatprovides_ptr(pool, obs); *wp; wp++) + if (pool->solvables + *wp == s) + return 1; + } + return 0; +} + /*------------------------------------------------------------------- * * add rule for update @@ -1389,9 +1414,8 @@ solver_addupdaterule(Solver *solv, Solvable *s) if (MAPTST(&solv->multiversion, qs.elements[i])) { Solvable *ps = pool->solvables + qs.elements[i]; - /* if keepexplicitobsoletes is set and the name is different, - * we assume that there is an obsoletes. XXX: not 100% correct */ - if (solv->keepexplicitobsoletes && ps->name != s->name) + /* check if there is an explicit obsoletes */ + if (solv->keepexplicitobsoletes && ps->obsoletes && is_multiversion_obsoleteed(pool, s, ps)) { qs.elements[j++] = qs.elements[i]; continue; @@ -2189,7 +2213,7 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q) if (pool->solvables[p].repo == installed) return; if (solv->multiversion.size && MAPTST(&solv->multiversion, p) && !solv->keepexplicitobsoletes) - return; + return; /* will not obsolete anything, so just return */ } omap.size = 0; qstart = q->count; @@ -2273,6 +2297,34 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q) #endif } return; + + case SOLVER_LOCK: + if (!installed) + break; + qstart = q->count; + if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && what == installed->repoid)) + { + FOR_REPO_SOLVABLES(installed, p, s) + { + for (i = qstart; i < q->count; i += 2) + if (q->elements[i] == DISABLE_DUP && q->elements[i + 1] == pool->solvables[p].name) + break; + if (i == q->count) + queue_push2(q, DISABLE_DUP, pool->solvables[p].name); + } + } + FOR_JOB_SELECT(p, pp, select, what) + { + if (pool->solvables[p].repo != installed) + continue; + for (i = qstart; i < q->count; i += 2) + if (q->elements[i] == DISABLE_DUP && q->elements[i + 1] == pool->solvables[p].name) + break; + if (i == q->count) + queue_push2(q, DISABLE_DUP, pool->solvables[p].name); + } + break; + default: return; } @@ -3260,8 +3312,19 @@ prune_to_dup_packages(Solver *solv, Id p, Queue *q) queue_truncate(q, j); } +static void +prune_best_update(Solver *solv, Id p, Queue *q) +{ + if (solv->update_targets && solv->update_targets->elements[p - solv->installed->start]) + prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[p - solv->installed->start], q); + if (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p)) + prune_to_dup_packages(solv, p, q); + /* select best packages, just look at prio and version */ + policy_filter_unwanted(solv, q, POLICY_MODE_RECOMMEND); +} + void -solver_addbestrules(Solver *solv, int havebestinstalljobs) +solver_addbestrules(Solver *solv, int havebestinstalljobs, int haslockjob) { Pool *pool = solv->pool; Id p; @@ -3271,12 +3334,26 @@ solver_addbestrules(Solver *solv, int havebestinstalljobs) Rule *r; Queue infoq; int i, oldcnt; + Map *lockedmap = 0; solv->bestrules = solv->nrules; queue_init(&q); queue_init(&q2); queue_init(&infoq); + if (haslockjob) + { + int i; + lockedmap = solv_calloc(1, sizeof(Map)); + map_init(lockedmap, pool->nsolvables); + for (i = 0, r = solv->rules + solv->jobrules; i < solv->ruletojob.count; i++, r++) + { + if (r->w2 || (solv->job.elements[solv->ruletojob.elements[i]] & SOLVER_JOBMASK) != SOLVER_LOCK) + continue; + p = r->p > 0 ? r->p : -r->p; + MAPSET(lockedmap, p); + } + } if (havebestinstalljobs) { for (i = 0; i < solv->job.count; i += 2) @@ -3284,7 +3361,7 @@ solver_addbestrules(Solver *solv, int havebestinstalljobs) Id how = solv->job.elements[i]; if ((how & (SOLVER_JOBMASK | SOLVER_FORCEBEST)) == (SOLVER_INSTALL | SOLVER_FORCEBEST)) { - int j; + int j, k; Id p2, pp2; for (j = 0; j < solv->ruletojob.count; j++) { @@ -3307,6 +3384,25 @@ solver_addbestrules(Solver *solv, int havebestinstalljobs) policy_filter_unwanted(solv, &q, POLICY_MODE_RECOMMEND); if (q.count == oldcnt) continue; /* nothing filtered */ + if (lockedmap) + { + FOR_RULELITERALS(p2, pp2, r) + { + if (p2 <= 0) + continue; + if (installed && pool->solvables[p2].repo == installed) + { + if (MAPTST(lockedmap, p2)) + queue_pushunique(&q, p2); /* we always want that package */ + } + else if (MAPTST(lockedmap, p2)) + continue; + queue_push(&q2, p2); + } + policy_filter_unwanted(solv, &q2, POLICY_MODE_RECOMMEND); + for (k = 0; k < q2.count; k++) + queue_pushunique(&q, q2.elements[k]); + } if (q2.count) queue_insertn(&q, 0, q2.count, q2.elements); p2 = queue_shift(&q); @@ -3361,14 +3457,38 @@ solver_addbestrules(Solver *solv, int havebestinstalljobs) if (p2 > 0) queue_push(&q, p2); } - if (solv->update_targets && solv->update_targets->elements[p - installed->start]) - prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[p - installed->start], &q); - if (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p)) - prune_to_dup_packages(solv, p, &q); - /* select best packages, just look at prio and version */ - policy_filter_unwanted(solv, &q, POLICY_MODE_RECOMMEND); + if (lockedmap) + { + queue_empty(&q2); + queue_insertn(&q2, 0, q.count, q.elements); + } + prune_best_update(solv, p, &q); if (!q.count) continue; /* orphaned */ + if (lockedmap) + { + int j; + /* always ok to keep installed locked packages */ + if (MAPTST(lockedmap, p)) + queue_pushunique(&q2, p); + for (j = 0; j < q2.count; j++) + { + Id p2 = q2.elements[j]; + if (pool->solvables[p2].repo == installed && MAPTST(lockedmap, p2)) + queue_pushunique(&q, p2); + } + /* filter out locked packages */ + for (i = j = 0; j < q2.count; j++) + { + Id p2 = q2.elements[j]; + if (pool->solvables[p2].repo == installed || !MAPTST(lockedmap, p2)) + q2.elements[i++] = p2; + } + queue_truncate(&q2, i); + prune_best_update(solv, p, &q2); + for (j = 0; j < q2.count; j++) + queue_pushunique(&q, q2.elements[j]); + } if (solv->bestobeypolicy) { /* also filter the best of the feature rule packages and add them */ @@ -3380,13 +3500,20 @@ solver_addbestrules(Solver *solv, int havebestinstalljobs) FOR_RULELITERALS(p2, pp2, r) if (p2 > 0) queue_push(&q2, p2); - if (solv->update_targets && solv->update_targets->elements[p - installed->start]) - prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[p - installed->start], &q2); - if (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p)) - prune_to_dup_packages(solv, p, &q2); - policy_filter_unwanted(solv, &q2, POLICY_MODE_RECOMMEND); + prune_best_update(solv, p, &q2); for (j = 0; j < q2.count; j++) queue_pushunique(&q, q2.elements[j]); + if (lockedmap) + { + queue_empty(&q2); + FOR_RULELITERALS(p2, pp2, r) + if (p2 > 0) + if (pool->solvables[p2].repo == installed || !MAPTST(lockedmap, p2)) + queue_push(&q2, p2); + prune_best_update(solv, p, &q2); + for (j = 0; j < q2.count; j++) + queue_pushunique(&q, q2.elements[j]); + } } } if (solv->allowuninstall || solv->allowuninstall_all || (solv->allowuninstallmap.size && MAPTST(&solv->allowuninstallmap, p - installed->start))) @@ -3427,6 +3554,11 @@ solver_addbestrules(Solver *solv, int havebestinstalljobs) queue_free(&q); queue_free(&q2); queue_free(&infoq); + if (lockedmap) + { + map_free(lockedmap); + solv_free(lockedmap); + } } diff --git a/src/rules.h b/src/rules.h index 1db0551..6b8511f 100644 --- a/src/rules.h +++ b/src/rules.h @@ -129,7 +129,7 @@ extern void solver_addchoicerules(struct s_Solver *solv); extern void solver_disablechoicerules(struct s_Solver *solv, Rule *r); /* best rules */ -extern void solver_addbestrules(struct s_Solver *solv, int havebestinstalljobs); +extern void solver_addbestrules(struct s_Solver *solv, int havebestinstalljobs, int haslockjob); /* yumobs rules */ extern void solver_addyumobsrules(struct s_Solver *solv); diff --git a/src/selection.c b/src/selection.c index a160122..e58d731 100644 --- a/src/selection.c +++ b/src/selection.c @@ -21,7 +21,13 @@ #include "selection.h" #include "solver.h" #include "evr.h" +#ifdef ENABLE_CONDA +#include "conda.h" +#endif +#ifdef _WIN32 +#include "strfncs.h" +#endif static int str2archid(Pool *pool, const char *arch) @@ -1149,6 +1155,19 @@ selection_canon(Pool *pool, Queue *selection, const char *name, int flags) flags |= SELECTION_NAME; flags &= ~SELECTION_PROVIDES; +#ifdef ENABLE_CONDA + if (pool->disttype == DISTTYPE_CONDA) + { + Id *wp, id = pool_conda_matchspec(pool, name); + if (!id) + return 0; + wp = pool_whatprovides_ptr(pool, id); /* check if there is a match */ + if (!wp || !*wp) + return 0; + queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id); + return SELECTION_CANON; + } +#endif if (pool->disttype == DISTTYPE_DEB) { if ((r = strchr(name, '_')) == 0) @@ -1552,7 +1571,7 @@ selection_make_matchdeps_common(Pool *pool, Queue *selection, const char *name, revr = pool_str2id(pool, r, 1); ret |= SELECTION_REL; } - if ((flags & SELECTION_GLOB) != 0 && !strpbrk(rname, "[*?") != 0) + if ((flags & SELECTION_GLOB) != 0 && strpbrk(rname, "[*?") == 0) flags &= ~SELECTION_GLOB; if ((flags & SELECTION_GLOB) == 0 && (flags & SELECTION_NOCASE) == 0 && (flags & SELECTION_MATCH_DEPSTR) == 0) diff --git a/src/solvable.c b/src/solvable.c index 331f290..d3d2d31 100644 --- a/src/solvable.c +++ b/src/solvable.c @@ -32,9 +32,9 @@ pool_solvable2str(Pool *pool, Solvable *s) int nl, el, al; char *p; n = pool_id2str(pool, s->name); - e = pool_id2str(pool, s->evr); + e = s->evr ? pool_id2str(pool, s->evr) : ""; /* XXX: may want to skip the epoch here */ - a = pool_id2str(pool, s->arch); + a = s->arch ? pool_id2str(pool, s->arch) : ""; nl = strlen(n); el = strlen(e); al = strlen(a); @@ -58,6 +58,16 @@ pool_solvable2str(Pool *pool, Solvable *s) p[nl + el] = pool->disttype == DISTTYPE_HAIKU ? '-' : '.'; strcpy(p + nl + el + 1, a); } + if (pool->disttype == DISTTYPE_CONDA && solvable_lookup_type(s, SOLVABLE_BUILDFLAVOR)) + { + Queue flavorq; + int i; + queue_init(&flavorq); + solvable_lookup_idarray(s, SOLVABLE_BUILDFLAVOR, &flavorq); + for (i = 0; i < flavorq.count; i++) + p = pool_tmpappend(pool, p, "-", pool_id2str(pool, flavorq.elements[i])); + queue_free(&flavorq); + } return p; } @@ -110,10 +120,15 @@ solvable_lookup_str_joinarray(Solvable *s, Id keyname, const char *joinstr) if (solvable_lookup_idarray(s, keyname, &q) && q.count) { Pool *pool = s->repo->pool; - int i; - str = pool_tmpjoin(pool, pool_id2str(pool, q.elements[0]), 0, 0); - for (i = 1; i < q.count; i++) - str = pool_tmpappend(pool, str, joinstr, pool_id2str(pool, q.elements[i])); + if (q.count == 1) + str = (char *)pool_id2str(pool, q.elements[0]); + else + { + int i; + str = pool_tmpjoin(pool, pool_id2str(pool, q.elements[0]), 0, 0); + for (i = 1; i < q.count; i++) + str = pool_tmpappend(pool, str, joinstr, pool_id2str(pool, q.elements[i])); + } } queue_free(&q); return str; @@ -126,7 +141,7 @@ solvable_lookup_str(Solvable *s, Id keyname) if (!s->repo) return 0; str = repo_lookup_str(s->repo, s - s->repo->pool->solvables, keyname); - if (!str && (keyname == SOLVABLE_LICENSE || keyname == SOLVABLE_GROUP)) + if (!str && (keyname == SOLVABLE_LICENSE || keyname == SOLVABLE_GROUP || keyname == SOLVABLE_BUILDFLAVOR)) str = solvable_lookup_str_joinarray(s, keyname, ", "); return str; } @@ -238,14 +253,14 @@ solvable_lookup_str_poollang(Solvable *s, Id keyname) const char * solvable_lookup_str_lang(Solvable *s, Id keyname, const char *lang, int usebase) { - if (s->repo) - { - Id id = pool_id2langid(s->repo->pool, keyname, lang, 0); - if (id) - return solvable_lookup_str_base(s, id, keyname, usebase); - if (!usebase) - return 0; - } + Id id; + if (!s->repo) + return 0; + id = pool_id2langid(s->repo->pool, keyname, lang, 0); + if (id) + return solvable_lookup_str_base(s, id, keyname, usebase); + if (!usebase) + return 0; return solvable_lookup_str(s, keyname); } @@ -278,25 +293,27 @@ solvable_lookup_void(Solvable *s, Id keyname) int solvable_lookup_bool(Solvable *s, Id keyname) { + Id type; if (!s->repo) return 0; /* historic nonsense: there are two ways of storing a bool, as num == 1 or void. test both. */ - if (repo_lookup_type(s->repo, s - s->repo->pool->solvables, keyname) == REPOKEY_TYPE_VOID) + type = repo_lookup_type(s->repo, s - s->repo->pool->solvables, keyname); + if (type == REPOKEY_TYPE_VOID) return 1; - return repo_lookup_num(s->repo, s - s->repo->pool->solvables, keyname, 0) == 1; + if (type == REPOKEY_TYPE_NUM || type == REPOKEY_TYPE_CONSTANT) + return repo_lookup_num(s->repo, s - s->repo->pool->solvables, keyname, 0) == 1; + return 0; } const unsigned char * solvable_lookup_bin_checksum(Solvable *s, Id keyname, Id *typep) { - Repo *repo = s->repo; - - if (!repo) + if (!s->repo) { *typep = 0; return 0; } - return repo_lookup_bin_checksum(repo, s - repo->pool->solvables, keyname, typep); + return repo_lookup_bin_checksum(s->repo, s - s->repo->pool->solvables, keyname, typep); } const char * @@ -456,7 +473,7 @@ pool_create_state_maps(Pool *pool, Queue *installed, Map *installedmap, Map *con int solvable_identical(Solvable *s1, Solvable *s2) { - unsigned int bt1, bt2; + unsigned long long bt1, bt2; Id rq1, rq2; Id *reqp; if (s1->name != s2->name) @@ -504,6 +521,19 @@ solvable_identical(Solvable *s1, Solvable *s2) if (rq1 != rq2) return 0; } + if (s1->repo && s1->repo->pool->disttype == DISTTYPE_CONDA) + { + /* check buildflavor and buildversion */ + const char *str1, *str2; + str1 = solvable_lookup_str(s1, SOLVABLE_BUILDFLAVOR); + str2 = solvable_lookup_str(s2, SOLVABLE_BUILDFLAVOR); + if (str1 != str2 && (!str1 || !str2 || strcmp(str1, str2) != 0)) + return 0; + str1 = solvable_lookup_str(s1, SOLVABLE_BUILDVERSION); + str2 = solvable_lookup_str(s2, SOLVABLE_BUILDVERSION); + if (str1 != str2 && (!str1 || !str2 || strcmp(str1, str2) != 0)) + return 0; + } return 1; } diff --git a/src/solver.c b/src/solver.c index b335e6a..e7a9dc0 100644 --- a/src/solver.c +++ b/src/solver.c @@ -1382,7 +1382,6 @@ solver_free(Solver *solv) queuep_free(&solv->recommendscplxq); queuep_free(&solv->suggestscplxq); queuep_free(&solv->brokenorphanrules); - queuep_free(&solv->favorq); queuep_free(&solv->recommendsruleq); map_free(&solv->recommendsmap); @@ -1914,6 +1913,8 @@ resolve_dependencies(Solver *solv, int level, int disablerules, Queue *dq) } if (i == solv->nrules) i = 1; + if (solv->focus_best && solv->do_extra_reordering && i >= solv->featurerules) + continue; r = solv->rules + i; if (r->d < 0) /* ignore disabled rules */ continue; @@ -3281,36 +3282,44 @@ add_complex_jobrules(Solver *solv, Id dep, int flags, int jobidx, int weak) } #endif -/* sort by package id, last entry wins */ -static int -setup_favormap_cmp(const void *ap, const void *bp, void *dp) -{ - const Id *a = ap, *b = bp; - if ((*a - *b) != 0) - return *a - *b; - return (b[1] < 0 ? -b[1] : b[1]) - (a[1] < 0 ? -a[1] : a[1]); -} - static void setup_favormap(Solver *solv) { - Queue *q = solv->favorq; + Queue *job = &solv->job; Pool *pool = solv->pool; - int i; - Id oldp = 0; - if (q->count > 2) - solv_sort(q->elements, q->count / 2, 2 * sizeof(Id), setup_favormap_cmp, solv); + int i, idx; + Id p, pp, how, what, select; + + solv_free(solv->favormap); solv->favormap = solv_calloc(pool->nsolvables, sizeof(Id)); - solv->havedisfavored = 0; - for (i = 0; i < q->count; i += 2) + for (i = 0; i < job->count; i += 2) { - Id p = q->elements[i]; - if (p == oldp) + how = job->elements[i]; + if ((how & SOLVER_JOBMASK) != SOLVER_FAVOR && (how & SOLVER_JOBMASK) != SOLVER_DISFAVOR) continue; - oldp = p; - solv->favormap[p] = q->elements[i + 1]; - if (q->elements[i + 1] < 0) - solv->havedisfavored = 1; + what = job->elements[i + 1]; + select = how & SOLVER_SELECTMASK; + idx = (how & SOLVER_JOBMASK) == SOLVER_FAVOR ? i + 1 : -(i + 1); + if (select == SOLVER_SOLVABLE_REPO) + { + Repo *repo = pool_id2repo(pool, what); + if (repo) + { + Solvable *s; + FOR_REPO_SOLVABLES(repo, p, s) + { + solv->favormap[p] = idx; + if (idx < 0) + solv->havedisfavored = 1; + } + } + } + FOR_JOB_SELECT(p, pp, select, what) + { + solv->favormap[p] = idx; + if (idx < 0) + solv->havedisfavored = 1; + } } } @@ -3336,6 +3345,8 @@ solver_solve(Solver *solv, Queue *job) int now, solve_start; int needduprules = 0; int hasbestinstalljob = 0; + int hasfavorjob = 0; + int haslockjob = 0; solve_start = solv_timems(0); @@ -3343,6 +3354,7 @@ solver_solve(Solver *solv, Queue *job) POOL_DEBUG(SOLV_DEBUG_STATS, "solver started\n"); POOL_DEBUG(SOLV_DEBUG_STATS, "dosplitprovides=%d, noupdateprovide=%d, noinfarchcheck=%d\n", solv->dosplitprovides, solv->noupdateprovide, solv->noinfarchcheck); POOL_DEBUG(SOLV_DEBUG_STATS, "allowuninstall=%d, allowdowngrade=%d, allownamechange=%d, allowarchchange=%d, allowvendorchange=%d\n", solv->allowuninstall, solv->allowdowngrade, solv->allownamechange, solv->allowarchchange, solv->allowvendorchange); + POOL_DEBUG(SOLV_DEBUG_STATS, "dupallowdowngrade=%d, dupallownamechange=%d, dupallowarchchange=%d, dupallowvendorchange=%d\n", solv->dup_allowdowngrade, solv->dup_allownamechange, solv->dup_allowarchchange, solv->dup_allowvendorchange); POOL_DEBUG(SOLV_DEBUG_STATS, "promoteepoch=%d, forbidselfconflicts=%d\n", pool->promoteepoch, pool->forbidselfconflicts); POOL_DEBUG(SOLV_DEBUG_STATS, "obsoleteusesprovides=%d, implicitobsoleteusesprovides=%d, obsoleteusescolors=%d, implicitobsoleteusescolors=%d\n", pool->obsoleteusesprovides, pool->implicitobsoleteusesprovides, pool->obsoleteusescolors, pool->implicitobsoleteusescolors); POOL_DEBUG(SOLV_DEBUG_STATS, "dontinstallrecommended=%d, addalreadyrecommended=%d onlynamespacerecommended=%d\n", solv->dontinstallrecommended, solv->addalreadyrecommended, solv->only_namespace_recommended); @@ -3914,6 +3926,8 @@ 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); + if (solv->nrules != oldnrules) + haslockjob = 1; break; case SOLVER_DISTUPGRADE: POOL_DEBUG(SOLV_DEBUG_JOB, "job: distupgrade %s\n", solver_select2str(pool, select, what)); @@ -3930,15 +3944,7 @@ solver_solve(Solver *solv, Queue *job) case SOLVER_FAVOR: case SOLVER_DISFAVOR: POOL_DEBUG(SOLV_DEBUG_JOB, "job: %s %s\n", (how & SOLVER_JOBMASK) == SOLVER_FAVOR ? "favor" : "disfavor", solver_select2str(pool, select, what)); - FOR_JOB_SELECT(p, pp, select, what) - { - if (!solv->favorq) - { - solv->favorq = solv_calloc(1, sizeof(Queue)); - queue_init(solv->favorq); - } - queue_push2(solv->favorq, p, (how & SOLVER_JOBMASK) == SOLVER_FAVOR ? i + 1 : -(i + 1)); - } + hasfavorjob = 1; break; default: POOL_DEBUG(SOLV_DEBUG_JOB, "job: unknown job\n"); @@ -3960,8 +3966,8 @@ solver_solve(Solver *solv, Queue *job) assert(solv->ruletojob.count == solv->nrules - solv->jobrules); solv->jobrules_end = solv->nrules; - /* sort favorq and transform it into two maps */ - if (solv->favorq) + /* create favormap if we have favor jobs */ + if (hasfavorjob) setup_favormap(solv); /* now create infarch and dup rules */ @@ -3981,7 +3987,7 @@ solver_solve(Solver *solv, Queue *job) #endif if (solv->bestupdatemap_all || solv->bestupdatemap.size || hasbestinstalljob) - solver_addbestrules(solv, hasbestinstalljob); + solver_addbestrules(solv, hasbestinstalljob, haslockjob); else solv->bestrules = solv->bestrules_end = solv->bestrules_up = solv->nrules; diff --git a/src/solver.h b/src/solver.h index 93baa34..daf4f63 100644 --- a/src/solver.h +++ b/src/solver.h @@ -205,7 +205,6 @@ struct s_Solver { Map allowuninstallmap; /* ok to uninstall those */ int allowuninstall_all; - Queue *favorq; Id *favormap; /* favor job index, > 0: favored, < 0: disfavored */ int havedisfavored; /* do we have disfavored packages? */ @@ -11,7 +11,13 @@ #include <stdlib.h> #include <unistd.h> #include <string.h> -#include <sys/time.h> +#include <fcntl.h> +#ifdef _WIN32 + #include <windows.h> + #include <io.h> +#else + #include <sys/time.h> +#endif #include "util.h" @@ -123,6 +129,9 @@ solv_strdup(const char *s) unsigned int solv_timems(unsigned int subtract) { +#ifdef _WIN32 + return GetTickCount() - subtract; +#else struct timeval tv; unsigned int r; @@ -132,6 +141,17 @@ solv_timems(unsigned int subtract) r += ((unsigned int)tv.tv_sec & 0xffff) * 1000; r += (unsigned int)tv.tv_usec / 1000; return r - subtract; +#endif +} + +int +solv_setcloexec(int fd, int state) +{ + #ifdef _WIN32 + return SetHandleInformation((HANDLE) _get_osfhandle(fd), HANDLE_FLAG_INHERIT, state ? 0 : HANDLE_FLAG_INHERIT); + #else + return fcntl(fd, F_SETFD, state ? FD_CLOEXEC : 0) == 0; + #endif } /* bsd's qsort_r has different arguments, so we define our @@ -34,6 +34,7 @@ extern void *solv_free(void *); extern char *solv_strdup(const char *); extern void solv_oom(size_t, size_t); extern unsigned int solv_timems(unsigned int subtract); +extern int solv_setcloexec(int fd, int state); extern void solv_sort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *compard); extern char *solv_dupjoin(const char *str1, const char *str2, const char *str3); extern char *solv_dupappend(const char *str1, const char *str2, const char *str3); |