X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fpool.c;h=e375b915c4989b541f8b57c8e2a37c8a5e2880e1;hb=42f00b0f81834d61893165bf2486ee2771fe2446;hp=98fe188bf728525210f96246e7fac3e872934b91;hpb=e78a2b4d833a85e40d808952a56482309fed8543;p=platform%2Fupstream%2Flibsolv.git diff --git a/src/pool.c b/src/pool.c index 98fe188..e375b91 100644 --- a/src/pool.c +++ b/src/pool.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Novell Inc. + * Copyright (c) 2007-2009, Novell Inc. * * This program is licensed under the BSD license, read LICENSE.BSD * for further information @@ -76,8 +76,7 @@ pool_free(Pool *pool) repo_freeallrepos(pool, 1); sat_free(pool->id2arch); sat_free(pool->solvables); - sat_free(pool->ss.stringspace); - sat_free(pool->ss.strings); + stringpool_free(&pool->ss); sat_free(pool->rels); queue_free(&pool->vendormap); for (i = 0; i < POOL_TMPSPACEBUF; i++) @@ -124,13 +123,20 @@ pool_free_solvable_block(Pool *pool, Id start, int count, int reuseids) } -static Pool *pool_shrink_whatprovides_sortcmp_data; +void +pool_set_installed(Pool *pool, Repo *installed) +{ + if (pool->installed == installed) + return; + pool->installed = installed; + pool_freewhatprovides(pool); +} static int -pool_shrink_whatprovides_sortcmp(const void *ap, const void *bp) +pool_shrink_whatprovides_sortcmp(const void *ap, const void *bp, void *dp) { int r; - Pool *pool = pool_shrink_whatprovides_sortcmp_data; + Pool *pool = dp; Id oa, ob, *da, *db; oa = pool->whatprovides[*(Id *)ap]; ob = pool->whatprovides[*(Id *)bp]; @@ -170,8 +176,7 @@ pool_shrink_whatprovides(Pool *pool) sorted = sat_malloc2(pool->ss.nstrings, sizeof(Id)); for (id = 0; id < pool->ss.nstrings; id++) sorted[id] = id; - pool_shrink_whatprovides_sortcmp_data = pool; - qsort(sorted + 1, pool->ss.nstrings - 1, sizeof(Id), pool_shrink_whatprovides_sortcmp); + sat_sort(sorted + 1, pool->ss.nstrings - 1, sizeof(Id), pool_shrink_whatprovides_sortcmp, pool); last = 0; lastid = 0; for (i = 1; i < pool->ss.nstrings; i++) @@ -252,7 +257,10 @@ pool_createwhatprovides(Pool *pool) Offset *idp, n; Offset *whatprovides; Id *whatprovidesdata, *d; + Repo *installed = pool->installed; + unsigned int now; + now = sat_timems(0); POOL_DEBUG(SAT_DEBUG_STATS, "number of solvables: %d\n", pool->nsolvables); POOL_DEBUG(SAT_DEBUG_STATS, "number of ids: %d + %d\n", pool->ss.nstrings, pool->nrels); @@ -269,7 +277,9 @@ pool_createwhatprovides(Pool *pool) s = pool->solvables + i; if (!s->provides) continue; - if (!pool_installable(pool, s)) + /* we always need the installed solvable in the whatprovides data, + otherwise obsoletes/conflicts on them won't work */ + if (s->repo != installed && !pool_installable(pool, s)) continue; pp = s->repo->idarraydata + s->provides; while ((id = *pp++) != ID_NULL) @@ -315,7 +325,7 @@ pool_createwhatprovides(Pool *pool) s = pool->solvables + i; if (!s->provides) continue; - if (!pool_installable(pool, s)) + if (s->repo != installed && !pool_installable(pool, s)) continue; /* for all provides of this solvable */ @@ -333,8 +343,8 @@ pool_createwhatprovides(Pool *pool) d++; while (*d) /* find free slot */ d++; - if (d[-1] == i) - continue; + if (d[-1] == i) /* solvable already tacked at end ? */ + continue; /* Y: skip, on to next provides */ } *d = i; /* put solvable Id into data */ } @@ -343,11 +353,14 @@ pool_createwhatprovides(Pool *pool) pool->whatprovidesdataoff = off; pool->whatprovidesdataleft = extra; pool_shrink_whatprovides(pool); + POOL_DEBUG(SAT_DEBUG_STATS, "whatprovides memory used: %d K id array, %d K data\n", (pool->ss.nstrings + pool->nrels + WHATPROVIDES_BLOCK) / (int)(1024/sizeof(Id)), (pool->whatprovidesdataoff + pool->whatprovidesdataleft) / (int)(1024/sizeof(Id))); + POOL_DEBUG(SAT_DEBUG_STATS, "createwhatprovides took %d ms\n", sat_timems(now)); } /* * free all of our whatprovides data - * be careful, everything internalized with pool_queuetowhatprovides is gone, too + * be careful, everything internalized with pool_queuetowhatprovides is + * gone, too */ void pool_freewhatprovides(Pool *pool) @@ -377,8 +390,8 @@ pool_queuetowhatprovides(Pool *pool, Queue *q) Offset off; int count = q->count; - if (count == 0) /* queue empty -> ID_EMPTY */ - return ID_EMPTY; + if (count == 0) /* queue empty -> 1 */ + return 1; /* extend whatprovidesdata if needed, +1 for ID_NULL-termination */ if (pool->whatprovidesdataleft < count + 1) @@ -403,6 +416,109 @@ pool_queuetowhatprovides(Pool *pool, Queue *q) /*************************************************************************/ +/* check if a package's nevr matches a dependency */ + +int +pool_match_nevr_rel(Pool *pool, Solvable *s, Id d) +{ + Reldep *rd = GETRELDEP(pool, d); + Id name = rd->name; + Id evr = rd->evr; + int flags = rd->flags; + + if (flags > 7) + { + switch (flags) + { + case REL_ARCH: + if (s->arch != evr) + return 0; + return pool_match_nevr(pool, s, name); + case REL_OR: + if (pool_match_nevr(pool, s, name)) + return 1; + return pool_match_nevr(pool, s, evr); + case REL_AND: + case REL_WITH: + if (!pool_match_nevr(pool, s, name)) + return 0; + return pool_match_nevr(pool, s, evr); + default: + return 0; + } + } + if (!pool_match_nevr(pool, s, name)) + return 0; + if (evr == s->evr) + return flags & 2 ? 1 : 0; + if (!flags) + return 0; + if (flags == 7) + return 1; + if (flags != 2 && flags != 5) + flags ^= 5; +#ifdef DEBIAN_SEMANTICS + if ((flags & (1 << (1 + evrcmp(pool, s->evr, evr, EVRCMP_COMPARE)))) != 0) + return 1; +#else + if ((flags & (1 << (1 + evrcmp(pool, s->evr, evr, EVRCMP_MATCH_RELEASE)))) != 0) + return 1; +#endif + return 0; +} + +/* match two dependencies */ + +int +pool_match_dep(Pool *pool, Id d1, Id d2) +{ + Reldep *rd1, *rd2; + int pflags, flags; + + if (d1 == d2) + return 1; + if (!ISRELDEP(d1)) + { + if (!ISRELDEP(d2)) + return 0; + rd2 = GETRELDEP(pool, d2); + return pool_match_dep(pool, d1, rd2->name); + } + rd1 = GETRELDEP(pool, d1); + if (!ISRELDEP(d2)) + { + return pool_match_dep(pool, rd1->name, d2); + } + rd2 = GETRELDEP(pool, d2); + if (!pool_match_dep(pool, rd1->name, rd2->name)) + return 0; + pflags = rd1->flags; + flags = rd2->flags; + if (!pflags || !flags || pflags >= 8 || flags >= 8) + return 0; + if (flags == 7 || pflags == 7) + return 1; + if ((pflags & flags & 5) != 0) + return 1; + if (rd1->evr == rd2->evr) + { + if ((pflags & flags & 2) != 0) + return 1; + } + else + { + int f = flags == 5 ? 5 : flags == 2 ? pflags : (flags ^ 5) & (pflags | 5); +#ifdef DEBIAN_SEMANTICS + if ((f & (1 << (1 + evrcmp(pool, rd1->evr, rd2->evr, EVRCMP_COMPARE)))) != 0) + return 1; +#else + if ((f & (1 << (1 + evrcmp(pool, rd1->evr, rd2->evr, EVRCMP_MATCH_RELEASE)))) != 0) + return 1; +#endif + } + return 0; +} + /* * addrelproviders * @@ -411,7 +527,7 @@ pool_queuetowhatprovides(Pool *pool, Queue *q) * */ -Id * +Id pool_addrelproviders(Pool *pool, Id d) { Reldep *rd = GETRELDEP(pool, d); @@ -422,8 +538,7 @@ pool_addrelproviders(Pool *pool, Id d) Id evr = rd->evr; int flags = rd->flags; Id pid, *pidp; - Id p, *pp, *pp2, *pp3; - int i; + Id p, wp, *pp, *pp2, *pp3; d = GETRELID(d); queue_init_buffer(&plist, buf, sizeof(buf)/sizeof(*buf)); @@ -431,8 +546,8 @@ pool_addrelproviders(Pool *pool, Id d) { case REL_AND: case REL_WITH: - pp = pool_whatprovides(pool, name); - pp2 = pool_whatprovides(pool, evr); + pp = pool_whatprovides_ptr(pool, name); + pp2 = pool_whatprovides_ptr(pool, evr); while ((p = *pp++) != 0) { for (pp3 = pp2; *pp3;) @@ -444,14 +559,20 @@ pool_addrelproviders(Pool *pool, Id d) } break; case REL_OR: - pp = pool_whatprovides(pool, name); + pp = pool_whatprovides_ptr(pool, name); while ((p = *pp++) != 0) queue_push(&plist, p); - pp = pool_whatprovides(pool, evr); + pp = pool_whatprovides_ptr(pool, evr); while ((p = *pp++) != 0) queue_pushunique(&plist, p); break; case REL_NAMESPACE: + if (name == NAMESPACE_OTHERPROVIDERS) + { + wp = pool_whatprovides(pool, evr); + pool->whatprovides_rel[d] = wp; + return wp; + } if (pool->nscallback) { /* ask callback which packages provide the dependency @@ -464,25 +585,44 @@ pool_addrelproviders(Pool *pool, Id d) { queue_free(&plist); pool->whatprovides_rel[d] = p; - return pool->whatprovidesdata + p; + return p; } if (p == 1) queue_push(&plist, SYSTEMSOLVABLE); } break; case REL_ARCH: - pp = pool_whatprovides(pool, name); - i = 0; + /* small hack: make it possible to match .src + * we have to iterate over the solvables as src packages do not + * provide anything, thus they are not indexed in our + * whatprovides hash */ + if (evr == ARCH_SRC) + { + Solvable *s; + for (p = 1, s = pool->solvables + p; p < pool->nsolvables; p++, s++) + { + if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) + continue; + if (pool_match_nevr(pool, s, name)) + queue_push(&plist, p); + } + break; + } + wp = pool_whatprovides(pool, name); + pp = pool->whatprovidesdata + wp; while ((p = *pp++) != 0) { Solvable *s = pool->solvables + p; if (s->arch == evr) queue_push(&plist, p); else - i = 1; + wp = 0; + } + if (wp) + { + pool->whatprovides_rel[d] = wp; + return wp; } - if (i == 0) - return pp; break; default: break; @@ -494,7 +634,7 @@ pool_addrelproviders(Pool *pool, Id d) #endif if (flags && flags < 8) { - pp = pool_whatprovides(pool, name); + pp = pool_whatprovides_ptr(pool, name); while (ISRELDEP(name)) { rd = GETRELDEP(pool, name); @@ -502,11 +642,19 @@ pool_addrelproviders(Pool *pool, Id d) } while ((p = *pp++) != 0) { + Solvable *s = pool->solvables + p; #if 0 - POOL_DEBUG(DEBUG_1, "addrelproviders: checking package %s\n", id2str(pool, pool->p[p].name)); + POOL_DEBUG(DEBUG_1, "addrelproviders: checking package %s\n", id2str(pool, s->name)); #endif + if (!s->provides) + { + /* no provides - check nevr */ + if (pool_match_nevr_rel(pool, s, MAKERELDEP(d))) + queue_push(&plist, p); + continue; + } /* solvable p provides name in some rels */ - pidp = pool->solvables[p].repo->idarraydata + pool->solvables[p].provides; + pidp = s->repo->idarraydata + s->provides; while ((pid = *pidp++) != 0) { int pflags; @@ -543,8 +691,13 @@ pool_addrelproviders(Pool *pool, Id d) else { int f = flags == 5 ? 5 : flags == 2 ? pflags : (flags ^ 5) & (pflags | 5); +#ifdef DEBIAN_SEMANTICS + if ((f & (1 << (1 + evrcmp(pool, pevr, evr, EVRCMP_COMPARE)))) != 0) + break; +#else if ((f & (1 << (1 + evrcmp(pool, pevr, evr, EVRCMP_MATCH_RELEASE)))) != 0) break; +#endif } } if (!pid) @@ -562,7 +715,7 @@ pool_addrelproviders(Pool *pool, Id d) pool->whatprovides_rel[d] = pool_queuetowhatprovides(pool, &plist); queue_free(&plist); - return pool->whatprovidesdata + pool->whatprovides_rel[d]; + return pool->whatprovides_rel[d]; } /*************************************************************************/ @@ -733,16 +886,26 @@ addfileprovides_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyV return 0; } +static int +addfileprovides_setid_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv) +{ + Map *provideids = cbdata; + if (key->type != REPOKEY_TYPE_IDARRAY) + return 0; + MAPSET(provideids, kv->id); + return kv->eof ? SEARCH_NEXT_SOLVABLE : 0; +} + static void pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, struct searchfiles *sf, Repo *repoonly) { - Id p, start, end, *idp; + Id p, start, end; Solvable *s; Repodata *data = 0, *nextdata; Repo *oldrepo = 0; int dataincludes = 0; - int i; + int i, j; Map providedids; cbd->nfiles = sf->nfiles; @@ -765,6 +928,7 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru { if (!s->repo || (repoonly && s->repo != repoonly)) continue; + /* check if p is in (oldrepo,data) */ if (s->repo != oldrepo || (data && p >= data->end)) { data = 0; @@ -772,28 +936,35 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru } if (oldrepo == 0) { + /* nope, find new repo/repodata */ + /* if we don't find a match, set data to the next repodata */ nextdata = 0; for (i = 0, data = s->repo->repodata; i < s->repo->nrepodata; i++, data++) { - if (!data->addedfileprovides || p >= data->end) + if (p >= data->end) + continue; + if (data->state != REPODATA_AVAILABLE) continue; + for (j = 1; j < data->nkeys; j++) + if (data->keys[j].name == REPOSITORY_ADDEDFILEPROVIDES && data->keys[j].type == REPOKEY_TYPE_IDARRAY) + break; + if (j == data->nkeys) + continue; + /* great, this repodata contains addedfileprovides */ if (!nextdata || nextdata->start > data->start) nextdata = data; if (p >= data->start) break; } if (i == s->repo->nrepodata) - data = nextdata; + data = nextdata; /* no direct hit, use next repodata */ if (data) { map_init(&providedids, pool->ss.nstrings); - for (idp = data->addedfileprovides; *idp; idp++) - MAPSET(&providedids, *idp); + repodata_search(data, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, 0, addfileprovides_setid_cb, &providedids); for (i = 0; i < cbd->nfiles; i++) if (!MAPTST(&providedids, cbd->ids[i])) - { - break; - } + break; map_free(&providedids); dataincludes = i == cbd->nfiles; } @@ -839,8 +1010,6 @@ pool_addfileprovides_ids(Pool *pool, Repo *installed, Id **idp) pool_addfileprovides_dep(pool, repo->idarraydata + s->supplements, &sf, isfp); if (s->enhances) pool_addfileprovides_dep(pool, repo->idarraydata + s->enhances, &sf, isfp); - if (s->freshens) - pool_addfileprovides_dep(pool, repo->idarraydata + s->freshens, &sf, isfp); } map_free(&sf.seen); map_free(&isf.seen); @@ -896,9 +1065,9 @@ pool_addfileprovides_ids(Pool *pool, Repo *installed, Id **idp) } void -pool_addfileprovides(Pool *pool, Repo *installed) +pool_addfileprovides(Pool *pool) { - pool_addfileprovides_ids(pool, installed, 0); + pool_addfileprovides_ids(pool, pool->installed, 0); } void @@ -916,6 +1085,12 @@ pool_search(Pool *pool, Id p, Id key, const char *match, int flags, int (*callba repo_search(pool->solvables[p].repo, p, key, match, flags, callback, cbdata); } +void +pool_clear_pos(Pool *pool) +{ + memset(&pool->pos, 0, sizeof(pool->pos)); +} + void pool_set_languages(Pool *pool, const char **languages, int nlanguages) @@ -938,6 +1113,28 @@ pool_set_languages(Pool *pool, const char **languages, int nlanguages) pool->languages[i] = strdup(languages[i]); } +Id +pool_id2langid(Pool *pool, Id id, const char *lang, int create) +{ + const char *n; + char buf[256], *p; + int l; + + if (!lang) + return id; + n = id2str(pool, id); + l = strlen(n) + strlen(lang) + 2; + if (l > sizeof(buf)) + p = sat_malloc(strlen(n) + strlen(lang) + 2); + else + p = buf; + sprintf(p, "%s:%s", n, lang); + id = str2id(pool, p, create); + if (p != buf) + free(p); + return id; +} + char * pool_alloctmpspace(Pool *pool, int len) { @@ -967,6 +1164,7 @@ struct ducbdata { DUChanges *mps; struct mptree *mptree; int addsub; + int hasdu; Id *dirmap; int nmap; @@ -1032,6 +1230,7 @@ solver_fill_DU_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyVa cbd->nmap = data->dirpool.ndirs; cbd->olddata = data; } + cbd->hasdu = 1; if (value->id < 0 || value->id >= cbd->nmap) return 0; mp = cbd->dirmap[value->id]; @@ -1065,7 +1264,7 @@ propagate_mountpoints(struct mptree *mptree, int pos, Id mountpoint) #define MPTREE_BLOCK 15 void -pool_calc_duchanges(Pool *pool, Queue *pkgs, DUChanges *mps, int nmps) +pool_calc_duchanges(Pool *pool, Map *installedmap, DUChanges *mps, int nmps) { char *p; const char *path, *compstr; @@ -1074,7 +1273,12 @@ pool_calc_duchanges(Pool *pool, Queue *pkgs, DUChanges *mps, int nmps) int pos, compl; int mp; struct ducbdata cbd; + Solvable *s; + Id sp; + Map ignoredu; + Repo *oldinstalled = pool->installed; + memset(&ignoredu, 0, sizeof(ignoredu)); cbd.mps = mps; cbd.addsub = 0; cbd.dirmap = 0; @@ -1151,38 +1355,290 @@ pool_calc_duchanges(Pool *pool, Queue *pkgs, DUChanges *mps, int nmps) cbd.mptree = mptree; cbd.addsub = 1; - for (i = 0; i < pkgs->count; i++) + for (sp = 1, s = pool->solvables + sp; sp < pool->nsolvables; sp++, s++) { - Id sp = pkgs->elements[i]; - if (sp > 0) - repo_search(pool->solvables[sp].repo, sp, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); + if (!s->repo || (oldinstalled && s->repo == oldinstalled)) + continue; + if (!MAPTST(installedmap, sp)) + continue; + cbd.hasdu = 0; + repo_search(s->repo, sp, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); + if (!cbd.hasdu && oldinstalled) + { + Id op, opp; + /* no du data available, ignore data of all installed solvables we obsolete */ + if (!ignoredu.map) + map_init(&ignoredu, oldinstalled->end - oldinstalled->start); + if (s->obsoletes) + { + Id obs, *obsp = s->repo->idarraydata + s->obsoletes; + while ((obs = *obsp++) != 0) + FOR_PROVIDES(op, opp, obs) + if (op >= oldinstalled->start && op < oldinstalled->end) + MAPSET(&ignoredu, op - oldinstalled->start); + } + FOR_PROVIDES(op, opp, s->name) + if (pool->solvables[op].name == s->name) + if (op >= oldinstalled->start && op < oldinstalled->end) + MAPSET(&ignoredu, op - oldinstalled->start); + } } cbd.addsub = -1; - for (i = 0; i < pkgs->count; i++) + if (oldinstalled) { - Id sp = pkgs->elements[i]; - if (sp < 0) - repo_search(pool->solvables[-sp].repo, -sp, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); + /* assumes we allways have du data for installed solvables */ + FOR_REPO_SOLVABLES(oldinstalled, sp, s) + { + if (MAPTST(installedmap, sp)) + continue; + if (ignoredu.map && MAPTST(&ignoredu, sp - oldinstalled->start)) + continue; + repo_search(oldinstalled, sp, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); + } } + if (ignoredu.map) + map_free(&ignoredu); sat_free(cbd.dirmap); sat_free(mptree); } int -pool_calc_installsizechange(Pool *pool, Queue *pkgs) +pool_calc_installsizechange(Pool *pool, Map *installedmap) { - int i, change; + Id sp; + Solvable *s; + int change = 0; + Repo *oldinstalled = pool->installed; - change = 0; - for (i = 0; i < pkgs->count; i++) + for (sp = 1, s = pool->solvables + sp; sp < pool->nsolvables; sp++, s++) { - Id sp = pkgs->elements[i]; - if (sp > 0) - change += repo_lookup_num(pool->solvables + sp, SOLVABLE_INSTALLSIZE); - else if (sp < 0) - change -= repo_lookup_num(pool->solvables - sp, SOLVABLE_INSTALLSIZE); + if (!s->repo || (oldinstalled && s->repo == oldinstalled)) + continue; + if (!MAPTST(installedmap, sp)) + continue; + change += solvable_lookup_num(s, SOLVABLE_INSTALLSIZE, 0); + } + if (oldinstalled) + { + FOR_REPO_SOLVABLES(oldinstalled, sp, s) + { + if (MAPTST(installedmap, sp)) + continue; + change -= solvable_lookup_num(s, SOLVABLE_INSTALLSIZE, 0); + } } return change; } +/* 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 = rd = GETRELDEP(pool, dep); + dep = rd->name; + } + return dep; +} + +static int providedbyinstalled_multiversion(Pool *pool, unsigned char *map, Id n, Id dep) +{ + 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) + return 1; + } + return 0; +} + +static inline int providedbyinstalled(Pool *pool, unsigned char *map, Id dep, int ispatch, Map *noobsoletesmap) +{ + 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 && noobsoletesmap && noobsoletesmap->size && MAPTST(noobsoletesmap, 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_noobsoletesmap(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res, Map *noobsoletesmap) +{ + int i, r, m, did; + Id p, *dp, con, *conp, req, *reqp; + unsigned char *map; + Solvable *s; + + map = sat_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; + break; + } + m |= r; /* 1 | 9 | 16 | 17 */ + } + if (req) + continue; + if ((m & 9) == 9) + m = 9; + } + if (s->conflicts) + { + int ispatch = 0; /* see solver.c patch handling */ + + if (!strncmp("patch:", id2str(pool, s->name), 6)) + ispatch = 1; + conp = s->repo->idarraydata + s->conflicts; + while ((con = *conp++) != 0) + { + if ((providedbyinstalled(pool, map, con, ispatch, noobsoletesmap) & 1) != 0) + { + map[p] = 2; + break; + } + if ((m == 1 || m == 17) && ISRELDEP(con)) + { + con = dep2name(pool, con); + if ((providedbyinstalled(pool, map, con, ispatch, noobsoletesmap) & 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_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_noobsoletesmap(pool, installedmap, pkgs, res, 0); +} + // EOF