diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dataiterator.h | 11 | ||||
-rw-r--r-- | src/knownid.h | 24 | ||||
-rw-r--r-- | src/libsolv.ver | 2 | ||||
-rw-r--r-- | src/policy.c | 24 | ||||
-rw-r--r-- | src/pool.c | 47 | ||||
-rw-r--r-- | src/pool.h | 6 | ||||
-rw-r--r-- | src/repo.h | 13 | ||||
-rw-r--r-- | src/repo_write.c | 2 | ||||
-rw-r--r-- | src/repodata.c | 126 | ||||
-rw-r--r-- | src/repodata.h | 1 | ||||
-rw-r--r-- | src/repopack.h | 4 | ||||
-rw-r--r-- | src/rules.c | 95 | ||||
-rw-r--r-- | src/rules.h | 1 | ||||
-rw-r--r-- | src/selection.c | 32 | ||||
-rw-r--r-- | src/solvable.c | 47 | ||||
-rw-r--r-- | src/solver.c | 171 | ||||
-rw-r--r-- | src/solver.h | 52 |
17 files changed, 510 insertions, 148 deletions
diff --git a/src/dataiterator.h b/src/dataiterator.h index 6f8fd32..a77d902 100644 --- a/src/dataiterator.h +++ b/src/dataiterator.h @@ -132,6 +132,16 @@ typedef struct _Dataiterator } parents[3]; int nparents; + /* vertical data */ + unsigned char *vert_ddp; + Id vert_off; + Id vert_len; + Id vert_storestate; + + /* strdup data */ + char *dupstr; + int dupstrn; + } Dataiterator; @@ -165,6 +175,7 @@ void dataiterator_jump_to_repo(Dataiterator *di, struct _Repo *repo); void dataiterator_entersub(Dataiterator *di); void dataiterator_clonepos(Dataiterator *di, Dataiterator *from); void dataiterator_seek(Dataiterator *di, int whence); +void dataiterator_strdup(Dataiterator *di); #define DI_SEEK_STAY (1 << 16) #define DI_SEEK_CHILD 1 diff --git a/src/knownid.h b/src/knownid.h index ad8b4a4..83b943e 100644 --- a/src/knownid.h +++ b/src/knownid.h @@ -58,6 +58,7 @@ KNOWNID(ARCH_SRC, "src"), KNOWNID(ARCH_NOSRC, "nosrc"), KNOWNID(ARCH_NOARCH, "noarch"), KNOWNID(ARCH_ALL, "all"), +KNOWNID(ARCH_ANY, "any"), KNOWNID(REPOSITORY_SOLVABLES, "repository:solvables"), KNOWNID(REPOSITORY_DELTAINFO, "repository:deltainfo"), @@ -133,6 +134,11 @@ KNOWNID(SOLVABLE_LEADSIGID, "solvable:leadsigid"), /* leadsigid: md5sum over l KNOWNID(SOLVABLE_PATCHCATEGORY, "solvable:patchcategory"), KNOWNID(SOLVABLE_HEADEREND, "solvable:headerend"), +KNOWNID(SOLVABLE_CHANGELOG, "solvable:changelog"), +KNOWNID(SOLVABLE_CHANGELOG_AUTHOR, "solvable:changelog:author"), +KNOWNID(SOLVABLE_CHANGELOG_TIME, "solvable:changelog:time"), +KNOWNID(SOLVABLE_CHANGELOG_TEXT, "solvable:changelog:text"), + /* stuff for solvables of type pattern */ KNOWNID(SOLVABLE_CATEGORY, "solvable:category"), @@ -184,6 +190,10 @@ KNOWNID(SUSETAGS_FILE, "susetags:file"), KNOWNID(SUSETAGS_FILE_NAME, "susetags:file:name"), KNOWNID(SUSETAGS_FILE_TYPE, "susetags:file:type"), KNOWNID(SUSETAGS_FILE_CHECKSUM, "susetags:file:checksum"), +KNOWNID(SUSETAGS_SHARE_NAME, "susetags:share:name"), +KNOWNID(SUSETAGS_SHARE_EVR, "susetags:share:evr"), +KNOWNID(SUSETAGS_SHARE_ARCH, "susetags:share:arch"), + /* timestamp then the repository was generated */ KNOWNID(REPOSITORY_TIMESTAMP, "repository:timestamp"), @@ -200,11 +210,13 @@ KNOWNID(REPOSITORY_UPDATES, "repository:updates"), KNOWNID(REPOSITORY_DISTROS, "repository:distros"), KNOWNID(REPOSITORY_PRODUCT_LABEL, "repository:product:label"), KNOWNID(REPOSITORY_PRODUCT_CPEID, "repository:product:cpeid"), +KNOWNID(REPOSITORY_REPOID, "repository:repoid"), /* obsolete? */ /* keyword (tags) for this repository */ KNOWNID(REPOSITORY_KEYWORDS, "repository:keywords"), /* revision of the repository. arbitrary string */ KNOWNID(REPOSITORY_REVISION, "repository:revision"), +KNOWNID(REPOSITORY_TOOLVERSION, "repository:toolversion"), KNOWNID(DELTA_PACKAGE_NAME, "delta:pkgname"), KNOWNID(DELTA_PACKAGE_EVR, "delta:pkgevr"), @@ -229,23 +241,13 @@ KNOWNID(REPOSITORY_REPOMD_LOCATION, "repository:repomd:location"), KNOWNID(REPOSITORY_REPOMD_TIMESTAMP, "repository:repomd:timestamp"), KNOWNID(REPOSITORY_REPOMD_CHECKSUM, "repository:repomd:checksum"), KNOWNID(REPOSITORY_REPOMD_OPENCHECKSUM, "repository:repomd:openchecksum"), +KNOWNID(REPOSITORY_REPOMD_SIZE, "repository:repomd:size"), KNOWNID(PUBKEY_KEYID, "pubkey:keyid"), KNOWNID(PUBKEY_FINGERPRINT, "pubkey:fingerprint"), KNOWNID(PUBKEY_EXPIRES, "pubkey:expires"), KNOWNID(PUBKEY_SIGNATURES, "pubkey:signatures"), -KNOWNID(REPOSITORY_TOOLVERSION, "repository:toolversion"), -KNOWNID(REPOSITORY_REPOID, "repository:repoid"), - -KNOWNID(SUSETAGS_SHARE_NAME, "susetags:share:name"), -KNOWNID(SUSETAGS_SHARE_EVR, "susetags:share:evr"), -KNOWNID(SUSETAGS_SHARE_ARCH, "susetags:share:arch"), - -KNOWNID(ARCH_ANY, "any"), - -KNOWNID(REPOSITORY_REPOMD_SIZE, "repository:repomd:size"), - KNOWNID(ID_NUM_INTERNAL, 0) #ifdef KNOWNID_INITIALIZE diff --git a/src/libsolv.ver b/src/libsolv.ver index bc487ce..52b51da 100644 --- a/src/libsolv.ver +++ b/src/libsolv.ver @@ -19,6 +19,7 @@ SOLV_1.0 { dataiterator_skip_repo; dataiterator_skip_solvable; dataiterator_step; + dataiterator_strdup; datamatcher_free; datamatcher_init; datamatcher_match; @@ -89,6 +90,7 @@ SOLV_1.0 { pool_rel2id; pool_search; pool_selection2str; + pool_set_custom_vendorcheck; pool_set_flag; pool_set_installed; pool_set_languages; diff --git a/src/policy.c b/src/policy.c index abd07e5..916590c 100644 --- a/src/policy.c +++ b/src/policy.c @@ -601,11 +601,6 @@ prune_to_best_version(Pool *pool, Queue *plist) static void prune_best_arch_name_version(const Solver *solv, Pool *pool, Queue *plist) { - if (solv && solv->bestSolvableCb) - { /* The application is responsible for */ - return solv->bestSolvableCb(solv->pool, plist); - } - if (plist->count > 1) prune_to_best_arch(pool, plist); if (plist->count > 1) @@ -675,11 +670,6 @@ policy_illegal_archchange(Solver *solv, Solvable *s1, Solvable *s2) Pool *pool = solv->pool; Id a1 = s1->arch, a2 = s2->arch; - if (solv && solv->archCheckCb) - { /* The application is responsible for */ - return solv->archCheckCb(solv->pool, s1, s2); - } - /* we allow changes to/from noarch */ if (a1 == a2 || a1 == pool->noarchid || a2 == pool->noarchid) return 0; @@ -701,10 +691,9 @@ policy_illegal_vendorchange(Solver *solv, Solvable *s1, Solvable *s2) Id v1, v2; Id vendormask1, vendormask2; - if (solv->vendorCheckCb) - { /* The application is responsible for */ - return solv->vendorCheckCb(pool, s1, s2); - } + if (pool->custom_vendorcheck) + return pool->custom_vendorcheck(pool, s1, s2); + /* treat a missing vendor as empty string */ v1 = s1->vendor ? s1->vendor : ID_EMPTY; v2 = s2->vendor ? s2->vendor : ID_EMPTY; @@ -768,6 +757,8 @@ policy_create_obsolete_index(Solver *solv) Id p, pp, obs, *obsp, *obsoletes, *obsoletes_data; int i, n, cnt; + solv->obsoletes = solv_free(solv->obsoletes); + solv->obsoletes_data = solv_free(solv->obsoletes_data); if (!installed || installed->start == installed->end) return; cnt = installed->end - installed->start; @@ -867,11 +858,6 @@ policy_findupdatepackages(Solver *solv, Solvable *s, Queue *qs, int allow_all) queue_empty(qs); - if (solv && solv->updateCandidateCb) - { /* The application is responsible for */ - return solv->updateCandidateCb(solv->pool, s, qs); - } - n = s - pool->solvables; /* @@ -758,6 +758,8 @@ pool_addrelproviders(Pool *pool, Id d) continue; if (s->arch != evr && s->arch != ARCH_NOSRC) continue; + if (pool_disabled_solvable(pool, s)) + continue; if (pool_match_nevr(pool, s, name)) queue_push(&plist, p); } @@ -2096,6 +2098,39 @@ pool_lookup_deltalocation(Pool *pool, Id entry, unsigned int *medianrp) return loc; } +static void +add_new_provider(Pool *pool, Id id, Id p) +{ + Queue q; + Id *pp; + + while (ISRELDEP(id)) + { + Reldep *rd = GETRELDEP(pool, id); + id = rd->name; + } + + queue_init(&q); + for (pp = pool->whatprovidesdata + pool->whatprovides[id]; *pp; pp++) + { + if (*pp == p) + { + queue_free(&q); + return; + } + if (*pp > p) + { + queue_push(&q, p); + p = 0; + } + queue_push(&q, *pp); + } + if (p) + queue_push(&q, p); + pool->whatprovides[id] = pool_queuetowhatprovides(pool, &q); + queue_free(&q); +} + void pool_add_fileconflicts_deps(Pool *pool, Queue *conflicts) { @@ -2107,7 +2142,6 @@ pool_add_fileconflicts_deps(Pool *pool, Queue *conflicts) if (!conflicts->count) return; - pool_freewhatprovides(pool); for (i = 0; i < conflicts->count; i += 5) { fn = conflicts->elements[i]; @@ -2119,6 +2153,10 @@ pool_add_fileconflicts_deps(Pool *pool, Queue *conflicts) if (!s->repo) continue; s->provides = repo_addid_dep(s->repo, s->provides, id, SOLVABLE_FILEMARKER); + if (pool->whatprovides) + add_new_provider(pool, fn, p); + if (pool->whatprovides_rel) + pool->whatprovides_rel[GETRELID(id)] = 0; /* clear cache */ s = pool->solvables + q; if (!s->repo) continue; @@ -2161,4 +2199,11 @@ pool_get_rootdir(Pool *pool) return pool->rootdir; } +/* only used in libzypp */ +void +pool_set_custom_vendorcheck(Pool *pool, int (*vendorcheck)(Pool *, Solvable *, Solvable *)) +{ + pool->custom_vendorcheck = vendorcheck; +} + /* EOF */ @@ -148,8 +148,8 @@ struct _Pool { char *rootdir; + int (*custom_vendorcheck)(struct _Pool *, Solvable *, Solvable *); #endif - }; #define DISTTYPE_RPM 0 @@ -223,6 +223,7 @@ extern void pool_debug(Pool *pool, int type, const char *format, ...) __attribut extern void pool_setdebugcallback(Pool *pool, void (*debugcallback)(struct _Pool *, void *data, int type, const char *str), void *debugcallbackdata); extern void pool_setdebugmask(Pool *pool, int mask); extern void pool_setloadcallback(Pool *pool, int (*cb)(struct _Pool *, struct _Repodata *, void *), void *loadcbdata); +extern void pool_set_custom_vendorcheck(Pool *pool, int (*vendorcheck)(struct _Pool *, Solvable *, Solvable *)); extern char *pool_alloctmpspace(Pool *pool, int len); @@ -265,8 +266,7 @@ Id pool_id2langid(Pool *pool, Id id, const char *lang, int create); int solvable_trivial_installable_map(Solvable *s, Map *installedmap, Map *conflictsmap, Map *noobsoletesmap); int solvable_trivial_installable_repo(Solvable *s, struct _Repo *installed, Map *noobsoletesmap); int solvable_trivial_installable_queue(Solvable *s, Queue *installed, Map *noobsoletesmap); -struct _Solver; /* argh, needed for vendorchange callback FIXME */ -int solvable_is_irrelevant_patch(Solvable *s, Map *installedmap, struct _Solver *solv); +int solvable_is_irrelevant_patch(Solvable *s, Map *installedmap); void pool_create_state_maps(Pool *pool, Queue *installed, Map *installedmap, Map *conflictsmap); @@ -84,6 +84,19 @@ static inline Repo *pool_id2repo(Pool *pool, Id repoid) return repoid < pool->nrepos ? pool->repos[repoid] : 0; } +static inline int pool_disabled_solvable(const Pool *pool, Solvable *s) +{ + if (s->repo && s->repo->disabled) + return 1; + if (pool->considered) + { + Id id = s - pool->solvables; + if (!MAPTST(pool->considered, id)) + return 1; + } + return 0; +} + static inline int pool_installable(const Pool *pool, Solvable *s) { if (!s->arch || s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) diff --git a/src/repo_write.c b/src/repo_write.c index f6e9fd6..fd8ff40 100644 --- a/src/repo_write.c +++ b/src/repo_write.c @@ -976,6 +976,8 @@ static Id verticals[] = { SOLVABLE_PKGID, SOLVABLE_HDRID, SOLVABLE_LEADSIGID, + SOLVABLE_CHANGELOG_AUTHOR, + SOLVABLE_CHANGELOG_TEXT, 0 }; diff --git a/src/repodata.c b/src/repodata.c index 9d3bb6b..2462c10 100644 --- a/src/repodata.c +++ b/src/repodata.c @@ -474,7 +474,7 @@ static unsigned char * get_vertical_data(Repodata *data, Repokey *key, Id off, Id len) { unsigned char *dp; - if (!len) + if (len <= 0) return 0; if (off >= data->lastverticaloffset) { @@ -489,6 +489,7 @@ get_vertical_data(Repodata *data, Repokey *key, Id off, Id len) off += data->verticaloffset[key - data->keys]; /* fprintf(stderr, "key %d page %d\n", key->name, off / REPOPAGE_BLOBSIZE); */ dp = repopagestore_load_page_range(&data->store, off / REPOPAGE_BLOBSIZE, (off + len - 1) / REPOPAGE_BLOBSIZE); + data->storestate++; if (dp) dp += off % REPOPAGE_BLOBSIZE; return dp; @@ -834,19 +835,21 @@ repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int f case REPOKEY_TYPE_DIRSTRARRAY: if (!(flags & SEARCH_FILES)) return 1; /* match just the basename */ + if (kv->num) + return 1; /* already stringified */ /* Put the full filename into kv->str. */ kv->str = repodata_dir2str(data, kv->id, kv->str); - /* And to compensate for that put the "empty" directory into - kv->id, so that later calls to repodata_dir2str on this data - come up with the same filename again. */ - kv->id = 0; + kv->num = 1; /* mark stringification */ return 1; case REPOKEY_TYPE_MD5: case REPOKEY_TYPE_SHA1: case REPOKEY_TYPE_SHA256: if (!(flags & SEARCH_CHECKSUMS)) return 0; /* skip em */ + if (kv->num) + return 1; /* already stringified */ kv->str = repodata_chk2str(data, key->type, (const unsigned char *)kv->str); + kv->num = 1; /* mark stringification */ return 1; default: return 0; @@ -1235,6 +1238,19 @@ void dataiterator_init_clone(Dataiterator *di, Dataiterator *from) { *di = *from; + if (di->dupstr) + { + if (di->dupstr == di->kv.str) + { + di->dupstr = solv_malloc(di->dupstrn); + memcpy(di->dupstr, from->dupstr, di->dupstrn); + } + else + { + di->dupstr = 0; + di->dupstrn = 0; + } + } memset(&di->matcher, 0, sizeof(di->matcher)); if (from->matcher.match) datamatcher_init(&di->matcher, from->matcher.match, from->matcher.flags); @@ -1319,6 +1335,8 @@ dataiterator_free(Dataiterator *di) { if (di->matcher.match) datamatcher_free(&di->matcher); + if (di->dupstr) + solv_free(di->dupstr); } static inline unsigned char * @@ -1366,6 +1384,15 @@ dataiterator_step(Dataiterator *di) { Id schema; + if (di->state == di_nextattr && di->key->storage == KEY_STORAGE_VERTICAL_OFFSET && di->vert_ddp && di->vert_storestate != di->data->storestate) { + unsigned int ddpoff = di->ddp - di->vert_ddp; + di->vert_off += ddpoff; + di->vert_len -= ddpoff; + di->ddp = di->vert_ddp = get_vertical_data(di->data, di->key, di->vert_off, di->vert_len); + di->vert_storestate = di->data->storestate; + if (!di->ddp) + di->state = di_nextkey; + } for (;;) { switch (di->state) @@ -1429,7 +1456,27 @@ dataiterator_step(Dataiterator *di) case di_enterkey: di_enterkey: di->kv.entry = -1; di->key = di->data->keys + *di->keyp; - di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0); + if (!di->dp) + goto di_nextkey; + /* this is get_data() modified to store vert_ data */ + if (di->key->storage == KEY_STORAGE_VERTICAL_OFFSET) + { + Id off, len; + di->dp = data_read_id(di->dp, &off); + di->dp = data_read_id(di->dp, &len); + di->vert_ddp = di->ddp = get_vertical_data(di->data, di->key, off, len); + di->vert_off = off; + di->vert_len = len; + di->vert_storestate = di->data->storestate; + } + else if (di->key->storage == KEY_STORAGE_INCORE) + { + di->ddp = di->dp; + if (di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0)) + di->dp = data_skip_key(di->data, di->dp, di->key); + } + else + di->ddp = 0; if (!di->ddp) goto di_nextkey; if (di->key->type == REPOKEY_TYPE_DELETED) @@ -1683,6 +1730,14 @@ dataiterator_clonepos(Dataiterator *di, Dataiterator *from) di->parents[i].kv.parent = &di->parents[i - 1].kv; di->kv.parent = &di->parents[di->nparents - 1].kv; } + di->dupstr = 0; + di->dupstrn = 0; + if (from->dupstr && from->dupstr == from->kv.str) + { + di->dupstrn = from->dupstrn; + di->dupstr = solv_malloc(from->dupstrn); + memcpy(di->dupstr, from->dupstr, di->dupstrn); + } } void @@ -1829,6 +1884,60 @@ dataiterator_match(Dataiterator *di, Datamatcher *ma) return datamatcher_match(ma, di->kv.str); } +void +dataiterator_strdup(Dataiterator *di) +{ + int l = -1; + + if (!di->kv.str || di->kv.str == di->dupstr) + return; + switch (di->key->type) + { + case REPOKEY_TYPE_MD5: + case REPOKEY_TYPE_SHA1: + case REPOKEY_TYPE_SHA256: + case REPOKEY_TYPE_DIRSTRARRAY: + if (di->kv.num) /* was it stringified into tmp space? */ + l = strlen(di->kv.str) + 1; + break; + default: + break; + } + if (l < 0 && di->key->storage == KEY_STORAGE_VERTICAL_OFFSET) + { + switch (di->key->type) + { + case REPOKEY_TYPE_STR: + case REPOKEY_TYPE_DIRSTRARRAY: + l = strlen(di->kv.str) + 1; + break; + case REPOKEY_TYPE_MD5: + l = SIZEOF_MD5; + break; + case REPOKEY_TYPE_SHA1: + l = SIZEOF_SHA1; + break; + case REPOKEY_TYPE_SHA256: + l = SIZEOF_SHA256; + break; + case REPOKEY_TYPE_BINARY: + l = di->kv.num; + break; + } + } + if (l >= 0) + { + if (!di->dupstrn || di->dupstrn < l) + { + di->dupstrn = l + 16; + di->dupstr = solv_realloc(di->dupstr, di->dupstrn); + } + if (l) + memcpy(di->dupstr, di->kv.str, l); + di->kv.str = di->dupstr; + } +} + /************************************************************************ * data modify functions */ @@ -3071,7 +3180,10 @@ void repodata_disable_paging(Repodata *data) { if (maybe_load_repodata(data, 0)) - repopagestore_disable_paging(&data->store); + { + repopagestore_disable_paging(&data->store); + data->storestate++; + } } static void diff --git a/src/repodata.h b/src/repodata.h index 7ce415b..54fb3df 100644 --- a/src/repodata.h +++ b/src/repodata.h @@ -96,6 +96,7 @@ typedef struct _Repodata { Id lastverticaloffset; /* end of verticals */ Repopagestore store; /* our page store */ + Id storestate; /* incremented every time the store might change */ unsigned char *vincore; /* internal vertical data */ unsigned int vincorelen; /* data size */ diff --git a/src/repopack.h b/src/repopack.h index 81b7b88..d75e61a 100644 --- a/src/repopack.h +++ b/src/repopack.h @@ -164,12 +164,15 @@ data_fetch(unsigned char *dp, KeyValue *kv, Repokey *key) kv->num2 = 0; return data_read_u32(dp, &kv->num); case REPOKEY_TYPE_MD5: + kv->num = 0; /* not stringified yet */ kv->str = (const char *)dp; return dp + SIZEOF_MD5; case REPOKEY_TYPE_SHA1: + kv->num = 0; /* not stringified yet */ kv->str = (const char *)dp; return dp + SIZEOF_SHA1; case REPOKEY_TYPE_SHA256: + kv->num = 0; /* not stringified yet */ kv->str = (const char *)dp; return dp + SIZEOF_SHA256; case REPOKEY_TYPE_BINARY: @@ -180,6 +183,7 @@ data_fetch(unsigned char *dp, KeyValue *kv, Repokey *key) return data_read_ideof(dp, &kv->id, &kv->eof); case REPOKEY_TYPE_DIRSTRARRAY: dp = data_read_ideof(dp, &kv->id, &kv->eof); + kv->num = 0; /* not stringified yet */ kv->str = (const char *)dp; return dp + strlen(kv->str) + 1; case REPOKEY_TYPE_DIRNUMNUMARRAY: diff --git a/src/rules.c b/src/rules.c index f6facf4..1003878 100644 --- a/src/rules.c +++ b/src/rules.c @@ -377,6 +377,12 @@ solver_addrule(Solver *solv, Id p, Id d) return r; } +void +solver_shrinkrules(Solver *solv, int nrules) +{ + solv->nrules = nrules; + solv->rules = solv_extend_resize(solv->rules, solv->nrules, sizeof(Rule), RULES_BLOCK); +} /****************************************************************************** *** @@ -507,13 +513,15 @@ solver_addrpmrulesforsolvable(Solver *solv, Solvable *s, Map *m) dontfix = 1; /* dont care about broken rpm deps */ } - if (!dontfix - && s->arch != ARCH_SRC - && s->arch != ARCH_NOSRC - && !pool_installable(pool, s)) + if (!dontfix) { - POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "package %s [%d] is not installable\n", pool_solvable2str(pool, s), (Id)(s - pool->solvables)); - addrpmrule(solv, -n, 0, SOLVER_RULE_RPM_NOT_INSTALLABLE, 0); + if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC + ? pool_disabled_solvable(pool, s) + : !pool_installable(pool, s)) + { + POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "package %s [%d] is not installable\n", pool_solvable2str(pool, s), (Id)(s - pool->solvables)); + addrpmrule(solv, -n, 0, SOLVER_RULE_RPM_NOT_INSTALLABLE, 0); + } } /* yet another SUSE hack, sigh */ @@ -1822,17 +1830,46 @@ void solver_reenablepolicyrules(Solver *solv, int jobidx) { Queue *job = &solv->job; - int i, j; + int i, j, k, ai; Queue q, allq; Rule *r; Id lastjob = -1; - Id qbuf[32], allqbuf[128]; + Id qbuf[32], allqbuf[32]; queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf)); - queue_init_buffer(&allq, allqbuf, sizeof(allqbuf)/sizeof(*allqbuf)); jobtodisablelist(solv, job->elements[jobidx - 1], job->elements[jobidx], &q); if (!q.count) - return; + { + queue_free(&q); + return; + } + /* now remove everything from q that is disabled by other jobs */ + + /* first remove cleandeps packages, they count as DISABLE_UPDATE */ + if (solv->cleandepsmap.size) + { + solver_createcleandepsmap(solv, &solv->cleandepsmap, 0); + for (j = k = 0; j < q.count; j += 2) + { + if (q.elements[j] == DISABLE_UPDATE) + { + Id p = q.elements[j + 1]; + if (p >= solv->installed->start && p < solv->installed->end && MAPTST(&solv->cleandepsmap, p - solv->installed->start)) + continue; /* remove element from q */ + } + q.elements[k++] = q.elements[j]; + q.elements[k++] = q.elements[j + 1]; + } + q.count = k; + if (!q.count) + { + queue_free(&q); + return; + } + } + + /* now go through the disable list of all other jobs */ + queue_init_buffer(&allq, allqbuf, sizeof(allqbuf)/sizeof(*allqbuf)); for (i = solv->jobrules; i < solv->jobrules_end; i++) { r = solv->rules + i; @@ -1843,22 +1880,35 @@ solver_reenablepolicyrules(Solver *solv, int jobidx) continue; lastjob = j; jobtodisablelist(solv, job->elements[j], job->elements[j + 1], &allq); + if (!allq.count) + continue; + /* remove all elements in allq from q */ + for (j = k = 0; j < q.count; j += 2) + { + Id type = q.elements[j], arg = q.elements[j + 1]; + for (ai = 0; ai < allq.count; ai += 2) + if (allq.elements[ai] == type && allq.elements[ai + 1] == arg) + break; + if (ai < allq.count) + continue; /* found it in allq, remove element from q */ + q.elements[k++] = q.elements[j]; + q.elements[k++] = q.elements[j + 1]; + } + q.count = k; + if (!q.count) + { + queue_free(&q); + queue_free(&allq); + return; + } + queue_empty(&allq); } - if (solv->cleandepsmap.size) - { - solver_createcleandepsmap(solv, &solv->cleandepsmap, 0); - for (i = solv->installed->start; i < solv->installed->end; i++) - if (MAPTST(&solv->cleandepsmap, i - solv->installed->start)) - queue_push2(&allq, DISABLE_UPDATE, i); - } + queue_free(&allq); + + /* now re-enable anything that's left in q */ for (j = 0; j < q.count; j += 2) { Id type = q.elements[j], arg = q.elements[j + 1]; - for (i = 0; i < allq.count; i += 2) - if (allq.elements[i] == type && allq.elements[i + 1] == arg) - break; - if (i < allq.count) - continue; /* still disabled */ switch(type) { case DISABLE_UPDATE: @@ -1872,7 +1922,6 @@ solver_reenablepolicyrules(Solver *solv, int jobidx) break; } } - queue_free(&allq); queue_free(&q); } diff --git a/src/rules.h b/src/rules.h index 144b683..4d6b8ad 100644 --- a/src/rules.h +++ b/src/rules.h @@ -99,6 +99,7 @@ solver_enablerule(struct _Solver *solv, Rule *r) extern Rule *solver_addrule(struct _Solver *solv, Id p, Id d); extern void solver_unifyrules(struct _Solver *solv); extern int solver_rulecmp(struct _Solver *solv, Rule *r1, Rule *r2); +extern void solver_shrinkrules(struct _Solver *solv, int nrules); /* rpm rules */ extern void solver_addrpmrulesforsolvable(struct _Solver *solv, Solvable *s, Map *m); diff --git a/src/selection.c b/src/selection.c index 2ef5e1e..c586a2c 100644 --- a/src/selection.c +++ b/src/selection.c @@ -121,7 +121,7 @@ selection_flatten(Pool *pool, Queue *selection) { Queue q; int i; - if (selection->count <= 1) + if (selection->count <= 2) return; for (i = 0; i < selection->count; i += 2) if ((selection->elements[i] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL) @@ -155,6 +155,7 @@ static void selection_filter_rel(Pool *pool, Queue *selection, Id relflags, Id relevr) { int i; + for (i = 0; i < selection->count; i += 2) { Id select = selection->elements[i] & SOLVER_SELECTMASK; @@ -196,7 +197,7 @@ selection_filter_rel(Pool *pool, Queue *selection, Id relflags, Id relevr) } queue_free(&q); } - else if (select == SOLVER_SOLVABLE_NAME && select == SOLVER_SOLVABLE_PROVIDES) + else if (select == SOLVER_SOLVABLE_NAME || select == SOLVER_SOLVABLE_PROVIDES) { /* don't stack src reldeps */ if (relflags == REL_ARCH && (relevr == ARCH_SRC || relevr == ARCH_NOSRC) && ISRELDEP(id)) @@ -245,7 +246,11 @@ selection_addsrc(Pool *pool, Queue *selection, int flags) if (s->name != name) continue; if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) - havesrc = 1; + { + if (pool_disabled_solvable(pool, s)) + continue; + havesrc = 1; + } else if (s->repo != pool->installed && !pool_installable(pool, s)) continue; queue_push(&q, p); @@ -316,6 +321,8 @@ selection_depglob(Pool *pool, Queue *selection, const char *name, int flags) { if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed) continue; /* just in case... src rpms can't be installed */ + if (pool_disabled_solvable(pool, s)) + continue; if ((flags & SELECTION_SOURCE_ONLY) != 0) id = pool_rel2id(pool, id, ARCH_SRC, REL_ARCH, 1); queue_push2(selection, SOLVER_SOLVABLE_NAME, id); @@ -377,8 +384,12 @@ selection_depglob(Pool *pool, Queue *selection, const char *name, int flags) { Solvable *s = pool->solvables + p; if (s->repo != pool->installed && !pool_installable(pool, s)) - if (!(flags & SELECTION_SOURCE_ONLY) || (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)) - continue; + { + if (!(flags & SELECTION_SOURCE_ONLY) || (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)) + continue; + if (pool_disabled_solvable(pool, s)) + continue; + } if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed) continue; id = s->name; @@ -476,8 +487,12 @@ selection_filelist(Pool *pool, Queue *selection, const char *name, int flags) if (!s->repo) continue; if (s->repo != pool->installed && !pool_installable(pool, s)) - if (!(flags & SELECTION_SOURCE_ONLY) || (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)) - continue; + { + if (!(flags & SELECTION_SOURCE_ONLY) || (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)) + continue; + if (pool_disabled_solvable(pool, s)) + continue; + } if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed) continue; queue_push(&q, di.solvid); @@ -722,7 +737,8 @@ selection_make(Pool *pool, Queue *selection, const char *name, int flags) ret = selection_depglob_arch(pool, selection, name, flags); if (!ret && (flags & SELECTION_CANON) != 0) ret = selection_canon(pool, selection, name, flags); - + if (ret && !selection->count) + ret = 0; /* no match -> always return zero */ if (ret && (flags & SELECTION_FLAT) != 0) selection_flatten(pool, selection); return ret; diff --git a/src/solvable.c b/src/solvable.c index 4594544..7ac79ee 100644 --- a/src/solvable.c +++ b/src/solvable.c @@ -462,7 +462,7 @@ solvable_trivial_installable_map(Solvable *s, Map *installedmap, Map *conflictsm { if (providedbyinstalled(pool, installedmap, con, ispatch, noobsoletesmap)) { - if (ispatch && solvable_is_irrelevant_patch(s, installedmap, 0)) + if (ispatch && solvable_is_irrelevant_patch(s, installedmap)) return -1; return 0; } @@ -473,7 +473,7 @@ solvable_trivial_installable_map(Solvable *s, Map *installedmap, Map *conflictsm interesting = 1; } } - if (ispatch && interesting && solvable_is_irrelevant_patch(s, installedmap, 0)) + if (ispatch && interesting && solvable_is_irrelevant_patch(s, installedmap)) interesting = 0; } #if 0 @@ -575,11 +575,33 @@ solvable_trivial_installable_repo(Solvable *s, Repo *installed, Map *noobsoletes return r; } +/* FIXME: this mirrors policy_illegal_vendorchange */ +static int +pool_illegal_vendorchange(Pool *pool, Solvable *s1, Solvable *s2) +{ + Id v1, v2; + Id vendormask1, vendormask2; + + if (pool->custom_vendorcheck) + return pool->custom_vendorcheck(pool, s1, s2); + /* treat a missing vendor as empty string */ + v1 = s1->vendor ? s1->vendor : ID_EMPTY; + v2 = s2->vendor ? s2->vendor : ID_EMPTY; + if (v1 == v2) + return 0; + vendormask1 = pool_vendor2mask(pool, v1); + if (!vendormask1) + return 1; /* can't match */ + vendormask2 = pool_vendor2mask(pool, v2); + if ((vendormask1 & vendormask2) != 0) + return 0; + return 1; /* no class matches */ +} /* check if this patch is relevant according to the vendor. To bad that patches * don't have a vendor, so we need to do some careful repo testing. */ int -solvable_is_irrelevant_patch(Solvable *s, Map *installedmap, Solver *solv) +solvable_is_irrelevant_patch(Solvable *s, Map *installedmap) { Pool *pool = s->repo->pool; Id con, *conp; @@ -618,23 +640,8 @@ solvable_is_irrelevant_patch(Solvable *s, Map *installedmap, Solver *solv) /* ok, we have a package from the patch repo that solves the conflict. check vendor */ if (si->vendor == s2->vendor) return 0; - /* FIXME: solv is only needed for the vendorchange callback */ - if (solv) - { - if (!policy_illegal_vendorchange(solv, si, s2)) - return 0; - } - else - { - Id v1 = si->vendor ? si->vendor : ID_EMPTY; - Id v2 = s2->vendor ? s2->vendor : ID_EMPTY; - if (v1 == v2) - return 0; - v1 = pool_vendor2mask(pool, v1); - v2 = pool_vendor2mask(pool, v2); - if ((v1 & v2) != 0) - return 0; - } + if (!pool_illegal_vendorchange(pool, si, s2)) + return 0; /* vendor change was illegal, ignore conflict */ } } diff --git a/src/solver.c b/src/solver.c index 43668d5..c1518db 100644 --- a/src/solver.c +++ b/src/solver.c @@ -965,11 +965,11 @@ solver_reset(Solver *solv) v = solv->decisionq.elements[i]; solv->decisionmap[v > 0 ? v : -v] = 0; } - solv->decisionq_why.count = 0; - solv->decisionq.count = 0; + queue_empty(&solv->decisionq_why); + queue_empty(&solv->decisionq); solv->recommends_index = -1; solv->propagate_index = 0; - solv->branches.count = 0; + queue_empty(&solv->branches); /* adapt learnt rule status to new set of enabled/disabled rules */ enabledisablelearntrules(solv); @@ -1436,6 +1436,7 @@ solver_create(Pool *pool) queue_init(&solv->branches); queue_init(&solv->weakruleq); queue_init(&solv->ruleassertions); + queue_init(&solv->addedmap_deduceq); queue_push(&solv->learnt_pool, 0); /* so that 0 does not describe a proof */ @@ -1473,6 +1474,7 @@ solver_free(Solver *solv) queue_free(&solv->branches); queue_free(&solv->weakruleq); queue_free(&solv->ruleassertions); + queue_free(&solv->addedmap_deduceq); if (solv->cleandeps_updatepkgs) { queue_free(solv->cleandeps_updatepkgs); @@ -2831,6 +2833,74 @@ transform_update_targets(Solver *solv) } +static void +addedmap2deduceq(Solver *solv, Map *addedmap) +{ + Pool *pool = solv->pool; + int i, j; + Id p; + Rule *r; + + queue_empty(&solv->addedmap_deduceq); + for (i = 2, j = solv->rpmrules_end - 1; i < pool->nsolvables && j > 0; j--) + { + r = solv->rules + j; + if (r->p >= 0) + continue; + if ((r->d == 0 || r->d == -1) && r->w2 < 0) + continue; + p = -r->p; + if (!MAPTST(addedmap, p)) + { + /* should never happen, but... */ + if (!solv->addedmap_deduceq.count || solv->addedmap_deduceq.elements[solv->addedmap_deduceq.count - 1] != -p) + queue_push(&solv->addedmap_deduceq, -p); + continue; + } + for (; i < p; i++) + if (MAPTST(addedmap, i)) + queue_push(&solv->addedmap_deduceq, i); + if (i == p) + i++; + } + for (; i < pool->nsolvables; i++) + if (MAPTST(addedmap, i)) + queue_push(&solv->addedmap_deduceq, i); + j = 0; + for (i = 2; i < pool->nsolvables; i++) + if (MAPTST(addedmap, i)) + j++; +} + +static void +deduceq2addedmap(Solver *solv, Map *addedmap) +{ + int j; + Id p; + Rule *r; + for (j = solv->rpmrules_end - 1; j > 0; j--) + { + r = solv->rules + j; + if (r->d < 0 && r->p) + solver_enablerule(solv, r); + if (r->p >= 0) + continue; + if ((r->d == 0 || r->d == -1) && r->w2 < 0) + continue; + p = -r->p; + MAPSET(addedmap, p); + } + for (j = 0; j < solv->addedmap_deduceq.count; j++) + { + p = solv->addedmap_deduceq.elements[j]; + if (p > 0) + MAPSET(addedmap, p); + else + MAPCLR(addedmap, p); + } +} + + /* * * solve job queue @@ -2843,7 +2913,7 @@ solver_solve(Solver *solv, Queue *job) Pool *pool = solv->pool; Repo *installed = solv->installed; int i; - int oldnrules; + int oldnrules, initialnrules; Map addedmap; /* '1' == have rpm-rules for solvable */ Map installcandidatemap; Id how, what, select, name, weak, p, pp, d; @@ -2893,6 +2963,81 @@ solver_solve(Solver *solv, Queue *job) queue_free(solv->cleandeps_updatepkgs); solv->cleandeps_updatepkgs = solv_free(solv->cleandeps_updatepkgs); } + queue_empty(&solv->ruleassertions); + solv->bestrules_pkg = solv_free(solv->bestrules_pkg); + solv->choicerules_ref = solv_free(solv->choicerules_ref); + if (solv->noupdate.size) + map_empty(&solv->noupdate); + if (solv->noobsoletes.size) + { + map_free(&solv->noobsoletes); + map_init(&solv->noobsoletes, 0); + } + solv->updatemap_all = 0; + if (solv->updatemap.size) + { + map_free(&solv->updatemap); + map_init(&solv->updatemap, 0); + } + solv->bestupdatemap_all = 0; + if (solv->bestupdatemap.size) + { + map_free(&solv->bestupdatemap); + map_init(&solv->bestupdatemap, 0); + } + solv->fixmap_all = 0; + if (solv->fixmap.size) + { + map_free(&solv->fixmap); + map_init(&solv->fixmap, 0); + } + solv->dupmap_all = 0; + if (solv->dupmap.size) + { + map_free(&solv->dupmap); + map_init(&solv->dupmap, 0); + } + if (solv->dupinvolvedmap.size) + { + map_free(&solv->dupinvolvedmap); + map_init(&solv->dupinvolvedmap, 0); + } + solv->droporphanedmap_all = 0; + if (solv->droporphanedmap.size) + { + map_free(&solv->droporphanedmap); + map_init(&solv->droporphanedmap, 0); + } + if (solv->cleandepsmap.size) + { + map_free(&solv->cleandepsmap); + map_init(&solv->cleandepsmap, 0); + } + + queue_empty(&solv->weakruleq); + solv->watches = solv_free(solv->watches); + queue_empty(&solv->ruletojob); + if (solv->decisionq.count) + memset(solv->decisionmap, 0, pool->nsolvables * sizeof(Id)); + queue_empty(&solv->decisionq); + queue_empty(&solv->decisionq_why); + solv->decisioncnt_update = solv->decisioncnt_keep = solv->decisioncnt_resolve = solv->decisioncnt_weak = solv->decisioncnt_orphan = 0; + queue_empty(&solv->learnt_why); + queue_empty(&solv->learnt_pool); + queue_empty(&solv->branches); + solv->propagate_index = 0; + queue_empty(&solv->problems); + queue_empty(&solv->solutions); + queue_empty(&solv->orphaned); + solv->stats_learned = solv->stats_unsolvable = 0; + if (solv->recommends_index) + { + map_empty(&solv->recommendsmap); + map_empty(&solv->suggestsmap); + solv->recommends_index = 0; + } + solv->multiversionupdaters = solv_free(solv->multiversionupdaters); + /* * create basic rule set of all involved packages @@ -2914,6 +3059,14 @@ solver_solve(Solver *solv, Queue *job) * so called: rpm rules * */ + initialnrules = solv->rpmrules_end ? solv->rpmrules_end : 1; + if (initialnrules > 1) + deduceq2addedmap(solv, &addedmap); + if (solv->nrules != initialnrules) + solver_shrinkrules(solv, initialnrules); + solv->nrules = initialnrules; + solv->rpmrules_end = 0; + if (installed) { /* check for update/verify jobs as they need to be known early */ @@ -3087,8 +3240,12 @@ solver_solve(Solver *solv, Queue *job) POOL_DEBUG(SOLV_DEBUG_STATS, "%d of %d installable solvables considered for solving\n", possible, installable); } - solver_unifyrules(solv); /* remove duplicate rpm rules */ - solv->rpmrules_end = solv->nrules; /* mark end of rpm rules */ + if (solv->nrules > initialnrules) + solver_unifyrules(solv); /* remove duplicate rpm rules */ + solv->rpmrules_end = solv->nrules; /* mark end of rpm rules */ + + if (solv->nrules > initialnrules) + addedmap2deduceq(solv, &addedmap); /* so that we can recreate the addedmap */ POOL_DEBUG(SOLV_DEBUG_STATS, "rpm rule memory used: %d K\n", solv->nrules * (int)sizeof(Rule) / 1024); POOL_DEBUG(SOLV_DEBUG_STATS, "rpm rule creation took %d ms\n", solv_timems(now)); @@ -3754,7 +3911,7 @@ solver_trivial_installable(Solver *solv, Queue *pkgs, Queue *res) if (res->elements[i] != -1) { Solvable *s = pool->solvables + pkgs->elements[i]; - if (!strncmp("patch:", pool_id2str(pool, s->name), 6) && solvable_is_irrelevant_patch(s, &installedmap, solv)) + if (!strncmp("patch:", pool_id2str(pool, s->name), 6) && solvable_is_irrelevant_patch(s, &installedmap)) res->elements[i] = -1; } map_free(&installedmap); diff --git a/src/solver.h b/src/solver.h index a134718..b735329 100644 --- a/src/solver.h +++ b/src/solver.h @@ -26,15 +26,6 @@ extern "C" { #include "rules.h" #include "problems.h" -/* - * Callback definitions in order to "overwrite" the policies by an external application. - */ - -typedef void (*BestSolvableCb) (Pool *pool, Queue *canditates); -typedef int (*ArchCheckCb) (Pool *pool, Solvable *solvable1, Solvable *solvable2); -typedef int (*VendorCheckCb) (Pool *pool, Solvable *solvable1, Solvable *solvable2); -typedef void (*UpdateCandidateCb) (Pool *pool, Solvable *solvable, Queue *canditates); - struct _Solver { Pool *pool; /* back pointer to pool */ @@ -43,46 +34,7 @@ struct _Solver { int (*solution_callback)(struct _Solver *solv, void *data); void *solution_callback_data; - /* Callbacks for defining the bahaviour of the solver */ - - /* Finding best candidate - * - * Callback definition: - * void bestSolvable (Pool *pool, Queue *canditates) - * candidates : List of canditates which has to be sorted by the function call - * return candidates: Sorted list of the candidates(first is the best). - */ - BestSolvableCb bestSolvableCb; - - /* Checking if two solvables has compatible architectures - * - * Callback definition: - * int archCheck (Pool *pool, Solvable *solvable1, Solvable *solvable2); - * - * return 0 it the two solvables has compatible architectures - */ - ArchCheckCb archCheckCb; - - /* Checking if two solvables has compatible vendors - * - * Callback definition: - * int vendorCheck (Pool *pool, Solvable *solvable1, Solvable *solvable2); - * - * return 0 it the two solvables has compatible architectures - */ - VendorCheckCb vendorCheckCb; - - /* Evaluate update candidate - * - * Callback definition: - * void UpdateCandidateCb (Pool *pool, Solvable *solvable, Queue *canditates) - * solvable : for which updates should be search - * candidates : List of candidates (This list depends on other - * restrictions like architecture and vendor policies too) - */ - UpdateCandidateCb updateCandidateCb; - - int pooljobcnt; /* number of pooljob entries in job queue */ + int pooljobcnt; /* number of pooljob entries in job queue */ #ifdef LIBSOLV_INTERNAL Repo *installed; /* copy of pool->installed */ @@ -229,6 +181,8 @@ struct _Solver { Queue *update_targets; /* update to specific packages */ Queue *installsuppdepq; /* deps from the install namespace provides hack */ + + Queue addedmap_deduceq; /* deduce addedmap from rpm rules */ #endif /* LIBSOLV_INTERNAL */ }; |