summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--VERSION.cmake2
-rw-r--r--bindings/solv.i10
-rw-r--r--examples/solv.c1
-rw-r--r--ext/repo_arch.c6
-rw-r--r--ext/testcase.c40
-rw-r--r--package/libsolv.changes11
-rw-r--r--src/policy.c2
-rw-r--r--src/policy.h3
-rw-r--r--src/pool.c58
-rw-r--r--src/pool.h3
-rw-r--r--src/poolid.c2
-rw-r--r--src/poolvendor.c4
-rw-r--r--src/problems.c10
-rw-r--r--src/qsort_r.c2
-rw-r--r--src/repo.c4
-rw-r--r--src/repo.h2
-rw-r--r--src/repo_solv.c38
-rw-r--r--src/repo_write.c4
-rw-r--r--src/repodata.c8
-rw-r--r--src/rules.c250
-rw-r--r--src/rules.h6
-rw-r--r--src/selection.c10
-rw-r--r--src/solver.c12
-rw-r--r--src/solver.h6
-rw-r--r--src/solverdebug.c2
-rw-r--r--src/strpool.c2
-rw-r--r--src/transaction.c2
-rw-r--r--test/testcases/yumobs/split.t24
-rw-r--r--tools/testsolv.c5
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
}
diff --git a/src/pool.c b/src/pool.c
index 946f6da..8dff38a 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -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;
diff --git a/src/pool.h b/src/pool.h
index d29f615..9761ce1 100644
--- a/src/pool.h
+++ b/src/pool.h
@@ -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".
diff --git a/src/repo.c b/src/repo.c
index 511fd92..15e7e80 100644
--- a/src/repo.c
+++ b/src/repo.c
@@ -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));
diff --git a/src/repo.h b/src/repo.h
index 106f2a5..952dbeb 100644
--- a/src/repo.h
+++ b/src/repo.h
@@ -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