From: Michael Schroeder Date: Thu, 7 Apr 2016 15:09:14 +0000 (+0200) Subject: Implement filtering of Requires(pre,post) for installed packages X-Git-Tag: 0.6.20~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6afc1750d97d0297cb397278c20b962bc3b24209;p=thirdparty%2Flibsolv.git Implement filtering of Requires(pre,post) for installed packages Should fix issue#126. Except that we need to support it in the testcases as well. --- diff --git a/ext/repo_rpmdb.c b/ext/repo_rpmdb.c index 804d08ff..16b28b39 100644 --- a/ext/repo_rpmdb.c +++ b/ext/repo_rpmdb.c @@ -407,13 +407,44 @@ setutf8string(Repodata *repodata, Id handle, Id tag, const char *str) repodata_set_str(repodata, handle, tag, str); } +static int +add_prereq_ignoreinst_sortcmp(const void *va, const void *vb, void *dp) +{ + return *(Id *)va - *(Id *)vb; +} + +static void +add_prereq_ignoreinst(Pool *pool, Repodata *data, Id handle, Queue *ign, Queue *keep) +{ + int ii, ik; + + /* sort both queues */ + if (ign->count > 1) + solv_sort(ign->elements, ign->count, sizeof(Id), add_prereq_ignoreinst_sortcmp, 0); + if (keep->count > 1) + solv_sort(keep->elements, keep->count, sizeof(Id), add_prereq_ignoreinst_sortcmp, 0); + for (ii = ik = 0; ii < ign->count; ) + { + if (ik == keep->count || ign->elements[ii] < keep->elements[ik]) + { + Id id = ign->elements[ii++]; + repodata_add_idarray(data, handle, SOLVABLE_PREREQ_IGNOREINST, id); + while (ii < ign->count && ign->elements[ii] == id) + ii++; + } + else if (ign->elements[ii] > keep->elements[ik]) + ik++; + else + ii++; + } +} /* * strong: 0: ignore strongness * 1: filter to strong * 2: filter to weak */ static unsigned int -makedeps(Pool *pool, Repo *repo, RpmHead *rpmhead, int tagn, int tagv, int tagf, int flags) +makedeps(Pool *pool, Repo *repo, RpmHead *rpmhead, int tagn, int tagv, int tagf, int flags, Queue *ignq, Queue *keepq) { char **n, **v; unsigned int *f; @@ -512,6 +543,7 @@ makedeps(Pool *pool, Repo *repo, RpmHead *rpmhead, int tagn, int tagv, int tagf, cc += haspre; /* add slot for the prereq marker */ olddeps = repo_reserve_ids(repo, 0, cc); ida = repo->idarraydata + olddeps; + for (i = 0; ; i++) { Id id; @@ -564,6 +596,13 @@ makedeps(Pool *pool, Repo *repo, RpmHead *rpmhead, int tagn, int tagv, int tagf, id = pool_rel2id(pool, id, evr, fl, 1); } *ida++ = id; + if (haspre == 2 && ignq) + { + if ((f[i] & DEP_PRE_IN) != 0 && (f[i] & DEP_PRE_UN) == 0) + queue_push(ignq, id); + else + queue_push(keepq, id); + } } *ida++ = 0; repo->idarraysize += cc + 1; @@ -909,6 +948,10 @@ rpm2solv(Pool *pool, Repo *repo, Repodata *data, Solvable *s, RpmHead *rpmhead, char *name; char *evr; char *sourcerpm; + Queue ignq; + Queue keepq; + Id ignqbuf[16]; + Id keepqbuf[16]; name = headstring(rpmhead, TAG_NAME); if (!name) @@ -935,21 +978,30 @@ rpm2solv(Pool *pool, Repo *repo, Repodata *data, Solvable *s, RpmHead *rpmhead, s->evr = pool_str2id(pool, evr, 1); s->vendor = pool_str2id(pool, headstring(rpmhead, TAG_VENDOR), 1); - s->provides = makedeps(pool, repo, rpmhead, TAG_PROVIDENAME, TAG_PROVIDEVERSION, TAG_PROVIDEFLAGS, 0); + queue_init_buffer(&ignq, ignqbuf, sizeof(ignqbuf)/sizeof(*ignqbuf)); + queue_init_buffer(&keepq, keepqbuf, sizeof(keepqbuf)/sizeof(*keepqbuf)); + + s->provides = makedeps(pool, repo, rpmhead, TAG_PROVIDENAME, TAG_PROVIDEVERSION, TAG_PROVIDEFLAGS, 0, 0, 0); if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); - s->requires = makedeps(pool, repo, rpmhead, TAG_REQUIRENAME, TAG_REQUIREVERSION, TAG_REQUIREFLAGS, flags); - s->conflicts = makedeps(pool, repo, rpmhead, TAG_CONFLICTNAME, TAG_CONFLICTVERSION, TAG_CONFLICTFLAGS, 0); - s->obsoletes = makedeps(pool, repo, rpmhead, TAG_OBSOLETENAME, TAG_OBSOLETEVERSION, TAG_OBSOLETEFLAGS, 0); + s->requires = makedeps(pool, repo, rpmhead, TAG_REQUIRENAME, TAG_REQUIREVERSION, TAG_REQUIREFLAGS, flags, &ignq, &keepq); + s->conflicts = makedeps(pool, repo, rpmhead, TAG_CONFLICTNAME, TAG_CONFLICTVERSION, TAG_CONFLICTFLAGS, 0, 0, 0); + s->obsoletes = makedeps(pool, repo, rpmhead, TAG_OBSOLETENAME, TAG_OBSOLETEVERSION, TAG_OBSOLETEFLAGS, 0, 0, 0); - s->recommends = makedeps(pool, repo, rpmhead, TAG_RECOMMENDNAME, TAG_RECOMMENDVERSION, TAG_RECOMMENDFLAGS, 0); - s->suggests = makedeps(pool, repo, rpmhead, TAG_SUGGESTNAME, TAG_SUGGESTVERSION, TAG_SUGGESTFLAGS, 0); - s->supplements = makedeps(pool, repo, rpmhead, TAG_SUPPLEMENTNAME, TAG_SUPPLEMENTVERSION, TAG_SUPPLEMENTFLAGS, 0); - s->enhances = makedeps(pool, repo, rpmhead, TAG_ENHANCENAME, TAG_ENHANCEVERSION, TAG_ENHANCEFLAGS, 0); + s->recommends = makedeps(pool, repo, rpmhead, TAG_RECOMMENDNAME, TAG_RECOMMENDVERSION, TAG_RECOMMENDFLAGS, 0, 0, 0); + s->suggests = makedeps(pool, repo, rpmhead, TAG_SUGGESTNAME, TAG_SUGGESTVERSION, TAG_SUGGESTFLAGS, 0, 0, 0); + s->supplements = makedeps(pool, repo, rpmhead, TAG_SUPPLEMENTNAME, TAG_SUPPLEMENTVERSION, TAG_SUPPLEMENTFLAGS, 0, 0, 0); + s->enhances = makedeps(pool, repo, rpmhead, TAG_ENHANCENAME, TAG_ENHANCEVERSION, TAG_ENHANCEFLAGS, 0, 0, 0); s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0); s->conflicts = repo_fix_conflicts(repo, s->conflicts); + if (data && ignq.count) + add_prereq_ignoreinst(pool, data, s - pool->solvables, &ignq, &keepq); + + queue_free(&ignq); + queue_free(&keepq); + if (data) { Id handle; @@ -1014,7 +1066,7 @@ rpm2solv(Pool *pool, Repo *repo, Repodata *data, Solvable *s, RpmHead *rpmhead, repodata_set_sourcepkg(data, handle, sourcerpm); if ((flags & RPM_ADD_TRIGGERS) != 0) { - unsigned int ida = makedeps(pool, repo, rpmhead, TAG_TRIGGERNAME, TAG_TRIGGERVERSION, TAG_TRIGGERFLAGS, 0); + unsigned int ida = makedeps(pool, repo, rpmhead, TAG_TRIGGERNAME, TAG_TRIGGERVERSION, TAG_TRIGGERFLAGS, 0, 0, 0); Id id, lastid = 0; for (lastid = 0; (id = repo->idarraydata[ida]) != 0; ida++, lastid = id) if (id != lastid) diff --git a/src/knownid.h b/src/knownid.h index c094bf5b..64cc6fc0 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/rules.c b/src/rules.c index f06c03f8..32855e4a 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); }