Id job;
const char *str;
} job2str[] = {
- { SOLVER_NOOP, "noop" },
- { SOLVER_INSTALL, "install" },
- { SOLVER_ERASE, "erase" },
- { SOLVER_UPDATE, "update" },
- { SOLVER_WEAKENDEPS, "weakendeps" },
- { SOLVER_MULTIVERSION, "multiversion" },
- { SOLVER_MULTIVERSION, "noobsoletes" }, /* old name */
- { SOLVER_LOCK, "lock" },
- { SOLVER_DISTUPGRADE, "distupgrade" },
- { SOLVER_VERIFY, "verify" },
- { SOLVER_DROP_ORPHANED, "droporphaned" },
- { SOLVER_USERINSTALLED, "userinstalled" },
+ { SOLVER_NOOP, "noop" },
+ { SOLVER_INSTALL, "install" },
+ { SOLVER_ERASE, "erase" },
+ { SOLVER_UPDATE, "update" },
+ { SOLVER_WEAKENDEPS, "weakendeps" },
+ { SOLVER_MULTIVERSION, "multiversion" },
+ { SOLVER_MULTIVERSION, "noobsoletes" }, /* old name */
+ { SOLVER_LOCK, "lock" },
+ { SOLVER_DISTUPGRADE, "distupgrade" },
+ { SOLVER_VERIFY, "verify" },
+ { SOLVER_DROP_ORPHANED, "droporphaned" },
+ { SOLVER_USERINSTALLED, "userinstalled" },
+ { SOLVER_ALLOWUNINSTALL, "allowuninstall" },
+ { SOLVER_FAVOR, "favor" },
+ { SOLVER_DISFAVOR, "disfavor" },
{ 0, 0 }
};
{ TESTCASE_RESULT_RECOMMENDED, "recommended" },
{ TESTCASE_RESULT_UNNEEDED, "unneeded" },
{ TESTCASE_RESULT_ALTERNATIVES, "alternatives" },
+ { TESTCASE_RESULT_RULES, "rules" },
+ { TESTCASE_RESULT_GENID, "genid" },
+ { TESTCASE_RESULT_REASON, "reason" },
{ 0, 0 }
};
{ SOLVER_FLAG_BREAK_ORPHANS, "breakorphans", 0 },
{ SOLVER_FLAG_FOCUS_INSTALLED, "focusinstalled", 0 },
{ SOLVER_FLAG_YUM_OBSOLETES, "yumobsoletes", 0 },
+ { SOLVER_FLAG_NEED_UPDATEPROVIDE, "needupdateprovide", 0 },
+ { SOLVER_FLAG_URPM_REORDER, "urpmreorder", 0 },
{ 0, 0, 0 }
};
{ POOL_FLAG_HAVEDISTEPOCH, "havedistepoch", 0 },
{ POOL_FLAG_NOOBSOLETESMULTIVERSION, "noobsoletesmultiversion", 0 },
{ POOL_FLAG_ADDFILEPROVIDESFILTERED, "addfileprovidesfiltered", 0 },
+ { POOL_FLAG_NOWHATPROVIDESAUX, "nowhatprovidesaux", 0 },
{ 0, 0, 0 }
};
{ 0, 0 }
};
+static const char *features[] = {
+#ifdef ENABLE_LINKED_PKGS
+ "linked_packages",
+#endif
+#ifdef ENABLE_COMPLEX_DEPS
+ "complex_deps",
+#endif
+ 0
+};
typedef struct strqueue {
char **str;
/* we need escaping! */
s2 = s2p = pool_alloctmpspace(pool, strlen(s) + bad * 2 + 1);
- ss = s;
if (!strncmp(s, "namespace:", 10))
{
strcpy(s2p, "namespace\\3a");
s2p += 12;
s += 10;
}
+ ss = s;
for (; *ss; ss++)
{
*s2p++ = *ss;
{ REL_COND, "<IF>" },
{ REL_COMPAT, "compat >=" },
{ REL_KIND, "<KIND>" },
+ { REL_ELSE, "<ELSE>" },
{ REL_LT, "<" },
{ 0, 0 }
};
const char *release;
const char *tmp;
unsigned int ti;
+ Queue q;
fprintf(fp, "=Ver: 3.0\n");
+ queue_init(&q);
FOR_REPO_SOLVABLES(repo, p, s)
{
name = pool_id2str(pool, s->name);
writedeps(repo, fp, "Sup:", SOLVABLE_SUPPLEMENTS, s, s->supplements);
writedeps(repo, fp, "Sug:", SOLVABLE_SUGGESTS, s, s->suggests);
writedeps(repo, fp, "Enh:", SOLVABLE_ENHANCES, s, s->enhances);
+ if (solvable_lookup_idarray(s, SOLVABLE_PREREQ_IGNOREINST, &q))
+ {
+ int i;
+ fprintf(fp, "+Ipr:\n");
+ for (i = 0; i < q.count; i++)
+ fprintf(fp, "%s\n", testcase_dep2str(pool, q.elements[i]));
+ fprintf(fp, "-Ipr:\n");
+ }
if (s->vendor)
fprintf(fp, "=Vnd: %s\n", pool_id2str(pool, s->vendor));
ti = solvable_lookup_num(s, SOLVABLE_BUILDTIME, 0);
fprintf(fp, "=Tim: %u\n", ti);
writefilelist(repo, fp, "Fls:", s);
}
+ queue_free(&q);
return 0;
}
repodata_add_dirstr(data, s - pool->solvables, SOLVABLE_FILELIST, did, p);
}
}
- s->supplements = repo_fix_supplements(s->repo, s->provides, s->supplements, 0);
- s->conflicts = repo_fix_conflicts(s->repo, s->conflicts);
+ repo_rewrite_suse_deps(s, 0);
}
/* stripped down version of susetags parser used for testcases */
case 'E' << 16 | 'n' << 8 | 'h':
s->enhances = adddep(repo, s->enhances, line + 6, 0);
break;
+ case 'I' << 16 | 'p' << 8 | 'r':
+ {
+ Id id = line[6] == '/' ? pool_str2id(pool, line + 6, 1) : testcase_str2dep(pool, line + 6);
+ repodata_add_idarray(data, s - pool->solvables, SOLVABLE_PREREQ_IGNOREINST, id);
+ break;
+ }
default:
break;
}
pool_debug(solv->pool, SOLV_ERROR, "setsolverflags: unknown flag '%.*s'\n", (int)(p - s), s);
return 0;
}
- solver_set_flag(solv, solverflags2str[i].flag, v);
+ if (solver_set_flag(solv, solverflags2str[i].flag, v) == -1)
+ {
+ pool_debug(solv->pool, SOLV_ERROR, "setsolverflags: unsupported flag '%s'\n", solverflags2str[i].str);
+ return 0;
+ }
}
return 1;
}
{ 0, 0 }
};
+static struct reason2str {
+ Id reason;
+ const char *str;
+} reason2str[] = {
+ { SOLVER_REASON_UNRELATED, "unrelated" },
+ { SOLVER_REASON_UNIT_RULE, "unit" },
+ { SOLVER_REASON_KEEP_INSTALLED, "keep" },
+ { SOLVER_REASON_RESOLVE_JOB, "job" },
+ { SOLVER_REASON_UPDATE_INSTALLED, "update" },
+ { SOLVER_REASON_CLEANDEPS_ERASE, "cleandeps" },
+ { SOLVER_REASON_RESOLVE, "resolve" },
+ { SOLVER_REASON_WEAKDEP, "weakdep" },
+ { SOLVER_REASON_RESOLVE_ORPHAN, "orphan" },
+
+ { SOLVER_REASON_RECOMMENDED, "recommended" },
+ { SOLVER_REASON_SUPPLEMENTED, "supplemented" },
+ { 0, 0 }
+};
+
+static const char *
+testcase_reason2str(Id reason)
+{
+ int i;
+ for (i = 0; reason2str[i].str; i++)
+ if (reason == reason2str[i].reason)
+ return reason2str[i].str;
+ return "?";
+}
+
+static struct rclass2str {
+ Id rclass;
+ const char *str;
+} rclass2str[] = {
+ { SOLVER_RULE_PKG, "pkg" },
+ { SOLVER_RULE_UPDATE, "update" },
+ { SOLVER_RULE_FEATURE, "feature" },
+ { SOLVER_RULE_JOB, "job" },
+ { SOLVER_RULE_DISTUPGRADE, "distupgrade" },
+ { SOLVER_RULE_INFARCH, "infarch" },
+ { SOLVER_RULE_CHOICE, "choice" },
+ { SOLVER_RULE_LEARNT, "learnt" },
+ { SOLVER_RULE_BEST, "best" },
+ { SOLVER_RULE_YUMOBS, "yumobs" },
+ { 0, 0 }
+};
+
+static const char *
+testcase_rclass2str(Id rclass)
+{
+ int i;
+ for (i = 0; rclass2str[i].str; i++)
+ if (rclass == rclass2str[i].rclass)
+ return rclass2str[i].str;
+ return "unknown";
+}
+
+static int
+dump_genid(Pool *pool, Strqueue *sq, Id id, int cnt)
+{
+ struct oplist *op;
+ char cntbuf[20];
+ const char *s;
+
+ if (ISRELDEP(id))
+ {
+ Reldep *rd = GETRELDEP(pool, id);
+ for (op = oplist; op->flags; op++)
+ if (rd->flags == op->flags)
+ break;
+ cnt = dump_genid(pool, sq, rd->name, cnt);
+ cnt = dump_genid(pool, sq, rd->evr, cnt);
+ sprintf(cntbuf, "genid %2d: genid ", cnt++);
+ s = pool_tmpjoin(pool, cntbuf, "op ", op->flags ? op->opname : "unknown");
+ }
+ else
+ {
+ sprintf(cntbuf, "genid %2d: genid ", cnt++);
+ s = pool_tmpjoin(pool, cntbuf, id ? "lit " : "null", id ? pool_id2str(pool, id) : 0);
+ }
+ strqueue_push(sq, s);
+ return cnt;
+}
+
char *
testcase_solverresult(Solver *solv, int resultflags)
{
queue_free(&q);
queue_free(&rq);
}
+ if ((resultflags & TESTCASE_RESULT_RULES) != 0)
+ {
+ /* dump all rules */
+ Id rid;
+ SolverRuleinfo rclass;
+ Queue q;
+ int i;
+ queue_init(&q);
+ for (rid = 1; (rclass = solver_ruleclass(solv, rid)) != SOLVER_RULE_UNKNOWN; rid++)
+ {
+ char *prefix = solv_dupjoin("rule ", testcase_rclass2str(rclass), " ");
+ prefix = solv_dupappend(prefix, testcase_ruleid(solv, rid), 0);
+ solver_ruleliterals(solv, rid, &q);
+ if (rclass == SOLVER_RULE_FEATURE && q.count == 1 && q.elements[0] == -SYSTEMSOLVABLE)
+ continue;
+ for (i = 0; i < q.count; i++)
+ {
+ Id p = q.elements[i];
+ const char *s;
+ if (p < 0)
+ s = pool_tmpjoin(pool, prefix, " -", testcase_solvid2str(pool, -p));
+ else
+ s = pool_tmpjoin(pool, prefix, " ", testcase_solvid2str(pool, p));
+ strqueue_push(&sq, s);
+ }
+ solv_free(prefix);
+ }
+ queue_free(&q);
+ }
+ if ((resultflags & TESTCASE_RESULT_GENID) != 0)
+ {
+ for (i = 0 ; i < solv->job.count; i += 2)
+ {
+ Id id, id2;
+ if (solv->job.elements[i] != (SOLVER_NOOP | SOLVER_SOLVABLE_PROVIDES))
+ continue;
+ id = solv->job.elements[i + 1];
+ s = testcase_dep2str(pool, id);
+ strqueue_push(&sq, pool_tmpjoin(pool, "genid dep ", s, 0));
+ if ((id2 = testcase_str2dep(pool, s)) != id)
+ {
+ s = pool_tmpjoin(pool, "genid roundtrip error: ", testcase_dep2str(pool, id2), 0);
+ strqueue_push(&sq, s);
+ }
+ dump_genid(pool, &sq, id, 1);
+ }
+ }
+ if ((resultflags & TESTCASE_RESULT_REASON) != 0)
+ {
+ Queue whyq;
+ queue_init(&whyq);
+ FOR_POOL_SOLVABLES(p)
+ {
+ Id info, p2, id;
+ int reason = solver_describe_decision(solv, p, &info);
+ if (reason == SOLVER_REASON_UNRELATED)
+ continue;
+ if (reason == SOLVER_REASON_WEAKDEP)
+ {
+ solver_describe_weakdep_decision(solv, p, &whyq);
+ if (whyq.count)
+ {
+ for (i = 0; i < whyq.count; i += 3)
+ {
+ reason = whyq.elements[i];
+ p2 = whyq.elements[i + 1];
+ id = whyq.elements[i + 2];
+ s = pool_tmpjoin(pool, "reason ", testcase_solvid2str(pool, p), 0);
+ s = pool_tmpappend(pool, s, " ", testcase_reason2str(reason));
+ s = pool_tmpappend(pool, s, " ", testcase_dep2str(pool, id));
+ if (p2)
+ s = pool_tmpappend(pool, s, " ", testcase_solvid2str(pool, p2));
+ strqueue_push(&sq, s);
+ }
+ continue;
+ }
+ }
+ s = pool_tmpjoin(pool, "reason ", testcase_solvid2str(pool, p), 0);
+ s = pool_tmpappend(pool, s, " ", testcase_reason2str(reason));
+ if (info)
+ s = pool_tmpappend(pool, s, " ", testcase_ruleid(solv, info));
+ strqueue_push(&sq, s);
+ }
+ queue_free(&whyq);
+ }
strqueue_sort(&sq);
result = strqueue_join(&sq);
strqueue_free(&sq);
}
-int
-testcase_write(Solver *solv, char *dir, int resultflags, const char *testcasename, const char *resultname)
+static int
+testcase_write_mangled(Solver *solv, const char *dir, int resultflags, const char *testcasename, const char *resultname)
{
Pool *pool = solv->pool;
Repo *repo;
else
sprintf(priobuf, "%d", repo->priority);
out = pool_tmpjoin(pool, name, ".repo", ".gz");
+ for (i = 0; out[i]; i++)
+ if (out[i] == '/')
+ out[i] = '_';
cmd = pool_tmpjoin(pool, "repo ", name, " ");
cmd = pool_tmpappend(pool, cmd, priobuf, " ");
cmd = pool_tmpappend(pool, cmd, "testtags ", out);
return 1;
}
+int
+testcase_write(Solver *solv, const char *dir, int resultflags, const char *testcasename, const char *resultname)
+{
+ Pool *pool = solv->pool;
+ int i, r, repoid;
+ int mangle = 1;
+ const char **orignames;
+
+ /* mangle repo names so that there are no conflicts */
+ orignames = solv_calloc(pool->nrepos, sizeof(char *));
+ for (repoid = 1; repoid < pool->nrepos; repoid++)
+ {
+ Repo *repo = pool_id2repo(pool, repoid);
+ char *buf = solv_malloc((repo->name ? strlen(repo->name) : 0) + 40);
+ char *mp;
+ orignames[i] = repo->name;
+ if (!repo->name || !repo->name[0])
+ sprintf(buf, "#%d", repoid);
+ else
+ strcpy(buf, repo->name);
+ for (i = 0; buf[i]; i++)
+ if (buf[i] == ' ' || buf[i] == '\t' || buf[i] == '/')
+ buf[i] = '_';
+ mp = buf + strlen(buf);
+ for (;;)
+ {
+ for (i = 1; i < repoid; i++)
+ if (!strcmp(buf, pool_id2repo(pool, i)->name))
+ break;
+ if (i == repoid)
+ break;
+ sprintf(mp, "_%d", mangle++);
+ }
+ repo->name = buf;
+ }
+ r = testcase_write_mangled(solv, dir, resultflags, testcasename, resultname);
+ for (repoid = 1; repoid < pool->nrepos; repoid++)
+ {
+ Repo *repo = pool_id2repo(pool, repoid);
+ solv_free((void *)repo->name);
+ repo->name = orignames[i];
+ }
+ solv_free(orignames);
+ return r;
+}
+
static char *
read_inline_file(FILE *fp, char **bufp, char **bufpp, int *buflp)
{
}
Solver *
-testcase_read(Pool *pool, FILE *fp, char *testcase, Queue *job, char **resultp, int *resultflagsp)
+testcase_read(Pool *pool, FILE *fp, const char *testcase, Queue *job, char **resultp, int *resultflagsp)
{
Solver *solv;
char *buf, *bufp;
int prepared = 0;
int closefp = !fp;
int poolflagsreset = 0;
+ int missing_features = 0;
+ Id *genid = 0;
+ int ngenid = 0;
if (!fp && !(fp = fopen(testcase, "r")))
{
else if (!strcmp(pieces[0], "system") && npieces >= 3)
{
int i;
- prepared = 0;
+
/* must set the disttype before the arch */
- for (i = 0; disttype2str[i].str != 0; i++)
- if (!strcmp(disttype2str[i].str, pieces[2]))
- break;
- if (!disttype2str[i].str)
- pool_debug(pool, SOLV_ERROR, "testcase_read: system: unknown disttype '%s'\n", pieces[2]);
- else if (pool->disttype != disttype2str[i].type)
+ prepared = 0;
+ if (strcmp(pieces[2], "*") != 0)
{
+ char *dp = pieces[2];
+ while (dp && *dp)
+ {
+ char *dpe = strchr(dp, ',');
+ if (dpe)
+ *dpe = 0;
+ for (i = 0; disttype2str[i].str != 0; i++)
+ if (!strcmp(disttype2str[i].str, dp))
+ break;
+ if (dpe)
+ *dpe++ = ',';
+ if (disttype2str[i].str)
+ {
#ifdef MULTI_SEMANTICS
- pool_setdisttype(pool, disttype2str[i].type);
-#else
- pool_debug(pool, SOLV_ERROR, "testcase_read: system: cannot change disttype to '%s'\n", pieces[2]);
+ if (pool->disttype != disttype2str[i].type)
+ pool_setdisttype(pool, disttype2str[i].type);
#endif
+ if (pool->disttype == disttype2str[i].type)
+ break;
+ }
+ dp = dpe;
+ }
+ if (!(dp && *dp))
+ {
+ pool_debug(pool, SOLV_ERROR, "testcase_read: system: could not change disttype to '%s'\n", pieces[2]);
+ missing_features = 1;
+ }
}
if (strcmp(pieces[1], "unset") == 0)
pool_setarch(pool, 0);
else
pool_debug(pool, SOLV_ERROR, "disable: unknown package '%s'\n", pieces[2]);
}
+ else if (!strcmp(pieces[0], "feature"))
+ {
+ int i, j;
+ for (i = 1; i < npieces; i++)
+ {
+ for (j = 0; features[j]; j++)
+ if (!strcmp(pieces[i], features[j]))
+ break;
+ if (!features[j])
+ {
+ pool_debug(pool, SOLV_ERROR, "testcase_read: missing feature '%s'\n", pieces[i]);
+ missing_features++;
+ }
+ }
+ if (missing_features)
+ break;
+ }
+ else if (!strcmp(pieces[0], "genid") && npieces > 1)
+ {
+ Id id;
+ /* rejoin */
+ if (npieces > 2)
+ {
+ char *sp;
+ for (sp = pieces[2]; sp < pieces[npieces - 1]; sp++)
+ if (*sp == 0)
+ *sp = ' ';
+ }
+ genid = solv_extend(genid, ngenid, 1, sizeof(*genid), 7);
+ if (!strcmp(pieces[1], "op") && npieces > 2)
+ {
+ struct oplist *op;
+ for (op = oplist; op->flags; op++)
+ if (!strncmp(pieces[2], op->opname, strlen(op->opname)))
+ break;
+ if (!op->flags)
+ {
+ pool_debug(pool, SOLV_ERROR, "testcase_read: genid: unknown op '%s'\n", pieces[2]);
+ break;
+ }
+ if (ngenid < 2)
+ {
+ pool_debug(pool, SOLV_ERROR, "testcase_read: genid: out of stack\n");
+ break;
+ }
+ ngenid -= 2;
+ id = pool_rel2id(pool, genid[ngenid] , genid[ngenid + 1], op->flags, 1);
+ }
+ else if (!strcmp(pieces[1], "lit"))
+ id = pool_str2id(pool, npieces > 2 ? pieces[2] : "", 1);
+ else if (!strcmp(pieces[1], "null"))
+ id = 0;
+ else if (!strcmp(pieces[1], "dep"))
+ id = testcase_str2dep(pool, pieces[2]);
+ else
+ {
+ pool_debug(pool, SOLV_ERROR, "testcase_read: genid: unknown command '%s'\n", pieces[1]);
+ break;
+ }
+ genid[ngenid++] = id;
+ }
else
{
pool_debug(pool, SOLV_ERROR, "testcase_read: cannot parse command '%s'\n", pieces[0]);
}
}
+ while (job && ngenid > 0)
+ queue_push2(job, SOLVER_NOOP | SOLVER_SOLVABLE_PROVIDES, genid[--ngenid]);
+ genid = solv_free(genid);
buf = solv_free(buf);
pieces = solv_free(pieces);
solv_free(testcasedir);
}
if (closefp)
fclose(fp);
+ if (missing_features)
+ {
+ solver_free(solv);
+ solv = 0;
+ if (resultflagsp)
+ *resultflagsp = 77; /* hack for testsolv */
+ }
return solv;
}
char *
-testcase_resultdiff(char *result1, char *result2)
+testcase_resultdiff(const char *result1, const char *result2)
{
Strqueue sq1, sq2, osq;
char *r;