X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=ext%2Ftestcase.c;h=32547c85aa4503aec49c9ad860fa346d8794200a;hb=1a4fc4d68c2a8bd5d027bc2f76d3bfc2c187efea;hp=6129657cc4b35404e1e1d5c299cc7cb8b4ee4e85;hpb=527eab20fa8b5225b3c9d8420cfc09cd9965ceba;p=platform%2Fupstream%2Flibsolv.git diff --git a/ext/testcase.c b/ext/testcase.c index 6129657..32547c8 100644 --- a/ext/testcase.c +++ b/ext/testcase.c @@ -18,19 +18,16 @@ #include "poolarch.h" #include "poolvendor.h" #include "repo.h" -#include "repo_susetags.h" +#include "repo_solv.h" #include "solver.h" #include "solverdebug.h" #include "chksum.h" #include "testcase.h" +#include "selection.h" #include "solv_xfopen.h" -#ifndef ENABLE_SUSEREPO -# define DISABLE_JOIN2 -# include "tools_util.h" -#else -# include "repo_susetags.h" -#endif +#define DISABLE_JOIN2 +#include "tools_util.h" static struct job2str { Id job; @@ -41,7 +38,8 @@ static struct job2str { { SOLVER_ERASE, "erase" }, { SOLVER_UPDATE, "update" }, { SOLVER_WEAKENDEPS, "weakendeps" }, - { SOLVER_NOOBSOLETES, "noobsoletes" }, + { SOLVER_MULTIVERSION, "multiversion" }, + { SOLVER_MULTIVERSION, "noobsoletes" }, /* old name */ { SOLVER_LOCK, "lock" }, { SOLVER_DISTUPGRADE, "distupgrade" }, { SOLVER_VERIFY, "verify" }, @@ -57,6 +55,10 @@ static struct jobflags2str { { SOLVER_WEAK, "weak" }, { SOLVER_ESSENTIAL, "essential" }, { SOLVER_CLEANDEPS, "cleandeps" }, + { SOLVER_ORUPDATE, "orupdate" }, + { SOLVER_FORCEBEST, "forcebest" }, + { SOLVER_TARGETED, "targeted" }, + { SOLVER_NOTBYUSER, "notbyuser" }, { SOLVER_SETEV, "setev" }, { SOLVER_SETEVR, "setevr" }, { SOLVER_SETARCH, "setarch" }, @@ -84,17 +86,75 @@ static struct solverflags2str { int def; } solverflags2str[] = { { SOLVER_FLAG_ALLOW_DOWNGRADE, "allowdowngrade", 0 }, + { SOLVER_FLAG_ALLOW_NAMECHANGE, "allownamechange", 1 }, { SOLVER_FLAG_ALLOW_ARCHCHANGE, "allowarchchange", 0 }, { SOLVER_FLAG_ALLOW_VENDORCHANGE, "allowvendorchange", 0 }, { SOLVER_FLAG_ALLOW_UNINSTALL, "allowuninstall", 0 }, { SOLVER_FLAG_NO_UPDATEPROVIDE, "noupdateprovide", 0 }, { SOLVER_FLAG_SPLITPROVIDES, "splitprovides", 0 }, { SOLVER_FLAG_IGNORE_RECOMMENDED, "ignorerecommended", 0 }, - { SOLVER_FLAG_IGNORE_ALREADY_RECOMMENDED, "ignorealreadyrecommended", 0 }, + { SOLVER_FLAG_ADD_ALREADY_RECOMMENDED, "addalreadyrecommended", 0 }, { SOLVER_FLAG_NO_INFARCHCHECK, "noinfarchcheck", 0 }, + { SOLVER_FLAG_KEEP_EXPLICIT_OBSOLETES, "keepexplicitobsoletes", 0 }, + { SOLVER_FLAG_BEST_OBEY_POLICY, "bestobeypolicy", 0 }, + { SOLVER_FLAG_NO_AUTOTARGET, "noautotarget", 0 }, + { SOLVER_FLAG_DUP_ALLOW_DOWNGRADE, "dupallowdowngrade", 1 }, + { SOLVER_FLAG_DUP_ALLOW_ARCHCHANGE, "dupallowarchchange", 1 }, + { SOLVER_FLAG_DUP_ALLOW_VENDORCHANGE, "dupallowvendorchange", 1 }, + { SOLVER_FLAG_DUP_ALLOW_NAMECHANGE, "dupallownamechange", 1 }, + { SOLVER_FLAG_KEEP_ORPHANS, "keeporphans", 0 }, + { SOLVER_FLAG_BREAK_ORPHANS, "breakorphans", 0 }, { 0, 0, 0 } }; +static struct poolflags2str { + Id flag; + const char *str; + int def; +} poolflags2str[] = { + { POOL_FLAG_PROMOTEEPOCH, "promoteepoch", 0 }, + { POOL_FLAG_FORBIDSELFCONFLICTS, "forbidselfconflicts", 0 }, + { POOL_FLAG_OBSOLETEUSESPROVIDES, "obsoleteusesprovides", 0 }, + { POOL_FLAG_IMPLICITOBSOLETEUSESPROVIDES, "implicitobsoleteusesprovides", 0 }, + { POOL_FLAG_OBSOLETEUSESCOLORS, "obsoleteusescolors", 0 }, + { POOL_FLAG_IMPLICITOBSOLETEUSESCOLORS, "implicitobsoleteusescolors", 0 }, + { POOL_FLAG_NOINSTALLEDOBSOLETES, "noinstalledobsoletes", 0 }, + { POOL_FLAG_HAVEDISTEPOCH, "havedistepoch", 0 }, + { POOL_FLAG_NOOBSOLETESMULTIVERSION, "noobsoletesmultiversion", 0 }, + { POOL_FLAG_ADDFILEPROVIDESFILTERED, "addfileprovidesfiltered", 0 }, + { 0, 0, 0 } +}; + +static struct disttype2str { + Id type; + const char *str; +} disttype2str[] = { + { DISTTYPE_RPM, "rpm" }, + { DISTTYPE_DEB, "deb" }, + { DISTTYPE_ARCH, "arch" }, + { DISTTYPE_HAIKU, "haiku" }, + { 0, 0 } +}; + +static struct selflags2str { + Id flag; + const char *str; +} selflags2str[] = { + { SELECTION_NAME, "name" }, + { SELECTION_PROVIDES, "provides" }, + { SELECTION_FILELIST, "filelist" }, + { SELECTION_CANON, "canon" }, + { SELECTION_DOTARCH, "dotarch" }, + { SELECTION_REL, "rel" }, + { SELECTION_INSTALLED_ONLY, "installedonly" }, + { SELECTION_GLOB, "glob" }, + { SELECTION_FLAT, "flat" }, + { SELECTION_NOCASE, "nocase" }, + { SELECTION_SOURCE_ONLY, "sourceonly" }, + { SELECTION_WITH_SOURCE, "withsource" }, + { 0, 0 } +}; + typedef struct strqueue { char **str; @@ -186,6 +246,8 @@ static void strqueue_split(Strqueue *q, const char *s) { const char *p; + if (!s) + return; while ((p = strchr(s, '\n')) != 0) { q->str = solv_extend(q->str, q->nstr, 1, sizeof(*q->str), STRQUEUE_BLOCK); @@ -232,21 +294,14 @@ pool_isknownarch(Pool *pool, Id id) return 1; } -Id -testcase_str2dep(Pool *pool, char *s) +static Id +testcase_str2dep_simple(Pool *pool, const char **sp) { - char *n, *a; - Id id; + const char *s = *sp; + const char *n, *a; + Id id, evr; int flags; - if ((n = strchr(s, '|')) != 0) - { - id = testcase_str2dep(pool, n + 1); - *n = 0; - id = pool_rel2id(pool, testcase_str2dep(pool, s), id, REL_OR, 1); - *n = '|'; - return id; - } while (*s == ' ' || *s == '\t') s++; n = s; @@ -256,9 +311,9 @@ testcase_str2dep(Pool *pool, char *s) { while (*s && *s != ')') s++; + continue; } - else - s++; + s++; } if ((a = strchr(n, '.')) != 0 && a + 1 < s && s[-1] != ')') { @@ -271,32 +326,105 @@ testcase_str2dep(Pool *pool, char *s) else id = pool_strn2id(pool, n, s - n, 1); } + else if (s - n > 4 && s[-4] == ':' && !strncmp(s - 4, ":any", 4)) + { + id = pool_strn2id(pool, n, s - n - 4, 1); + id = pool_rel2id(pool, id, ARCH_ANY, REL_MULTIARCH, 1); + } else id = pool_strn2id(pool, n, s - n, 1); if (!*s) - return id; + { + *sp = s; + return id; + } while (*s == ' ' || *s == '\t') s++; flags = 0; + if (*s == '!' && s[1] == '=') /* support != as synonym for <> */ + { + flags = REL_LT | REL_GT; + s += 2; + } for (;;s++) - { + { if (*s == '<') - flags |= REL_LT; + flags |= REL_LT; else if (*s == '=') - flags |= REL_EQ; + flags |= REL_EQ; else if (*s == '>') - flags |= REL_GT; + flags |= REL_GT; else - break; + break; } if (!flags) - return id; + { + *sp = s; + return id; + } while (*s == ' ' || *s == '\t') s++; n = s; while (*s && *s != ' ' && *s != '\t') s++; - return pool_rel2id(pool, id, pool_strn2id(pool, n, s - n, 1), flags, 1); + evr = pool_strn2id(pool, n, s - n, 1); + if (*s == ' ' && !strcmp(s, " compat >= ")) + { + s += 11; + while (*s == ' ' || *s == '\t') + s++; + n = s; + while (*s && *s != ' ' && *s != '\t') + s++; + evr = pool_rel2id(pool, evr, pool_strn2id(pool, n, s - n, 1), REL_COMPAT, 1); + } + *sp = s; + return pool_rel2id(pool, id, evr, flags, 1); +} + +static Id +testcase_str2dep_complex(Pool *pool, const char **sp) +{ + const char *s = *sp; + Id id; +#ifdef ENABLE_COMPLEX_DEPS + while (*s == ' ' || *s == '\t') + s++; + if (*s == '(') + { + s++; + id = testcase_str2dep_complex(pool, &s); + if (*s == ')') + s++; + while (*s == ' ' || *s == '\t') + s++; + } + else +#endif + id = testcase_str2dep_simple(pool, &s); + if (*s == '|') + { + s++; + id = pool_rel2id(pool, id, testcase_str2dep_complex(pool, &s), REL_OR, 1); + } + else if (*s == '&') + { + s++; + id = pool_rel2id(pool, id, testcase_str2dep_complex(pool, &s), REL_AND, 1); + } + else if (*s == 'I' && s[1] == 'F' && (s[2] == ' ' || s[2] == '\t')) + { + s += 2; + id = pool_rel2id(pool, id, testcase_str2dep_complex(pool, &s), REL_COND, 1); + } + *sp = s; + return id; +} + +Id +testcase_str2dep(Pool *pool, const char *s) +{ + return testcase_str2dep_complex(pool, &s); } const char * @@ -315,7 +443,7 @@ testcase_repoid2str(Pool *pool, Id repoid) else { char buf[20]; - sprintf(buf, "@#%d", repoid); + sprintf(buf, "#%d", repoid); return pool_tmpjoin(pool, buf, 0, 0); } } @@ -324,12 +452,16 @@ const char * testcase_solvid2str(Pool *pool, Id p) { Solvable *s = pool->solvables + p; - const char *str; - char buf[20]; + const char *n, *e, *a; + char *str, buf[20]; if (p == SYSTEMSOLVABLE) return "@SYSTEM"; - str = pool_solvid2str(pool, p); + n = pool_id2str(pool, s->name); + e = pool_id2str(pool, s->evr); + a = pool_id2str(pool, s->arch); + str = pool_alloctmpspace(pool, strlen(n) + strlen(e) + strlen(a) + 3); + sprintf(str, "%s-%s.%s", n, e, a); if (!s->repo) return pool_tmpappend(pool, str, "@", 0); if (s->repo->name) @@ -528,6 +660,50 @@ testcase_job2str(Pool *pool, Id how, Id what) return ret; } +static int +str2selflags(Pool *pool, char *s) /* modifies the string! */ +{ + int i, selflags = 0; + while (s) + { + char *se = strchr(s, ','); + if (se) + *se++ = 0; + for (i = 0; selflags2str[i].str; i++) + if (!strcmp(s, selflags2str[i].str)) + { + selflags |= selflags2str[i].flag; + break; + } + if (!selflags2str[i].str) + pool_debug(pool, SOLV_ERROR, "str2job: unknown selection flag '%s'\n", s); + s = se; + } + return selflags; +} + +static int +str2jobflags(Pool *pool, char *s) /* modifies the string */ +{ + int i, jobflags = 0; + while (s) + { + char *se = strchr(s, ','); + if (se) + *se++ = 0; + for (i = 0; jobflags2str[i].str; i++) + if (!strcmp(s, jobflags2str[i].str)) + { + jobflags |= jobflags2str[i].flag; + break; + } + if (!jobflags2str[i].str) + pool_debug(pool, SOLV_ERROR, "str2job: unknown job flag '%s'\n", s); + s = se; + } + return jobflags; +} + Id testcase_str2job(Pool *pool, const char *str, Id *whatp) { @@ -558,7 +734,8 @@ testcase_str2job(Pool *pool, const char *str, Id *whatp) if (npieces < 3) { pool_debug(pool, SOLV_ERROR, "str2job: bad line '%s'\n", str); - return 0; + solv_free(pieces); + return -1; } for (i = 0; job2str[i].str; i++) @@ -567,34 +744,20 @@ testcase_str2job(Pool *pool, const char *str, Id *whatp) if (!job2str[i].str) { pool_debug(pool, SOLV_ERROR, "str2job: unknown job '%s'\n", str); - return 0; + solv_free(pieces); + return -1; } job = job2str[i].job; + what = 0; if (npieces > 3) { char *flags = pieces[npieces - 1]; - char *nf; if (*flags == '[' && flags[strlen(flags) - 1] == ']') { npieces--; flags++; - flags[strlen(flags) - 1] = ','; - while (*flags) - { - for (nf = flags; *nf != ','; nf++) - ; - *nf++ = 0; - for (i = 0; jobflags2str[i].str; i++) - if (!strcmp(flags, jobflags2str[i].str)) - break; - if (!jobflags2str[i].str) - { - pool_debug(pool, SOLV_ERROR, "str2job: unknown jobflags in '%s'\n", str); - return 0; - } - job |= jobflags2str[i].flag; - flags = nf; - } + flags[strlen(flags) - 1] = 0; + job |= str2jobflags(pool, flags); } } if (!strcmp(pieces[1], "pkg")) @@ -602,14 +765,16 @@ testcase_str2job(Pool *pool, const char *str, Id *whatp) if (npieces != 3) { pool_debug(pool, SOLV_ERROR, "str2job: bad pkg selector in '%s'\n", str); - return 0; + solv_free(pieces); + return -1; } job |= SOLVER_SOLVABLE; what = testcase_str2solvid(pool, pieces[2]); if (!what) { pool_debug(pool, SOLV_ERROR, "str2job: unknown package '%s'\n", pieces[2]); - return 0; + solv_free(pieces); + return -1; } } else if (!strcmp(pieces[1], "name") || !strcmp(pieces[1], "provides")) @@ -619,7 +784,25 @@ testcase_str2job(Pool *pool, const char *str, Id *whatp) for (sp = pieces[2]; sp < pieces[npieces - 1]; sp++) if (*sp == 0) *sp = ' '; - what = testcase_str2dep(pool, pieces[2]); + what = 0; + if (pieces[1][0] == 'p' && strncmp(pieces[2], "namespace:", 10) == 0) + { + char *spe = strchr(pieces[2], '('); + int l = strlen(pieces[2]); + if (spe && pieces[2][l - 1] == ')') + { + /* special namespace provides */ + if (strcmp(spe, "()") != 0) + { + pieces[2][l - 1] = 0; + what = testcase_str2dep(pool, spe + 1); + pieces[2][l - 1] = ')'; + } + what = pool_rel2id(pool, pool_strn2id(pool, pieces[2], spe - pieces[2], 1), what, REL_NAMESPACE, 1); + } + } + if (!what) + what = testcase_str2dep(pool, pieces[2]); if (pieces[1][0] == 'n') job |= SOLVER_SOLVABLE_NAME; else @@ -639,7 +822,8 @@ testcase_str2job(Pool *pool, const char *str, Id *whatp) { pool_debug(pool, SOLV_ERROR, "str2job: unknown package '%s'\n", pieces[i]); queue_free(&q); - return 0; + solv_free(pieces); + return -1; } queue_push(&q, p); } @@ -653,13 +837,15 @@ testcase_str2job(Pool *pool, const char *str, Id *whatp) if (npieces != 3) { pool_debug(pool, SOLV_ERROR, "str2job: bad line '%s'\n", str); - return 0; + 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]); - return 0; + solv_free(pieces); + return -1; } job |= SOLVER_SOLVABLE_REPO; what = repo->repoid; @@ -669,7 +855,8 @@ testcase_str2job(Pool *pool, const char *str, Id *whatp) if (npieces != 3 && strcmp(pieces[2], "packages") != 0) { pool_debug(pool, SOLV_ERROR, "str2job: bad line '%s'\n", str); - return 0; + solv_free(pieces); + return -1; } job |= SOLVER_SOLVABLE_ALL; what = 0; @@ -677,12 +864,56 @@ testcase_str2job(Pool *pool, const char *str, Id *whatp) else { pool_debug(pool, SOLV_ERROR, "str2job: unknown selection in '%s'\n", str); - return 0; + solv_free(pieces); + return -1; } *whatp = what; + solv_free(pieces); return job; } +int +addselectionjob(Pool *pool, char **pieces, int npieces, Queue *jobqueue) +{ + Id job; + int i, r; + int selflags; + Queue sel; + + 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; + } + job = job2str[i].job; + if (npieces > 3) + { + char *flags = pieces[npieces - 1]; + if (*flags == '[' && flags[strlen(flags) - 1] == ']') + { + npieces--; + flags++; + flags[strlen(flags) - 1] = 0; + job |= str2jobflags(pool, flags); + } + } + if (npieces < 4) + { + pool_debug(pool, SOLV_ERROR, "selstr2job: no selection flags\n"); + return -1; + } + selflags = str2selflags(pool, pieces[3]); + queue_init(&sel); + r = selection_make(pool, &sel, pieces[2], selflags); + for (i = 0; i < sel.count; i += 2) + queue_push2(jobqueue, job | sel.elements[i], sel.elements[i + 1]); + queue_free(&sel); + return r; +} + static void writedeps(Repo *repo, FILE *fp, const char *tag, Id key, Solvable *s, Offset off) { @@ -808,7 +1039,7 @@ writedeps(Repo *repo, FILE *fp, const char *tag, Id key, Solvable *s, Offset off } int -testcase_write_susetags(Repo *repo, FILE *fp) +testcase_write_testtags(Repo *repo, FILE *fp) { Pool *pool = repo->pool; Solvable *s; @@ -829,7 +1060,7 @@ testcase_write_susetags(Repo *repo, FILE *fp) release = strrchr(evr, '-'); if (!release) release = evr + strlen(evr); - fprintf(fp, "=Pkg: %s %.*s %s %s\n", name, release - evr, evr, *release && release[1] ? release + 1 : "-", arch); + fprintf(fp, "=Pkg: %s %.*s %s %s\n", name, (int)(release - evr), evr, *release && release[1] ? release + 1 : "-", arch); tmp = solvable_lookup_str(s, SOLVABLE_SUMMARY); if (tmp) fprintf(fp, "=Sum: %s\n", tmp); @@ -850,8 +1081,6 @@ testcase_write_susetags(Repo *repo, FILE *fp) return 0; } -#ifndef ENABLE_SUSEREPO - static inline Offset adddep(Repo *repo, Offset olddeps, char *str, Id marker) { @@ -865,15 +1094,15 @@ finish_solvable(Pool *pool, Repodata *data, Solvable *s, char *filelist, int nfi if (nfilelist) { int l; - Id did; - for (l = 0; l < nfilelist; l += strlen(filelist + l) + 1) + Id did; + for (l = 0; l < nfilelist; l += strlen(filelist + l) + 1) { char *p = strrchr(filelist + l, '/'); - if (!p) + if (!p) continue; - *p++ = 0; + *p++ = 0; did = repodata_str2dir(data, filelist + l, 1); - p[-1] = '/'; + p[-1] = '/'; if (!did) did = repodata_str2dir(data, "/", 1); repodata_add_dirstr(data, s - pool->solvables, SOLVABLE_FILELIST, did, p); @@ -887,7 +1116,7 @@ finish_solvable(Pool *pool, Repodata *data, Solvable *s, char *filelist, int nfi /* stripped down version of susetags parser used for testcases */ int -testcase_add_susetags(Repo *repo, FILE *fp, int flags) +testcase_add_testtags(Repo *repo, FILE *fp, int flags) { Pool *pool = repo->pool; char *line, *linep; @@ -923,7 +1152,7 @@ testcase_add_susetags(Repo *repo, FILE *fp, int flags) linep += strlen(linep); if (linep == line || linep[-1] != '\n') continue; - *--linep = 0; + linep[-1] = 0; linep = line + intag; if (intag) { @@ -1035,15 +1264,61 @@ testcase_add_susetags(Repo *repo, FILE *fp, int flags) return 0; } -#else +const char * +testcase_getpoolflags(Pool *pool) +{ + const char *str = 0; + int i, v; + for (i = 0; poolflags2str[i].str; i++) + { + v = pool_get_flag(pool, poolflags2str[i].flag); + if (v == poolflags2str[i].def) + continue; + str = pool_tmpappend(pool, str, v ? " " : " !", poolflags2str[i].str); + } + return str ? str + 1 : ""; +} int -testcase_add_susetags(Repo *repo, FILE *fp, int flags) +testcase_setpoolflags(Pool *pool, const char *str) { - return repo_add_susetags(repo, fp, 0, 0, flags); + const char *p = str, *s; + int i, v; + for (;;) + { + while (*p == ' ' || *p == '\t' || *p == ',') + p++; + v = 1; + if (*p == '!') + { + p++; + v = 0; + } + if (!*p) + break; + s = p; + while (*p && *p != ' ' && *p != '\t' && *p != ',') + p++; + for (i = 0; poolflags2str[i].str; i++) + 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; + } + pool_set_flag(pool, poolflags2str[i].flag, v); + } + return 1; } -#endif +void +testcase_resetpoolflags(Pool *pool) +{ + int i; + for (i = 0; poolflags2str[i].str; i++) + pool_set_flag(pool, poolflags2str[i].flag, poolflags2str[i].def); +} const char * testcase_getsolverflags(Solver *solv) @@ -1086,7 +1361,7 @@ testcase_setsolverflags(Solver *solv, const char *str) break; if (!solverflags2str[i].str) { - pool_debug(solv->pool, SOLV_ERROR, "setsolverflags: unknown flag '%.*s'\n", p - s, s); + 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); @@ -1108,7 +1383,7 @@ testcase_ruleid(Solver *solv, Id rid) Strqueue sq; Queue q; int i; - void *chk; + Chksum *chk; const unsigned char *md5; int md5l; const char *s; @@ -1141,7 +1416,7 @@ testcase_problemid(Solver *solv, Id problem) { Strqueue sq; Queue q; - void *chk; + Chksum *chk; const unsigned char *md5; int i, md5l; const char *s; @@ -1168,7 +1443,7 @@ static const char * testcase_solutionid(Solver *solv, Id problem, Id solution) { Id intid; - void *chk; + Chksum *chk; const unsigned char *md5; int md5l; const char *s; @@ -1229,7 +1504,7 @@ testcase_solverresult(Solver *solv, int resultflags) for (i = 0; class2str[i].str; i++) { queue_empty(&q); - transaction_classify_pkgs(trans, 0, class2str[i].class, 0, 0, &q); + transaction_classify_pkgs(trans, SOLVER_TRANSACTION_KEEP_PSEUDO, class2str[i].class, 0, 0, &q); for (j = 0; j < q.count; j++) { p = q.elements[j]; @@ -1326,6 +1601,30 @@ testcase_solverresult(Solver *solv, int resultflags) queue_free(&qs); } + if ((resultflags & TESTCASE_RESULT_UNNEEDED) != 0) + { + Queue q, qf; + + queue_init(&q); + queue_init(&qf); + solver_get_unneeded(solv, &q, 0); + solver_get_unneeded(solv, &qf, 1); + for (i = j = 0; i < q.count; i++) + { + /* we rely on qf containing a subset of q in the same order */ + if (j < qf.count && q.elements[i] == qf.elements[j]) + { + s = pool_tmpjoin(pool, "unneeded_filtered ", testcase_solvid2str(pool, q.elements[i]), 0); + j++; + } + else + s = pool_tmpjoin(pool, "unneeded ", testcase_solvid2str(pool, q.elements[i]), 0); + strqueue_push(&sq, s); + } + queue_free(&q); + queue_free(&qf); + } + strqueue_sort(&sq); result = strqueue_join(&sq); strqueue_free(&sq); @@ -1334,7 +1633,7 @@ testcase_solverresult(Solver *solv, int resultflags) int -testcase_write(Solver *solv, char *dir, int resultflags) +testcase_write(Solver *solv, char *dir, int resultflags, const char *testcasename, const char *resultname) { Pool *pool = solv->pool; Repo *repo; @@ -1346,6 +1645,11 @@ testcase_write(Solver *solv, char *dir, int resultflags) char *cmd, *out; const char *s; + if (!testcasename) + testcasename = "testcase.t"; + if (!resultname) + resultname = "solver.result"; + if (mkdir(dir, 0777) && errno != EEXIST) { pool_debug(solv->pool, SOLV_ERROR, "testcase_write: could not create directory '%s'\n", dir); @@ -1363,7 +1667,7 @@ testcase_write(Solver *solv, char *dir, int resultflags) out = pool_tmpjoin(pool, name, ".repo", ".gz"); cmd = pool_tmpjoin(pool, "repo ", name, " "); cmd = pool_tmpappend(pool, cmd, priobuf, " "); - cmd = pool_tmpappend(pool, cmd, "susetags ", out); + cmd = pool_tmpappend(pool, cmd, "testtags ", out); strqueue_push(&sq, cmd); out = pool_tmpjoin(pool, dir, "/", out); if (!(fp = solv_xfopen(out, "w"))) @@ -1372,7 +1676,7 @@ testcase_write(Solver *solv, char *dir, int resultflags) strqueue_free(&sq); return 0; } - testcase_write_susetags(repo, fp); + testcase_write_testtags(repo, fp); if (fclose(fp)) { pool_debug(solv->pool, SOLV_ERROR, "testcase_write: write error\n"); @@ -1382,7 +1686,7 @@ testcase_write(Solver *solv, char *dir, int resultflags) } /* hmm, this is not optimal... we currently search for the lowest score */ lowscore = 0; - arch = ARCH_NOARCH; + arch = pool->solvables[SYSTEMSOLVABLE].arch; for (i = 0; i < pool->lastarch; i++) { if (pool->id2arch[i] == 1 && !lowscore) @@ -1393,10 +1697,20 @@ testcase_write(Solver *solv, char *dir, int resultflags) lowscore = pool->id2arch[i]; } } - cmd = pool_tmpjoin(pool, "system ", pool_id2str(pool, arch), pool->disttype == DISTTYPE_DEB ? " deb" : " rpm"); + cmd = pool_tmpjoin(pool, "system ", pool->lastarch ? pool_id2str(pool, arch) : "unset", 0); + for (i = 0; disttype2str[i].str != 0; i++) + if (pool->disttype == disttype2str[i].type) + break; + pool_tmpappend(pool, cmd, " ", disttype2str[i].str ? disttype2str[i].str : "unknown"); if (pool->installed) cmd = pool_tmpappend(pool, cmd, " ", testcase_repoid2str(pool, pool->installed->repoid)); strqueue_push(&sq, cmd); + s = testcase_getpoolflags(solv->pool); + if (*s) + { + cmd = pool_tmpjoin(pool, "poolflags ", s, 0); + strqueue_push(&sq, cmd); + } if (pool->vendorclasses) { @@ -1430,8 +1744,9 @@ testcase_write(Solver *solv, char *dir, int resultflags) Reldep *rd = pool->rels + rid; if (rd->flags != REL_NAMESPACE || rd->name == NAMESPACE_OTHERPROVIDERS) continue; - /* check if we evaluated it, also skip empty results */ - if (!(d = pool->whatprovides_rel[rid]) || !pool->whatprovidesdata[d]) + /* evaluate all namespace ids, skip empty results */ + d = pool_whatprovides(pool, MAKERELDEP(rid)); + if (!d || !pool->whatprovidesdata[d]) continue; cmd = pool_tmpjoin(pool, "namespace ", pool_id2str(pool, rd->name), "("); cmd = pool_tmpappend(pool, cmd, pool_id2str(pool, rd->evr), ")"); @@ -1451,48 +1766,68 @@ testcase_write(Solver *solv, char *dir, int resultflags) if (resultflags) { char *result; - out = pool_tmpjoin(pool, dir, "/", "solver.result"); - if (!(fp = fopen(out, "w"))) - { - pool_debug(solv->pool, SOLV_ERROR, "testcase_write: could not open '%s' for writing\n", out); - strqueue_free(&sq); - return 0; - } - result = testcase_solverresult(solv, resultflags); - if (fwrite(result, strlen(result), 1, fp) != 1) - { - pool_debug(solv->pool, SOLV_ERROR, "testcase_write: write error\n"); - solv_free(result); - strqueue_free(&sq); - return 0; - } - solv_free(result); - if (fclose(fp)) - { - pool_debug(solv->pool, SOLV_ERROR, "testcase_write: write error\n"); - strqueue_free(&sq); - return 0; - } cmd = 0; for (i = 0; resultflags2str[i].str; i++) if ((resultflags & resultflags2str[i].flag) != 0) cmd = pool_tmpappend(pool, cmd, cmd ? "," : 0, resultflags2str[i].str); - cmd = pool_tmpjoin(pool, "result ", cmd ? cmd : "?", " solver.result"); + cmd = pool_tmpjoin(pool, "result ", cmd ? cmd : "?", 0); + cmd = pool_tmpappend(pool, cmd, " ", resultname); strqueue_push(&sq, cmd); + result = testcase_solverresult(solv, resultflags); + if (!strcmp(resultname, "")) + { + int i; + Strqueue rsq; + strqueue_init(&rsq); + strqueue_split(&rsq, result); + for (i = 0; i < rsq.nstr; i++) + { + cmd = pool_tmpjoin(pool, "#>", rsq.str[i], 0); + strqueue_push(&sq, cmd); + } + strqueue_free(&rsq); + } + else + { + 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); + 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"); + solv_free(result); + strqueue_free(&sq); + fclose(fp); + return 0; + } + if (fclose(fp)) + { + pool_debug(solv->pool, SOLV_ERROR, "testcase_write: write error\n"); + strqueue_free(&sq); + return 0; + } + } + solv_free(result); } cmd = strqueue_join(&sq); - out = pool_tmpjoin(pool, dir, "/", "testcase.t"); + 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); strqueue_free(&sq); return 0; } - if (fwrite(cmd, strlen(cmd), 1, fp) != 1) + if (*cmd && fwrite(cmd, strlen(cmd), 1, fp) != 1) { pool_debug(solv->pool, SOLV_ERROR, "testcase_write: write error\n"); strqueue_free(&sq); + fclose(fp); return 0; } if (fclose(fp)) @@ -1506,6 +1841,111 @@ testcase_write(Solver *solv, char *dir, int resultflags) return 1; } +static char * +read_inline_file(FILE *fp, char **bufp, char **bufpp, int *buflp) +{ + char *result = solv_malloc(1024); + char *rp = result; + int resultl = 1024; + + for (;;) + { + size_t rl; + if (rp - result + 256 >= resultl) + { + resultl = rp - result; + result = solv_realloc(result, resultl + 1024); + rp = result + resultl; + resultl += 1024; + } + if (!fgets(rp, resultl - (rp - result), fp)) + *rp = 0; + rl = strlen(rp); + if (rl && (rp == result || rp[-1] == '\n')) + { + if (rl > 1 && rp[0] == '#' && rp[1] == '>') + { + memmove(rp, rp + 2, rl - 2); + rl -= 2; + } + else + { + while (rl + 16 > *buflp) + { + *bufp = solv_realloc(*bufp, *buflp + 512); + *buflp += 512; + } + memmove(*bufp, rp, rl); + if ((*bufp)[rl - 1] == '\n') + { + ungetc('\n', fp); + rl--; + } + (*bufp)[rl] = 0; + (*bufpp) = *bufp + rl; + rl = 0; + } + } + if (rl <= 0) + { + *rp = 0; + break; + } + rp += rl; + } + return result; +} + +static char * +read_file(FILE *fp) +{ + char *result = solv_malloc(1024); + char *rp = result; + int resultl = 1024; + + for (;;) + { + size_t rl; + if (rp - result + 256 >= resultl) + { + resultl = rp - result; + result = solv_realloc(result, resultl + 1024); + rp = result + resultl; + resultl += 1024; + } + rl = fread(rp, 1, resultl - (rp - result), fp); + if (rl <= 0) + { + *rp = 0; + break; + } + rp += rl; + } + return result; +} + +static int +str2resultflags(Pool *pool, char *s) /* modifies the string! */ +{ + int i, resultflags = 0; + while (s) + { + char *se = strchr(s, ','); + if (se) + *se++ = 0; + for (i = 0; resultflags2str[i].str; i++) + if (!strcmp(s, resultflags2str[i].str)) + { + resultflags |= resultflags2str[i].flag; + break; + } + if (!resultflags2str[i].str) + pool_debug(pool, SOLV_ERROR, "result: unknown flag '%s'\n", s); + s = se; + } + return resultflags; +} + Solver * testcase_read(Pool *pool, FILE *fp, char *testcase, Queue *job, char **resultp, int *resultflagsp) { @@ -1518,6 +1958,7 @@ testcase_read(Pool *pool, FILE *fp, char *testcase, Queue *job, char **resultp, int npieces = 0; int prepared = 0; int closefp = !fp; + int poolflagsreset = 0; if (!fp && !(fp = fopen(testcase, "r"))) { @@ -1582,6 +2023,11 @@ testcase_read(Pool *pool, FILE *fp, char *testcase, Queue *job, char **resultp, const char *rdata; prepared = 0; + if (!poolflagsreset) + { + poolflagsreset = 1; + testcase_resetpoolflags(pool); /* hmm */ + } if (sscanf(pieces[2], "%d.%d", &prio, &subprio) != 2) { subprio = 0; @@ -1589,26 +2035,73 @@ testcase_read(Pool *pool, FILE *fp, char *testcase, Queue *job, char **resultp, } repo->priority = prio; repo->subpriority = subprio; - rdata = pool_tmpjoin(pool, testcasedir, pieces[4], 0); - if ((rfp = solv_xfopen(rdata, "r")) == 0) + if (strcmp(pieces[3], "empty") != 0) { - pool_debug(pool, SOLV_ERROR, "testcase_read: could not open '%s'\n", rdata); - } - else if (!strcmp(pieces[3], "susetags")) - { - testcase_add_susetags(repo, rfp, 0); - fclose(rfp); - } - else - { - fclose(rfp); - pool_debug(pool, SOLV_ERROR, "testcase_read: unknown repo type for repo '%s'\n", repo->name); + const char *repotype = pool_tmpjoin(pool, pieces[3], 0, 0); /* gets overwritten in case */ + if (!strcmp(pieces[4], "")) + { + char *idata = read_inline_file(fp, &buf, &bufp, &bufl); + rdata = ""; + rfp = solv_xfopen_buf(rdata, &idata, 0, "rf"); + } + else + { + rdata = pool_tmpjoin(pool, testcasedir, pieces[4], 0); + rfp = solv_xfopen(rdata, "r"); + } + if (!rfp) + { + pool_debug(pool, SOLV_ERROR, "testcase_read: could not open '%s'\n", rdata); + } + else if (!strcmp(repotype, "testtags")) + { + testcase_add_testtags(repo, rfp, 0); + fclose(rfp); + } + else if (!strcmp(repotype, "solv")) + { + repo_add_solv(repo, rfp, 0); + fclose(rfp); + } +#if 0 + else if (!strcmp(repotype, "helix")) + { + extern int repo_add_helix(Repo *repo, FILE *fp, int flags); + repo_add_helix(repo, rfp, 0); + fclose(rfp); + } +#endif + else + { + fclose(rfp); + pool_debug(pool, SOLV_ERROR, "testcase_read: unknown repo type for repo '%s'\n", repo->name); + } } } else if (!strcmp(pieces[0], "system") && npieces >= 3) { + int i; prepared = 0; - pool_setarch(pool, pieces[1]); + /* 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) + { +#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]); +#endif + } + if (strcmp(pieces[1], "unset") == 0) + pool_setarch(pool, 0); + else if (pieces[1][0] == ':') + pool_setarchpolicy(pool, pieces[1] + 1); + else + pool_setarch(pool, pieces[1]); if (npieces > 3) { Repo *repo = testcase_str2repo(pool, pieces[3]); @@ -1628,6 +2121,11 @@ testcase_read(Pool *pool, FILE *fp, char *testcase, Queue *job, char **resultp, pool_createwhatprovides(pool); prepared = 1; } + if (npieces >= 3 && !strcmp(pieces[2], "selection")) + { + addselectionjob(pool, pieces + 1, npieces - 1, job); + continue; + } /* rejoin */ for (sp = pieces[1]; sp < pieces[npieces - 1]; sp++) if (*sp == 0) @@ -1673,6 +2171,17 @@ testcase_read(Pool *pool, FILE *fp, char *testcase, Queue *job, char **resultp, queue_free(&q); } } + else if (!strcmp(pieces[0], "poolflags")) + { + int i; + if (!poolflagsreset) + { + poolflagsreset = 1; + testcase_resetpoolflags(pool); /* hmm */ + } + for (i = 1; i < npieces; i++) + testcase_setpoolflags(pool, pieces[i]); + } else if (!strcmp(pieces[0], "solverflags") && npieces > 1) { int i; @@ -1686,103 +2195,36 @@ testcase_read(Pool *pool, FILE *fp, char *testcase, Queue *job, char **resultp, } else if (!strcmp(pieces[0], "result") && npieces > 1) { - FILE *rfp; + char *result = 0; + int resultflags = str2resultflags(pool, pieces[1]); const char *rdata; - int resultflags = 0; - char *s = pieces[1]; - int i; - while (s) + if (npieces > 2) { - char *se = strchr(s, ','); - if (se) - *se++ = 0; - for (i = 0; resultflags2str[i].str; i++) - if (!strcmp(s, resultflags2str[i].str)) - { - resultflags |= resultflags2str[i].flag; - break; - } - if (!resultflags2str[i].str) - pool_debug(pool, SOLV_ERROR, "result: unknown flag '%s'\n", s); - s = se; - } - - rdata = pool_tmpjoin(pool, testcasedir, pieces[2], 0); - if (!strcmp(pieces[2], "")) - rfp = fp; - else - rfp = fopen(rdata, "r"); - if (!rfp) - { - pool_debug(pool, SOLV_ERROR, "testcase_read: could not open '%s'\n", rdata); - } - else - { - /* slurp it in... */ - char *result = solv_malloc(1024); - char *rp = result; - int resultl = 1024; - for (;;) + rdata = pool_tmpjoin(pool, testcasedir, pieces[2], 0); + if (!strcmp(pieces[2], "")) + result = read_inline_file(fp, &buf, &bufp, &bufl); + else { - size_t rl; - if (rp - result + 256 >= resultl) - { - resultl = rp - result; - result = solv_realloc(result, resultl + 1024); - rp = result + resultl; - resultl += 1024; - } - if (fp == rfp) - { - if (!fgets(rp, resultl - (rp - result), fp)) - rl = 0; - else - { - rl = strlen(rp); - if (rl && (rp == result || rp[-1] == '\n')) - { - if (rl > 1 && rp[0] == '#' && rp[1] == '>') - { - memmove(rp, rp + 2, rl - 2); - rl -= 2; - } - else - { - while (rl + 16 > bufl) - { - buf = solv_realloc(buf, bufl + 512); - bufl += 512; - } - memmove(buf, rp, rl); - if (buf[rl - 1] == '\n') - { - ungetc('\n', fp); - rl--; - } - bufp = buf + rl; - rl = 0; - } - } - } - } + FILE *rfp = fopen(rdata, "r"); + if (!rfp) + pool_debug(pool, SOLV_ERROR, "testcase_read: could not open '%s'\n", rdata); else - rl = fread(rp, 1, resultl - (rp - result), rfp); - if (rl <= 0) { - *rp = 0; - break; + result = read_file(rfp); + fclose(rfp); } - rp += rl; } - if (rfp != fp) - fclose(rfp); - if (resultp) - *resultp = result; - else - solv_free(result); - if (resultflagsp) - *resultflagsp = resultflags; } + if (resultp) + *resultp = result; + else + solv_free(result); + if (resultflagsp) + *resultflagsp = resultflags; + } + else if (!strcmp(pieces[0], "nextjob") && npieces == 1) + { + break; } else {