diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/diskusage.c | 348 | ||||
-rw-r--r-- | src/fileprovides.c | 373 | ||||
-rw-r--r-- | src/knownid.h | 2 | ||||
-rw-r--r-- | src/libsolv.ver | 1 | ||||
-rw-r--r-- | src/linkedpkg.c | 27 | ||||
-rw-r--r-- | src/linkedpkg.h | 3 | ||||
-rw-r--r-- | src/pool.c | 715 | ||||
-rw-r--r-- | src/pool.h | 11 | ||||
-rw-r--r-- | src/poolid.c | 19 | ||||
-rw-r--r-- | src/repodata.c | 25 | ||||
-rw-r--r-- | src/repodata.h | 3 | ||||
-rw-r--r-- | src/rules.c | 206 | ||||
-rw-r--r-- | src/rules.h | 3 | ||||
-rw-r--r-- | src/selection.c | 10 | ||||
-rw-r--r-- | src/solver.c | 37 | ||||
-rw-r--r-- | src/util.c | 4 |
17 files changed, 1024 insertions, 766 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a2c0098..241890d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,7 +18,8 @@ SET (libsolv_SRCS solver.c solverdebug.c repo_solv.c repo_write.c evr.c pool.c 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) + chksum.c md5.c sha1.c sha2.c solvversion.c selection.c + fileprovides.c diskusage.c) SET (libsolv_HEADERS bitmap.h evr.h hash.h policy.h poolarch.h poolvendor.h pool.h diff --git a/src/diskusage.c b/src/diskusage.c new file mode 100644 index 0000000..b764b98 --- /dev/null +++ b/src/diskusage.c @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2007-2016, SUSE LLC + * + * This program is licensed under the BSD license, read LICENSE.BSD + * for further information + */ + +/* + * diskusage.c + * + * calculate needed space on partitions + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <string.h> + +#include "pool.h" +#include "poolarch.h" +#include "repo.h" +#include "util.h" +#include "bitmap.h" + + +struct mptree { + Id sibling; + Id child; + const char *comp; + int compl; + Id mountpoint; +}; + +struct ducbdata { + DUChanges *mps; + struct mptree *mptree; + int addsub; + int hasdu; + + Id *dirmap; + int nmap; + Repodata *olddata; +}; + + +static int +solver_fill_DU_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *value) +{ + struct ducbdata *cbd = cbdata; + Id mp; + + if (data != cbd->olddata) + { + Id dn, mp, comp, *dirmap, *dirs; + int i, compl; + const char *compstr; + struct mptree *mptree; + + /* create map from dir to mptree */ + cbd->dirmap = solv_free(cbd->dirmap); + cbd->nmap = 0; + dirmap = solv_calloc(data->dirpool.ndirs, sizeof(Id)); + mptree = cbd->mptree; + mp = 0; + for (dn = 2, dirs = data->dirpool.dirs + dn; dn < data->dirpool.ndirs; dn++) + { + comp = *dirs++; + if (comp <= 0) + { + mp = dirmap[-comp]; + continue; + } + if (mp < 0) + { + /* unconnected */ + dirmap[dn] = mp; + continue; + } + if (!mptree[mp].child) + { + dirmap[dn] = -mp; + continue; + } + if (data->localpool) + compstr = stringpool_id2str(&data->spool, comp); + else + compstr = pool_id2str(data->repo->pool, comp); + compl = strlen(compstr); + for (i = mptree[mp].child; i; i = mptree[i].sibling) + if (mptree[i].compl == compl && !strncmp(mptree[i].comp, compstr, compl)) + break; + dirmap[dn] = i ? i : -mp; + } + /* change dirmap to point to mountpoint instead of mptree */ + for (dn = 0; dn < data->dirpool.ndirs; dn++) + { + mp = dirmap[dn]; + dirmap[dn] = mptree[mp > 0 ? mp : -mp].mountpoint; + } + cbd->dirmap = dirmap; + 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]; + if (mp < 0) + return 0; + if (cbd->addsub > 0) + { + cbd->mps[mp].kbytes += value->num; + cbd->mps[mp].files += value->num2; + } + else if (!(cbd->mps[mp].flags & DUCHANGES_ONLYADD)) + { + cbd->mps[mp].kbytes -= value->num; + cbd->mps[mp].files -= value->num2; + } + return 0; +} + +static void +propagate_mountpoints(struct mptree *mptree, int pos, Id mountpoint) +{ + int i; + if (mptree[pos].mountpoint == -1) + mptree[pos].mountpoint = mountpoint; + else + mountpoint = mptree[pos].mountpoint; + for (i = mptree[pos].child; i; i = mptree[i].sibling) + propagate_mountpoints(mptree, i, mountpoint); +} + +#define MPTREE_BLOCK 15 + +static struct mptree * +create_mptree(DUChanges *mps, int nmps) +{ + int i, nmptree; + struct mptree *mptree; + int pos, compl; + int mp; + const char *p, *path, *compstr; + + mptree = solv_extend_resize(0, 1, sizeof(struct mptree), MPTREE_BLOCK); + + /* our root node */ + mptree[0].sibling = 0; + mptree[0].child = 0; + mptree[0].comp = 0; + mptree[0].compl = 0; + mptree[0].mountpoint = -1; + nmptree = 1; + + /* create component tree */ + for (mp = 0; mp < nmps; mp++) + { + mps[mp].kbytes = 0; + mps[mp].files = 0; + pos = 0; + path = mps[mp].path; + while(*path == '/') + path++; + while (*path) + { + if ((p = strchr(path, '/')) == 0) + { + compstr = path; + compl = strlen(compstr); + path += compl; + } + else + { + compstr = path; + compl = p - path; + path = p + 1; + while(*path == '/') + path++; + } + for (i = mptree[pos].child; i; i = mptree[i].sibling) + if (mptree[i].compl == compl && !strncmp(mptree[i].comp, compstr, compl)) + break; + if (!i) + { + /* create new node */ + mptree = solv_extend(mptree, nmptree, 1, sizeof(struct mptree), MPTREE_BLOCK); + i = nmptree++; + mptree[i].sibling = mptree[pos].child; + mptree[i].child = 0; + mptree[i].comp = compstr; + mptree[i].compl = compl; + mptree[i].mountpoint = -1; + mptree[pos].child = i; + } + pos = i; + } + mptree[pos].mountpoint = mp; + } + + propagate_mountpoints(mptree, 0, mptree[0].mountpoint); + +#if 0 + for (i = 0; i < nmptree; i++) + { + printf("#%d sibling: %d\n", i, mptree[i].sibling); + printf("#%d child: %d\n", i, mptree[i].child); + printf("#%d comp: %s\n", i, mptree[i].comp); + printf("#%d compl: %d\n", i, mptree[i].compl); + printf("#%d mountpont: %d\n", i, mptree[i].mountpoint); + } +#endif + + return mptree; +} + +void +pool_calc_duchanges(Pool *pool, Map *installedmap, DUChanges *mps, int nmps) +{ + struct mptree *mptree; + struct ducbdata cbd; + Solvable *s; + int i, sp; + Map ignoredu; + Repo *oldinstalled = pool->installed; + int haveonlyadd = 0; + + map_init(&ignoredu, 0); + mptree = create_mptree(mps, nmps); + + for (i = 0; i < nmps; i++) + if ((mps[i].flags & DUCHANGES_ONLYADD) != 0) + haveonlyadd = 1; + cbd.mps = mps; + cbd.dirmap = 0; + cbd.nmap = 0; + cbd.olddata = 0; + cbd.mptree = mptree; + cbd.addsub = 1; + for (sp = 1, s = pool->solvables + sp; sp < pool->nsolvables; sp++, s++) + { + 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; + int didonlyadd = 0; + /* no du data available, ignore data of all installed solvables we obsolete */ + if (!ignoredu.size) + map_grow(&ignoredu, oldinstalled->end - oldinstalled->start); + FOR_PROVIDES(op, opp, s->name) + { + Solvable *s2 = pool->solvables + op; + if (!pool->implicitobsoleteusesprovides && s->name != s2->name) + continue; + if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, s2)) + continue; + if (op >= oldinstalled->start && op < oldinstalled->end) + { + MAPSET(&ignoredu, op - oldinstalled->start); + if (haveonlyadd && pool->solvables[op].repo == oldinstalled && !didonlyadd) + { + repo_search(oldinstalled, op, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); + cbd.addsub = -1; + repo_search(oldinstalled, op, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); + cbd.addsub = 1; + didonlyadd = 1; + } + } + } + if (s->obsoletes) + { + Id obs, *obsp = s->repo->idarraydata + s->obsoletes; + while ((obs = *obsp++) != 0) + FOR_PROVIDES(op, opp, obs) + { + Solvable *s2 = pool->solvables + op; + if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, s2, obs)) + continue; + if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2)) + continue; + if (op >= oldinstalled->start && op < oldinstalled->end) + { + MAPSET(&ignoredu, op - oldinstalled->start); + if (haveonlyadd && pool->solvables[op].repo == oldinstalled && !didonlyadd) + { + repo_search(oldinstalled, op, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); + cbd.addsub = -1; + repo_search(oldinstalled, op, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); + cbd.addsub = 1; + didonlyadd = 1; + } + } + } + } + } + } + cbd.addsub = -1; + if (oldinstalled) + { + /* 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); + } + } + map_free(&ignoredu); + solv_free(cbd.dirmap); + solv_free(mptree); +} + +int +pool_calc_installsizechange(Pool *pool, Map *installedmap) +{ + Id sp; + Solvable *s; + int change = 0; + Repo *oldinstalled = pool->installed; + + for (sp = 1, s = pool->solvables + sp; sp < pool->nsolvables; sp++, s++) + { + if (!s->repo || (oldinstalled && s->repo == oldinstalled)) + continue; + if (!MAPTST(installedmap, sp)) + continue; + change += solvable_lookup_sizek(s, SOLVABLE_INSTALLSIZE, 0); + } + if (oldinstalled) + { + FOR_REPO_SOLVABLES(oldinstalled, sp, s) + { + if (MAPTST(installedmap, sp)) + continue; + change -= solvable_lookup_sizek(s, SOLVABLE_INSTALLSIZE, 0); + } + } + return change; +} + diff --git a/src/fileprovides.c b/src/fileprovides.c new file mode 100644 index 0000000..11ff4f5 --- /dev/null +++ b/src/fileprovides.c @@ -0,0 +1,373 @@ +/* + * Copyright (c) 2007-2016, SUSE LLC + * + * This program is licensed under the BSD license, read LICENSE.BSD + * for further information + */ + +/* + * fileprovides.c + * + * Add missing file dependencies to the package provides + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <string.h> + +#include "pool.h" +#include "repo.h" +#include "util.h" +#include "bitmap.h" + +struct searchfiles { + Id *ids; + int nfiles; + Map seen; +}; + +#define SEARCHFILES_BLOCK 127 + +static void +pool_addfileprovides_dep(Pool *pool, Id *ida, struct searchfiles *sf, struct searchfiles *isf) +{ + Id dep, sid; + const char *s; + struct searchfiles *csf; + + while ((dep = *ida++) != 0) + { + csf = sf; + while (ISRELDEP(dep)) + { + Reldep *rd; + sid = pool->ss.nstrings + GETRELID(dep); + if (MAPTST(&csf->seen, sid)) + { + dep = 0; + break; + } + MAPSET(&csf->seen, sid); + rd = GETRELDEP(pool, dep); + if (rd->flags < 8) + dep = rd->name; + else if (rd->flags == REL_NAMESPACE) + { + if (rd->name == NAMESPACE_SPLITPROVIDES) + { + csf = isf; + if (!csf || MAPTST(&csf->seen, sid)) + { + dep = 0; + break; + } + MAPSET(&csf->seen, sid); + } + dep = rd->evr; + } + else if (rd->flags == REL_FILECONFLICT) + { + dep = 0; + break; + } + else + { + Id ids[2]; + ids[0] = rd->name; + ids[1] = 0; + pool_addfileprovides_dep(pool, ids, csf, isf); + dep = rd->evr; + } + } + if (!dep) + continue; + if (MAPTST(&csf->seen, dep)) + continue; + MAPSET(&csf->seen, dep); + s = pool_id2str(pool, dep); + if (*s != '/') + continue; + if (csf != isf && pool->addedfileprovides == 1 && !repodata_filelistfilter_matches(0, s)) + continue; /* skip non-standard locations csf == isf: installed case */ + csf->ids = solv_extend(csf->ids, csf->nfiles, 1, sizeof(Id), SEARCHFILES_BLOCK); + csf->ids[csf->nfiles++] = dep; + } +} + +struct addfileprovides_cbdata { + int nfiles; + Id *ids; + char **dirs; + char **names; + + Id *dids; + + Map providedids; + + Map useddirs; +}; + +static int +addfileprovides_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *value) +{ + struct addfileprovides_cbdata *cbd = cbdata; + int i; + + if (!cbd->useddirs.size) + { + map_init(&cbd->useddirs, data->dirpool.ndirs + 1); + if (!cbd->dirs) + { + cbd->dirs = solv_malloc2(cbd->nfiles, sizeof(char *)); + cbd->names = solv_malloc2(cbd->nfiles, sizeof(char *)); + for (i = 0; i < cbd->nfiles; i++) + { + char *s = solv_strdup(pool_id2str(data->repo->pool, cbd->ids[i])); + cbd->dirs[i] = s; + s = strrchr(s, '/'); + *s = 0; + cbd->names[i] = s + 1; + } + } + for (i = 0; i < cbd->nfiles; i++) + { + Id did; + if (MAPTST(&cbd->providedids, cbd->ids[i])) + { + cbd->dids[i] = 0; + continue; + } + did = repodata_str2dir(data, cbd->dirs[i], 0); + cbd->dids[i] = did; + if (did) + MAPSET(&cbd->useddirs, did); + } + repodata_free_dircache(data); + } + if (value->id >= data->dirpool.ndirs || !MAPTST(&cbd->useddirs, value->id)) + return 0; + for (i = 0; i < cbd->nfiles; i++) + if (cbd->dids[i] == value->id && !strcmp(cbd->names[i], value->str)) + s->provides = repo_addid_dep(s->repo, s->provides, cbd->ids[i], SOLVABLE_FILEMARKER); + return 0; +} + +static void +pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, struct searchfiles *sf, Repo *repoonly) +{ + Id p; + Repodata *data; + Repo *repo; + Queue fileprovidesq; + int i, j, repoid, repodataid; + int provstart, provend; + Map donemap; + int ndone, incomplete; + + if (!pool->urepos) + return; + + cbd->nfiles = sf->nfiles; + cbd->ids = sf->ids; + cbd->dirs = 0; + cbd->names = 0; + cbd->dids = solv_realloc2(cbd->dids, sf->nfiles, sizeof(Id)); + map_init(&cbd->providedids, pool->ss.nstrings); + + repoid = 1; + repo = repoonly ? repoonly : pool->repos[repoid]; + map_init(&donemap, pool->nsolvables); + queue_init(&fileprovidesq); + provstart = provend = 0; + for (;;) + { + if (!repo || repo->disabled) + { + if (repoonly || ++repoid == pool->nrepos) + break; + repo = pool->repos[repoid]; + continue; + } + ndone = 0; + FOR_REPODATAS(repo, repodataid, data) + { + if (ndone >= repo->nsolvables) + break; + + if (repodata_lookup_idarray(data, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, &fileprovidesq)) + { + map_empty(&cbd->providedids); + for (i = 0; i < fileprovidesq.count; i++) + MAPSET(&cbd->providedids, fileprovidesq.elements[i]); + provstart = data->start; + provend = data->end; + for (i = 0; i < cbd->nfiles; i++) + if (!MAPTST(&cbd->providedids, cbd->ids[i])) + break; + if (i == cbd->nfiles) + { + /* great! no need to search files */ + for (p = data->start; p < data->end; p++) + if (pool->solvables[p].repo == repo) + { + if (MAPTST(&donemap, p)) + continue; + MAPSET(&donemap, p); + ndone++; + } + continue; + } + } + + if (!repodata_has_keyname(data, SOLVABLE_FILELIST)) + continue; + + if (data->start < provstart || data->end > provend) + { + map_empty(&cbd->providedids); + provstart = provend = 0; + } + + /* check if the data is incomplete */ + incomplete = 0; + if (data->state == REPODATA_AVAILABLE) + { + for (j = 1; j < data->nkeys; j++) + if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST) + break; + if (j < data->nkeys) + { +#if 0 + for (i = 0; i < cbd->nfiles; i++) + if (!MAPTST(&cbd->providedids, cbd->ids[i]) && !repodata_filelistfilter_matches(data, pool_id2str(pool, cbd->ids[i]))) + printf("need complete filelist because of %s\n", pool_id2str(pool, cbd->ids[i])); +#endif + for (i = 0; i < cbd->nfiles; i++) + if (!MAPTST(&cbd->providedids, cbd->ids[i]) && !repodata_filelistfilter_matches(data, pool_id2str(pool, cbd->ids[i]))) + break; + if (i < cbd->nfiles) + incomplete = 1; + } + } + + /* do the search */ + map_init(&cbd->useddirs, 0); + for (p = data->start; p < data->end; p++) + if (pool->solvables[p].repo == repo) + { + if (MAPTST(&donemap, p)) + continue; + repodata_search(data, p, SOLVABLE_FILELIST, 0, addfileprovides_cb, cbd); + if (!incomplete) + { + MAPSET(&donemap, p); + ndone++; + } + } + map_free(&cbd->useddirs); + } + + if (repoonly || ++repoid == pool->nrepos) + break; + repo = pool->repos[repoid]; + } + map_free(&donemap); + queue_free(&fileprovidesq); + map_free(&cbd->providedids); + if (cbd->dirs) + { + for (i = 0; i < cbd->nfiles; i++) + solv_free(cbd->dirs[i]); + cbd->dirs = solv_free(cbd->dirs); + cbd->names = solv_free(cbd->names); + } +} + +void +pool_addfileprovides_queue(Pool *pool, Queue *idq, Queue *idqinst) +{ + Solvable *s; + Repo *installed, *repo; + struct searchfiles sf, isf, *isfp; + struct addfileprovides_cbdata cbd; + int i; + unsigned int now; + + installed = pool->installed; + now = solv_timems(0); + memset(&sf, 0, sizeof(sf)); + map_init(&sf.seen, pool->ss.nstrings + pool->nrels); + memset(&isf, 0, sizeof(isf)); + map_init(&isf.seen, pool->ss.nstrings + pool->nrels); + pool->addedfileprovides = pool->addfileprovidesfiltered ? 1 : 2; + + if (idq) + queue_empty(idq); + if (idqinst) + queue_empty(idqinst); + isfp = installed ? &isf : 0; + for (i = 1, s = pool->solvables + i; i < pool->nsolvables; i++, s++) + { + repo = s->repo; + if (!repo) + continue; + if (s->obsoletes) + pool_addfileprovides_dep(pool, repo->idarraydata + s->obsoletes, &sf, isfp); + if (s->conflicts) + pool_addfileprovides_dep(pool, repo->idarraydata + s->conflicts, &sf, isfp); + if (s->requires) + pool_addfileprovides_dep(pool, repo->idarraydata + s->requires, &sf, isfp); + if (s->recommends) + pool_addfileprovides_dep(pool, repo->idarraydata + s->recommends, &sf, isfp); + if (s->suggests) + pool_addfileprovides_dep(pool, repo->idarraydata + s->suggests, &sf, isfp); + if (s->supplements) + pool_addfileprovides_dep(pool, repo->idarraydata + s->supplements, &sf, isfp); + if (s->enhances) + pool_addfileprovides_dep(pool, repo->idarraydata + s->enhances, &sf, isfp); + } + map_free(&sf.seen); + map_free(&isf.seen); + POOL_DEBUG(SOLV_DEBUG_STATS, "found %d file dependencies, %d installed file dependencies\n", sf.nfiles, isf.nfiles); + cbd.dids = 0; + if (sf.nfiles) + { +#if 0 + for (i = 0; i < sf.nfiles; i++) + POOL_DEBUG(SOLV_DEBUG_STATS, "looking up %s in filelist\n", pool_id2str(pool, sf.ids[i])); +#endif + pool_addfileprovides_search(pool, &cbd, &sf, 0); + if (idq) + for (i = 0; i < sf.nfiles; i++) + queue_push(idq, sf.ids[i]); + if (idqinst) + for (i = 0; i < sf.nfiles; i++) + queue_push(idqinst, sf.ids[i]); + solv_free(sf.ids); + } + if (isf.nfiles) + { +#if 0 + for (i = 0; i < isf.nfiles; i++) + POOL_DEBUG(SOLV_DEBUG_STATS, "looking up %s in installed filelist\n", pool_id2str(pool, isf.ids[i])); +#endif + if (installed) + pool_addfileprovides_search(pool, &cbd, &isf, installed); + if (installed && idqinst) + for (i = 0; i < isf.nfiles; i++) + queue_pushunique(idqinst, isf.ids[i]); + solv_free(isf.ids); + } + solv_free(cbd.dids); + pool_freewhatprovides(pool); /* as we have added provides */ + POOL_DEBUG(SOLV_DEBUG_STATS, "addfileprovides took %d ms\n", solv_timems(now)); +} + +void +pool_addfileprovides(Pool *pool) +{ + pool_addfileprovides_queue(pool, 0, 0); +} + diff --git a/src/knownid.h b/src/knownid.h index c094bf5..64cc6fc 100644 --- a/src/knownid.h +++ b/src/knownid.h @@ -260,6 +260,8 @@ KNOWNID(PRODUCT_REGISTER_FLAVOR, "product:regflavor"), /* installed and availab KNOWNID(SOLVABLE_INSTALLSTATUS, "solvable:installstatus"), /* debian install status */ +KNOWNID(SOLVABLE_PREREQ_IGNOREINST, "solvable:prereq_ignoreinst"), /* ignore these pre-requires for installed packages */ + KNOWNID(ID_NUM_INTERNAL, 0) #ifdef KNOWNID_INITIALIZE diff --git a/src/libsolv.ver b/src/libsolv.ver index 6508288..cc79704 100644 --- a/src/libsolv.ver +++ b/src/libsolv.ver @@ -201,6 +201,7 @@ SOLV_1.0 { repodata_key2id; repodata_localize_id; repodata_lookup_bin_checksum; + repodata_lookup_bin_checksum_uninternalized; repodata_lookup_binary; repodata_lookup_dirstrarray_uninternalized; repodata_lookup_id; diff --git a/src/linkedpkg.c b/src/linkedpkg.c index 6387373..635e69b 100644 --- a/src/linkedpkg.c +++ b/src/linkedpkg.c @@ -37,7 +37,9 @@ #include "pool.h" #include "repo.h" +#include "solver.h" #include "evr.h" +#include "bitmap.h" #include "linkedpkg.h" #ifdef ENABLE_LINKED_PKGS @@ -377,5 +379,30 @@ pool_link_evrcmp(Pool *pool, Solvable *s1, Solvable *s2) return 0; } +void +extend_updatemap_to_buddies(Solver *solv) +{ + Pool *pool = solv->pool; + Repo *installed = solv->installed; + Solvable *s; + int p, ip; + + if (!installed) + return; + if (!solv->updatemap.size || !solv->instbuddy) + return; + FOR_REPO_SOLVABLES(installed, p, s) + { + if (!MAPTST(&solv->updatemap, p - installed->start)) + continue; + if ((ip = solv->instbuddy[p - installed->start]) <= 1) + continue; + if (!has_package_link(pool, s)) /* only look at pseudo -> real relations */ + continue; + if (ip < installed->start || ip >= installed->end || pool->solvables[ip].repo != installed) + continue; /* just in case... */ + MAPSET(&solv->updatemap, ip - installed->start); + } +} #endif diff --git a/src/linkedpkg.h b/src/linkedpkg.h index 4463280..51b82a5 100644 --- a/src/linkedpkg.h +++ b/src/linkedpkg.h @@ -18,7 +18,7 @@ has_package_link(Pool *pool, Solvable *s) const char *name = pool_id2str(pool, s->name); if (name[0] == 'a' && !strncmp("application:", name, 12)) return 1; - if (name[0] == 'p' && !strncmp("pattern:", name, 7)) + if (name[0] == 'p' && !strncmp("pattern:", name, 8)) return 1; if (name[0] == 'p' && !strncmp("product:", name, 8)) return 1; @@ -35,5 +35,6 @@ extern Id find_autoproduct_name(Pool *pool, Solvable *s); /* generic */ extern void find_package_link(Pool *pool, Solvable *s, Id *reqidp, Queue *qr, Id *prvidp, Queue *qp); extern int pool_link_evrcmp(Pool *pool, Solvable *s1, Solvable *s2); +extern void extend_updatemap_to_buddies(Solver *solv); #endif @@ -813,6 +813,45 @@ pool_match_dep(Pool *pool, Id d1, Id d2) if (d1 == d2) return 1; + + if (ISRELDEP(d1)) + { + /* 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 (pool_match_dep(pool, rd1->name, d2)) + return 1; + if (rd1->flags == REL_COND && 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)) + return 1; + return 0; + } + } + if (ISRELDEP(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 (pool_match_dep(pool, d1, rd2->name)) + return 1; + if (rd2->flags == REL_COND && 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)) + return 1; + return 0; + } + } if (!ISRELDEP(d1)) { if (!ISRELDEP(d2)) @@ -1412,357 +1451,6 @@ void pool_setnamespacecallback(Pool *pool, Id (*cb)(struct _Pool *, void *, Id, pool->nscallbackdata = nscbdata; } -/*************************************************************************/ - -struct searchfiles { - Id *ids; - int nfiles; - Map seen; -}; - -#define SEARCHFILES_BLOCK 127 - -static void -pool_addfileprovides_dep(Pool *pool, Id *ida, struct searchfiles *sf, struct searchfiles *isf) -{ - Id dep, sid; - const char *s; - struct searchfiles *csf; - - while ((dep = *ida++) != 0) - { - csf = sf; - while (ISRELDEP(dep)) - { - Reldep *rd; - sid = pool->ss.nstrings + GETRELID(dep); - if (MAPTST(&csf->seen, sid)) - { - dep = 0; - break; - } - MAPSET(&csf->seen, sid); - rd = GETRELDEP(pool, dep); - if (rd->flags < 8) - dep = rd->name; - else if (rd->flags == REL_NAMESPACE) - { - if (rd->name == NAMESPACE_SPLITPROVIDES) - { - csf = isf; - if (!csf || MAPTST(&csf->seen, sid)) - { - dep = 0; - break; - } - MAPSET(&csf->seen, sid); - } - dep = rd->evr; - } - else if (rd->flags == REL_FILECONFLICT) - { - dep = 0; - break; - } - else - { - Id ids[2]; - ids[0] = rd->name; - ids[1] = 0; - pool_addfileprovides_dep(pool, ids, csf, isf); - dep = rd->evr; - } - } - if (!dep) - continue; - if (MAPTST(&csf->seen, dep)) - continue; - MAPSET(&csf->seen, dep); - s = pool_id2str(pool, dep); - if (*s != '/') - continue; - if (csf != isf && pool->addedfileprovides == 1 && !repodata_filelistfilter_matches(0, s)) - continue; /* skip non-standard locations csf == isf: installed case */ - csf->ids = solv_extend(csf->ids, csf->nfiles, 1, sizeof(Id), SEARCHFILES_BLOCK); - csf->ids[csf->nfiles++] = dep; - } -} - -struct addfileprovides_cbdata { - int nfiles; - Id *ids; - char **dirs; - char **names; - - Id *dids; - - Map providedids; - - Map useddirs; -}; - -static int -addfileprovides_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *value) -{ - struct addfileprovides_cbdata *cbd = cbdata; - int i; - - if (!cbd->useddirs.size) - { - map_init(&cbd->useddirs, data->dirpool.ndirs + 1); - if (!cbd->dirs) - { - cbd->dirs = solv_malloc2(cbd->nfiles, sizeof(char *)); - cbd->names = solv_malloc2(cbd->nfiles, sizeof(char *)); - for (i = 0; i < cbd->nfiles; i++) - { - char *s = solv_strdup(pool_id2str(data->repo->pool, cbd->ids[i])); - cbd->dirs[i] = s; - s = strrchr(s, '/'); - *s = 0; - cbd->names[i] = s + 1; - } - } - for (i = 0; i < cbd->nfiles; i++) - { - Id did; - if (MAPTST(&cbd->providedids, cbd->ids[i])) - { - cbd->dids[i] = 0; - continue; - } - did = repodata_str2dir(data, cbd->dirs[i], 0); - cbd->dids[i] = did; - if (did) - MAPSET(&cbd->useddirs, did); - } - repodata_free_dircache(data); - } - if (value->id >= data->dirpool.ndirs || !MAPTST(&cbd->useddirs, value->id)) - return 0; - for (i = 0; i < cbd->nfiles; i++) - if (cbd->dids[i] == value->id && !strcmp(cbd->names[i], value->str)) - s->provides = repo_addid_dep(s->repo, s->provides, cbd->ids[i], SOLVABLE_FILEMARKER); - return 0; -} - -static void -pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, struct searchfiles *sf, Repo *repoonly) -{ - Id p; - Repodata *data; - Repo *repo; - Queue fileprovidesq; - int i, j, repoid, repodataid; - int provstart, provend; - Map donemap; - int ndone, incomplete; - - if (!pool->urepos) - return; - - cbd->nfiles = sf->nfiles; - cbd->ids = sf->ids; - cbd->dirs = 0; - cbd->names = 0; - cbd->dids = solv_realloc2(cbd->dids, sf->nfiles, sizeof(Id)); - map_init(&cbd->providedids, pool->ss.nstrings); - - repoid = 1; - repo = repoonly ? repoonly : pool->repos[repoid]; - map_init(&donemap, pool->nsolvables); - queue_init(&fileprovidesq); - provstart = provend = 0; - for (;;) - { - if (!repo || repo->disabled) - { - if (repoonly || ++repoid == pool->nrepos) - break; - repo = pool->repos[repoid]; - continue; - } - ndone = 0; - FOR_REPODATAS(repo, repodataid, data) - { - if (ndone >= repo->nsolvables) - break; - - if (repodata_lookup_idarray(data, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, &fileprovidesq)) - { - map_empty(&cbd->providedids); - for (i = 0; i < fileprovidesq.count; i++) - MAPSET(&cbd->providedids, fileprovidesq.elements[i]); - provstart = data->start; - provend = data->end; - for (i = 0; i < cbd->nfiles; i++) - if (!MAPTST(&cbd->providedids, cbd->ids[i])) - break; - if (i == cbd->nfiles) - { - /* great! no need to search files */ - for (p = data->start; p < data->end; p++) - if (pool->solvables[p].repo == repo) - { - if (MAPTST(&donemap, p)) - continue; - MAPSET(&donemap, p); - ndone++; - } - continue; - } - } - - if (!repodata_has_keyname(data, SOLVABLE_FILELIST)) - continue; - - if (data->start < provstart || data->end > provend) - { - map_empty(&cbd->providedids); - provstart = provend = 0; - } - - /* check if the data is incomplete */ - incomplete = 0; - if (data->state == REPODATA_AVAILABLE) - { - for (j = 1; j < data->nkeys; j++) - if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST) - break; - if (j < data->nkeys) - { -#if 0 - for (i = 0; i < cbd->nfiles; i++) - if (!MAPTST(&cbd->providedids, cbd->ids[i]) && !repodata_filelistfilter_matches(data, pool_id2str(pool, cbd->ids[i]))) - printf("need complete filelist because of %s\n", pool_id2str(pool, cbd->ids[i])); -#endif - for (i = 0; i < cbd->nfiles; i++) - if (!MAPTST(&cbd->providedids, cbd->ids[i]) && !repodata_filelistfilter_matches(data, pool_id2str(pool, cbd->ids[i]))) - break; - if (i < cbd->nfiles) - incomplete = 1; - } - } - - /* do the search */ - map_init(&cbd->useddirs, 0); - for (p = data->start; p < data->end; p++) - if (pool->solvables[p].repo == repo) - { - if (MAPTST(&donemap, p)) - continue; - repodata_search(data, p, SOLVABLE_FILELIST, 0, addfileprovides_cb, cbd); - if (!incomplete) - { - MAPSET(&donemap, p); - ndone++; - } - } - map_free(&cbd->useddirs); - } - - if (repoonly || ++repoid == pool->nrepos) - break; - repo = pool->repos[repoid]; - } - map_free(&donemap); - queue_free(&fileprovidesq); - map_free(&cbd->providedids); - if (cbd->dirs) - { - for (i = 0; i < cbd->nfiles; i++) - solv_free(cbd->dirs[i]); - cbd->dirs = solv_free(cbd->dirs); - cbd->names = solv_free(cbd->names); - } -} - -void -pool_addfileprovides_queue(Pool *pool, Queue *idq, Queue *idqinst) -{ - Solvable *s; - Repo *installed, *repo; - struct searchfiles sf, isf, *isfp; - struct addfileprovides_cbdata cbd; - int i; - unsigned int now; - - installed = pool->installed; - now = solv_timems(0); - memset(&sf, 0, sizeof(sf)); - map_init(&sf.seen, pool->ss.nstrings + pool->nrels); - memset(&isf, 0, sizeof(isf)); - map_init(&isf.seen, pool->ss.nstrings + pool->nrels); - pool->addedfileprovides = pool->addfileprovidesfiltered ? 1 : 2; - - if (idq) - queue_empty(idq); - if (idqinst) - queue_empty(idqinst); - isfp = installed ? &isf : 0; - for (i = 1, s = pool->solvables + i; i < pool->nsolvables; i++, s++) - { - repo = s->repo; - if (!repo) - continue; - if (s->obsoletes) - pool_addfileprovides_dep(pool, repo->idarraydata + s->obsoletes, &sf, isfp); - if (s->conflicts) - pool_addfileprovides_dep(pool, repo->idarraydata + s->conflicts, &sf, isfp); - if (s->requires) - pool_addfileprovides_dep(pool, repo->idarraydata + s->requires, &sf, isfp); - if (s->recommends) - pool_addfileprovides_dep(pool, repo->idarraydata + s->recommends, &sf, isfp); - if (s->suggests) - pool_addfileprovides_dep(pool, repo->idarraydata + s->suggests, &sf, isfp); - if (s->supplements) - pool_addfileprovides_dep(pool, repo->idarraydata + s->supplements, &sf, isfp); - if (s->enhances) - pool_addfileprovides_dep(pool, repo->idarraydata + s->enhances, &sf, isfp); - } - map_free(&sf.seen); - map_free(&isf.seen); - POOL_DEBUG(SOLV_DEBUG_STATS, "found %d file dependencies, %d installed file dependencies\n", sf.nfiles, isf.nfiles); - cbd.dids = 0; - if (sf.nfiles) - { -#if 0 - for (i = 0; i < sf.nfiles; i++) - POOL_DEBUG(SOLV_DEBUG_STATS, "looking up %s in filelist\n", pool_id2str(pool, sf.ids[i])); -#endif - pool_addfileprovides_search(pool, &cbd, &sf, 0); - if (idq) - for (i = 0; i < sf.nfiles; i++) - queue_push(idq, sf.ids[i]); - if (idqinst) - for (i = 0; i < sf.nfiles; i++) - queue_push(idqinst, sf.ids[i]); - solv_free(sf.ids); - } - if (isf.nfiles) - { -#if 0 - for (i = 0; i < isf.nfiles; i++) - POOL_DEBUG(SOLV_DEBUG_STATS, "looking up %s in installed filelist\n", pool_id2str(pool, isf.ids[i])); -#endif - if (installed) - pool_addfileprovides_search(pool, &cbd, &isf, installed); - if (installed && idqinst) - for (i = 0; i < isf.nfiles; i++) - queue_pushunique(idqinst, isf.ids[i]); - solv_free(isf.ids); - } - solv_free(cbd.dids); - pool_freewhatprovides(pool); /* as we have added provides */ - POOL_DEBUG(SOLV_DEBUG_STATS, "addfileprovides took %d ms\n", solv_timems(now)); -} - -void -pool_addfileprovides(Pool *pool) -{ - pool_addfileprovides_queue(pool, 0, 0); -} - void pool_search(Pool *pool, Id p, Id key, const char *match, int flags, int (*callback)(void *cbdata, Solvable *s, struct _Repodata *data, struct _Repokey *key, struct _KeyValue *kv), void *cbdata) { @@ -1784,7 +1472,6 @@ pool_clear_pos(Pool *pool) memset(&pool->pos, 0, sizeof(pool->pos)); } - void pool_set_languages(Pool *pool, const char **languages, int nlanguages) { @@ -1951,330 +1638,6 @@ pool_bin2hex(Pool *pool, const unsigned char *buf, int len) return s; } -/*******************************************************************/ - -struct mptree { - Id sibling; - Id child; - const char *comp; - int compl; - Id mountpoint; -}; - -struct ducbdata { - DUChanges *mps; - struct mptree *mptree; - int addsub; - int hasdu; - - Id *dirmap; - int nmap; - Repodata *olddata; -}; - - -static int -solver_fill_DU_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *value) -{ - struct ducbdata *cbd = cbdata; - Id mp; - - if (data != cbd->olddata) - { - Id dn, mp, comp, *dirmap, *dirs; - int i, compl; - const char *compstr; - struct mptree *mptree; - - /* create map from dir to mptree */ - cbd->dirmap = solv_free(cbd->dirmap); - cbd->nmap = 0; - dirmap = solv_calloc(data->dirpool.ndirs, sizeof(Id)); - mptree = cbd->mptree; - mp = 0; - for (dn = 2, dirs = data->dirpool.dirs + dn; dn < data->dirpool.ndirs; dn++) - { - comp = *dirs++; - if (comp <= 0) - { - mp = dirmap[-comp]; - continue; - } - if (mp < 0) - { - /* unconnected */ - dirmap[dn] = mp; - continue; - } - if (!mptree[mp].child) - { - dirmap[dn] = -mp; - continue; - } - if (data->localpool) - compstr = stringpool_id2str(&data->spool, comp); - else - compstr = pool_id2str(data->repo->pool, comp); - compl = strlen(compstr); - for (i = mptree[mp].child; i; i = mptree[i].sibling) - if (mptree[i].compl == compl && !strncmp(mptree[i].comp, compstr, compl)) - break; - dirmap[dn] = i ? i : -mp; - } - /* change dirmap to point to mountpoint instead of mptree */ - for (dn = 0; dn < data->dirpool.ndirs; dn++) - { - mp = dirmap[dn]; - dirmap[dn] = mptree[mp > 0 ? mp : -mp].mountpoint; - } - cbd->dirmap = dirmap; - 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]; - if (mp < 0) - return 0; - if (cbd->addsub > 0) - { - cbd->mps[mp].kbytes += value->num; - cbd->mps[mp].files += value->num2; - } - else if (!(cbd->mps[mp].flags & DUCHANGES_ONLYADD)) - { - cbd->mps[mp].kbytes -= value->num; - cbd->mps[mp].files -= value->num2; - } - return 0; -} - -static void -propagate_mountpoints(struct mptree *mptree, int pos, Id mountpoint) -{ - int i; - if (mptree[pos].mountpoint == -1) - mptree[pos].mountpoint = mountpoint; - else - mountpoint = mptree[pos].mountpoint; - for (i = mptree[pos].child; i; i = mptree[i].sibling) - propagate_mountpoints(mptree, i, mountpoint); -} - -#define MPTREE_BLOCK 15 - -static struct mptree * -create_mptree(DUChanges *mps, int nmps) -{ - int i, nmptree; - struct mptree *mptree; - int pos, compl; - int mp; - const char *p, *path, *compstr; - - mptree = solv_extend_resize(0, 1, sizeof(struct mptree), MPTREE_BLOCK); - - /* our root node */ - mptree[0].sibling = 0; - mptree[0].child = 0; - mptree[0].comp = 0; - mptree[0].compl = 0; - mptree[0].mountpoint = -1; - nmptree = 1; - - /* create component tree */ - for (mp = 0; mp < nmps; mp++) - { - mps[mp].kbytes = 0; - mps[mp].files = 0; - pos = 0; - path = mps[mp].path; - while(*path == '/') - path++; - while (*path) - { - if ((p = strchr(path, '/')) == 0) - { - compstr = path; - compl = strlen(compstr); - path += compl; - } - else - { - compstr = path; - compl = p - path; - path = p + 1; - while(*path == '/') - path++; - } - for (i = mptree[pos].child; i; i = mptree[i].sibling) - if (mptree[i].compl == compl && !strncmp(mptree[i].comp, compstr, compl)) - break; - if (!i) - { - /* create new node */ - mptree = solv_extend(mptree, nmptree, 1, sizeof(struct mptree), MPTREE_BLOCK); - i = nmptree++; - mptree[i].sibling = mptree[pos].child; - mptree[i].child = 0; - mptree[i].comp = compstr; - mptree[i].compl = compl; - mptree[i].mountpoint = -1; - mptree[pos].child = i; - } - pos = i; - } - mptree[pos].mountpoint = mp; - } - - propagate_mountpoints(mptree, 0, mptree[0].mountpoint); - -#if 0 - for (i = 0; i < nmptree; i++) - { - printf("#%d sibling: %d\n", i, mptree[i].sibling); - printf("#%d child: %d\n", i, mptree[i].child); - printf("#%d comp: %s\n", i, mptree[i].comp); - printf("#%d compl: %d\n", i, mptree[i].compl); - printf("#%d mountpont: %d\n", i, mptree[i].mountpoint); - } -#endif - - return mptree; -} - -void -pool_calc_duchanges(Pool *pool, Map *installedmap, DUChanges *mps, int nmps) -{ - struct mptree *mptree; - struct ducbdata cbd; - Solvable *s; - int i, sp; - Map ignoredu; - Repo *oldinstalled = pool->installed; - int haveonlyadd = 0; - - map_init(&ignoredu, 0); - mptree = create_mptree(mps, nmps); - - for (i = 0; i < nmps; i++) - if ((mps[i].flags & DUCHANGES_ONLYADD) != 0) - haveonlyadd = 1; - cbd.mps = mps; - cbd.dirmap = 0; - cbd.nmap = 0; - cbd.olddata = 0; - cbd.mptree = mptree; - cbd.addsub = 1; - for (sp = 1, s = pool->solvables + sp; sp < pool->nsolvables; sp++, s++) - { - 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; - int didonlyadd = 0; - /* no du data available, ignore data of all installed solvables we obsolete */ - if (!ignoredu.size) - map_grow(&ignoredu, oldinstalled->end - oldinstalled->start); - FOR_PROVIDES(op, opp, s->name) - { - Solvable *s2 = pool->solvables + op; - if (!pool->implicitobsoleteusesprovides && s->name != s2->name) - continue; - if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, s2)) - continue; - if (op >= oldinstalled->start && op < oldinstalled->end) - { - MAPSET(&ignoredu, op - oldinstalled->start); - if (haveonlyadd && pool->solvables[op].repo == oldinstalled && !didonlyadd) - { - repo_search(oldinstalled, op, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); - cbd.addsub = -1; - repo_search(oldinstalled, op, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); - cbd.addsub = 1; - didonlyadd = 1; - } - } - } - if (s->obsoletes) - { - Id obs, *obsp = s->repo->idarraydata + s->obsoletes; - while ((obs = *obsp++) != 0) - FOR_PROVIDES(op, opp, obs) - { - Solvable *s2 = pool->solvables + op; - if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, s2, obs)) - continue; - if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2)) - continue; - if (op >= oldinstalled->start && op < oldinstalled->end) - { - MAPSET(&ignoredu, op - oldinstalled->start); - if (haveonlyadd && pool->solvables[op].repo == oldinstalled && !didonlyadd) - { - repo_search(oldinstalled, op, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); - cbd.addsub = -1; - repo_search(oldinstalled, op, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); - cbd.addsub = 1; - didonlyadd = 1; - } - } - } - } - } - } - cbd.addsub = -1; - if (oldinstalled) - { - /* 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); - } - } - map_free(&ignoredu); - solv_free(cbd.dirmap); - solv_free(mptree); -} - -int -pool_calc_installsizechange(Pool *pool, Map *installedmap) -{ - Id sp; - Solvable *s; - int change = 0; - Repo *oldinstalled = pool->installed; - - for (sp = 1, s = pool->solvables + sp; sp < pool->nsolvables; sp++, s++) - { - if (!s->repo || (oldinstalled && s->repo == oldinstalled)) - continue; - if (!MAPTST(installedmap, sp)) - continue; - change += solvable_lookup_sizek(s, SOLVABLE_INSTALLSIZE, 0); - } - if (oldinstalled) - { - FOR_REPO_SOLVABLES(oldinstalled, sp, s) - { - if (MAPTST(installedmap, sp)) - continue; - change -= solvable_lookup_sizek(s, SOLVABLE_INSTALLSIZE, 0); - } - } - return change; -} - /* map: * 1: installed * 2: conflicts with installed @@ -34,9 +34,6 @@ extern "C" { #define SYSTEMSOLVABLE 1 -/* how many strings to maintain (round robin) */ -#define POOL_TMPSPACEBUF 16 - /*----------------------------------------------- */ struct _Repo; @@ -52,12 +49,20 @@ typedef struct _Datapos { Id dp; } Datapos; + +#ifdef LIBSOLV_INTERNAL + +/* how many strings to maintain (round robin) */ +#define POOL_TMPSPACEBUF 16 + struct _Pool_tmpspace { char *buf[POOL_TMPSPACEBUF]; int len[POOL_TMPSPACEBUF]; int n; }; +#endif + struct _Pool { void *appdata; /* application private pointer */ diff --git a/src/poolid.c b/src/poolid.c index 2138c42..91eba34 100644 --- a/src/poolid.c +++ b/src/poolid.c @@ -173,11 +173,11 @@ pool_id2rel(const Pool *pool, Id id) return pool->disttype == DISTTYPE_HAIKU ? " != " : rels[rd->flags]; #endif case REL_AND: - return " & "; + return pool->disttype == DISTTYPE_RPM ? " and " : " & "; case REL_OR: - return " | "; + return pool->disttype == DISTTYPE_RPM ? " or " : " | "; case REL_WITH: - return " + "; + return pool->disttype == DISTTYPE_RPM ? " with " : " + "; case REL_NAMESPACE: return " NAMESPACE "; /* actually not used in dep2str */ case REL_ARCH: @@ -187,13 +187,13 @@ pool_id2rel(const Pool *pool, Id id) case REL_FILECONFLICT: return " FILECONFLICT "; case REL_COND: - return " IF "; + return pool->disttype == DISTTYPE_RPM ? " if " : " IF "; case REL_COMPAT: return " compat >= "; case REL_KIND: return " KIND "; case REL_ELSE: - return " ELSE "; + return pool->disttype == DISTTYPE_RPM ? " else " : " ELSE "; default: break; } @@ -235,9 +235,10 @@ dep2strcpy(const Pool *pool, char *p, Id id, int oldrel) while (ISRELDEP(id)) { Reldep *rd = GETRELDEP(pool, id); - if (oldrel == REL_AND || oldrel == REL_OR || oldrel == REL_WITH) - if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_WITH) - if (oldrel != rd->flags) + int rel = rd->flags; + if (oldrel == REL_AND || oldrel == REL_OR || oldrel == REL_WITH || oldrel == REL_COND || oldrel == REL_ELSE || oldrel == -1) + if (rel == REL_AND || rel == REL_OR || rel == REL_WITH || rel == REL_COND || rel == REL_ELSE) + if ((oldrel != rel || rel == REL_COND || rel == REL_ELSE) && !(oldrel == REL_COND && rel == REL_ELSE)) { *p++ = '('; dep2strcpy(pool, p, rd->name, rd->flags); @@ -286,7 +287,7 @@ pool_dep2str(Pool *pool, Id id) if (!ISRELDEP(id)) return pool->ss.stringspace + pool->ss.strings[id]; p = pool_alloctmpspace(pool, dep2strlen(pool, id) + 1); - dep2strcpy(pool, p, id, 0); + dep2strcpy(pool, p, id, pool->disttype == DISTTYPE_RPM ? -1 : 0); return p; } diff --git a/src/repodata.c b/src/repodata.c index ad3e71a..b611afc 100644 --- a/src/repodata.c +++ b/src/repodata.c @@ -881,6 +881,31 @@ repodata_lookup_dirstrarray_uninternalized(Repodata *data, Id solvid, Id keyname return 0; } +const unsigned char * +repodata_lookup_bin_checksum_uninternalized(Repodata *data, Id solvid, Id keyname, Id *typep) +{ + Id *ap; + if (!data->attrs) + return 0; + ap = data->attrs[solvid - data->start]; + if (!ap) + return 0; + for (; *ap; ap += 2) + { + if (data->keys[*ap].name != keyname) + continue; + switch (data->keys[*ap].type) + { + case_CHKSUM_TYPES: + *typep = data->keys[*ap].type; + return (const unsigned char *)data->attrdata + ap[1]; + default: + break; + } + } + return 0; +} + /************************************************************************ * data search */ diff --git a/src/repodata.h b/src/repodata.h index c18c688..d72c60f 100644 --- a/src/repodata.h +++ b/src/repodata.h @@ -300,8 +300,11 @@ const char *repodata_chk2str(Repodata *data, Id type, const unsigned char *buf); void repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file); void repodata_set_deltalocation(Repodata *data, Id handle, int medianr, const char *dir, const char *file); void repodata_set_sourcepkg(Repodata *data, Id solvid, const char *sourcepkg); + +/* uninternalized data lookup */ Id repodata_lookup_id_uninternalized(Repodata *data, Id solvid, Id keyname, Id voidid); const char *repodata_lookup_dirstrarray_uninternalized(Repodata *data, Id solvid, Id keyname, Id *didp, Id *iterp); +const unsigned char *repodata_lookup_bin_checksum_uninternalized(Repodata *data, Id solvid, Id keyname, Id *typep); /* stats */ unsigned int repodata_memused(Repodata *data); diff --git a/src/rules.c b/src/rules.c index 4cd53d3..32855e4 100644 --- a/src/rules.c +++ b/src/rules.c @@ -671,7 +671,7 @@ add_complex_deprules(Solver *solv, Id p, Id dep, int type, int dontfix, Queue *w /*------------------------------------------------------------------- * - * add (install) rules for solvable + * add dependency rules for solvable * * s: Solvable for which to add rules * m: m[s] = 1 for solvables which have rules, prevent rule duplication @@ -697,6 +697,8 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m) Queue workq; /* list of solvables we still have to work on */ Id workqbuf[64]; + Queue prereqq; /* list of pre-req ids to ignore */ + Id prereqbuf[16]; int i; int dontfix; /* ignore dependency errors for installed solvables */ @@ -712,6 +714,8 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m) queue_init_buffer(&workq, workqbuf, sizeof(workqbuf)/sizeof(*workqbuf)); queue_push(&workq, s - pool->solvables); /* push solvable Id to work queue */ + queue_init_buffer(&prereqq, prereqbuf, sizeof(prereqbuf)/sizeof(*prereqbuf)); + /* loop until there's no more work left */ while (workq.count) { @@ -762,11 +766,33 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m) if (s->requires) { + int filterpre = 0; reqp = s->repo->idarraydata + s->requires; while ((req = *reqp++) != 0) /* go through all requires */ { if (req == SOLVABLE_PREREQMARKER) /* skip the marker */ - continue; + { + if (installed && s->repo == installed) + { + if (prereqq.count) + queue_empty(&prereqq); + solvable_lookup_idarray(s, SOLVABLE_PREREQ_IGNOREINST, &prereqq); + filterpre = prereqq.count; + } + continue; + } + if (filterpre) + { + /* check if this id is filtered. assumes that prereqq.count is small */ + for (i = 0; i < prereqq.count; i++) + if (req == prereqq.elements[i]) + break; + if (i < prereqq.count) + { + POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "package %s: ignoring filtered pre-req dependency %s\n", pool_solvable2str(pool, s), pool_dep2str(pool, req)); + continue; + } + } #ifdef ENABLE_COMPLEX_DEPS if (pool_is_complex_dep(pool, req)) @@ -1034,6 +1060,7 @@ solver_addpkgrulesforsolvable(Solver *solv, Solvable *s, Map *m) } } } + queue_free(&prereqq); queue_free(&workq); } @@ -1170,35 +1197,56 @@ solver_addpkgrulesforupdaters(Solver *solv, Solvable *s, Map *m, int allow_all) *** ***/ +static int +dup_maykeepinstalled(Solver *solv, Solvable *s) +{ + Pool *pool = solv->pool; + Id ip, pp; + + if (solv->dupmap.size && MAPTST(&solv->dupmap, s - pool->solvables)) + return 1; + /* is installed identical to a good one? */ + FOR_PROVIDES(ip, pp, s->name) + { + Solvable *is = pool->solvables + ip; + if (is->evr != s->evr) + continue; + if (solv->dupmap.size) + { + if (!MAPTST(&solv->dupmap, ip)) + continue; + } + else if (is->repo == pool->installed) + continue; + if (solvable_identical(s, is)) + return 1; + } + return 0; +} + + static Id -finddistupgradepackages(Solver *solv, Solvable *s, Queue *qs, int allow_all) +finddistupgradepackages(Solver *solv, Solvable *s, Queue *qs) { Pool *pool = solv->pool; - int i; + int i, j; - policy_findupdatepackages(solv, s, qs, allow_all ? allow_all : 2); - if (!qs->count) + policy_findupdatepackages(solv, s, qs, 2); + if (qs->count) { - if (allow_all) - return 0; /* orphaned, don't create feature rule */ - /* check if this is an orphaned package */ - policy_findupdatepackages(solv, s, qs, 1); - if (!qs->count) - return 0; /* orphaned, don't create update rule */ - qs->count = 0; - return -SYSTEMSOLVABLE; /* supported but not installable */ + /* remove installed packages we can't keep */ + for (i = j = 0; i < qs->count; i++) + { + Solvable *ns = pool->solvables + qs->elements[i]; + if (ns->repo == pool->installed && !dup_maykeepinstalled(solv, ns)) + continue; + qs->elements[j++] = qs->elements[i]; + } + queue_truncate(qs, j); } - if (allow_all) - return s - pool->solvables; /* check if it is ok to keep the installed package */ - if (solv->dupmap.size && MAPTST(&solv->dupmap, s - pool->solvables)) + if (dup_maykeepinstalled(solv, s)) return s - pool->solvables; - for (i = 0; i < qs->count; i++) - { - Solvable *ns = pool->solvables + qs->elements[i]; - if (s->evr == ns->evr && solvable_identical(s, ns)) - return s - pool->solvables; - } /* nope, it must be some other package */ return -SYSTEMSOLVABLE; } @@ -1240,6 +1288,73 @@ set_specialupdaters(Solver *solv, Solvable *s, Id d) solv->specialupdaters[s - solv->pool->solvables - installed->start] = d; } +#ifdef ENABLE_LINKED_PKGS +/* Check if this is a linked pseudo package. As it is linked, we do not need an update/feature rule */ +static inline int +is_linked_pseudo_package(Solver *solv, Solvable *s) +{ + Pool *pool = solv->pool; + if (solv->instbuddy && solv->instbuddy[s - pool->solvables - solv->installed->start]) + { + const char *name = pool_id2str(pool, s->name); + if (strncmp(name, "pattern:", 8) == 0 || strncmp(name, "application:", 12) == 0) + return 1; + } + return 0; +} +#endif + +void +solver_addfeaturerule(Solver *solv, Solvable *s) +{ + Pool *pool = solv->pool; + int i; + Id p; + Queue qs; + Id qsbuf[64]; + +#ifdef ENABLE_LINKED_PKGS + if (is_linked_pseudo_package(solv, s)) + { + solver_addrule(solv, 0, 0, 0); /* no feature rules for those */ + return; + } +#endif + queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf)); + p = s - pool->solvables; + policy_findupdatepackages(solv, s, &qs, 1); + if (solv->dupmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p))) + { + if (!dup_maykeepinstalled(solv, s)) + { + for (i = 0; i < qs.count; i++) + { + Solvable *ns = pool->solvables + qs.elements[i]; + if (ns->repo != pool->installed || dup_maykeepinstalled(solv, ns)) + break; + } + if (i == qs.count) + { + solver_addrule(solv, 0, 0, 0); /* this is an orphan */ + queue_free(&qs); + return; + } + } + } + if (qs.count > 1) + { + Id d = pool_queuetowhatprovides(pool, &qs); + queue_free(&qs); + solver_addrule(solv, p, 0, d); /* allow update of s */ + } + else + { + Id d = qs.count ? qs.elements[0] : 0; + queue_free(&qs); + solver_addrule(solv, p, d, 0); /* allow update of s */ + } +} + /*------------------------------------------------------------------- * * add rule for update @@ -1249,7 +1364,7 @@ set_specialupdaters(Solver *solv, Solvable *s, Id d) */ void -solver_addupdaterule(Solver *solv, Solvable *s, int allow_all) +solver_addupdaterule(Solver *solv, Solvable *s) { /* installed packages get a special upgrade allowed rule */ Pool *pool = solv->pool; @@ -1257,48 +1372,37 @@ solver_addupdaterule(Solver *solv, Solvable *s, int allow_all) Queue qs; Id qsbuf[64]; int isorphaned = 0; + Rule *r; - queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf)); p = s - pool->solvables; - /* find update candidates for 's' */ - if (solv->dupmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p))) - p = finddistupgradepackages(solv, s, &qs, allow_all); - else - policy_findupdatepackages(solv, s, &qs, allow_all); - -#ifdef ENABLE_LINKED_PKGS - if (solv->instbuddy && solv->instbuddy[s - pool->solvables - solv->installed->start]) + /* Orphan detection. We cheat by looking at the feature rule, which + * we already calculated */ + r = solv->rules + solv->featurerules + (p - solv->installed->start); + if (!r->p) { - const char *name = pool_id2str(pool, s->name); - if (strncmp(name, "pattern:", 8) == 0 || strncmp(name, "application:", 12) == 0) +#ifdef ENABLE_LINKED_PKGS + if (is_linked_pseudo_package(solv, s)) { - /* a linked pseudo package. As it is linked, we do not need an update/feature rule */ - /* nevertheless we set specialupdaters so we can update */ solver_addrule(solv, 0, 0, 0); - if (!allow_all && qs.count) - { - if (p != -SYSTEMSOLVABLE) - queue_unshift(&qs, p); - if (qs.count) - set_specialupdaters(solv, s, pool_queuetowhatprovides(pool, &qs)); - } - queue_free(&qs); return; } - } #endif - - if (!allow_all && !p) /* !p implies qs.count == 0 */ - { + p = 0; queue_push(&solv->orphaned, s - pool->solvables); /* an orphaned package */ if (solv->keep_orphans && !(solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, s - pool->solvables - solv->installed->start)))) p = s - pool->solvables; /* keep this orphaned package installed */ - queue_free(&qs); solver_addrule(solv, p, 0, 0); return; } - if (!allow_all && qs.count && solv->multiversion.size) + queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf)); + /* find update candidates for 's' */ + if (solv->dupmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p))) + p = finddistupgradepackages(solv, s, &qs); + else + policy_findupdatepackages(solv, s, &qs, 0); + + if (qs.count && solv->multiversion.size) { int i, j; diff --git a/src/rules.h b/src/rules.h index 606819b..29325ea 100644 --- a/src/rules.h +++ b/src/rules.h @@ -111,7 +111,8 @@ extern void solver_addpkgrulesforlinked(struct _Solver *solv, Map *m); extern void solver_addpkgrulesforupdaters(struct _Solver *solv, Solvable *s, Map *m, int allow_all); /* update/feature rules */ -extern void solver_addupdaterule(struct _Solver *solv, Solvable *s, int allow_all); +extern void solver_addfeaturerule(struct _Solver *solv, Solvable *s); +extern void solver_addupdaterule(struct _Solver *solv, Solvable *s); /* infarch rules */ extern void solver_addinfarchrules(struct _Solver *solv, Map *addedmap); diff --git a/src/selection.c b/src/selection.c index 8856436..7d9a918 100644 --- a/src/selection.c +++ b/src/selection.c @@ -873,11 +873,17 @@ matchdep(Pool *pool, Id id, char *rname, int rflags, char *revr, int flags) if (ISRELDEP(id)) { Reldep *rd = GETRELDEP(pool, id); - if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_WITH) + if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_WITH || rd->flags == REL_COND) { if (matchdep(pool, rd->name, rname, rflags, revr, flags)) return 1; - if (matchdep(pool, rd->evr, rname, rflags, revr, flags)) + if (rd->flags == REL_COND && ISRELDEP(rd->evr)) + { + rd = GETRELDEP(pool, rd->evr); + if (rd->flags != REL_ELSE) + return 0; + } + if (rd->flags != REL_COND && matchdep(pool, rd->evr, rname, rflags, revr, flags)) return 1; return 0; } diff --git a/src/solver.c b/src/solver.c index 261f367..d5989cc 100644 --- a/src/solver.c +++ b/src/solver.c @@ -2193,8 +2193,8 @@ solver_run_sat(Solver *solv, int disablerules, int doweak) rr -= solv->installed->end - solv->installed->start; if (!rr->p) /* identical to update rule? */ rr = r; - if (!rr->p && !(specialupdaters && specialupdaters[i - installed->start])) - continue; /* orpaned package */ + if (!rr->p) + continue; /* orpaned package or pseudo package */ /* check if we should update this package to the latest version * noupdate is set for erase jobs, in that case we want to deinstall @@ -2203,21 +2203,7 @@ solver_run_sat(Solver *solv, int disablerules, int doweak) queue_empty(&dq); if (!MAPTST(&solv->noupdate, i - installed->start) && (solv->decisionmap[i] < 0 || solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, i - installed->start)) || (rr->p && rr->p != i))) { - if (!rr->p) - { - /* specialupdater with no update/feature rule */ - for (d = specialupdaters[i - installed->start]; (p = pool->whatprovidesdata[d++]) != 0; ) - { - if (solv->decisionmap[p] > 0) - { - dq.count = 0; - break; - } - if (!solv->decisionmap[p]) - queue_push(&dq, p); - } - } - else if (specialupdaters && (d = specialupdaters[i - installed->start]) != 0) + if (specialupdaters && (d = specialupdaters[i - installed->start]) != 0) { /* special multiversion handling, make sure best version is chosen */ if (rr->p == i && solv->decisionmap[i] >= 0) @@ -3716,7 +3702,7 @@ solver_solve(Solver *solv, Queue *job) solver_addrule(solv, 0, 0, 0); /* create dummy rule */ continue; } - solver_addupdaterule(solv, s, 1); /* allow s to be updated */ + solver_addfeaturerule(solv, s); } /* make sure we accounted for all rules */ assert(solv->nrules - solv->featurerules == installed->end - installed->start); @@ -3744,7 +3730,7 @@ solver_solve(Solver *solv, Queue *job) solver_addrule(solv, 0, 0, 0); /* create dummy rule */ continue; } - solver_addupdaterule(solv, s, 0); /* allowall = 0: downgrades not allowed */ + solver_addupdaterule(solv, s); /* * check for and remove duplicate */ @@ -3759,9 +3745,10 @@ solver_solve(Solver *solv, Queue *job) /* it's also orphaned if the feature rule consists just of the installed package */ if (!solv->dupmap_all && sr->p == i && !sr->d && !sr->w2) queue_push(&solv->orphaned, i); + if (!solver_rulecmp(solv, r, sr)) memset(sr, 0, sizeof(*sr)); /* delete unneeded feature rule */ - else + else if (sr->p) solver_disablerule(solv, sr); /* disable feature rule for now */ } /* consistency check: we added a rule for _every_ installed solvable */ @@ -3990,6 +3977,11 @@ solver_solve(Solver *solv, Queue *job) else solv->duprules = solv->duprules_end = solv->nrules; +#ifdef ENABLE_LINKED_PKGS + if (solv->instbuddy && solv->updatemap.size) + extend_updatemap_to_buddies(solv); +#endif + if (solv->bestupdatemap_all || solv->bestupdatemap.size || hasbestinstalljob) solver_addbestrules(solv, hasbestinstalljob); else @@ -4485,6 +4477,11 @@ solver_describe_decision(Solver *solv, Id p, Id *infop) return SOLVER_REASON_CLEANDEPS_ERASE; return SOLVER_REASON_KEEP_INSTALLED; } + if (i < solv->decisioncnt_weak) + { + if (why == 0 && pp < 0) + return SOLVER_REASON_CLEANDEPS_ERASE; + } if (why > 0) return SOLVER_REASON_RESOLVE; /* weak or orphaned */ @@ -235,7 +235,7 @@ solv_hex2bin(const char **strp, unsigned char *buf, int bufl) d = c - ('A' - 10); else break; - c = *++str; + c = str[1]; d <<= 4; if (c >= '0' && c <= '9') d |= c - '0'; @@ -246,7 +246,7 @@ solv_hex2bin(const char **strp, unsigned char *buf, int bufl) else break; buf[i] = d; - ++str; + str += 2; } *strp = str; return i; |