diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2016-10-27 14:58:05 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2016-10-27 14:58:05 +0900 |
commit | f458102388250c8a1cbbfa8f18d27baa204c696c (patch) | |
tree | 447d75c1ae4449828e094d36a2f97f9b46b455ef /src | |
parent | 8fcc0d8e03716077d1f2c2ca79fc622880a32196 (diff) | |
download | libsolv-f458102388250c8a1cbbfa8f18d27baa204c696c.tar.gz libsolv-f458102388250c8a1cbbfa8f18d27baa204c696c.tar.bz2 libsolv-f458102388250c8a1cbbfa8f18d27baa204c696c.zip |
Imported Upstream version 0.6.23upstream/0.6.23
Change-Id: Idc1e282dc113b7350d8e123283f1a36097b76857
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/libsolv.ver | 1 | ||||
-rw-r--r-- | src/pool.c | 218 | ||||
-rw-r--r-- | src/pool.h | 36 | ||||
-rw-r--r-- | src/repo.c | 224 | ||||
-rw-r--r-- | src/repo.h | 7 | ||||
-rw-r--r-- | src/rules.c | 43 | ||||
-rw-r--r-- | src/solvable.c | 297 | ||||
-rw-r--r-- | src/solvable.h | 7 | ||||
-rw-r--r-- | src/solver.c | 23 | ||||
-rw-r--r-- | src/solver.h | 4 | ||||
-rw-r--r-- | src/solverdebug.c | 33 | ||||
-rw-r--r-- | src/solverdebug.h | 4 | ||||
-rw-r--r-- | src/solvversion.h.in | 24 | ||||
-rw-r--r-- | src/suse.c | 748 | ||||
-rw-r--r-- | src/transaction.c | 8 |
16 files changed, 862 insertions, 817 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 241890d..0109755 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,7 +19,7 @@ SET (libsolv_SRCS queue.c repo.c repodata.c repopage.c util.c policy.c solvable.c transaction.c order.c rules.c problems.c linkedpkg.c cplxdeps.c chksum.c md5.c sha1.c sha2.c solvversion.c selection.c - fileprovides.c diskusage.c) + fileprovides.c diskusage.c suse.c) SET (libsolv_HEADERS bitmap.h evr.h hash.h policy.h poolarch.h poolvendor.h pool.h diff --git a/src/libsolv.ver b/src/libsolv.ver index a5efd6a..dd1596e 100644 --- a/src/libsolv.ver +++ b/src/libsolv.ver @@ -167,6 +167,7 @@ SOLV_1.0 { repo_lookup_void; repo_matchvalue; repo_reserve_ids; + repo_rewrite_suse_deps; repo_search; repo_set_deparray; repo_set_id; @@ -1681,224 +1681,6 @@ pool_bin2hex(Pool *pool, const unsigned char *buf, int len) return s; } -/* map: - * 1: installed - * 2: conflicts with installed - * 8: interesting (only true if installed) - * 16: undecided - */ - -static inline Id dep2name(Pool *pool, Id dep) -{ - while (ISRELDEP(dep)) - { - Reldep *rd = GETRELDEP(pool, dep); - dep = rd->name; - } - return dep; -} - -static int providedbyinstalled_multiversion(Pool *pool, unsigned char *map, Id n, Id con) -{ - Id p, pp; - Solvable *sn = pool->solvables + n; - - FOR_PROVIDES(p, pp, sn->name) - { - Solvable *s = pool->solvables + p; - if (s->name != sn->name || s->arch != sn->arch) - continue; - if ((map[p] & 9) != 9) - continue; - if (pool_match_nevr(pool, pool->solvables + p, con)) - continue; - return 1; /* found installed package that doesn't conflict */ - } - return 0; -} - -static inline int providedbyinstalled(Pool *pool, unsigned char *map, Id dep, int ispatch, Map *multiversionmap) -{ - Id p, pp; - int r = 0; - FOR_PROVIDES(p, pp, dep) - { - if (p == SYSTEMSOLVABLE) - return 1; /* always boring, as never constraining */ - if (ispatch && !pool_match_nevr(pool, pool->solvables + p, dep)) - continue; - if (ispatch && multiversionmap && multiversionmap->size && MAPTST(multiversionmap, p) && ISRELDEP(dep)) - if (providedbyinstalled_multiversion(pool, map, p, dep)) - continue; - if ((map[p] & 9) == 9) - return 9; - r |= map[p] & 17; - } - return r; -} - -/* - * pool_trivial_installable - calculate if a set of solvables is - * trivial installable without any other installs/deinstalls of - * packages not belonging to the set. - * - * the state is returned in the result queue: - * 1: solvable is installable without any other package changes - * 0: solvable is not installable - * -1: solvable is installable, but doesn't constrain any installed packages - */ - -void -pool_trivial_installable_multiversionmap(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res, Map *multiversionmap) -{ - int i, r, m, did; - Id p, *dp, con, *conp, req, *reqp; - unsigned char *map; - Solvable *s; - - map = solv_calloc(pool->nsolvables, 1); - for (p = 1; p < pool->nsolvables; p++) - { - if (!MAPTST(installedmap, p)) - continue; - map[p] |= 9; - s = pool->solvables + p; - if (!s->conflicts) - continue; - conp = s->repo->idarraydata + s->conflicts; - while ((con = *conp++) != 0) - { - dp = pool_whatprovides_ptr(pool, con); - for (; *dp; dp++) - map[p] |= 2; /* XXX: self conflict ? */ - } - } - for (i = 0; i < pkgs->count; i++) - map[pkgs->elements[i]] = 16; - - for (i = 0, did = 0; did < pkgs->count; i++, did++) - { - if (i == pkgs->count) - i = 0; - p = pkgs->elements[i]; - if ((map[p] & 16) == 0) - continue; - if ((map[p] & 2) != 0) - { - map[p] = 2; - continue; - } - s = pool->solvables + p; - m = 1; - if (s->requires) - { - reqp = s->repo->idarraydata + s->requires; - while ((req = *reqp++) != 0) - { - if (req == SOLVABLE_PREREQMARKER) - continue; - r = providedbyinstalled(pool, map, req, 0, 0); - if (!r) - { - /* decided and miss */ - map[p] = 2; - did = 0; - break; - } - if (r == 16) - break; /* undecided */ - m |= r; /* 1 | 9 | 17 */ - } - if (req) - continue; - if ((m & 9) == 9) - m = 9; - } - if (s->conflicts) - { - int ispatch = 0; /* see solver.c patch handling */ - - if (!strncmp("patch:", pool_id2str(pool, s->name), 6)) - ispatch = 1; - conp = s->repo->idarraydata + s->conflicts; - while ((con = *conp++) != 0) - { - if ((providedbyinstalled(pool, map, con, ispatch, multiversionmap) & 1) != 0) - { - map[p] = 2; - did = 0; - break; - } - if ((m == 1 || m == 17) && ISRELDEP(con)) - { - con = dep2name(pool, con); - if ((providedbyinstalled(pool, map, con, ispatch, multiversionmap) & 1) != 0) - m = 9; - } - } - if (con) - continue; /* found a conflict */ - } -#if 0 - if (s->repo && s->repo != oldinstalled) - { - Id p2, obs, *obsp, *pp; - Solvable *s2; - if (s->obsoletes) - { - obsp = s->repo->idarraydata + s->obsoletes; - while ((obs = *obsp++) != 0) - { - if ((providedbyinstalled(pool, map, obs, 0, 0) & 1) != 0) - { - map[p] = 2; - break; - } - } - if (obs) - continue; - } - FOR_PROVIDES(p2, pp, s->name) - { - s2 = pool->solvables + p2; - if (s2->name == s->name && (map[p2] & 1) != 0) - { - map[p] = 2; - break; - } - } - if (p2) - continue; - } -#endif - if (m != map[p]) - { - map[p] = m; - did = 0; - } - } - queue_free(res); - queue_init_clone(res, pkgs); - for (i = 0; i < pkgs->count; i++) - { - m = map[pkgs->elements[i]]; - if ((m & 9) == 9) - r = 1; - else if (m & 1) - r = -1; - else - r = 0; - res->elements[i] = r; - } - free(map); -} - -void -pool_trivial_installable(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res) -{ - pool_trivial_installable_multiversionmap(pool, installedmap, pkgs, res, 0); -} - const char * pool_lookup_str(Pool *pool, Id entry, Id keyname) { @@ -289,13 +289,6 @@ 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 solvable_trivial_installable_map(Solvable *s, Map *installedmap, Map *conflictsmap, Map *multiversionmap); -int solvable_trivial_installable_repo(Solvable *s, struct _Repo *installed, Map *multiversionmap); -int solvable_trivial_installable_queue(Solvable *s, Queue *installed, Map *multiversionmap); -int solvable_is_irrelevant_patch(Solvable *s, Map *installedmap); - -void pool_create_state_maps(Pool *pool, Queue *installed, Map *installedmap, Map *conflictsmap); - int pool_intersect_evrs(Pool *pool, int pflags, Id pevr, int flags, int evr); int pool_match_dep(Pool *pool, Id d1, Id d2); @@ -358,6 +351,16 @@ void pool_search(Pool *pool, Id p, Id key, const char *match, int flags, int (*c void pool_clear_pos(Pool *pool); +/* lookup functions */ +const char *pool_lookup_str(Pool *pool, Id entry, Id keyname); +Id pool_lookup_id(Pool *pool, Id entry, Id keyname); +unsigned long long pool_lookup_num(Pool *pool, Id entry, Id keyname, unsigned long long notfound); +int pool_lookup_void(Pool *pool, Id entry, Id keyname); +const unsigned char *pool_lookup_bin_checksum(Pool *pool, Id entry, Id keyname, Id *typep); +int pool_lookup_idarray(Pool *pool, Id entry, Id keyname, Queue *q); +const char *pool_lookup_checksum(Pool *pool, Id entry, Id keyname, Id *typep); +const char *pool_lookup_deltalocation(Pool *pool, Id entry, unsigned int *medianrp); + #define DUCHANGES_ONLYADD 1 @@ -368,19 +371,10 @@ typedef struct _DUChanges { int flags; } DUChanges; -void pool_calc_duchanges(Pool *pool, Map *installedmap, DUChanges *mps, int nmps); -int pool_calc_installsizechange(Pool *pool, Map *installedmap); -void pool_trivial_installable(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res); -void pool_trivial_installable_multiversionmap(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res, Map *multiversionmap); -const char *pool_lookup_str(Pool *pool, Id entry, Id keyname); -Id pool_lookup_id(Pool *pool, Id entry, Id keyname); -unsigned long long pool_lookup_num(Pool *pool, Id entry, Id keyname, unsigned long long notfound); -int pool_lookup_void(Pool *pool, Id entry, Id keyname); -const unsigned char *pool_lookup_bin_checksum(Pool *pool, Id entry, Id keyname, Id *typep); -int pool_lookup_idarray(Pool *pool, Id entry, Id keyname, Queue *q); -const char *pool_lookup_checksum(Pool *pool, Id entry, Id keyname, Id *typep); -const char *pool_lookup_deltalocation(Pool *pool, Id entry, unsigned int *medianrp); +void pool_create_state_maps(Pool *pool, Queue *installed, Map *installedmap, Map *conflictsmap); +void pool_calc_duchanges(Pool *pool, Map *installedmap, DUChanges *mps, int nmps); +int pool_calc_installsizechange(Pool *pool, Map *installedmap); void pool_add_fileconflicts_deps(Pool *pool, Queue *conflicts); @@ -411,6 +405,10 @@ void pool_add_fileconflicts_deps(Pool *pool, Queue *conflicts); #define POOL_DEBUG(type, ...) do {if ((pool->debugmask & (type)) != 0) pool_debug(pool, (type), __VA_ARGS__);} while (0) #define IF_POOLDEBUG(type) if ((pool->debugmask & (type)) != 0) +/* weird suse stuff */ +void pool_trivial_installable_multiversionmap(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res, Map *multiversionmap); +void pool_trivial_installable(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res); + #ifdef __cplusplus } #endif @@ -666,230 +666,6 @@ repo_reserve_ids(Repo *repo, Offset olddeps, int num) /***********************************************************************/ -/* - * some SUSE specific fixups, should go into a separate file - */ - -Offset -repo_fix_supplements(Repo *repo, Offset provides, Offset supplements, Offset freshens) -{ - Pool *pool = repo->pool; - Id id, idp, idl; - char buf[1024], *p, *dep; - int i, l; - - if (provides) - { - for (i = provides; repo->idarraydata[i]; i++) - { - id = repo->idarraydata[i]; - if (ISRELDEP(id)) - continue; - dep = (char *)pool_id2str(pool, id); - if (!strncmp(dep, "locale(", 7) && strlen(dep) < sizeof(buf) - 2) - { - idp = 0; - strcpy(buf + 2, dep); - dep = buf + 2 + 7; - if ((p = strchr(dep, ':')) != 0 && p != dep) - { - *p++ = 0; - idp = pool_str2id(pool, dep, 1); - dep = p; - } - id = 0; - while ((p = strchr(dep, ';')) != 0) - { - if (p == dep) - { - dep = p + 1; - continue; - } - *p++ = 0; - idl = pool_str2id(pool, dep, 1); - idl = pool_rel2id(pool, NAMESPACE_LANGUAGE, idl, REL_NAMESPACE, 1); - if (id) - id = pool_rel2id(pool, id, idl, REL_OR, 1); - else - id = idl; - dep = p; - } - if (dep[0] && dep[1]) - { - for (p = dep; *p && *p != ')'; p++) - ; - *p = 0; - idl = pool_str2id(pool, dep, 1); - idl = pool_rel2id(pool, NAMESPACE_LANGUAGE, idl, REL_NAMESPACE, 1); - if (id) - id = pool_rel2id(pool, id, idl, REL_OR, 1); - else - id = idl; - } - if (idp) - id = pool_rel2id(pool, idp, id, REL_AND, 1); - if (id) - supplements = repo_addid_dep(repo, supplements, id, 0); - } - else if ((p = strchr(dep, ':')) != 0 && p != dep && p[1] == '/' && strlen(dep) < sizeof(buf)) - { - strcpy(buf, dep); - p = buf + (p - dep); - *p++ = 0; - idp = pool_str2id(pool, buf, 1); - /* strip trailing slashes */ - l = strlen(p); - while (l > 1 && p[l - 1] == '/') - p[--l] = 0; - id = pool_str2id(pool, p, 1); - id = pool_rel2id(pool, idp, id, REL_WITH, 1); - id = pool_rel2id(pool, NAMESPACE_SPLITPROVIDES, id, REL_NAMESPACE, 1); - supplements = repo_addid_dep(repo, supplements, id, 0); - } - } - } - if (supplements) - { - for (i = supplements; repo->idarraydata[i]; i++) - { - id = repo->idarraydata[i]; - if (ISRELDEP(id)) - continue; - dep = (char *)pool_id2str(pool, id); - if (!strncmp(dep, "system:modalias(", 16)) - dep += 7; - if (!strncmp(dep, "modalias(", 9) && dep[9] && dep[10] && strlen(dep) < sizeof(buf)) - { - strcpy(buf, dep); - p = strchr(buf + 9, ':'); - if (p && p != buf + 9 && strchr(p + 1, ':')) - { - *p++ = 0; - idp = pool_str2id(pool, buf + 9, 1); - p[strlen(p) - 1] = 0; - id = pool_str2id(pool, p, 1); - id = pool_rel2id(pool, NAMESPACE_MODALIAS, id, REL_NAMESPACE, 1); - id = pool_rel2id(pool, idp, id, REL_AND, 1); - } - else - { - p = buf + 9; - p[strlen(p) - 1] = 0; - id = pool_str2id(pool, p, 1); - id = pool_rel2id(pool, NAMESPACE_MODALIAS, id, REL_NAMESPACE, 1); - } - if (id) - repo->idarraydata[i] = id; - } - else if (!strncmp(dep, "packageand(", 11) && strlen(dep) < sizeof(buf)) - { - strcpy(buf, dep); - id = 0; - dep = buf + 11; - while ((p = strchr(dep, ':')) != 0) - { - if (p == dep) - { - dep = p + 1; - continue; - } - /* argh, allow pattern: prefix. sigh */ - if (p - dep == 7 && !strncmp(dep, "pattern", 7)) - { - p = strchr(p + 1, ':'); - if (!p) - break; - } - *p++ = 0; - idp = pool_str2id(pool, dep, 1); - if (id) - id = pool_rel2id(pool, id, idp, REL_AND, 1); - else - id = idp; - dep = p; - } - if (dep[0] && dep[1]) - { - dep[strlen(dep) - 1] = 0; - idp = pool_str2id(pool, dep, 1); - if (id) - id = pool_rel2id(pool, id, idp, REL_AND, 1); - else - id = idp; - } - if (id) - repo->idarraydata[i] = id; - } - else if (!strncmp(dep, "filesystem(", 11) && strlen(dep) < sizeof(buf)) - { - strcpy(buf, dep + 11); - if ((p = strrchr(buf, ')')) != 0) - *p = 0; - id = pool_str2id(pool, buf, 1); - id = pool_rel2id(pool, NAMESPACE_FILESYSTEM, id, REL_NAMESPACE, 1); - repo->idarraydata[i] = id; - } - } - } - if (freshens && repo->idarraydata[freshens]) - { - Id idsupp = 0, idfresh = 0; - if (!supplements || !repo->idarraydata[supplements]) - return freshens; - for (i = supplements; repo->idarraydata[i]; i++) - { - if (!idsupp) - idsupp = repo->idarraydata[i]; - else - idsupp = pool_rel2id(pool, idsupp, repo->idarraydata[i], REL_OR, 1); - } - for (i = freshens; repo->idarraydata[i]; i++) - { - if (!idfresh) - idfresh = repo->idarraydata[i]; - else - idfresh = pool_rel2id(pool, idfresh, repo->idarraydata[i], REL_OR, 1); - } - if (!idsupp) - idsupp = idfresh; - else - idsupp = pool_rel2id(pool, idsupp, idfresh, REL_AND, 1); - supplements = repo_addid_dep(repo, 0, idsupp, 0); - } - return supplements; -} - -Offset -repo_fix_conflicts(Repo *repo, Offset conflicts) -{ - char buf[1024], *p, *dep; - Pool *pool = repo->pool; - Id id; - int i; - - if (!conflicts) - return conflicts; - for (i = conflicts; repo->idarraydata[i]; i++) - { - id = repo->idarraydata[i]; - if (ISRELDEP(id)) - continue; - dep = (char *)pool_id2str(pool, id); - if (!strncmp(dep, "otherproviders(", 15) && strlen(dep) < sizeof(buf) - 2) - { - strcpy(buf, dep + 15); - if ((p = strchr(buf, ')')) != 0) - *p = 0; - id = pool_str2id(pool, buf, 1); - id = pool_rel2id(pool, NAMESPACE_OTHERPROVIDERS, id, REL_NAMESPACE, 1); - repo->idarraydata[i] = id; - } - } - return conflicts; -} - -/***********************************************************************/ - struct matchdata { Pool *pool; @@ -72,8 +72,6 @@ extern Id repo_add_solvable_block_before(Repo *repo, int count, Repo *beforerepo extern Offset repo_addid(Repo *repo, Offset olddeps, Id id); extern Offset repo_addid_dep(Repo *repo, Offset olddeps, Id id, Id marker); extern Offset repo_reserve_ids(Repo *repo, Offset olddeps, int num); -extern Offset repo_fix_supplements(Repo *repo, Offset provides, Offset supplements, Offset freshens); -extern Offset repo_fix_conflicts(Repo *repo, Offset conflicts); static inline const char *repo_name(const Repo *repo) { @@ -181,6 +179,11 @@ void repo_disable_paging(Repo *repo); for (rdid = 1; rdid < repo->nrepodata && (data = repo_id2repodata(repo, rdid)); rdid++) #endif +/* weird suse stuff, do not use */ +extern Offset repo_fix_supplements(Repo *repo, Offset provides, Offset supplements, Offset freshens); +extern Offset repo_fix_conflicts(Repo *repo, Offset conflicts); +extern void repo_rewrite_suse_deps(Solvable *s, Offset freshens); + #ifdef __cplusplus } #endif diff --git a/src/rules.c b/src/rules.c index 32855e4..aa90b5f 100644 --- a/src/rules.c +++ b/src/rules.c @@ -3869,9 +3869,8 @@ complex_cleandeps_addback(Pool *pool, Id ip, Id req, Map *im, Map *installedm, Q { if (!MAPTST(installedm, -p)) break; - continue; } - if (MAPTST(im, p)) + else if (p == ip) break; } if (!p) @@ -3880,6 +3879,8 @@ complex_cleandeps_addback(Pool *pool, Id ip, Id req, Map *im, Map *installedm, Q { if (p < 0) continue; + if (MAPTST(im, p)) + continue; if (!MAPTST(installedm, p)) continue; if (p == ip || MAPTST(userinstalled, p - pool->installed->start)) @@ -4387,6 +4388,36 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded) #ifdef CLEANDEPSDEBUG printf("adding back %s\n", pool_solvable2str(pool, s)); #endif + if (s->repo == installed && pool->implicitobsoleteusescolors) + { + Id a, bestarch = 0; + FOR_PROVIDES(p, pp, s->name) + { + Solvable *ps = pool->solvables + p; + if (ps->name != s->name || ps->repo == installed) + continue; + a = ps->arch; + a = (a <= pool->lastarch) ? pool->id2arch[a] : 0; + if (a && a != 1 && (!bestarch || a < bestarch)) + bestarch = a; + } + if (bestarch && (s->arch > pool->lastarch || pool->id2arch[s->arch] != bestarch)) + { + FOR_PROVIDES(p, pp, s->name) + { + Solvable *ps = pool->solvables + p; + if (ps->repo == installed && ps->name == s->name && ps->evr == s->evr && ps->arch != s->arch && ps->arch < pool->lastarch && pool->id2arch[ps->arch] == bestarch) + if (!MAPTST(&im, p)) + { +#ifdef CLEANDEPSDEBUG + printf("%s lockstep %s\n", pool_solvid2str(pool, ip), pool_solvid2str(pool, p)); +#endif + MAPSET(&im, p); + queue_push(&iq, p); + } + } + } + } if (s->requires) { reqp = s->repo->idarraydata + s->requires; @@ -4400,12 +4431,14 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded) } #endif FOR_PROVIDES(p, pp, req) - if (MAPTST(&im, p)) + if (p == ip) break; if (p) continue; FOR_PROVIDES(p, pp, req) { + if (MAPTST(&im, p)) + continue; if (MAPTST(&installedm, p)) { if (p == ip) @@ -4434,12 +4467,14 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded) } #endif FOR_PROVIDES(p, pp, req) - if (MAPTST(&im, p)) + if (p == ip) break; if (p) continue; FOR_PROVIDES(p, pp, req) { + if (MAPTST(&im, p)) + continue; if (MAPTST(&installedm, p)) { if (p == ip) diff --git a/src/solvable.c b/src/solvable.c index cccc89d..2570e4f 100644 --- a/src/solvable.c +++ b/src/solvable.c @@ -409,305 +409,12 @@ solvable_lookup_sourcepkg(Solvable *s) /*****************************************************************************/ -static inline Id dep2name(Pool *pool, Id dep) -{ - while (ISRELDEP(dep)) - { - Reldep *rd = GETRELDEP(pool, dep); - dep = rd->name; - } - return dep; -} - -static int providedbyinstalled_multiversion(Pool *pool, Map *installed, Id n, Id con) -{ - Id p, pp; - Solvable *sn = pool->solvables + n; - - FOR_PROVIDES(p, pp, sn->name) - { - Solvable *s = pool->solvables + p; - if (s->name != sn->name || s->arch != sn->arch) - continue; - if (!MAPTST(installed, p)) - continue; - if (pool_match_nevr(pool, pool->solvables + p, con)) - continue; - return 1; /* found installed package that doesn't conflict */ - } - return 0; -} - -static inline int providedbyinstalled(Pool *pool, Map *installed, Id dep, int ispatch, Map *multiversionmap) -{ - Id p, pp; - FOR_PROVIDES(p, pp, dep) - { - if (p == SYSTEMSOLVABLE) - return -1; - if (ispatch && !pool_match_nevr(pool, pool->solvables + p, dep)) - continue; - if (ispatch && multiversionmap && multiversionmap->size && MAPTST(multiversionmap, p) && ISRELDEP(dep)) - if (providedbyinstalled_multiversion(pool, installed, p, dep)) - continue; - if (MAPTST(installed, p)) - return 1; - } - return 0; -} - -/* - * solvable_trivial_installable_map - anwers is a solvable is installable - * without any other installs/deinstalls. - * The packages considered to be installed are provided via the - * installedmap bitmap. A additional "conflictsmap" bitmap providing - * information about the conflicts of the installed packages can be - * used for extra speed up. Provide a NULL pointer if you do not - * have this information. - * Both maps can be created with pool_create_state_maps() or - * solver_create_state_maps(). - * - * returns: - * 1: solvable is installable without any other package changes - * 0: solvable is not installable - * -1: solvable is installable, but doesn't constrain any installed packages - */ -int -solvable_trivial_installable_map(Solvable *s, Map *installedmap, Map *conflictsmap, Map *multiversionmap) -{ - Pool *pool = s->repo->pool; - Solvable *s2; - Id p, *dp; - Id *reqp, req; - Id *conp, con; - int r, interesting = 0; - - if (conflictsmap && MAPTST(conflictsmap, s - pool->solvables)) - return 0; - if (s->requires) - { - reqp = s->repo->idarraydata + s->requires; - while ((req = *reqp++) != 0) - { - if (req == SOLVABLE_PREREQMARKER) - continue; - r = providedbyinstalled(pool, installedmap, req, 0, 0); - if (!r) - return 0; - if (r > 0) - interesting = 1; - } - } - if (s->conflicts) - { - int ispatch = 0; - - if (!strncmp("patch:", pool_id2str(pool, s->name), 6)) - ispatch = 1; - conp = s->repo->idarraydata + s->conflicts; - while ((con = *conp++) != 0) - { - if (providedbyinstalled(pool, installedmap, con, ispatch, multiversionmap)) - { - if (ispatch && solvable_is_irrelevant_patch(s, installedmap)) - return -1; - return 0; - } - if (!interesting && ISRELDEP(con)) - { - con = dep2name(pool, con); - if (providedbyinstalled(pool, installedmap, con, ispatch, multiversionmap)) - interesting = 1; - } - } - if (ispatch && interesting && solvable_is_irrelevant_patch(s, installedmap)) - interesting = 0; - } -#if 0 - if (s->repo) - { - Id *obsp, obs; - Repo *installed = 0; - if (s->obsoletes && s->repo != installed) - { - obsp = s->repo->idarraydata + s->obsoletes; - while ((obs = *obsp++) != 0) - { - if (providedbyinstalled(pool, installedmap, obs, 0, 0)) - return 0; - } - } - if (s->repo != installed) - { - Id pp; - FOR_PROVIDES(p, pp, s->name) - { - s2 = pool->solvables + p; - if (s2->repo == installed && s2->name == s->name) - return 0; - } - } - } -#endif - if (!conflictsmap) - { - int i; - - p = s - pool->solvables; - for (i = 1; i < pool->nsolvables; i++) - { - if (!MAPTST(installedmap, i)) - continue; - s2 = pool->solvables + i; - if (!s2->conflicts) - continue; - conp = s2->repo->idarraydata + s2->conflicts; - while ((con = *conp++) != 0) - { - dp = pool_whatprovides_ptr(pool, con); - for (; *dp; dp++) - if (*dp == p) - return 0; - } - } - } - return interesting ? 1 : -1; -} - -/* - * different interface for solvable_trivial_installable_map, where - * the information about the installed packages is provided - * by a queue. - */ -int -solvable_trivial_installable_queue(Solvable *s, Queue *installed, Map *multiversionmap) -{ - Pool *pool = s->repo->pool; - int i; - Id p; - Map installedmap; - int r; - - map_init(&installedmap, pool->nsolvables); - for (i = 0; i < installed->count; i++) - { - p = installed->elements[i]; - if (p > 0) /* makes it work with decisionq */ - MAPSET(&installedmap, p); - } - r = solvable_trivial_installable_map(s, &installedmap, 0, multiversionmap); - map_free(&installedmap); - return r; -} - -/* - * different interface for solvable_trivial_installable_map, where - * the information about the installed packages is provided - * by a repo containing the installed solvables. - */ -int -solvable_trivial_installable_repo(Solvable *s, Repo *installed, Map *multiversionmap) -{ - Pool *pool = s->repo->pool; - Id p; - Solvable *s2; - Map installedmap; - int r; - - map_init(&installedmap, pool->nsolvables); - FOR_REPO_SOLVABLES(installed, p, s2) - MAPSET(&installedmap, p); - r = solvable_trivial_installable_map(s, &installedmap, 0, multiversionmap); - map_free(&installedmap); - return r; -} - -/* FIXME: this mirrors policy_illegal_vendorchange */ -static int -pool_illegal_vendorchange(Pool *pool, Solvable *s1, Solvable *s2) -{ - Id v1, v2; - Id vendormask1, vendormask2; - - if (pool->custom_vendorcheck) - return pool->custom_vendorcheck(pool, s1, s2); - /* treat a missing vendor as empty string */ - v1 = s1->vendor ? s1->vendor : ID_EMPTY; - v2 = s2->vendor ? s2->vendor : ID_EMPTY; - if (v1 == v2) - return 0; - vendormask1 = pool_vendor2mask(pool, v1); - if (!vendormask1) - return 1; /* can't match */ - vendormask2 = pool_vendor2mask(pool, v2); - if ((vendormask1 & vendormask2) != 0) - return 0; - return 1; /* no class matches */ -} - -/* check if this patch is relevant according to the vendor. To bad that patches - * don't have a vendor, so we need to do some careful repo testing. */ -int -solvable_is_irrelevant_patch(Solvable *s, Map *installedmap) -{ - Pool *pool = s->repo->pool; - Id con, *conp; - int hadpatchpackage = 0; - - if (!s->conflicts) - return 0; - conp = s->repo->idarraydata + s->conflicts; - while ((con = *conp++) != 0) - { - Reldep *rd; - Id p, pp, p2, pp2; - if (!ISRELDEP(con)) - continue; - rd = GETRELDEP(pool, con); - if (rd->flags != REL_LT) - continue; - FOR_PROVIDES(p, pp, con) - { - Solvable *si; - if (!MAPTST(installedmap, p)) - continue; - si = pool->solvables + p; - if (!pool_match_nevr(pool, si, con)) - continue; - FOR_PROVIDES(p2, pp2, rd->name) - { - Solvable *s2 = pool->solvables + p2; - if (!pool_match_nevr(pool, s2, rd->name)) - continue; - if (pool_match_nevr(pool, s2, con)) - continue; /* does not fulfill patch */ - if (s2->repo == s->repo) - { - hadpatchpackage = 1; - /* ok, we have a package from the patch repo that solves the conflict. check vendor */ - if (si->vendor == s2->vendor) - return 0; - if (!pool_illegal_vendorchange(pool, si, s2)) - return 0; - /* vendor change was illegal, ignore conflict */ - } - } - } - } - /* if we didn't find a patchpackage don't claim that the patch is irrelevant */ - if (!hadpatchpackage) - return 0; - return 1; -} - -/*****************************************************************************/ - /* * Create maps containing the state of each solvable. Input is a "installed" queue, * it contains all solvable ids that are considered to be installed. * - * The created maps can be used for solvable_trivial_installable_map(), - * pool_calc_duchanges(), pool_calc_installsizechange(). + * The created maps can be used for * pool_calc_duchanges() and + * pool_calc_installsizechange(). * */ void diff --git a/src/solvable.h b/src/solvable.h index 85d20c4..090b758 100644 --- a/src/solvable.h +++ b/src/solvable.h @@ -17,6 +17,7 @@ #include "pooltypes.h" #include "queue.h" +#include "bitmap.h" #ifdef __cplusplus extern "C" { @@ -80,6 +81,12 @@ int solvable_identical(Solvable *s1, Solvable *s2); Id solvable_selfprovidedep(Solvable *s); int solvable_matchesdep(Solvable *s, Id keyname, Id dep, int marker); +/* weird suse stuff */ +int solvable_is_irrelevant_patch(Solvable *s, Map *installedmap); +int solvable_trivial_installable_map(Solvable *s, Map *installedmap, Map *conflictsmap, Map *multiversionmap); +int solvable_trivial_installable_queue(Solvable *s, Queue *installed, Map *multiversionmap); +int solvable_trivial_installable_repo(Solvable *s, struct _Repo *installed, Map *multiversionmap); + #ifdef __cplusplus } #endif diff --git a/src/solver.c b/src/solver.c index 4f849ec..5fca20d 100644 --- a/src/solver.c +++ b/src/solver.c @@ -2913,6 +2913,8 @@ solver_run_sat(Solver *solv, int disablerules, int doweak) lastsi = -1; break; } + if (solv->isdisfavormap.size && MAPTST(&solv->isdisfavormap, p)) + continue; if (lastsi < 0 && (MAPTST(&solv->recommendsmap, p) || solver_is_supplementing(solv, pool->solvables + p))) lastsi = i; } @@ -2925,6 +2927,9 @@ solver_run_sat(Solver *solv, int disablerules, int doweak) p = -solv->branches.elements[i]; if (p <= 0 || solv->decisionmap[p] != l + 1) continue; + if (solv->favormap.size && MAPTST(&solv->favormap, p)) + if (!(solv->isdisfavormap.size && MAPTST(&solv->isdisfavormap, p))) + continue; /* current selection is favored */ if (!(MAPTST(&solv->recommendsmap, p) || solver_is_supplementing(solv, pool->solvables + p))) { lasti = lastsi; @@ -4480,24 +4485,6 @@ solver_create_state_maps(Solver *solv, Map *installedmap, Map *conflictsmap) pool_create_state_maps(solv->pool, &solv->decisionq, installedmap, conflictsmap); } -void -solver_trivial_installable(Solver *solv, Queue *pkgs, Queue *res) -{ - Pool *pool = solv->pool; - Map installedmap; - int i; - pool_create_state_maps(pool, &solv->decisionq, &installedmap, 0); - pool_trivial_installable_multiversionmap(pool, &installedmap, pkgs, res, solv->multiversion.size ? &solv->multiversion : 0); - for (i = 0; i < res->count; i++) - if (res->elements[i] != -1) - { - Solvable *s = pool->solvables + pkgs->elements[i]; - if (!strncmp("patch:", pool_id2str(pool, s->name), 6) && solvable_is_irrelevant_patch(s, &installedmap)) - res->elements[i] = -1; - } - map_free(&installedmap); -} - /*------------------------------------------------------------------- * * decision introspection diff --git a/src/solver.h b/src/solver.h index 3495fd8..758f1eb 100644 --- a/src/solver.h +++ b/src/solver.h @@ -348,7 +348,6 @@ extern void solver_create_state_maps(Solver *solv, Map *installedmap, Map *confl extern void solver_calc_duchanges(Solver *solv, DUChanges *mps, int nmps); extern int solver_calc_installsizechange(Solver *solv); -extern void solver_trivial_installable(Solver *solv, Queue *pkgs, Queue *res); extern void pool_job2solvables(Pool *pool, Queue *pkgs, Id how, Id what); extern int pool_isemptyupdatejob(Pool *pool, Id how, Id what); @@ -384,6 +383,9 @@ extern const char *solver_alternative2str(Solver *solv, int type, Id id, Id from continue; \ else +/* weird suse stuff */ +extern void solver_trivial_installable(Solver *solv, Queue *pkgs, Queue *res); + #ifdef __cplusplus } #endif diff --git a/src/solverdebug.c b/src/solverdebug.c index 39f5d78..bb74ef6 100644 --- a/src/solverdebug.c +++ b/src/solverdebug.c @@ -568,36 +568,3 @@ solver_printallsolutions(Solver *solv) } } -void -solver_printtrivial(Solver *solv) -{ - Pool *pool = solv->pool; - Queue in, out; - Id p; - const char *n; - Solvable *s; - int i; - - queue_init(&in); - for (p = 1, s = pool->solvables + p; p < solv->pool->nsolvables; p++, s++) - { - n = pool_id2str(pool, s->name); - if (strncmp(n, "patch:", 6) != 0 && strncmp(n, "pattern:", 8) != 0) - continue; - queue_push(&in, p); - } - if (!in.count) - { - queue_free(&in); - return; - } - queue_init(&out); - solver_trivial_installable(solv, &in, &out); - POOL_DEBUG(SOLV_DEBUG_RESULT, "trivial installable status:\n"); - for (i = 0; i < in.count; i++) - POOL_DEBUG(SOLV_DEBUG_RESULT, " %s: %d\n", pool_solvid2str(pool, in.elements[i]), out.elements[i]); - POOL_DEBUG(SOLV_DEBUG_RESULT, "\n"); - queue_free(&in); - queue_free(&out); -} - diff --git a/src/solverdebug.h b/src/solverdebug.h index 32e427e..b6923b4 100644 --- a/src/solverdebug.h +++ b/src/solverdebug.h @@ -33,10 +33,12 @@ extern void solver_printprobleminfo(Solver *solv, Id problem); extern void solver_printcompleteprobleminfo(Solver *solv, Id problem); extern void solver_printsolution(Solver *solv, Id problem, Id solution); extern void solver_printallsolutions(Solver *solv); -extern void solver_printtrivial(Solver *solv); extern void transaction_print(Transaction *trans); +/* weird suse stuff */ +extern void solver_printtrivial(Solver *solv); + #ifdef __cplusplus } #endif diff --git a/src/solvversion.h.in b/src/solvversion.h.in index 268219c..75dc63f 100644 --- a/src/solvversion.h.in +++ b/src/solvversion.h.in @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Novell Inc. + * Copyright (c) 2016, SUSE LLC * * This program is licensed under the BSD license, read LICENSE.BSD * for further information @@ -24,4 +24,26 @@ extern int solv_version_major; extern int solv_version_minor; extern int solv_version_patch; +#cmakedefine LIBSOLV_FEATURE_LINKED_PKGS +#cmakedefine LIBSOLV_FEATURE_COMPLEX_DEPS +#cmakedefine LIBSOLV_FEATURE_MULTI_SEMANTICS + +#cmakedefine LIBSOLVEXT_FEATURE_RPMDB +#cmakedefine LIBSOLVEXT_FEATURE_RPMDB_BYRPMHEADER +#cmakedefine LIBSOLVEXT_FEATURE_PUBKEY +#cmakedefine LIBSOLVEXT_FEATURE_RPMMD +#cmakedefine LIBSOLVEXT_FEATURE_SUSEREPO +#cmakedefine LIBSOLVEXT_FEATURE_COMPS +#cmakedefine LIBSOLVEXT_FEATURE_HELIXREPO +#cmakedefine LIBSOLVEXT_FEATURE_DEBIAN +#cmakedefine LIBSOLVEXT_FEATURE_ARCHREPO +#cmakedefine LIBSOLVEXT_FEATURE_CUDFREPO +#cmakedefine LIBSOLVEXT_FEATURE_HAIKU +#cmakedefine LIBSOLVEXT_FEATURE_APPDATA +#cmakedefine LIBSOLVEXT_FEATURE_LZMA_COMPRESSION +#cmakedefine LIBSOLVEXT_FEATURE_BZIP2_COMPRESSION + +/* see tools/common_write.c for toolversion history */ +#define LIBSOLV_TOOLVERSION "1.1" + #endif diff --git a/src/suse.c b/src/suse.c new file mode 100644 index 0000000..6106f3f --- /dev/null +++ b/src/suse.c @@ -0,0 +1,748 @@ +/* + * Copyright (c) 2016, SUSE LLC. + * + * This program is licensed under the BSD license, read LICENSE.BSD + * for further information + */ + +/* weird SUSE stuff. better not use it for your projects. */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include "solver.h" +#include "solver_private.h" +#include "bitmap.h" +#include "pool.h" +#include "poolvendor.h" +#include "util.h" + +Offset +repo_fix_supplements(Repo *repo, Offset provides, Offset supplements, Offset freshens) +{ + Pool *pool = repo->pool; + Id id, idp, idl; + char buf[1024], *p, *dep; + int i, l; + + if (provides) + { + for (i = provides; repo->idarraydata[i]; i++) + { + id = repo->idarraydata[i]; + if (ISRELDEP(id)) + continue; + dep = (char *)pool_id2str(pool, id); + if (!strncmp(dep, "locale(", 7) && strlen(dep) < sizeof(buf) - 2) + { + idp = 0; + strcpy(buf + 2, dep); + dep = buf + 2 + 7; + if ((p = strchr(dep, ':')) != 0 && p != dep) + { + *p++ = 0; + idp = pool_str2id(pool, dep, 1); + dep = p; + } + id = 0; + while ((p = strchr(dep, ';')) != 0) + { + if (p == dep) + { + dep = p + 1; + continue; + } + *p++ = 0; + idl = pool_str2id(pool, dep, 1); + idl = pool_rel2id(pool, NAMESPACE_LANGUAGE, idl, REL_NAMESPACE, 1); + if (id) + id = pool_rel2id(pool, id, idl, REL_OR, 1); + else + id = idl; + dep = p; + } + if (dep[0] && dep[1]) + { + for (p = dep; *p && *p != ')'; p++) + ; + *p = 0; + idl = pool_str2id(pool, dep, 1); + idl = pool_rel2id(pool, NAMESPACE_LANGUAGE, idl, REL_NAMESPACE, 1); + if (id) + id = pool_rel2id(pool, id, idl, REL_OR, 1); + else + id = idl; + } + if (idp) + id = pool_rel2id(pool, idp, id, REL_AND, 1); + if (id) + supplements = repo_addid_dep(repo, supplements, id, 0); + } + else if ((p = strchr(dep, ':')) != 0 && p != dep && p[1] == '/' && strlen(dep) < sizeof(buf)) + { + strcpy(buf, dep); + p = buf + (p - dep); + *p++ = 0; + idp = pool_str2id(pool, buf, 1); + /* strip trailing slashes */ + l = strlen(p); + while (l > 1 && p[l - 1] == '/') + p[--l] = 0; + id = pool_str2id(pool, p, 1); + id = pool_rel2id(pool, idp, id, REL_WITH, 1); + id = pool_rel2id(pool, NAMESPACE_SPLITPROVIDES, id, REL_NAMESPACE, 1); + supplements = repo_addid_dep(repo, supplements, id, 0); + } + } + } + if (supplements) + { + for (i = supplements; repo->idarraydata[i]; i++) + { + id = repo->idarraydata[i]; + if (ISRELDEP(id)) + continue; + dep = (char *)pool_id2str(pool, id); + if (!strncmp(dep, "system:modalias(", 16)) + dep += 7; + if (!strncmp(dep, "modalias(", 9) && dep[9] && dep[10] && strlen(dep) < sizeof(buf)) + { + strcpy(buf, dep); + p = strchr(buf + 9, ':'); + if (p && p != buf + 9 && strchr(p + 1, ':')) + { + *p++ = 0; + idp = pool_str2id(pool, buf + 9, 1); + p[strlen(p) - 1] = 0; + id = pool_str2id(pool, p, 1); + id = pool_rel2id(pool, NAMESPACE_MODALIAS, id, REL_NAMESPACE, 1); + id = pool_rel2id(pool, idp, id, REL_AND, 1); + } + else + { + p = buf + 9; + p[strlen(p) - 1] = 0; + id = pool_str2id(pool, p, 1); + id = pool_rel2id(pool, NAMESPACE_MODALIAS, id, REL_NAMESPACE, 1); + } + if (id) + repo->idarraydata[i] = id; + } + else if (!strncmp(dep, "packageand(", 11) && strlen(dep) < sizeof(buf)) + { + strcpy(buf, dep); + id = 0; + dep = buf + 11; + while ((p = strchr(dep, ':')) != 0) + { + if (p == dep) + { + dep = p + 1; + continue; + } + /* argh, allow pattern: prefix. sigh */ + if (p - dep == 7 && !strncmp(dep, "pattern", 7)) + { + p = strchr(p + 1, ':'); + if (!p) + break; + } + *p++ = 0; + idp = pool_str2id(pool, dep, 1); + if (id) + id = pool_rel2id(pool, id, idp, REL_AND, 1); + else + id = idp; + dep = p; + } + if (dep[0] && dep[1]) + { + dep[strlen(dep) - 1] = 0; + idp = pool_str2id(pool, dep, 1); + if (id) + id = pool_rel2id(pool, id, idp, REL_AND, 1); + else + id = idp; + } + if (id) + repo->idarraydata[i] = id; + } + else if (!strncmp(dep, "filesystem(", 11) && strlen(dep) < sizeof(buf)) + { + strcpy(buf, dep + 11); + if ((p = strrchr(buf, ')')) != 0) + *p = 0; + id = pool_str2id(pool, buf, 1); + id = pool_rel2id(pool, NAMESPACE_FILESYSTEM, id, REL_NAMESPACE, 1); + repo->idarraydata[i] = id; + } + } + } + if (freshens && repo->idarraydata[freshens]) + { + Id idsupp = 0, idfresh = 0; + if (!supplements || !repo->idarraydata[supplements]) + return freshens; + for (i = supplements; repo->idarraydata[i]; i++) + { + if (!idsupp) + idsupp = repo->idarraydata[i]; + else + idsupp = pool_rel2id(pool, idsupp, repo->idarraydata[i], REL_OR, 1); + } + for (i = freshens; repo->idarraydata[i]; i++) + { + if (!idfresh) + idfresh = repo->idarraydata[i]; + else + idfresh = pool_rel2id(pool, idfresh, repo->idarraydata[i], REL_OR, 1); + } + if (!idsupp) + idsupp = idfresh; + else + idsupp = pool_rel2id(pool, idsupp, idfresh, REL_AND, 1); + supplements = repo_addid_dep(repo, 0, idsupp, 0); + } + return supplements; +} + +Offset +repo_fix_conflicts(Repo *repo, Offset conflicts) +{ + char buf[1024], *p, *dep; + Pool *pool = repo->pool; + Id id; + int i; + + if (!conflicts) + return conflicts; + for (i = conflicts; repo->idarraydata[i]; i++) + { + id = repo->idarraydata[i]; + if (ISRELDEP(id)) + continue; + dep = (char *)pool_id2str(pool, id); + if (!strncmp(dep, "otherproviders(", 15) && strlen(dep) < sizeof(buf) - 2) + { + strcpy(buf, dep + 15); + if ((p = strchr(buf, ')')) != 0) + *p = 0; + id = pool_str2id(pool, buf, 1); + id = pool_rel2id(pool, NAMESPACE_OTHERPROVIDERS, id, REL_NAMESPACE, 1); + repo->idarraydata[i] = id; + } + } + return conflicts; +} + +void +repo_rewrite_suse_deps(Solvable *s, Offset freshens) +{ + s->supplements = repo_fix_supplements(s->repo, s->provides, s->supplements, freshens); + if (s->conflicts) + s->conflicts = repo_fix_conflicts(s->repo, s->conflicts); +} + +/**********************************************************************************/ + +static inline Id +dep2name(Pool *pool, Id dep) +{ + while (ISRELDEP(dep)) + { + Reldep *rd = GETRELDEP(pool, dep); + dep = rd->name; + } + return dep; +} + +static int +providedbyinstalled_multiversion(Pool *pool, Map *installed, Id n, Id con) +{ + Id p, pp; + Solvable *sn = pool->solvables + n; + + FOR_PROVIDES(p, pp, sn->name) + { + Solvable *s = pool->solvables + p; + if (s->name != sn->name || s->arch != sn->arch) + continue; + if (!MAPTST(installed, p)) + continue; + if (pool_match_nevr(pool, pool->solvables + p, con)) + continue; + return 1; /* found installed package that doesn't conflict */ + } + return 0; +} + +static inline int +providedbyinstalled(Pool *pool, Map *installed, Id dep, int ispatch, Map *multiversionmap) +{ + Id p, pp; + FOR_PROVIDES(p, pp, dep) + { + if (p == SYSTEMSOLVABLE) + return -1; + if (ispatch && !pool_match_nevr(pool, pool->solvables + p, dep)) + continue; + if (ispatch && multiversionmap && multiversionmap->size && MAPTST(multiversionmap, p) && ISRELDEP(dep)) + if (providedbyinstalled_multiversion(pool, installed, p, dep)) + continue; + if (MAPTST(installed, p)) + return 1; + } + return 0; +} + +/* xmap: + * 1: installed + * 2: conflicts with installed + * 8: interesting (only true if installed) + * 16: undecided + */ + +static int +providedbyinstalled_multiversion_xmap(Pool *pool, unsigned char *map, Id n, Id con) +{ + Id p, pp; + Solvable *sn = pool->solvables + n; + + FOR_PROVIDES(p, pp, sn->name) + { + Solvable *s = pool->solvables + p; + if (s->name != sn->name || s->arch != sn->arch) + continue; + if ((map[p] & 9) != 9) + continue; + if (pool_match_nevr(pool, pool->solvables + p, con)) + continue; + return 1; /* found installed package that doesn't conflict */ + } + return 0; +} + + +static inline int +providedbyinstalled_xmap(Pool *pool, unsigned char *map, Id dep, int ispatch, Map *multiversionmap) +{ + Id p, pp; + int r = 0; + FOR_PROVIDES(p, pp, dep) + { + if (p == SYSTEMSOLVABLE) + return 1; /* always boring, as never constraining */ + if (ispatch && !pool_match_nevr(pool, pool->solvables + p, dep)) + continue; + if (ispatch && multiversionmap && multiversionmap->size && MAPTST(multiversionmap, p) && ISRELDEP(dep)) + if (providedbyinstalled_multiversion_xmap(pool, map, p, dep)) + continue; + if ((map[p] & 9) == 9) + return 9; + r |= map[p] & 17; + } + return r; +} + +/* FIXME: this mirrors policy_illegal_vendorchange */ +static int +pool_illegal_vendorchange(Pool *pool, Solvable *s1, Solvable *s2) +{ + Id v1, v2; + Id vendormask1, vendormask2; + + if (pool->custom_vendorcheck) + return pool->custom_vendorcheck(pool, s1, s2); + /* treat a missing vendor as empty string */ + v1 = s1->vendor ? s1->vendor : ID_EMPTY; + v2 = s2->vendor ? s2->vendor : ID_EMPTY; + if (v1 == v2) + return 0; + vendormask1 = pool_vendor2mask(pool, v1); + if (!vendormask1) + return 1; /* can't match */ + vendormask2 = pool_vendor2mask(pool, v2); + if ((vendormask1 & vendormask2) != 0) + return 0; + return 1; /* no class matches */ +} + +/* check if this patch is relevant according to the vendor. To bad that patches + * don't have a vendor, so we need to do some careful repo testing. */ +int +solvable_is_irrelevant_patch(Solvable *s, Map *installedmap) +{ + Pool *pool = s->repo->pool; + Id con, *conp; + int hadpatchpackage = 0; + + if (!s->conflicts) + return 0; + conp = s->repo->idarraydata + s->conflicts; + while ((con = *conp++) != 0) + { + Reldep *rd; + Id p, pp, p2, pp2; + if (!ISRELDEP(con)) + continue; + rd = GETRELDEP(pool, con); + if (rd->flags != REL_LT) + continue; + FOR_PROVIDES(p, pp, con) + { + Solvable *si; + if (!MAPTST(installedmap, p)) + continue; + si = pool->solvables + p; + if (!pool_match_nevr(pool, si, con)) + continue; + FOR_PROVIDES(p2, pp2, rd->name) + { + Solvable *s2 = pool->solvables + p2; + if (!pool_match_nevr(pool, s2, rd->name)) + continue; + if (pool_match_nevr(pool, s2, con)) + continue; /* does not fulfill patch */ + if (s2->repo == s->repo) + { + hadpatchpackage = 1; + /* ok, we have a package from the patch repo that solves the conflict. check vendor */ + if (si->vendor == s2->vendor) + return 0; + if (!pool_illegal_vendorchange(pool, si, s2)) + return 0; + /* vendor change was illegal, ignore conflict */ + } + } + } + } + /* if we didn't find a patchpackage don't claim that the patch is irrelevant */ + if (!hadpatchpackage) + return 0; + return 1; +} + +/* + * solvable_trivial_installable_map - answers if a solvable is installable + * without any other installs/deinstalls. + * The packages considered to be installed are provided via the + * installedmap bitmap. A additional "conflictsmap" bitmap providing + * information about the conflicts of the installed packages can be + * used for extra speed up. Provide a NULL pointer if you do not + * have this information. + * Both maps can be created with pool_create_state_maps() or + * solver_create_state_maps(). + * + * returns: + * 1: solvable is installable without any other package changes + * 0: solvable is not installable + * -1: solvable is installable, but doesn't constrain any installed packages + */ +int +solvable_trivial_installable_map(Solvable *s, Map *installedmap, Map *conflictsmap, Map *multiversionmap) +{ + Pool *pool = s->repo->pool; + Solvable *s2; + Id p, *dp; + Id *reqp, req; + Id *conp, con; + int r, interesting = 0; + + if (conflictsmap && MAPTST(conflictsmap, s - pool->solvables)) + return 0; + if (s->requires) + { + reqp = s->repo->idarraydata + s->requires; + while ((req = *reqp++) != 0) + { + if (req == SOLVABLE_PREREQMARKER) + continue; + r = providedbyinstalled(pool, installedmap, req, 0, 0); + if (!r) + return 0; + if (r > 0) + interesting = 1; + } + } + if (s->conflicts) + { + int ispatch = 0; + + if (!strncmp("patch:", pool_id2str(pool, s->name), 6)) + ispatch = 1; + conp = s->repo->idarraydata + s->conflicts; + while ((con = *conp++) != 0) + { + if (providedbyinstalled(pool, installedmap, con, ispatch, multiversionmap)) + { + if (ispatch && solvable_is_irrelevant_patch(s, installedmap)) + return -1; + return 0; + } + if (!interesting && ISRELDEP(con)) + { + con = dep2name(pool, con); + if (providedbyinstalled(pool, installedmap, con, ispatch, multiversionmap)) + interesting = 1; + } + } + if (ispatch && interesting && solvable_is_irrelevant_patch(s, installedmap)) + interesting = 0; + } + if (!conflictsmap) + { + int i; + + p = s - pool->solvables; + for (i = 1; i < pool->nsolvables; i++) + { + if (!MAPTST(installedmap, i)) + continue; + s2 = pool->solvables + i; + if (!s2->conflicts) + continue; + conp = s2->repo->idarraydata + s2->conflicts; + while ((con = *conp++) != 0) + { + dp = pool_whatprovides_ptr(pool, con); + for (; *dp; dp++) + if (*dp == p) + return 0; + } + } + } + return interesting ? 1 : -1; +} + +/* + * different interface for solvable_trivial_installable_map, where + * the information about the installed packages is provided + * by a queue. + */ +int +solvable_trivial_installable_queue(Solvable *s, Queue *installed, Map *multiversionmap) +{ + Pool *pool = s->repo->pool; + int i; + Id p; + Map installedmap; + int r; + + map_init(&installedmap, pool->nsolvables); + for (i = 0; i < installed->count; i++) + { + p = installed->elements[i]; + if (p > 0) /* makes it work with decisionq */ + MAPSET(&installedmap, p); + } + r = solvable_trivial_installable_map(s, &installedmap, 0, multiversionmap); + map_free(&installedmap); + return r; +} + +/* + * different interface for solvable_trivial_installable_map, where + * the information about the installed packages is provided + * by a repo containing the installed solvables. + */ +int +solvable_trivial_installable_repo(Solvable *s, Repo *installed, Map *multiversionmap) +{ + Pool *pool = s->repo->pool; + Id p; + Solvable *s2; + Map installedmap; + int r; + + map_init(&installedmap, pool->nsolvables); + FOR_REPO_SOLVABLES(installed, p, s2) + MAPSET(&installedmap, p); + r = solvable_trivial_installable_map(s, &installedmap, 0, multiversionmap); + map_free(&installedmap); + return r; +} + +/* + * pool_trivial_installable - calculate if a set of solvables is + * trivial installable without any other installs/deinstalls of + * packages not belonging to the set. + * + * the state is returned in the result queue: + * 1: solvable is installable without any other package changes + * 0: solvable is not installable + * -1: solvable is installable, but doesn't constrain any installed packages + */ + +void +pool_trivial_installable_multiversionmap(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res, Map *multiversionmap) +{ + int i, r, m, did; + Id p, *dp, con, *conp, req, *reqp; + unsigned char *map; + Solvable *s; + + map = solv_calloc(pool->nsolvables, 1); + for (p = 1; p < pool->nsolvables; p++) + { + if (!MAPTST(installedmap, p)) + continue; + map[p] |= 9; + s = pool->solvables + p; + if (!s->conflicts) + continue; + conp = s->repo->idarraydata + s->conflicts; + while ((con = *conp++) != 0) + { + dp = pool_whatprovides_ptr(pool, con); + for (; *dp; dp++) + map[p] |= 2; /* XXX: self conflict ? */ + } + } + for (i = 0; i < pkgs->count; i++) + map[pkgs->elements[i]] = 16; + + for (i = 0, did = 0; did < pkgs->count; i++, did++) + { + if (i == pkgs->count) + i = 0; + p = pkgs->elements[i]; + if ((map[p] & 16) == 0) + continue; + if ((map[p] & 2) != 0) + { + map[p] = 2; + continue; + } + s = pool->solvables + p; + m = 1; + if (s->requires) + { + reqp = s->repo->idarraydata + s->requires; + while ((req = *reqp++) != 0) + { + if (req == SOLVABLE_PREREQMARKER) + continue; + r = providedbyinstalled_xmap(pool, map, req, 0, 0); + if (!r) + { + /* decided and miss */ + map[p] = 2; + did = 0; + break; + } + if (r == 16) + break; /* undecided */ + m |= r; /* 1 | 9 | 17 */ + } + if (req) + continue; + if ((m & 9) == 9) + m = 9; + } + if (s->conflicts) + { + int ispatch = 0; /* see solver.c patch handling */ + + if (!strncmp("patch:", pool_id2str(pool, s->name), 6)) + ispatch = 1; + conp = s->repo->idarraydata + s->conflicts; + while ((con = *conp++) != 0) + { + if ((providedbyinstalled_xmap(pool, map, con, ispatch, multiversionmap) & 1) != 0) + { + map[p] = 2; + did = 0; + break; + } + if ((m == 1 || m == 17) && ISRELDEP(con)) + { + con = dep2name(pool, con); + if ((providedbyinstalled_xmap(pool, map, con, ispatch, multiversionmap) & 1) != 0) + m = 9; + } + } + if (con) + continue; /* found a conflict */ + } + if (m != map[p]) + { + map[p] = m; + did = 0; + } + } + queue_free(res); + queue_init_clone(res, pkgs); + for (i = 0; i < pkgs->count; i++) + { + m = map[pkgs->elements[i]]; + if ((m & 9) == 9) + r = 1; + else if (m & 1) + r = -1; + else + r = 0; + res->elements[i] = r; + } + free(map); +} + +void +pool_trivial_installable(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res) +{ + pool_trivial_installable_multiversionmap(pool, installedmap, pkgs, res, 0); +} + +void +solver_trivial_installable(Solver *solv, Queue *pkgs, Queue *res) +{ + Pool *pool = solv->pool; + Map installedmap; + int i; + pool_create_state_maps(pool, &solv->decisionq, &installedmap, 0); + pool_trivial_installable_multiversionmap(pool, &installedmap, pkgs, res, solv->multiversion.size ? &solv->multiversion : 0); + for (i = 0; i < res->count; i++) + if (res->elements[i] != -1) + { + Solvable *s = pool->solvables + pkgs->elements[i]; + if (!strncmp("patch:", pool_id2str(pool, s->name), 6) && solvable_is_irrelevant_patch(s, &installedmap)) + res->elements[i] = -1; + } + map_free(&installedmap); +} + +void +solver_printtrivial(Solver *solv) +{ + Pool *pool = solv->pool; + Queue in, out; + Id p; + const char *n; + Solvable *s; + int i; + + queue_init(&in); + for (p = 1, s = pool->solvables + p; p < solv->pool->nsolvables; p++, s++) + { + n = pool_id2str(pool, s->name); + if (strncmp(n, "patch:", 6) != 0 && strncmp(n, "pattern:", 8) != 0) + continue; + queue_push(&in, p); + } + if (!in.count) + { + queue_free(&in); + return; + } + queue_init(&out); + solver_trivial_installable(solv, &in, &out); + POOL_DEBUG(SOLV_DEBUG_RESULT, "trivial installable status:\n"); + for (i = 0; i < in.count; i++) + POOL_DEBUG(SOLV_DEBUG_RESULT, " %s: %d\n", pool_solvid2str(pool, in.elements[i]), out.elements[i]); + POOL_DEBUG(SOLV_DEBUG_RESULT, "\n"); + queue_free(&in); + queue_free(&out); +} + + diff --git a/src/transaction.c b/src/transaction.c index ffe1ec2..9a32966 100644 --- a/src/transaction.c +++ b/src/transaction.c @@ -56,6 +56,14 @@ obsq_sortcmp(const void *ap, const void *bp, void *dp) r = pool_evrcmp(pool, oas->evr, obs->evr, EVRCMP_COMPARE); if (r) return -r; /* highest version first */ + if (oas->arch != obs->arch) + { + /* bring same arch to front */ + if (oas->arch == s->arch) + return -1; + if (obs->arch == s->arch) + return 1; + } return oa - ob; } |