#include "pool.h"
#include "poolarch.h"
#include "poolvendor.h"
+#include "evr.h"
#include "repo.h"
#include "repo_solv.h"
#include "solver.h"
#include "testcase.h"
#include "selection.h"
#include "solv_xfopen.h"
+#if ENABLE_TESTCASE_HELIXREPO
+#include "ext/repo_helix.h"
+#endif
#define DISABLE_JOIN2
#include "tools_util.h"
{ TESTCASE_RESULT_RULES, "rules" },
{ TESTCASE_RESULT_GENID, "genid" },
{ TESTCASE_RESULT_REASON, "reason" },
+ { TESTCASE_RESULT_CLEANDEPS, "cleandeps" },
+ { TESTCASE_RESULT_JOBS, "jobs" },
{ 0, 0 }
};
{ SOLVER_FLAG_FOCUS_BEST, "focusbest", 0 },
{ SOLVER_FLAG_STRONG_RECOMMENDS, "strongrecommends", 0 },
{ SOLVER_FLAG_INSTALL_ALSO_UPDATES, "installalsoupdates", 0 },
+ { SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED, "onlynamespacerecommended", 0 },
{ 0, 0, 0 }
};
{ SELECTION_NOCASE, "nocase" },
{ SELECTION_SOURCE_ONLY, "sourceonly" },
{ SELECTION_WITH_SOURCE, "withsource" },
+ { SELECTION_SKIP_KIND, "skipkind" },
+ { SELECTION_MATCH_DEPSTR, "depstr" },
+ { SELECTION_WITH_DISABLED, "withdisabled" },
+ { SELECTION_WITH_BADARCH, "withbadarch" },
+ { SELECTION_ADD, "add" },
+ { SELECTION_SUBTRACT, "subtract" },
+ { SELECTION_FILTER, "filter" },
{ 0, 0 }
};
#ifdef ENABLE_COMPLEX_DEPS
"complex_deps",
#endif
+#if ENABLE_TESTCASE_HELIXREPO
+ "testcase_helixrepo",
+#endif
0
};
{ REL_AND, "&" },
{ REL_OR , "|" },
{ REL_WITH , "+" },
+ { REL_WITHOUT , "-" },
{ REL_NAMESPACE , "<NAMESPACE>" },
{ REL_ARCH, "." },
{ REL_MULTIARCH, "<MULTIARCH>" },
{ REL_KIND, "<KIND>" },
{ REL_ELSE, "<ELSE>" },
{ REL_ERROR, "<ERROR>" },
+ { REL_UNLESS, "<UNLESS>" },
{ REL_LT, "<" },
{ 0, 0 }
};
break;
}
if (!selflags2str[i].str)
- pool_debug(pool, SOLV_ERROR, "str2job: unknown selection flag '%s'\n", s);
+ pool_error(pool, 0, "str2job: unknown selection flag '%s'", s);
s = se;
}
return selflags;
break;
}
if (!jobflags2str[i].str)
- pool_debug(pool, SOLV_ERROR, "str2job: unknown job flag '%s'\n", s);
+ pool_error(pool, 0, "str2job: unknown job flag '%s'", s);
s = se;
}
return jobflags;
}
if (npieces < 3)
{
- pool_debug(pool, SOLV_ERROR, "str2job: bad line '%s'\n", str);
+ pool_error(pool, -1, "str2job: bad line '%s'", str);
solv_free(pieces);
return -1;
}
break;
if (!job2str[i].str)
{
- pool_debug(pool, SOLV_ERROR, "str2job: unknown job '%s'\n", str);
+ pool_error(pool, -1, "str2job: unknown job '%s'", str);
solv_free(pieces);
return -1;
}
{
if (npieces != 3)
{
- pool_debug(pool, SOLV_ERROR, "str2job: bad pkg selector in '%s'\n", str);
+ pool_error(pool, -1, "str2job: bad pkg selector in '%s'", str);
solv_free(pieces);
return -1;
}
what = testcase_str2solvid(pool, pieces[2]);
if (!what)
{
- pool_debug(pool, SOLV_ERROR, "str2job: unknown package '%s'\n", pieces[2]);
+ pool_error(pool, -1, "str2job: unknown package '%s'", pieces[2]);
solv_free(pieces);
return -1;
}
Queue q;
job |= SOLVER_SOLVABLE_ONE_OF;
queue_init(&q);
- if (npieces > 3 && strcmp(pieces[2], "nothing") != 0)
+ if (npieces > 2 && strcmp(pieces[2], "nothing") != 0)
{
for (i = 2; i < npieces; i++)
{
Id p = testcase_str2solvid(pool, pieces[i]);
if (!p)
{
- pool_debug(pool, SOLV_ERROR, "str2job: unknown package '%s'\n", pieces[i]);
+ pool_error(pool, -1, "str2job: unknown package '%s'", pieces[i]);
queue_free(&q);
solv_free(pieces);
return -1;
Repo *repo;
if (npieces != 3)
{
- pool_debug(pool, SOLV_ERROR, "str2job: bad line '%s'\n", str);
+ pool_error(pool, -1, "str2job: bad line '%s'", str);
solv_free(pieces);
return -1;
}
repo = testcase_str2repo(pool, pieces[2]);
if (!repo)
{
- pool_debug(pool, SOLV_ERROR, "str2job: unknown repo '%s'\n", pieces[2]);
+ pool_error(pool, -1, "str2job: unknown repo '%s'", pieces[2]);
solv_free(pieces);
return -1;
}
{
if (npieces != 3 && strcmp(pieces[2], "packages") != 0)
{
- pool_debug(pool, SOLV_ERROR, "str2job: bad line '%s'\n", str);
+ pool_error(pool, -1, "str2job: bad line '%s'", str);
solv_free(pieces);
return -1;
}
}
else
{
- pool_debug(pool, SOLV_ERROR, "str2job: unknown selection in '%s'\n", str);
+ pool_error(pool, -1, "str2job: unknown selection in '%s'", str);
solv_free(pieces);
return -1;
}
return job;
}
+#define SELECTIONJOB_MATCHDEPS 1
+#define SELECTIONJOB_MATCHDEPID 2
+#define SELECTIONJOB_MATCHSOLVABLE 3
+
static int
-addselectionjob(Pool *pool, char **pieces, int npieces, Queue *jobqueue)
+addselectionjob(Pool *pool, char **pieces, int npieces, Queue *jobqueue, int type, int keyname)
{
Id job;
- int i, r;
+ int i, r = 0;
int selflags;
Queue sel;
+ char *sp;
for (i = 0; job2str[i].str; i++)
if (!strcmp(pieces[0], job2str[i].str))
break;
if (!job2str[i].str)
- {
- pool_debug(pool, SOLV_ERROR, "selstr2job: unknown job '%s'\n", pieces[0]);
- return -1;
- }
+ return pool_error(pool, -1, "selstr2job: unknown job '%s'", pieces[0]);
job = job2str[i].job;
if (npieces > 3)
{
}
}
if (npieces < 4)
- {
- pool_debug(pool, SOLV_ERROR, "selstr2job: no selection flags\n");
- return -1;
- }
- selflags = str2selflags(pool, pieces[3]);
+ return pool_error(pool, -1, "selstr2job: no selection flags");
+ selflags = str2selflags(pool, pieces[npieces - 1]);
+ /* re-join pieces */
+ for (sp = pieces[2]; sp < pieces[npieces - 2]; sp++)
+ if (*sp == 0)
+ *sp = ' ';
queue_init(&sel);
- r = selection_make(pool, &sel, pieces[2], selflags);
+ if (selflags & (SELECTION_ADD | SELECTION_SUBTRACT | SELECTION_FILTER))
+ {
+ for (i = 0; i < jobqueue->count; i += 2)
+ queue_push2(&sel, jobqueue->elements[i] & (SOLVER_SELECTMASK | SOLVER_SETMASK), jobqueue->elements[i + 1]);
+ queue_empty(jobqueue);
+ }
+ if (!type)
+ r = selection_make(pool, &sel, pieces[2], selflags);
+ else if (type == SELECTIONJOB_MATCHDEPS)
+ r = selection_make_matchdeps(pool, &sel, pieces[2], selflags, keyname, 0);
+ else if (type == SELECTIONJOB_MATCHDEPID)
+ r = selection_make_matchdepid(pool, &sel, testcase_str2dep(pool, pieces[2]), selflags, keyname, 0);
+ else if (type == SELECTIONJOB_MATCHSOLVABLE)
+ r = selection_make_matchsolvable(pool, &sel, testcase_str2solvid(pool, pieces[2]), selflags, keyname, 0);
for (i = 0; i < sel.count; i += 2)
queue_push2(jobqueue, job | sel.elements[i], sel.elements[i + 1]);
queue_free(&sel);
if (*line != '=' || !line[1] || !line[2] || !line[3] || line[4] != ':')
continue;
tag = line[1] << 16 | line[2] << 8 | line[3];
+ /* tags that do not need a solvable */
switch(tag)
- {
+ {
case 'V' << 16 | 'e' << 8 | 'r':
tagsversion = atoi(line + 6);
addselfprovides = tagsversion < 3 || strstr(line + 6, "addselfprovides") != 0;
- break;
+ continue;
case 'P' << 16 | 'k' << 8 | 'g':
if (s)
{
sp[2][-1] = '-';
s->evr = makeevr(pool, sp[1]);
s->arch = pool_str2id(pool, sp[3], 1);
+ continue;
+ default:
break;
+ }
+ if (!s)
+ continue;
+ /* tags that need a solvable */
+ switch(tag)
+ {
case 'S' << 16 | 'u' << 8 | 'm':
repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, line + 6);
break;
if (!strncmp(poolflags2str[i].str, s, p - s) && poolflags2str[i].str[p - s] == 0)
break;
if (!poolflags2str[i].str)
- {
- pool_debug(pool, SOLV_ERROR, "setpoolflags: unknown flag '%.*s'\n", (int)(p - s), s);
- return 0;
- }
+ return pool_error(pool, 0, "setpoolflags: unknown flag '%.*s'", (int)(p - s), s);
pool_set_flag(pool, poolflags2str[i].flag, v);
}
return 1;
if (!strncmp(solverflags2str[i].str, s, p - s) && solverflags2str[i].str[p - s] == 0)
break;
if (!solverflags2str[i].str)
- {
- pool_debug(solv->pool, SOLV_ERROR, "setsolverflags: unknown flag '%.*s'\n", (int)(p - s), s);
- return 0;
- }
+ return pool_error(solv->pool, 0, "setsolverflags: unknown flag '%.*s'", (int)(p - s), s);
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 pool_error(solv->pool, 0, "setsolverflags: unsupported flag '%s'", solverflags2str[i].str);
}
return 1;
}
}
queue_free(&whyq);
}
+ if ((resultflags & TESTCASE_RESULT_CLEANDEPS) != 0)
+ {
+ Queue q;
+
+ queue_init(&q);
+ solver_get_cleandeps(solv, &q);
+ for (i = 0; i < q.count; i++)
+ {
+ s = pool_tmpjoin(pool, "cleandeps ", testcase_solvid2str(pool, q.elements[i]), 0);
+ strqueue_push(&sq, s);
+ }
+ queue_free(&q);
+ }
+ if ((resultflags & TESTCASE_RESULT_JOBS) != 0)
+ {
+ for (i = 0; i < solv->job.count; i += 2)
+ {
+ s = (char *)testcase_job2str(pool, solv->job.elements[i], solv->job.elements[i + 1]);
+ s = pool_tmpjoin(pool, "job ", s, 0);
+ strqueue_push(&sq, s);
+ }
+ }
strqueue_sort(&sq);
result = strqueue_join(&sq);
strqueue_free(&sq);
resultname = "solver.result";
if (mkdir(dir, 0777) && errno != EEXIST)
- {
- pool_debug(solv->pool, SOLV_ERROR, "testcase_write: could not create directory '%s'\n", dir);
- return 0;
- }
+ return pool_error(solv->pool, 0, "testcase_write: could not create directory '%s'", dir);
strqueue_init(&sq);
FOR_REPOS(repoid, repo)
{
out = pool_tmpjoin(pool, dir, "/", out);
if (!(fp = solv_xfopen(out, "w")))
{
- pool_debug(solv->pool, SOLV_ERROR, "testcase_write: could not open '%s' for writing\n", out);
+ pool_error(solv->pool, 0, "testcase_write: could not open '%s' for writing", out);
strqueue_free(&sq);
return 0;
}
testcase_write_testtags(repo, fp);
if (fclose(fp))
{
- pool_debug(solv->pool, SOLV_ERROR, "testcase_write: write error\n");
+ pool_error(solv->pool, 0, "testcase_write: write error");
strqueue_free(&sq);
return 0;
}
strqueue_push(&sq, cmd);
}
- if (resultflags)
+ if ((resultflags & ~TESTCASE_RESULT_REUSE_SOLVER) != 0)
{
char *result;
cmd = 0;
out = pool_tmpjoin(pool, dir, "/", resultname);
if (!(fp = fopen(out, "w")))
{
- pool_debug(solv->pool, SOLV_ERROR, "testcase_write: could not open '%s' for writing\n", out);
+ pool_error(solv->pool, 0, "testcase_write: could not open '%s' for writing", out);
solv_free(result);
strqueue_free(&sq);
return 0;
}
if (result && *result && fwrite(result, strlen(result), 1, fp) != 1)
{
- pool_debug(solv->pool, SOLV_ERROR, "testcase_write: write error\n");
+ pool_error(solv->pool, 0, "testcase_write: write error");
solv_free(result);
strqueue_free(&sq);
fclose(fp);
}
if (fclose(fp))
{
- pool_debug(solv->pool, SOLV_ERROR, "testcase_write: write error\n");
+ pool_error(solv->pool, 0, "testcase_write: write error");
strqueue_free(&sq);
return 0;
}
out = pool_tmpjoin(pool, dir, "/", testcasename);
if (!(fp = fopen(out, "w")))
{
- pool_debug(solv->pool, SOLV_ERROR, "testcase_write: could not open '%s' for writing\n", out);
+ pool_error(solv->pool, 0, "testcase_write: could not open '%s' for writing", out);
strqueue_free(&sq);
return 0;
}
if (*cmd && fwrite(cmd, strlen(cmd), 1, fp) != 1)
{
- pool_debug(solv->pool, SOLV_ERROR, "testcase_write: write error\n");
+ pool_error(solv->pool, 0, "testcase_write: write error");
strqueue_free(&sq);
fclose(fp);
return 0;
}
if (fclose(fp))
{
- pool_debug(solv->pool, SOLV_ERROR, "testcase_write: write error\n");
+ pool_error(solv->pool, 0, "testcase_write: write error");
strqueue_free(&sq);
return 0;
}
break;
}
if (!resultflags2str[i].str)
- pool_debug(pool, SOLV_ERROR, "result: unknown flag '%s'\n", s);
+ pool_error(pool, 0, "result: unknown flag '%s'", s);
s = se;
}
return resultflags;
int ngenid = 0;
Queue autoinstq;
+ if (resultp)
+ *resultp = 0;
+ if (resultflagsp)
+ *resultflagsp = 0;
if (!fp && !(fp = fopen(testcase, "r")))
{
- pool_debug(pool, SOLV_ERROR, "testcase_read: could not open '%s'\n", testcase);
+ pool_error(pool, 0, "testcase_read: could not open '%s'", testcase);
return 0;
}
testcasedir = solv_strdup(testcase);
}
if (!rfp)
{
- pool_debug(pool, SOLV_ERROR, "testcase_read: could not open '%s'\n", rdata);
+ pool_error(pool, 0, "testcase_read: could not open '%s'", rdata);
}
else if (!strcmp(repotype, "testtags"))
{
repo_add_solv(repo, rfp, 0);
fclose(rfp);
}
-#if 0
+#if ENABLE_TESTCASE_HELIXREPO
else if (!strcmp(repotype, "helix"))
{
- extern int repo_add_helix(Repo *repo, FILE *fp, int flags);
repo_add_helix(repo, rfp, 0);
fclose(rfp);
}
else
{
fclose(rfp);
- pool_debug(pool, SOLV_ERROR, "testcase_read: unknown repo type for repo '%s'\n", repo->name);
+ pool_error(pool, 0, "testcase_read: unknown repo type for repo '%s'", repo->name);
}
}
}
}
if (!(dp && *dp))
{
- pool_debug(pool, SOLV_ERROR, "testcase_read: system: could not change disttype to '%s'\n", pieces[2]);
+ pool_error(pool, 0, "testcase_read: system: could not change disttype to '%s'", pieces[2]);
missing_features = 1;
}
}
{
Repo *repo = testcase_str2repo(pool, pieces[3]);
if (!repo)
- pool_debug(pool, SOLV_ERROR, "testcase_read: system: unknown repo '%s'\n", pieces[3]);
+ pool_error(pool, 0, "testcase_read: system: unknown repo '%s'", pieces[3]);
else
pool_set_installed(pool, repo);
}
}
if (npieces >= 3 && !strcmp(pieces[2], "selection"))
{
- addselectionjob(pool, pieces + 1, npieces - 1, job);
+ addselectionjob(pool, pieces + 1, npieces - 1, job, 0, 0);
+ continue;
+ }
+ if (npieces >= 4 && !strcmp(pieces[2], "selection_matchdeps"))
+ {
+ pieces[2] = pieces[1];
+ addselectionjob(pool, pieces + 2, npieces - 2, job, SELECTIONJOB_MATCHDEPS, pool_str2id(pool, pieces[3], 1));
+ continue;
+ }
+ if (npieces >= 4 && !strcmp(pieces[2], "selection_matchdepid"))
+ {
+ pieces[2] = pieces[1];
+ addselectionjob(pool, pieces + 2, npieces - 2, job, SELECTIONJOB_MATCHDEPID, pool_str2id(pool, pieces[3], 1));
+ continue;
+ }
+ if (npieces >= 4 && !strcmp(pieces[2], "selection_matchsolvable"))
+ {
+ pieces[2] = pieces[1];
+ addselectionjob(pool, pieces + 2, npieces - 2, job, SELECTIONJOB_MATCHSOLVABLE, pool_str2id(pool, pieces[3], 1));
continue;
}
/* rejoin */
s = strchr(pieces[1], '(');
if (!s && pieces[1][i - 1] != ')')
{
- pool_debug(pool, SOLV_ERROR, "testcase_read: bad namespace '%s'\n", pieces[1]);
+ pool_error(pool, 0, "testcase_read: bad namespace '%s'", pieces[1]);
}
else
{
{
FILE *rfp = fopen(rdata, "r");
if (!rfp)
- pool_debug(pool, SOLV_ERROR, "testcase_read: could not open '%s'\n", rdata);
+ pool_error(pool, 0, "testcase_read: could not open '%s'", rdata);
else
{
result = read_file(rfp);
if (resultflagsp)
*resultflagsp = resultflags;
}
- else if (!strcmp(pieces[0], "nextjob") && npieces == 1)
+ else if (!strcmp(pieces[0], "nextjob"))
{
+ if (npieces == 2 && resultflagsp && !strcmp(pieces[1], "reusesolver"))
+ *resultflagsp |= TESTCASE_RESULT_REUSE_SOLVER;
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]);
+ pool_error(pool, 0, "testcase_read: bad disable type '%s'", pieces[1]);
continue;
}
if (!prepared)
if (p)
MAPCLR(pool->considered, p);
else
- pool_debug(pool, SOLV_ERROR, "disable: unknown package '%s'\n", pieces[2]);
+ pool_error(pool, 0, "disable: unknown package '%s'", pieces[2]);
}
else if (!strcmp(pieces[0], "feature"))
{
break;
if (!features[j])
{
- pool_debug(pool, SOLV_ERROR, "testcase_read: missing feature '%s'\n", pieces[i]);
+ pool_error(pool, 0, "testcase_read: missing feature '%s'", pieces[i]);
missing_features++;
}
}
break;
if (!op->flags)
{
- pool_debug(pool, SOLV_ERROR, "testcase_read: genid: unknown op '%s'\n", pieces[2]);
+ pool_error(pool, 0, "testcase_read: genid: unknown op '%s'", pieces[2]);
break;
}
if (ngenid < 2)
{
- pool_debug(pool, SOLV_ERROR, "testcase_read: genid: out of stack\n");
+ pool_error(pool, 0, "testcase_read: genid: out of stack");
break;
}
ngenid -= 2;
id = testcase_str2dep(pool, pieces[2]);
else
{
- pool_debug(pool, SOLV_ERROR, "testcase_read: genid: unknown command '%s'\n", pieces[1]);
+ pool_error(pool, 0, "testcase_read: genid: unknown command '%s'", pieces[1]);
break;
}
genid[ngenid++] = id;
{
if (strcmp(pieces[1], "name"))
{
- pool_debug(pool, SOLV_ERROR, "testcase_read: autoinst: illegal mode\n");
+ pool_error(pool, 0, "testcase_read: autoinst: illegal mode");
break;
}
queue_push(&autoinstq, pool_str2id(pool, pieces[2], 1));
}
+ else if (!strcmp(pieces[0], "evrcmp") && npieces == 3)
+ {
+ Id evr1 = pool_str2id(pool, pieces[1], 1);
+ Id evr2 = pool_str2id(pool, pieces[2], 1);
+ int r = pool_evrcmp(pool, evr1, evr2, EVRCMP_COMPARE);
+ r = r < 0 ? REL_LT : r > 0 ? REL_GT : REL_EQ;
+ queue_push2(job, SOLVER_NOOP | SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, evr1, evr2, r, 1));
+ }
else
{
- pool_debug(pool, SOLV_ERROR, "testcase_read: cannot parse command '%s'\n", pieces[0]);
+ pool_error(pool, 0, "testcase_read: cannot parse command '%s'", pieces[0]);
}
}
while (job && ngenid > 0)