diff options
-rw-r--r-- | VERSION.cmake | 2 | ||||
-rw-r--r-- | bindings/solv.i | 10 | ||||
-rw-r--r-- | examples/solv.c | 1 | ||||
-rw-r--r-- | ext/repo_arch.c | 6 | ||||
-rw-r--r-- | ext/testcase.c | 40 | ||||
-rw-r--r-- | package/libsolv.changes | 11 | ||||
-rw-r--r-- | src/policy.c | 2 | ||||
-rw-r--r-- | src/policy.h | 3 | ||||
-rw-r--r-- | src/pool.c | 58 | ||||
-rw-r--r-- | src/pool.h | 3 | ||||
-rw-r--r-- | src/poolid.c | 2 | ||||
-rw-r--r-- | src/poolvendor.c | 4 | ||||
-rw-r--r-- | src/problems.c | 10 | ||||
-rw-r--r-- | src/qsort_r.c | 2 | ||||
-rw-r--r-- | src/repo.c | 4 | ||||
-rw-r--r-- | src/repo.h | 2 | ||||
-rw-r--r-- | src/repo_solv.c | 38 | ||||
-rw-r--r-- | src/repo_write.c | 4 | ||||
-rw-r--r-- | src/repodata.c | 8 | ||||
-rw-r--r-- | src/rules.c | 250 | ||||
-rw-r--r-- | src/rules.h | 6 | ||||
-rw-r--r-- | src/selection.c | 10 | ||||
-rw-r--r-- | src/solver.c | 12 | ||||
-rw-r--r-- | src/solver.h | 6 | ||||
-rw-r--r-- | src/solverdebug.c | 2 | ||||
-rw-r--r-- | src/strpool.c | 2 | ||||
-rw-r--r-- | src/transaction.c | 2 | ||||
-rw-r--r-- | test/testcases/yumobs/split.t | 24 | ||||
-rw-r--r-- | tools/testsolv.c | 5 |
29 files changed, 478 insertions, 51 deletions
diff --git a/VERSION.cmake b/VERSION.cmake index ac9ef35..324dfa7 100644 --- a/VERSION.cmake +++ b/VERSION.cmake @@ -49,5 +49,5 @@ SET(LIBSOLVEXT_SOVERSION "0") SET(LIBSOLV_MAJOR "0") SET(LIBSOLV_MINOR "6") -SET(LIBSOLV_PATCH "4") +SET(LIBSOLV_PATCH "5") diff --git a/bindings/solv.i b/bindings/solv.i index 2d8f775..e8acd35 100644 --- a/bindings/solv.i +++ b/bindings/solv.i @@ -1397,6 +1397,15 @@ typedef struct { return pool_queuetowhatprovides($self, &q); } + %typemap(out) Queue whatmatchesdep Queue2Array(XSolvable *, 1, new_XSolvable(arg1, id)); + %newobject whatmatchesdep; + Queue whatmatchesdep(Id keyname, DepId dep, Id marker = -1) { + Queue q; + queue_init(&q); + pool_whatmatchesdep($self, keyname, dep, &q, marker); + return q; + } + #ifdef SWIGRUBY %rename("isknownarch?") isknownarch; #endif @@ -2769,6 +2778,7 @@ rb_eval_string( static const int SOLVER_FLAG_KEEP_ORPHANS = SOLVER_FLAG_KEEP_ORPHANS; static const int SOLVER_FLAG_BREAK_ORPHANS = SOLVER_FLAG_BREAK_ORPHANS; static const int SOLVER_FLAG_FOCUS_INSTALLED = SOLVER_FLAG_FOCUS_INSTALLED; + static const int SOLVER_FLAG_YUM_OBSOLETES = SOLVER_FLAG_YUM_OBSOLETES; static const int SOLVER_REASON_UNRELATED = SOLVER_REASON_UNRELATED; static const int SOLVER_REASON_UNIT_RULE = SOLVER_REASON_UNIT_RULE; diff --git a/examples/solv.c b/examples/solv.c index d9b03a1..7ae67e3 100644 --- a/examples/solv.c +++ b/examples/solv.c @@ -2464,6 +2464,7 @@ showdiskusagechanges(Transaction *trans) int i; /* XXX: use mountpoints here */ + memset(duc, 0, sizeof(duc)); duc[0].path = "/"; duc[1].path = "/usr/share/man"; duc[2].path = "/sbin"; diff --git a/ext/repo_arch.c b/ext/repo_arch.c index 394e8b5..a0c45ce 100644 --- a/ext/repo_arch.c +++ b/ext/repo_arch.c @@ -294,13 +294,13 @@ adddep(Repo *repo, Offset olddeps, char *line) char *p; Id id; - while (*line == ' ' && *line == '\t') + while (*line == ' ' || *line == '\t') line++; p = line; while (*p && *p != ' ' && *p != '\t' && *p != '<' && *p != '=' && *p != '>') p++; id = pool_strn2id(pool, line, p - line, 1); - while (*p == ' ' && *p == '\t') + while (*p == ' ' || *p == '\t') p++; if (*p == '<' || *p == '=' || *p == '>') { @@ -316,7 +316,7 @@ adddep(Repo *repo, Offset olddeps, char *line) else break; } - while (*p == ' ' && *p == '\t') + while (*p == ' ' || *p == '\t') p++; line = p; while (*p && *p != ' ' && *p != '\t') diff --git a/ext/testcase.c b/ext/testcase.c index 3da7aff..fa9c807 100644 --- a/ext/testcase.c +++ b/ext/testcase.c @@ -105,6 +105,7 @@ static struct solverflags2str { { SOLVER_FLAG_KEEP_ORPHANS, "keeporphans", 0 }, { SOLVER_FLAG_BREAK_ORPHANS, "breakorphans", 0 }, { SOLVER_FLAG_FOCUS_INSTALLED, "focusinstalled", 0 }, + { SOLVER_FLAG_YUM_OBSOLETES, "yumobsoletes", 0 }, { 0, 0, 0 } }; @@ -1728,6 +1729,18 @@ testcase_write(Solver *solv, char *dir, int resultflags, const char *testcasenam } } + /* dump disabled packages (must come before the namespace/job lines) */ + if (pool->considered) + { + Id p; + FOR_POOL_SOLVABLES(p) + if (!MAPTST(pool->considered, p)) + { + cmd = pool_tmpjoin(pool, "disable pkg ", testcase_solvid2str(pool, p), 0); + strqueue_push(&sq, cmd); + } + } + s = testcase_getsolverflags(solv); if (*s) { @@ -2116,7 +2129,7 @@ testcase_read(Pool *pool, FILE *fp, char *testcase, Queue *job, char **resultp, { char *sp; Id how, what; - if (!prepared) + if (prepared <= 0) { pool_addfileprovides(pool); pool_createwhatprovides(pool); @@ -2162,7 +2175,7 @@ testcase_read(Pool *pool, FILE *fp, char *testcase, Queue *job, char **resultp, for (i = 2; i < npieces; i++) queue_push(&q, testcase_str2solvid(pool, pieces[i])); /* now do the callback */ - if (!prepared) + if (prepared <= 0) { pool_addfileprovides(pool); pool_createwhatprovides(pool); @@ -2227,6 +2240,29 @@ testcase_read(Pool *pool, FILE *fp, char *testcase, Queue *job, char **resultp, { break; } + else if (!strcmp(pieces[0], "disable") && npieces == 3) + { + Id p; + if (strcmp(pieces[1], "pkg")) + { + pool_debug(pool, SOLV_ERROR, "testcase_read: bad disable type '%s'\n", pieces[1]); + continue; + } + if (!prepared) + pool_createwhatprovides(pool); + prepared = -1; + if (!pool->considered) + { + pool->considered = solv_calloc(1, sizeof(Map)); + map_init(pool->considered, pool->nsolvables); + map_setall(pool->considered); + } + p = testcase_str2solvid(pool, pieces[2]); + if (p) + MAPCLR(pool->considered, p); + else + pool_debug(pool, SOLV_ERROR, "disable: unknown package '%s'\n", pieces[2]); + } else { pool_debug(pool, SOLV_ERROR, "testcase_read: cannot parse command '%s'\n", pieces[0]); diff --git a/package/libsolv.changes b/package/libsolv.changes index 7368f38..28bd976 100644 --- a/package/libsolv.changes +++ b/package/libsolv.changes @@ -1,4 +1,15 @@ ------------------------------------------------------------------- +Thu Sep 11 17:33:04 CEST 2014 - mls@suse.de + +- support DUCHANGES_ONLYADD flag in diskusage calculation + [bnc#783100] +- add whatmatchesdep to bindings +- support pool->considered in testcases +- always call selection_filelist if SELECTION_FILELIST is set +- support yum style obsolete handling for package splits +- bump version to 0.6.5 + +------------------------------------------------------------------- Tue Jul 8 14:13:40 CEST 2014 - mls@suse.de - expand solver_identical fix to applications [bnc#885830] diff --git a/src/policy.c b/src/policy.c index 5b72517..9e5a934 100644 --- a/src/policy.c +++ b/src/policy.c @@ -776,7 +776,7 @@ move_installed_to_front(Pool *pool, Queue *plist) * sort list of packages (given through plist) by name and evr * return result through plist */ -static void +void prune_to_best_version(Pool *pool, Queue *plist) { int i, j; diff --git a/src/policy.h b/src/policy.h index d034f0d..a4dd4c4 100644 --- a/src/policy.h +++ b/src/policy.h @@ -36,6 +36,9 @@ extern void policy_update_recommendsmap(Solver *solv); extern void policy_create_obsolete_index(Solver *solv); +/* internal, do not use */ +extern void prune_to_best_version(Pool *pool, Queue *plist); + #ifdef __cplusplus } @@ -118,7 +118,7 @@ pool_free(Pool *pool) solv_free(pool->tmpspace.buf[i]); for (i = 0; i < pool->nlanguages; i++) free((char *)pool->languages[i]); - solv_free(pool->languages); + solv_free((void *)pool->languages); solv_free(pool->languagecache); solv_free(pool->errstr); solv_free(pool->rootdir); @@ -1674,7 +1674,7 @@ pool_set_languages(Pool *pool, const char **languages, int nlanguages) pool->languagecacheother = 0; for (i = 0; i < pool->nlanguages; i++) free((char *)pool->languages[i]); - pool->languages = solv_free(pool->languages); + pool->languages = solv_free((void *)pool->languages); pool->nlanguages = nlanguages; if (!nlanguages) return; @@ -1922,7 +1922,7 @@ solver_fill_DU_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyVa cbd->mps[mp].kbytes += value->num; cbd->mps[mp].files += value->num2; } - else + else if (!(cbd->mps[mp].flags & DUCHANGES_ONLYADD)) { cbd->mps[mp].kbytes -= value->num; cbd->mps[mp].files -= value->num2; @@ -2030,13 +2030,17 @@ pool_calc_duchanges(Pool *pool, Map *installedmap, DUChanges *mps, int nmps) struct mptree *mptree; struct ducbdata cbd; Solvable *s; - int sp; + 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; @@ -2054,21 +2058,55 @@ pool_calc_duchanges(Pool *pool, Map *installedmap, DUChanges *mps, int nmps) 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) - if (op >= oldinstalled->start && op < oldinstalled->end) - MAPSET(&ignoredu, op - oldinstalled->start); + { + 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; + } + } + } } - 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; @@ -346,10 +346,13 @@ void pool_search(Pool *pool, Id p, Id key, const char *match, int flags, int (*c void pool_clear_pos(Pool *pool); +#define DUCHANGES_ONLYADD 1 + typedef struct _DUChanges { const char *path; int kbytes; int files; + int flags; } DUChanges; void pool_calc_duchanges(Pool *pool, Map *installedmap, DUChanges *mps, int nmps); diff --git a/src/poolid.c b/src/poolid.c index 5fe502b..7bcc1f6 100644 --- a/src/poolid.c +++ b/src/poolid.c @@ -65,7 +65,7 @@ pool_rel2id(Pool *pool, Id name, Id evr, int flags, int create) ran = pool->rels; /* extend hashtable if needed */ - if (pool->nrels * 2 > hashmask) + if ((Hashval)pool->nrels * 2 > hashmask) { solv_free(pool->relhashtbl); pool->relhashmask = hashmask = mkmask(pool->nrels + REL_BLOCK); diff --git a/src/poolvendor.c b/src/poolvendor.c index a52a94b..ec25f9d 100644 --- a/src/poolvendor.c +++ b/src/poolvendor.c @@ -89,7 +89,7 @@ pool_setvendorclasses(Pool *pool, const char **vendorclasses) { for (v = pool->vendorclasses; v[0] || v[1]; v++) solv_free((void *)*v); - pool->vendorclasses = solv_free(pool->vendorclasses); + pool->vendorclasses = solv_free((void *)pool->vendorclasses); } if (!vendorclasses || !vendorclasses[0]) return; @@ -120,7 +120,7 @@ pool_addvendorclass(Pool *pool, const char **vendorclass) if (i) i++; } - pool->vendorclasses = solv_realloc2(pool->vendorclasses, i + j + 2, sizeof(const char *)); + pool->vendorclasses = solv_realloc2((void *)pool->vendorclasses, i + j + 2, sizeof(const char *)); for (j = 0; vendorclass[j]; j++) pool->vendorclasses[i++] = solv_strdup(vendorclass[j]); pool->vendorclasses[i++] = 0; diff --git a/src/problems.c b/src/problems.c index bb00aa6..b2063a5 100644 --- a/src/problems.c +++ b/src/problems.c @@ -918,7 +918,7 @@ findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp, MAPSET(rseen, rid - solv->learntrules); findproblemrule_internal(solv, solv->learnt_why.elements[rid - solv->learntrules], &lreqr, &lconr, &lsysr, &ljobr, rseen); } - else if ((rid >= solv->jobrules && rid < solv->jobrules_end) || (rid >= solv->infarchrules && rid < solv->infarchrules_end) || (rid >= solv->duprules && rid < solv->duprules_end) || (rid >= solv->bestrules && rid < solv->bestrules_end)) + else if ((rid >= solv->jobrules && rid < solv->jobrules_end) || (rid >= solv->infarchrules && rid < solv->infarchrules_end) || (rid >= solv->duprules && rid < solv->duprules_end) || (rid >= solv->bestrules && rid < solv->bestrules_end) || (rid >= solv->yumobsrules && rid <= solv->yumobsrules_end)) { if (!*jobrp) *jobrp = rid; @@ -1105,6 +1105,10 @@ solver_problemruleinfo2str(Solver *solv, SolverRuleinfo type, Id source, Id targ return pool_tmpjoin(pool, pool_dep2str(pool, dep), " is provided by the system", 0); case SOLVER_RULE_RPM: return "some dependency problem"; + case SOLVER_RULE_BEST: + if (source > 0) + return pool_tmpjoin(pool, "cannot install the best update candidate for package ", pool_solvid2str(pool, source), 0); + return "cannot install the best candidate for the job"; case SOLVER_RULE_RPM_NOT_INSTALLABLE: return pool_tmpjoin(pool, "package ", pool_solvid2str(pool, source), " is not installable"); case SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP: @@ -1135,6 +1139,10 @@ solver_problemruleinfo2str(Solver *solv, SolverRuleinfo type, Id source, Id targ case SOLVER_RULE_RPM_SELF_CONFLICT: s = pool_tmpjoin(pool, "package ", pool_solvid2str(pool, source), " conflicts with "); return pool_tmpappend(pool, s, pool_dep2str(pool, dep), " provided by itself"); + case SOLVER_RULE_YUMOBS: + s = pool_tmpjoin(pool, "both package ", pool_solvid2str(pool, source), " and "); + s = pool_tmpjoin(pool, s, pool_solvid2str(pool, target), " obsolete "); + return pool_tmpappend(pool, s, pool_dep2str(pool, dep), 0); default: return "bad problem rule type"; } diff --git a/src/qsort_r.c b/src/qsort_r.c index f264ed0..d49049a 100644 --- a/src/qsort_r.c +++ b/src/qsort_r.c @@ -47,7 +47,9 @@ typedef int cmp_t(const void *, const void *, void *); static inline char *med3(char *, char *, char *, cmp_t *, void *); static inline void swapfunc(char *, char *, int, int); +#ifndef min #define min(a, b) (a) < (b) ? a : b +#endif /* * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". @@ -388,10 +388,10 @@ repo_addid_dep_hash(Repo *repo, Offset olddeps, Id id, Id marker, int size) } /* maintain hash and lastmarkerpos */ - if (repo->lastidhash_idarraysize != repo->idarraysize || size * 2 > repo->lastidhash_mask || repo->lastmarker != marker) + if (repo->lastidhash_idarraysize != repo->idarraysize || (Hashval)size * 2 > repo->lastidhash_mask || repo->lastmarker != marker) { repo->lastmarkerpos = 0; - if (size * 2 > repo->lastidhash_mask) + if (size * 2 > (Hashval)repo->lastidhash_mask) { repo->lastidhash_mask = mkmask(size < REPO_ADDID_DEP_HASHMIN ? REPO_ADDID_DEP_HASHMIN : size); repo->lastidhash = solv_realloc2(repo->lastidhash, repo->lastidhash_mask + 1, sizeof(Id)); @@ -41,7 +41,7 @@ typedef struct _Repo { Id *idarraydata; /* array of metadata Ids, solvable dependencies are offsets into this array */ int idarraysize; - unsigned nrepodata; /* number of our stores.. */ + int nrepodata; /* number of our stores.. */ Id *rpmdbid; /* solvable side data: rpm database id */ diff --git a/src/repo_solv.c b/src/repo_solv.c index 0e8b854..86c851c 100644 --- a/src/repo_solv.c +++ b/src/repo_solv.c @@ -113,7 +113,7 @@ read_id(Repodata *data, Id max) if (!(c & 128)) { x = (x << 7) | c; - if (max && x >= max) + if (max && x >= (unsigned int)max) { data->error = pool_error(data->repo->pool, SOLV_ERROR_ID_RANGE, "read_id: id too large (%u/%u)", x, max); return 0; @@ -149,7 +149,7 @@ read_idarray(Repodata *data, Id max, Id *map, Id *store, Id *end) continue; } x = (x << 6) | (c & 63); - if (max && x >= max) + if (max && x >= (unsigned int)max) { data->error = pool_error(data->repo->pool, SOLV_ERROR_ID_RANGE, "read_idarray: id too large (%u/%u)", x, max); return 0; @@ -217,7 +217,7 @@ data_read_idarray(unsigned char *dp, Id **storep, Id *map, int max, Repodata *da continue; } x = (x << 6) | (c & 63); - if (max && x >= max) + if (max && x >= (unsigned int)max) { data->error = pool_error(data->repo->pool, SOLV_ERROR_ID_RANGE, "data_read_idarray: id too large (%u/%u)", x, max); data->error = SOLV_ERROR_ID_RANGE; @@ -261,7 +261,7 @@ data_read_rel_idarray(unsigned char *dp, Id **storep, Id *map, int max, Repodata } x = old + (x - 1); old = x; - if (max && x >= max) + if (max && x >= (unsigned int)max) { data->error = pool_error(data->repo->pool, SOLV_ERROR_ID_RANGE, "data_read_rel_idarray: id too large (%u/%u)", x, max); break; @@ -360,7 +360,7 @@ incore_add_ideof(Repodata *data, Id sx, int eof) static void incore_add_blob(Repodata *data, unsigned char *buf, int len) { - if (data->incoredatafree < len) + if (data->incoredatafree < (unsigned int)len) { data->incoredata = solv_realloc(data->incoredata, data->incoredatalen + INCORE_ADD_CHUNK + len); data->incoredatafree = INCORE_ADD_CHUNK + len; @@ -444,8 +444,8 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) { Pool *pool = repo->pool; int i, l; - unsigned int numid, numrel, numdir, numsolv; - unsigned int numkeys, numschemata; + int numid, numrel, numdir, numsolv; + int numkeys, numschemata; Offset sizeid; Offset *str; /* map Id -> Offset into string space */ @@ -519,16 +519,26 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) return pool_error(pool, SOLV_ERROR_UNSUPPORTED, "unsupported SOLV version"); } - numid = read_u32(&data); - numrel = read_u32(&data); - numdir = read_u32(&data); - numsolv = read_u32(&data); - numkeys = read_u32(&data); - numschemata = read_u32(&data); + numid = (int)read_u32(&data); + numrel = (int)read_u32(&data); + numdir = (int)read_u32(&data); + numsolv = (int)read_u32(&data); + numkeys = (int)read_u32(&data); + numschemata = (int)read_u32(&data); solvflags = read_u32(&data); - if (numdir && numdir < 2) + if (numid < 0 || numid >= 0x20000000) + return pool_error(pool, SOLV_ERROR_CORRUPT, "bad number of ids"); + if (numrel < 0 || numrel >= 0x20000000) + return pool_error(pool, SOLV_ERROR_CORRUPT, "bad number of rels"); + if (numdir && (numdir < 2 || numdir >= 0x20000000)) return pool_error(pool, SOLV_ERROR_CORRUPT, "bad number of dirs"); + if (numsolv < 0 || numsolv >= 0x20000000) + return pool_error(pool, SOLV_ERROR_CORRUPT, "bad number of solvables"); + if (numkeys < 0 || numkeys >= 0x20000000) + return pool_error(pool, SOLV_ERROR_CORRUPT, "bad number of keys"); + if (numschemata < 0 || numschemata >= 0x20000000) + return pool_error(pool, SOLV_ERROR_CORRUPT, "bad number of schematas"); if (numrel && (flags & REPO_LOCALPOOL) != 0) return pool_error(pool, SOLV_ERROR_CORRUPT, "relations are forbidden in a local pool"); diff --git a/src/repo_write.c b/src/repo_write.c index 11002b4..210636c 100644 --- a/src/repo_write.c +++ b/src/repo_write.c @@ -1568,7 +1568,7 @@ for (i = 1; i < target.nkeys; i++) /* remove unused keys */ keyused = solv_calloc(target.nkeys, sizeof(Id)); - for (i = 1; i < target.schemadatalen; i++) + for (i = 1; i < (int)target.schemadatalen; i++) keyused[target.schemadata[i]] = 1; keyused[0] = 0; for (n = i = 1; i < target.nkeys; i++) @@ -1592,7 +1592,7 @@ for (i = 1; i < target.nkeys; i++) queue_truncate(keyq, 2 * n - 2); /* update schema data to the new key ids */ - for (i = 1; i < target.schemadatalen; i++) + for (i = 1; i < (int)target.schemadatalen; i++) target.schemadata[i] = keyused[target.schemadata[i]]; /* update keymap to the new key ids */ for (i = 0; i < cbdata.nkeymap; i++) diff --git a/src/repodata.c b/src/repodata.c index d527a42..4d57790 100644 --- a/src/repodata.c +++ b/src/repodata.c @@ -479,11 +479,11 @@ get_vertical_data(Repodata *data, Repokey *key, Id off, Id len) if (off >= data->lastverticaloffset) { off -= data->lastverticaloffset; - if (off + len > data->vincorelen) + if ((unsigned int)off + len > data->vincorelen) return 0; return data->vincore + off; } - if (off + len > key->size) + if ((unsigned int)off + len > key->size) return 0; /* we now have the offset, go into vertical */ off += data->verticaloffset[key - data->keys]; @@ -2928,7 +2928,7 @@ compact_attrdata(Repodata *data, int entry, int nentry) case REPOKEY_TYPE_STR: case REPOKEY_TYPE_BINARY: case_CHKSUM_TYPES: - if (attrs[1] < attrdatastart) + if ((unsigned int)attrs[1] < attrdatastart) attrdatastart = attrs[1]; break; case REPOKEY_TYPE_DIRSTRARRAY: @@ -2938,7 +2938,7 @@ compact_attrdata(Repodata *data, int entry, int nentry) /* FALLTHROUGH */ case REPOKEY_TYPE_IDARRAY: case REPOKEY_TYPE_DIRNUMNUMARRAY: - if (attrs[1] < attriddatastart) + if ((unsigned int)attrs[1] < attriddatastart) attriddatastart = attrs[1]; break; case REPOKEY_TYPE_FIXARRAY: diff --git a/src/rules.c b/src/rules.c index 6b561cc..922b9d0 100644 --- a/src/rules.c +++ b/src/rules.c @@ -434,8 +434,11 @@ makemultiversionconflict(Solver *solv, Id n, Id con) queue_push(&q, p); } if (q.count == 1) - return -n; /* no other package found, generate normal conflict */ - return pool_queuetowhatprovides(pool, &q); + n = -n; /* no other package found, generate normal conflict */ + else + n = pool_queuetowhatprovides(pool, &q); + queue_free(&q); + return n; } static inline void @@ -2649,8 +2652,26 @@ solver_ruleinfo(Solver *solv, Id rid, Id *fromp, Id *top, Id *depp) } if (rid >= solv->bestrules && rid < solv->bestrules_end) { + if (fromp && solv->bestrules_pkg[rid - solv->bestrules] > 0) + *fromp = solv->bestrules_pkg[rid - solv->bestrules]; return SOLVER_RULE_BEST; } + if (rid >= solv->yumobsrules && rid < solv->yumobsrules_end) + { + if (fromp) + *fromp = -r->p; + if (top) + { + /* first solvable is enough, we just need it for the name */ + if (!r->d || r->d == -1) + *top = r->w2; + else + *top = pool->whatprovidesdata[r->d < 0 ? -r->d : r->d]; + } + if (depp) + *depp = solv->yumobsrules_info[rid - solv->yumobsrules]; + return SOLVER_RULE_YUMOBS; + } if (rid >= solv->choicerules && rid < solv->choicerules_end) { return SOLVER_RULE_CHOICE; @@ -2681,6 +2702,8 @@ solver_ruleclass(Solver *solv, Id rid) return SOLVER_RULE_INFARCH; if (rid >= solv->bestrules && rid < solv->bestrules_end) return SOLVER_RULE_BEST; + if (rid >= solv->yumobsrules && rid < solv->yumobsrules_end) + return SOLVER_RULE_YUMOBS; if (rid >= solv->choicerules && rid < solv->choicerules_end) return SOLVER_RULE_CHOICE; if (rid >= solv->learntrules) @@ -3248,6 +3271,229 @@ solver_addbestrules(Solver *solv, int havebestinstalljobs) queue_free(&r2pkg); } + + + +/* yumobs rule handling */ + +static void +find_obsolete_group(Solver *solv, Id obs, Queue *q) +{ + Pool *pool = solv->pool; + Queue qn; + Id p2, pp2, op, *opp, opp2; + int i, j, qnc, ncnt; + + queue_empty(q); + FOR_PROVIDES(p2, pp2, obs) + { + Solvable *s2 = pool->solvables + p2; + if (s2->repo != pool->installed) + continue; + if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + p2, obs)) + continue; + /* we obsolete installed package s2 with obs. now find all other packages that have the same dep */ + for (opp = solv->obsoletes_data + solv->obsoletes[p2 - solv->installed->start]; (op = *opp++) != 0;) + { + Solvable *os = pool->solvables + op; + Id obs2, *obsp2; + if (!os->obsoletes) + continue; + if (pool->obsoleteusescolors && !pool_colormatch(pool, s2, os)) + continue; + obsp2 = os->repo->idarraydata + os->obsoletes; + while ((obs2 = *obsp2++) != 0) + if (obs2 == obs) + break; + if (obs2) + queue_pushunique(q, op); + } + /* also search packages with the same name */ + FOR_PROVIDES(op, opp2, s2->name) + { + Solvable *os = pool->solvables + op; + Id obs2, *obsp2; + if (os->name != s2->name) + continue; + if (!os->obsoletes) + continue; + if (pool->obsoleteusescolors && !pool_colormatch(pool, s2, os)) + continue; + obsp2 = os->repo->idarraydata + os->obsoletes; + while ((obs2 = *obsp2++) != 0) + if (obs2 == obs) + break; + if (obs2) + queue_pushunique(q, op); + } + } + /* find names so that we can build groups */ + queue_init_clone(&qn, q); + prune_to_best_version(solv->pool, &qn); +#if 0 +{ + for (i = 0; i < qn.count; i++) + printf(" + %s\n", pool_solvid2str(pool, qn.elements[i])); +} +#endif + /* filter into name groups */ + qnc = qn.count; + if (qnc == 1) + { + queue_free(&qn); + queue_empty(q); + return; + } + ncnt = 0; + for (i = 0; i < qnc; i++) + { + Id n = pool->solvables[qn.elements[i]].name; + int got = 0; + for (j = 0; j < q->count; j++) + { + Id p = q->elements[j]; + if (pool->solvables[p].name == n) + { + queue_push(&qn, p); + got = 1; + } + } + if (got) + { + queue_push(&qn, 0); + ncnt++; + } + } + if (ncnt <= 1) + { + queue_empty(q); + } + else + { + queue_empty(q); + queue_insertn(q, 0, qn.count - qnc, qn.elements + qnc); + } + queue_free(&qn); +} + +void +solver_addyumobsrules(Solver *solv) +{ + Pool *pool = solv->pool; + Repo *installed = solv->installed; + Id p, op, *opp; + Solvable *s; + Queue qo, qq, yumobsinfoq; + int i, j, k; + unsigned int now; + + solv->yumobsrules = solv->nrules; + if (!installed || !solv->obsoletes) + { + solv->yumobsrules_end = solv->nrules; + return; + } + now = solv_timems(0); + queue_init(&qo); + FOR_REPO_SOLVABLES(installed, p, s) + { + if (!solv->obsoletes[p - installed->start]) + continue; +#if 0 +printf("checking yumobs for %s\n", pool_solvable2str(pool, s)); +#endif + queue_empty(&qo); + for (opp = solv->obsoletes_data + solv->obsoletes[p - installed->start]; (op = *opp++) != 0;) + { + Solvable *os = pool->solvables + op; + Id obs, *obsp = os->repo->idarraydata + os->obsoletes; + Id p2, pp2; + while ((obs = *obsp++) != 0) + { + FOR_PROVIDES(p2, pp2, obs) + { + Solvable *s2 = pool->solvables + p2; + if (s2->repo != installed) + continue; + if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + p2, obs)) + continue; + if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2)) + continue; + queue_pushunique(&qo, obs); + break; + } + } + } + } + if (!qo.count) + { + queue_free(&qo); + return; + } + queue_init(&yumobsinfoq); + queue_init(&qq); + for (i = 0; i < qo.count; i++) + { + int group, groupk, groupstart; + queue_empty(&qq); +#if 0 +printf("investigating %s\n", pool_dep2str(pool, qo.elements[i])); +#endif + find_obsolete_group(solv, qo.elements[i], &qq); +#if 0 +printf("result:\n"); +for (j = 0; j < qq.count; j++) + if (qq.elements[j] == 0) + printf("---\n"); + else + printf("%s\n", pool_solvid2str(pool, qq.elements[j])); +#endif + + if (!qq.count) + continue; + /* at least two goups, build rules */ + group = 0; + for (j = 0; j < qq.count; j++) + { + p = qq.elements[j]; + if (!p) + { + group++; + continue; + } + if (pool->solvables[p].repo == installed) + continue; + groupk = 0; + groupstart = 0; + for (k = 0; k < qq.count; k++) + { + Id pk = qq.elements[k]; + if (pk) + continue; + if (group != groupk && k > groupstart) + { + /* add the rule */ + Queue qhelper; + memset(&qhelper, 0, sizeof(qhelper)); + qhelper.count = k - groupstart; + qhelper.elements = qq.elements + groupstart; + solver_addrule(solv, -p, pool_queuetowhatprovides(pool, &qhelper)); + queue_push(&yumobsinfoq, qo.elements[i]); + } + groupstart = k + 1; + groupk++; + } + } + } + if (yumobsinfoq.count) + solv->yumobsrules_info = solv_memdup2(yumobsinfoq.elements, yumobsinfoq.count, sizeof(Id)); + queue_free(&yumobsinfoq); + queue_free(&qq); + queue_free(&qo); + solv->yumobsrules_end = solv->nrules; + POOL_DEBUG(SOLV_DEBUG_STATS, "yumobs rule creation took %d ms\n", solv_timems(now)); +} + #undef CLEANDEPSDEBUG /* diff --git a/src/rules.h b/src/rules.h index 06048e4..3be3ea1 100644 --- a/src/rules.h +++ b/src/rules.h @@ -69,7 +69,8 @@ typedef enum { SOLVER_RULE_INFARCH = 0x600, SOLVER_RULE_CHOICE = 0x700, SOLVER_RULE_LEARNT = 0x800, - SOLVER_RULE_BEST = 0x900 + SOLVER_RULE_BEST = 0x900, + SOLVER_RULE_YUMOBS = 0xa00 } SolverRuleinfo; #define SOLVER_RULE_TYPEMASK 0xff00 @@ -127,6 +128,9 @@ extern void solver_disablechoicerules(struct _Solver *solv, Rule *r); /* best rules */ extern void solver_addbestrules(struct _Solver *solv, int havebestinstalljobs); +/* yumobs rules */ +extern void solver_addyumobsrules(struct _Solver *solv); + /* policy rule disabling/reenabling */ extern void solver_disablepolicyrules(struct _Solver *solv); extern void solver_reenablepolicyrules(struct _Solver *solv, int jobidx); diff --git a/src/selection.c b/src/selection.c index f0e61ea..8856436 100644 --- a/src/selection.c +++ b/src/selection.c @@ -551,6 +551,14 @@ selection_filelist(Pool *pool, Queue *selection, const char *name, int flags) Queue q; int type; + /* all files in the file list start with a '/' */ + if (*name != '/') + { + if (!(flags & SELECTION_GLOB)) + return 0; + if (*name != '*' && *name != '[' && *name != '?') + return 0; + } type = !(flags & SELECTION_GLOB) || strpbrk(name, "[*?") == 0 ? SEARCH_STRING : SEARCH_GLOB; if ((flags & SELECTION_NOCASE) != 0) type |= SEARCH_NOCASE; @@ -842,7 +850,7 @@ selection_make(Pool *pool, Queue *selection, const char *name, int flags) int ret = 0; queue_empty(selection); - if (*name == '/' && (flags & SELECTION_FILELIST)) + if ((flags & SELECTION_FILELIST) != 0) ret = selection_filelist(pool, selection, name, flags); if (!ret && (flags & SELECTION_REL) != 0 && strpbrk(name, "<=>") != 0) ret = selection_rel(pool, selection, name, flags); diff --git a/src/solver.c b/src/solver.c index b0f1bce..48b3aaa 100644 --- a/src/solver.c +++ b/src/solver.c @@ -1681,6 +1681,7 @@ solver_free(Solver *solv) solv_free(solv->specialupdaters); solv_free(solv->choicerules_ref); solv_free(solv->bestrules_pkg); + solv_free(solv->yumobsrules_info); solv_free(solv->instbuddy); solv_free(solv); } @@ -1730,6 +1731,8 @@ solver_get_flag(Solver *solv, int flag) return solv->break_orphans; case SOLVER_FLAG_FOCUS_INSTALLED: return solv->focus_installed; + case SOLVER_FLAG_YUM_OBSOLETES: + return solv->do_yum_obsoletes; default: break; } @@ -1802,6 +1805,9 @@ solver_set_flag(Solver *solv, int flag, int value) case SOLVER_FLAG_FOCUS_INSTALLED: solv->focus_installed = value; break; + case SOLVER_FLAG_YUM_OBSOLETES: + solv->do_yum_obsoletes = value; + break; default: break; } @@ -3401,6 +3407,7 @@ solver_solve(Solver *solv, Queue *job) queuep_free(&solv->cleandeps_updatepkgs); queue_empty(&solv->ruleassertions); solv->bestrules_pkg = solv_free(solv->bestrules_pkg); + solv->yumobsrules_info = solv_free(solv->yumobsrules_info); solv->choicerules_ref = solv_free(solv->choicerules_ref); if (solv->noupdate.size) map_empty(&solv->noupdate); @@ -3963,6 +3970,11 @@ solver_solve(Solver *solv, Queue *job) if (hasdupjob) solver_freedupmaps(solv); /* no longer needed */ + if (solv->do_yum_obsoletes) + solver_addyumobsrules(solv); + else + solv->yumobsrules = solv->yumobsrules_end = solv->nrules; + if (1) solver_addchoicerules(solv); else diff --git a/src/solver.h b/src/solver.h index 3d63b6f..49ccec8 100644 --- a/src/solver.h +++ b/src/solver.h @@ -70,6 +70,10 @@ struct _Solver { Id bestrules_end; Id *bestrules_pkg; + Id yumobsrules; /* rules from yum obsoletes handling */ + Id yumobsrules_end; + Id *yumobsrules_info; /* the dependency for each rule */ + Id choicerules; /* choice rules (always weak) */ Id choicerules_end; Id *choicerules_ref; @@ -161,6 +165,7 @@ struct _Solver { int bestobeypolicy; /* true: stay in policy with the best rules */ int noautotarget; /* true: do not assume targeted for up/dup jobs that contain no installed solvable */ int focus_installed; /* true: resolve update rules first */ + int do_yum_obsoletes; /* true: add special yumobs rules */ Map dupmap; /* dup these packages*/ int dupmap_all; /* dup all packages */ @@ -289,6 +294,7 @@ typedef struct _Solver Solver; #define SOLVER_FLAG_KEEP_ORPHANS 18 #define SOLVER_FLAG_BREAK_ORPHANS 19 #define SOLVER_FLAG_FOCUS_INSTALLED 20 +#define SOLVER_FLAG_YUM_OBSOLETES 21 #define GET_USERINSTALLED_NAMES (1 << 0) /* package names instead if ids */ #define GET_USERINSTALLED_INVERTED (1 << 1) /* autoinstalled */ diff --git a/src/solverdebug.c b/src/solverdebug.c index afec8c5..3e84046 100644 --- a/src/solverdebug.c +++ b/src/solverdebug.c @@ -126,6 +126,8 @@ solver_printruleclass(Solver *solv, int type, Rule *r) POOL_DEBUG(type, "UPDATE "); else if (p >= solv->featurerules && p < solv->featurerules_end) POOL_DEBUG(type, "FEATURE "); + else if (p >= solv->yumobsrules && p < solv->yumobsrules_end) + POOL_DEBUG(type, "YUMOBS "); solver_printrule(solv, type, r); } diff --git a/src/strpool.c b/src/strpool.c index 3ad0a80..af43e01 100644 --- a/src/strpool.c +++ b/src/strpool.c @@ -93,7 +93,7 @@ stringpool_strn2id(Stringpool *ss, const char *str, unsigned int len, int create hashtbl = ss->stringhashtbl; /* expand hashtable if needed */ - if (ss->nstrings * 2 > hashmask) + if ((Hashval)ss->nstrings * 2 > hashmask) { solv_free(hashtbl); diff --git a/src/transaction.c b/src/transaction.c index 7dac0a8..49e58e8 100644 --- a/src/transaction.c +++ b/src/transaction.c @@ -666,7 +666,7 @@ create_transaction_info(Transaction *trans, Queue *decisionq) s2 = pool->solvables + p2; if (s2->repo != installed) continue; - if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + p2, obs)) + if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, s2, obs)) continue; if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2)) continue; diff --git a/test/testcases/yumobs/split.t b/test/testcases/yumobs/split.t new file mode 100644 index 0000000..a3921ed --- /dev/null +++ b/test/testcases/yumobs/split.t @@ -0,0 +1,24 @@ +repo system 0 testtags <inline> +#>=Ver: 2.0 +#>=Pkg: c 27 1 x86_64 +repo available 0 testtags <inline> +#>=Ver: 2.0 +#>=Pkg: d 28 1 x86_64 +#>=Obs: c +#>=Pkg: e 28 1 x86_64 +#>=Obs: c + +system x86_64 rpm system + +job update all packages +result transaction,problems <inline> +#>erase c-27-1.x86_64@system d-28-1.x86_64@available +#>install d-28-1.x86_64@available + +nextjob +solverflags yumobsoletes +job update all packages +result transaction,problems <inline> +#>erase c-27-1.x86_64@system d-28-1.x86_64@available +#>install d-28-1.x86_64@available +#>install e-28-1.x86_64@available diff --git a/tools/testsolv.c b/tools/testsolv.c index 34f393b..279b43b 100644 --- a/tools/testsolv.c +++ b/tools/testsolv.c @@ -141,8 +141,11 @@ main(int argc, char **argv) printf("test %d:\n", multijob++); if (list) { + int selflags = SELECTION_NAME|SELECTION_PROVIDES|SELECTION_CANON|SELECTION_DOTARCH|SELECTION_REL|SELECTION_GLOB|SELECTION_FLAT; + if (*list == '/') + selflags |= SELECTION_FILELIST; queue_empty(&job); - selection_make(pool, &job, list, SELECTION_NAME|SELECTION_PROVIDES|SELECTION_FILELIST|SELECTION_CANON|SELECTION_DOTARCH|SELECTION_REL|SELECTION_GLOB|SELECTION_FLAT); + selection_make(pool, &job, list, selflags); if (!job.elements) printf("No match\n"); else |