X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fpool.c;h=60cc0f49c7dbfc7da8edb1c44e996ce55c3cc117;hb=e679b515eddb3dd340fb25620de0160211f40fdc;hp=c51c62eca9d43c8263fe70ab807d99cc3fe8d86f;hpb=bc8d0a48b41d6cc4d79f1c062dda7ed230841644;p=platform%2Fupstream%2Flibsolv.git diff --git a/src/pool.c b/src/pool.c index c51c62e..60cc0f4 100644 --- a/src/pool.c +++ b/src/pool.c @@ -44,7 +44,7 @@ pool_create(void) pool = (Pool *)solv_calloc(1, sizeof(*pool)); - stringpool_init (&pool->ss, initpool_data); + stringpool_init(&pool->ss, initpool_data); /* alloc space for RelDep 0 */ pool->rels = solv_extend_resize(0, 1, sizeof(Reldep), REL_BLOCK); @@ -705,6 +705,10 @@ pool_match_nevr_rel(Pool *pool, Solvable *s, Id d) if (!pool_match_nevr(pool, s, name)) return 0; return pool_match_nevr(pool, s, evr); + case REL_WITHOUT: + if (!pool_match_nevr(pool, s, name)) + return 0; + return !pool_match_nevr(pool, s, evr); case REL_MULTIARCH: if (evr != ARCH_ANY) return 0; @@ -799,7 +803,7 @@ pool_match_flags_evr_rel_compat(Pool *pool, Reldep *range, int flags, int evr) /* public (i.e. not inlined) version of pool_match_flags_evr */ int -pool_intersect_evrs(Pool *pool, int pflags, Id pevr, int flags, int evr) +pool_intersect_evrs(Pool *pool, int pflags, Id pevr, int flags, Id evr) { return pool_match_flags_evr(pool, pflags, pevr, flags, evr); } @@ -818,17 +822,17 @@ pool_match_dep(Pool *pool, Id d1, Id d2) { /* we use potentially matches for complex deps */ rd1 = GETRELDEP(pool, d1); - if (rd1->flags == REL_AND || rd1->flags == REL_OR || rd1->flags == REL_WITH || rd1->flags == REL_COND) + if (rd1->flags == REL_AND || rd1->flags == REL_OR || rd1->flags == REL_WITH || rd1->flags == REL_WITHOUT || rd1->flags == REL_COND || rd1->flags == REL_UNLESS) { if (pool_match_dep(pool, rd1->name, d2)) return 1; - if (rd1->flags == REL_COND && ISRELDEP(rd1->evr)) + if ((rd1->flags == REL_COND || rd1->flags == REL_UNLESS) && ISRELDEP(rd1->evr)) { rd1 = GETRELDEP(pool, rd1->evr); if (rd1->flags != REL_ELSE) return 0; } - if (rd1->flags != REL_COND && pool_match_dep(pool, rd1->evr, d2)) + if (rd1->flags != REL_COND && rd1->flags != REL_UNLESS && rd1->flags != REL_WITHOUT && pool_match_dep(pool, rd1->evr, d2)) return 1; return 0; } @@ -837,17 +841,17 @@ pool_match_dep(Pool *pool, Id d1, Id d2) { /* we use potentially matches for complex deps */ rd2 = GETRELDEP(pool, d2); - if (rd2->flags == REL_AND || rd2->flags == REL_OR || rd2->flags == REL_WITH || rd2->flags == REL_COND) + if (rd2->flags == REL_AND || rd2->flags == REL_OR || rd2->flags == REL_WITH || rd2->flags == REL_WITHOUT || rd2->flags == REL_COND || rd2->flags == REL_UNLESS) { if (pool_match_dep(pool, d1, rd2->name)) return 1; - if (rd2->flags == REL_COND && ISRELDEP(rd2->evr)) + if ((rd2->flags == REL_COND || rd2->flags == REL_UNLESS) && ISRELDEP(rd2->evr)) { rd2 = GETRELDEP(pool, rd2->evr); if (rd2->flags != REL_ELSE) return 0; } - if (rd2->flags != REL_COND && pool_match_dep(pool, d1, rd2->evr)) + if (rd2->flags != REL_COND && rd2->flags != REL_UNLESS && rd2->flags != REL_WITHOUT && pool_match_dep(pool, d1, rd2->evr)) return 1; return 0; } @@ -855,7 +859,7 @@ pool_match_dep(Pool *pool, Id d1, Id d2) if (!ISRELDEP(d1)) { if (!ISRELDEP(d2)) - return 0; + return 0; /* cannot match as d1 != d2 */ rd2 = GETRELDEP(pool, d2); return pool_match_dep(pool, d1, rd2->name); } @@ -998,6 +1002,64 @@ pool_is_kind(Pool *pool, Id name, Id kind) } /* + * rpm eq magic: + * + * some dependencies are of the from "foo = md5sum", like the + * buildid provides. There's not much we can do to speed up + * getting the providers, because rpm's complex evr comparison + * rules get in the way. But we can use the first character(s) + * of the md5sum to do a simple pre-check. + */ +static inline int +rpmeqmagic(Pool *pool, Id evr) +{ + const char *s = pool_id2str(pool, evr); + if (*s == '0') + { + while (*s == '0' && s[1] >= '0' && s[1] <= '9') + s++; + /* ignore epoch 0 */ + if (*s == '0' && s[1] == ':') + { + s += 2; + while (*s == '0' && s[1] >= '0' && s[1] <= '9') + s++; + } + } + if (*s >= '0' && *s <= '9') + { + if (s[1] >= '0' && s[1] <= '9') + return *s + (s[1] << 8); + return *s; + } + if ((*s >= 'a' && *s <= 'z') || (*s >= 'A' && *s <= 'Z')) + { + if ((s[1] >= 'a' && s[1] <= 'z') || (s[1] >= 'A' && s[1] <= 'Z')) + return *s + (s[1] << 8); + return *s; + } + return -1; +} + +static inline int +rpmeqmagic_init(Pool *pool, int flags, Id evr) +{ + if (flags != REL_EQ || pool->disttype != DISTTYPE_RPM || pool->promoteepoch || ISRELDEP(evr)) + return -1; + else + return rpmeqmagic(pool, evr); +} + +static inline int +rpmeqmagic_cantmatch(Pool *pool, int flags, Id evr, int eqmagic) +{ + int peqmagic = rpmeqmagic(pool, evr); + if (peqmagic > 0 && peqmagic != eqmagic) + return 1; + return 0; +} + +/* * addrelproviders * * add packages fulfilling the relation to whatprovides array @@ -1050,11 +1112,26 @@ pool_addrelproviders(Pool *pool, Id d) wp = 0; } break; - + case REL_WITHOUT: + wp = pool_whatprovides(pool, name); + pp2 = pool_whatprovides_ptr(pool, evr); + pp = pool->whatprovidesdata + wp; + while ((p = *pp++) != 0) + { + for (pp3 = pp2; *pp3; pp3++) + if (*pp3 == p) + break; + if (!*pp3) + queue_push(&plist, p); /* use it */ + else + wp = 0; + } + break; case REL_AND: case REL_OR: case REL_COND: - if (flags == REL_COND) + case REL_UNLESS: + if (flags == REL_COND || flags == REL_UNLESS) { if (ISRELDEP(evr)) { @@ -1218,6 +1295,7 @@ pool_addrelproviders(Pool *pool, Id d) else if (flags) { Id *ppaux = 0; + int eqmagic = 0; /* simple version comparison relation */ #if 0 POOL_DEBUG(SOLV_DEBUG_STATS, "addrelproviders: what provides %s?\n", pool_dep2str(pool, name)); @@ -1253,6 +1331,11 @@ pool_addrelproviders(Pool *pool, Id d) prd = GETRELDEP(pool, pid); if (prd->name != name) continue; /* wrong provides name */ + if (!eqmagic) + eqmagic = rpmeqmagic_init(pool, flags, evr); + if (eqmagic > 0 && prd->flags == REL_EQ && !ISRELDEP(prd->evr) && + rpmeqmagic_cantmatch(pool, prd->flags, prd->evr, eqmagic)) + continue; /* right package, both deps are rels. check flags/evr */ if (!pool_match_flags_evr(pool, prd->flags, prd->evr, flags, evr)) continue; @@ -1269,6 +1352,8 @@ pool_addrelproviders(Pool *pool, Id d) continue; } /* solvable p provides name in some rels */ + if (!eqmagic) + eqmagic = rpmeqmagic_init(pool, flags, evr); pidp = s->repo->idarraydata + s->provides; while ((pid = *pidp++) != 0) { @@ -1284,6 +1369,9 @@ pool_addrelproviders(Pool *pool, Id d) if (prd->name != name) continue; /* wrong provides name */ /* right package, both deps are rels. check flags/evr */ + if (eqmagic > 0 && prd->flags == REL_EQ && !ISRELDEP(prd->evr) && + rpmeqmagic_cantmatch(pool, prd->flags, prd->evr, eqmagic)) + continue; if (pool_match_flags_evr(pool, prd->flags, prd->evr, flags, evr)) break; /* matches */ } @@ -1322,7 +1410,8 @@ pool_flush_namespaceproviders(Pool *pool, Id ns, Id evr) continue; if (evr && rd->evr != evr) continue; - pool->whatprovides_rel[d] = 0; + if (pool->whatprovides_rel[d]) + pool_set_whatprovides(pool, MAKERELDEP(d), 0); } } @@ -1335,6 +1424,14 @@ pool_whatmatchesdep(Pool *pool, Id keyname, Id dep, Queue *q, int marker) int i; queue_empty(q); + if (keyname == SOLVABLE_NAME) + { + Id pp; + FOR_PROVIDES(p, pp, dep) + if (pool_match_dep(pool, p, dep)) + queue_push(q, p); + return; + } queue_init(&qq); FOR_POOL_SOLVABLES(p) { @@ -1420,6 +1517,9 @@ pool_error(Pool *pool, int ret, const char *format, ...) { va_list args; int l; + + if (!pool) + return ret; va_start(args, format); if (!pool->errstr) { @@ -1681,224 +1781,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) { @@ -1984,24 +1866,66 @@ pool_lookup_deltalocation(Pool *pool, Id entry, unsigned int *medianrp) return loc; } +void +pool_set_whatprovides(Pool *pool, Id id, Id providers) +{ + int d, nrels = pool->nrels; + Reldep *rd; + Map m; + + /* set new entry */ + if (ISRELDEP(id)) + { + d = GETRELID(id); + pool->whatprovides_rel[d] = providers; + d++; + } + else + { + pool->whatprovides[id] = providers; + if (id < pool->whatprovidesauxoff) + pool->whatprovidesaux[id] = 0; /* sorry */ + d = 1; + } + if (!pool->whatprovides_rel) + return; + /* clear cache of all rels that use it */ + map_init(&m, 0); + for (rd = pool->rels + d; d < nrels; d++, rd++) + { + if (rd->name == id || rd->evr == id || + (m.size && ISRELDEP(rd->name) && MAPTST(&m, GETRELID(rd->name))) || + (m.size && ISRELDEP(rd->evr) && MAPTST(&m, GETRELID(rd->evr)))) + { + pool->whatprovides_rel[d] = 0; /* clear cache */ + if (!m.size) + map_init(&m, nrels); + MAPSET(&m, d); + } + } + map_free(&m); +} + static void add_new_provider(Pool *pool, Id id, Id p) { Queue q; Id *pp; + /* find whatprovides entry */ while (ISRELDEP(id)) { Reldep *rd = GETRELDEP(pool, id); id = rd->name; } + /* add new provider to existing list keeping it sorted */ queue_init(&q); for (pp = pool->whatprovidesdata + pool->whatprovides[id]; *pp; pp++) { if (*pp == p) { - queue_free(&q); + queue_free(&q); /* already have it */ return; } if (*pp > p) @@ -2013,9 +1937,7 @@ add_new_provider(Pool *pool, Id id, Id p) } if (p) queue_push(&q, p); - pool->whatprovides[id] = pool_queuetowhatprovides(pool, &q); - if (id < pool->whatprovidesauxoff) - pool->whatprovidesaux[id] = 0; /* sorry */ + pool_set_whatprovides(pool, id, pool_queuetowhatprovides(pool, &q)); queue_free(&q); } @@ -2042,9 +1964,7 @@ pool_add_fileconflicts_deps(Pool *pool, Queue *conflicts) continue; s->provides = repo_addid_dep(s->repo, s->provides, id, SOLVABLE_FILEMARKER); if (pool->whatprovides) - add_new_provider(pool, fn, p); - if (pool->whatprovides_rel) - pool->whatprovides_rel[GETRELID(id)] = 0; /* clear cache */ + add_new_provider(pool, id, p); s = pool->solvables + q; if (!s->repo) continue;