summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt18
-rw-r--r--src/chksum.c4
-rw-r--r--src/cleandeps.c2
-rw-r--r--src/conda.c242
-rw-r--r--src/conda.h2
-rw-r--r--src/knownid.h15
-rw-r--r--src/libsolv.ver2
-rw-r--r--src/policy.c30
-rw-r--r--src/pool.c18
-rw-r--r--src/qsort_r.c2
-rw-r--r--src/repo.c13
-rw-r--r--src/repo_solv.c2
-rw-r--r--src/repodata.c32
-rw-r--r--src/repopage.c19
-rw-r--r--src/rules.c166
-rw-r--r--src/rules.h2
-rw-r--r--src/selection.c21
-rw-r--r--src/solvable.c74
-rw-r--r--src/solver.c78
-rw-r--r--src/solver.h1
-rw-r--r--src/util.c22
-rw-r--r--src/util.h1
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(&reg, buf, REG_EXTENDED | REG_NOSUB))
- return 0;
+ if (regcomp(&reg, buf, REG_EXTENDED | REG_NOSUB | (icase ? REG_ICASE : 0)))
+ {
+ solv_free(buf);
+ return 0;
+ }
r = regexec(&reg, evr, 0, NULL, 0);
regfree(&reg);
+ 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(&reg, buf, REG_EXTENDED | REG_NOSUB))
- return 0;
+ if (regcomp(&reg, buf, REG_EXTENDED | REG_NOSUB | (icase ? REG_ICASE : 0)))
+ {
+ solv_free(buf);
+ return 0;
+ }
r = regexec(&reg, evr, 0, NULL, 0);
regfree(&reg);
+ 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);
}
}
diff --git a/src/pool.c b/src/pool.c
index 09354ef..a554453 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -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 $ */
diff --git a/src/repo.c b/src/repo.c
index d163f13..da40219 100644
--- a/src/repo.c
+++ b/src/repo.c
@@ -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? */
diff --git a/src/util.c b/src/util.c
index 65c8629..72426e0 100644
--- a/src/util.c
+++ b/src/util.c
@@ -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
diff --git a/src/util.h b/src/util.h
index 5f7a93a..1dc5f32 100644
--- a/src/util.h
+++ b/src/util.h
@@ -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);