2 * Copyright (c) 2012, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
21 static struct job2str {
25 { SOLVER_NOOP, "noop" },
26 { SOLVER_INSTALL, "install" },
27 { SOLVER_ERASE, "erase" },
28 { SOLVER_UPDATE, "update" },
29 { SOLVER_WEAKENDEPS, "weakendeps" },
30 { SOLVER_NOOBSOLETES, "noobsoletes" },
31 { SOLVER_LOCK, "lock" },
32 { SOLVER_DISTUPGRADE, "distupgrade" },
33 { SOLVER_VERIFY, "verify" },
34 { SOLVER_DROP_ORPHANED, "droporphaned" },
35 { SOLVER_USERINSTALLED, "userinstalled" },
39 static struct jobflags2str {
43 { SOLVER_WEAK, "weak" },
44 { SOLVER_ESSENTIAL, "essential" },
45 { SOLVER_CLEANDEPS, "cleandeps" },
46 { SOLVER_SETEV, "setev" },
47 { SOLVER_SETEVR, "setevr" },
48 { SOLVER_SETARCH, "setarch" },
49 { SOLVER_SETVENDOR, "setvendor" },
50 { SOLVER_SETREPO, "setrepo" },
51 { SOLVER_NOAUTOSET, "noautoset" },
57 pool_isknownarch(Pool *pool, Id id)
59 if (!id || id == ID_EMPTY)
61 if (id == ARCH_SRC || id == ARCH_NOSRC || id == ARCH_NOARCH)
63 if (pool->id2arch && (id > pool->lastarch || !pool->id2arch[id]))
69 testcase_str2dep(Pool *pool, char *s)
75 if ((n = strchr(s, '|')) != 0)
77 id = testcase_str2dep(pool, n + 1);
79 id = pool_rel2id(pool, testcase_str2dep(pool, s), id, REL_OR, 1);
83 while (*s == ' ' || *s == '\t')
86 while (*s && *s != ' ' && *s != '\t' && *s != '<' && *s != '=' && *s != '>')
88 if ((a = strchr(n, '.')) != 0 && a + 1 < s)
90 Id archid = pool_strn2id(pool, a + 1, s - (a + 1), 0);
91 if (pool_isknownarch(pool, archid))
93 id = pool_strn2id(pool, n, a - n, 1);
94 id = pool_rel2id(pool, id, archid, REL_ARCH, 1);
97 id = pool_strn2id(pool, n, s - n, 1);
100 id = pool_strn2id(pool, n, s - n, 1);
103 while (*s == ' ' || *s == '\t')
119 while (*s == ' ' || *s == '\t')
122 while (*s && *s != ' ' && *s != '\t')
124 return pool_rel2id(pool, id, pool_strn2id(pool, n, s - n, 1), flags, 1);
128 testcase_solvid2str(Pool *pool, Id p)
130 Solvable *s = pool->solvables + p;
131 const char *str = pool_solvid2str(pool, p);
135 return pool_tmpappend(pool, str, "@", 0);
139 char *str2 = pool_tmpappend(pool, str, "@", s->repo->name);
141 if (str2[l] == ' ' || str2[l] == '\t')
145 sprintf(buf, "@#%d", s->repo->repoid);
146 return pool_tmpappend(pool, str, buf, 0);
150 testcase_str2repo(Pool *pool, const char *str)
154 if (str[0] == '#' && (str[1] >= '0' && str[1] <= '9'))
158 for (j = 1; str[j] >= '0' && str[j] <= '9'; j++)
159 repoid = repoid * 10 + (str[j] - '0');
160 if (!str[j] && repoid > 0 && repoid < pool->nrepos)
161 repo = pool_id2repo(pool, repoid);
165 FOR_REPOS(repoid, repo)
170 l = strlen(repo->name);
171 for (i = 0; i < l; i++)
173 int c = repo->name[i];
174 if (c == ' ' || c == '\t')
179 if (i == l && !str[l])
182 if (repoid >= pool->nrepos)
189 testcase_str2solvid(Pool *pool, const char *str)
191 int i, l = strlen(str);
199 for (i = l - 1; i >= 0; i--)
200 if (str[i] == '@' && (repo = testcase_str2repo(pool, str + i + 1)) != 0)
205 /* now find the arch (if present) */
207 for (i = repostart - 1; i > 0; i--)
210 arch = pool_strn2id(pool, str + i + 1, repostart - (i + 1), 0);
215 /* now find the name */
216 for (i = repostart - 1; i > 0; i--)
220 Id nid, evrid, p, pp;
221 nid = pool_strn2id(pool, str, i, 0);
224 evrid = pool_strn2id(pool, str + i + 1, repostart - (i + 1), 0);
227 FOR_PROVIDES(p, pp, nid)
229 Solvable *s = pool->solvables + p;
230 if (s->name != nid || s->evr != evrid)
232 if (repo && s->repo != repo)
234 if (arch && s->arch != arch)
244 testcase_job2str(Pool *pool, Id how, Id what)
251 Id select = how & SOLVER_SELECTMASK;
253 for (i = 0; job2str[i].str; i++)
254 if ((how & SOLVER_JOBMASK) == job2str[i].job)
256 jobstr = job2str[i].str ? job2str[i].str : "unknown";
257 if (select == SOLVER_SOLVABLE)
260 pkgstr = testcase_solvid2str(pool, what);
262 else if (select == SOLVER_SOLVABLE_NAME)
265 pkgstr = pool_dep2str(pool, what);
267 else if (select == SOLVER_SOLVABLE_PROVIDES)
269 selstr = " provides ";
270 pkgstr = pool_dep2str(pool, what);
272 else if (select == SOLVER_SOLVABLE_ONE_OF)
277 while ((p = pool->whatprovidesdata[what++]) != 0)
279 const char *s = testcase_solvid2str(pool, p);
282 pkgstr = pool_tmpappend(pool, pkgstr, " ", s);
283 pool_freetmpspace(pool, s);
291 else if (select == SOLVER_SOLVABLE_REPO)
293 Repo *repo = pool_id2repo(pool, what);
298 sprintf(buf, "#%d", repo->repoid);
299 pkgstr = pool_tmpjoin(pool, buf, 0, 0);
302 pkgstr = pool_tmpjoin(pool, repo->name, 0, 0);
304 else if (select == SOLVER_SOLVABLE_ALL)
311 selstr = " unknown ";
314 ret = pool_tmpjoin(pool, jobstr, selstr, pkgstr);
316 ret = pool_tmpappend(pool, ret, " ", 0);
317 for (i = 0; jobflags2str[i].str; i++)
318 if ((how & jobflags2str[i].flags) != 0)
319 ret = pool_tmpappend(pool, ret, ",", jobflags2str[i].str);
325 ret = pool_tmpappend(pool, ret, "]", 0);
331 testcase_str2job(Pool *pool, const char *str, Id *whatp)
341 /* so we can patch it */
342 s = pool_tmpjoin(pool, str, 0, 0);
343 /* split it in pieces */
346 while (*s == ' ' || *s == '\t')
350 pieces = solv_extend(pieces, npieces, 1, sizeof(*pieces), 7);
351 pieces[npieces++] = s;
352 while (*s && *s != ' ' && *s != '\t')
359 pool_debug(pool, SOLV_ERROR, "str2job: bad line '%s'\n", str);
363 for (i = 0; job2str[i].str; i++)
364 if (!strcmp(pieces[0], job2str[i].str))
368 pool_debug(pool, SOLV_ERROR, "str2job: unknown job '%s'\n", str);
371 job = job2str[i].job;
374 char *flags = pieces[npieces - 1];
376 if (*flags == '[' && flags[strlen(flags) - 1] == ']')
380 flags[strlen(flags) - 1] = ',';
383 for (nf = flags; *nf != ','; nf++)
386 for (i = 0; jobflags2str[i].str; i++)
387 if (!strcmp(flags, jobflags2str[i].str))
389 if (!jobflags2str[i].str)
391 pool_debug(pool, SOLV_ERROR, "str2job: unknown jobflags in '%s'\n", str);
394 job |= jobflags2str[i].flags;
399 if (!strcmp(pieces[1], "pkg"))
403 pool_debug(pool, SOLV_ERROR, "str2job: bad pkg selector in '%s'\n", str);
406 job |= SOLVER_SOLVABLE;
407 what = testcase_str2solvid(pool, pieces[2]);
410 pool_debug(pool, SOLV_ERROR, "str2job: unknown package '%s'\n", pieces[2]);
414 else if (!strcmp(pieces[1], "name") || !strcmp(pieces[1], "provides"))
416 /* join em again for dep2str... */
418 for (sp = pieces[2]; sp < pieces[npieces - 1]; sp++)
421 what = testcase_str2dep(pool, pieces[2]);
422 if (pieces[1][0] == 'n')
423 job |= SOLVER_SOLVABLE_NAME;
425 job |= SOLVER_SOLVABLE_PROVIDES;
427 else if (!strcmp(pieces[1], "oneof"))
430 job |= SOLVER_SOLVABLE_ONE_OF;
432 if (npieces > 3 && strcmp(pieces[2], "nothing") != 0)
434 for (i = 2; i < npieces; i++)
436 Id p = testcase_str2solvid(pool, pieces[i]);
439 pool_debug(pool, SOLV_ERROR, "str2job: unknown package '%s'\n", pieces[i]);
446 what = pool_queuetowhatprovides(pool, &q);
449 else if (!strcmp(pieces[1], "repo"))
454 pool_debug(pool, SOLV_ERROR, "str2job: bad line '%s'\n", str);
457 repo = testcase_str2repo(pool, pieces[2]);
460 pool_debug(pool, SOLV_ERROR, "str2job: unknown repo '%s'\n", pieces[2]);
463 job |= SOLVER_SOLVABLE_REPO;
466 else if (!strcmp(pieces[1], "all"))
468 if (npieces != 3 && strcmp(pieces[2], "packages") != 0)
470 pool_debug(pool, SOLV_ERROR, "str2job: bad line '%s'\n", str);
473 job |= SOLVER_SOLVABLE_ALL;
478 pool_debug(pool, SOLV_ERROR, "str2job: unknown selection in '%s'\n", str);
486 writedeps(Repo *repo, FILE *fp, const char *tag, Id key, Solvable *s, Offset off)
488 Pool *pool = repo->pool;
495 dp = repo->idarraydata + off;
496 while ((id = *dp++) != 0)
498 if (key == SOLVABLE_REQUIRES && id == SOLVABLE_PREREQMARKER)
501 fprintf(fp, "-%s\n", tag);
506 if (key == SOLVABLE_PROVIDES && id == SOLVABLE_FILEMARKER)
508 idstr = pool_dep2str(pool, id);
511 Reldep *rd = GETRELDEP(pool, id);
512 if (key == SOLVABLE_CONFLICTS && rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_OTHERPROVIDERS)
514 if (!strncmp(idstr, "namespace:", 10))
517 if (key == SOLVABLE_SUPPLEMENTS)
519 if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_FILESYSTEM)
521 if (!strncmp(idstr, "namespace:", 10))
524 else if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_MODALIAS)
526 if (!strncmp(idstr, "namespace:", 10))
529 else if (rd->flags == REL_AND)
531 /* either packageand chain or modalias */
533 if (ISRELDEP(rd->evr))
535 Reldep *mrd = GETRELDEP(pool, rd->evr);
536 if (mrd->flags == REL_NAMESPACE && mrd->name == NAMESPACE_MODALIAS)
538 idstr = pool_tmpjoin(pool, "modalias(", pool_dep2str(pool, rd->name), ":");
539 idstr = pool_tmpappend(pool, idstr, pool_dep2str(pool, mrd->evr), ")");
541 else if (mrd->flags >= 8)
546 /* must be and chain */
547 idstr = pool_dep2str(pool, rd->evr);
553 rd = GETRELDEP(pool, id);
554 if (rd->flags != REL_AND)
556 idstr = pool_tmpjoin(pool, pool_dep2str(pool, rd->evr), ":", idstr);
558 idstr = pool_tmpjoin(pool, pool_dep2str(pool, id), ":", idstr);
559 idstr = pool_tmpjoin(pool, "packageand(", idstr, ")");
562 else if (rd->flags >= 8)
568 fprintf(fp, "+%s\n", tag);
571 fprintf(fp, "%s\n", idstr);
573 if (key == SOLVABLE_PROVIDES)
575 /* add the filelist */
577 dataiterator_init(&di, pool, repo, s - pool->solvables, SOLVABLE_FILELIST, 0, 0);
578 while (dataiterator_step(&di))
582 fprintf(fp, "+%s", tag);
585 fprintf(fp, "%s\n", repodata_dir2str(di.data, di.kv.id, di.kv.str));
589 fprintf(fp, "-%s\n", tag);
593 testcase_write_susetags(Repo *repo, FILE *fp)
595 Pool *pool = repo->pool;
605 unsigned int medianr;
610 fprintf(fp, "=Ver: 2.0\n");
611 FOR_REPO_SOLVABLES(repo, p, s)
613 name = pool_id2str(pool, s->name);
614 evr = pool_id2str(pool, s->evr);
615 arch = pool_id2str(pool, s->arch);
616 release = strrchr(evr, '-');
618 release = evr + strlen(evr);
619 fprintf(fp, "=Pkg: %s %.*s %s %s\n", name, release - evr, evr, *release && release[1] ? release + 1 : "0", arch);
620 tmp = solvable_lookup_str(s, SOLVABLE_SUMMARY);
622 fprintf(fp, "=Sum: %s\n", tmp);
624 chksum = solvable_lookup_checksum(s, SOLVABLE_CHECKSUM, &chksumtype);
626 fprintf(fp, "=Cks: %s %s\n", solv_chksum_type2str(chksumtype), chksum);
628 writedeps(repo, fp, "Req:", SOLVABLE_REQUIRES, s, s->requires);
629 writedeps(repo, fp, "Prv:", SOLVABLE_PROVIDES, s, s->provides);
630 writedeps(repo, fp, "Obs:", SOLVABLE_OBSOLETES, s, s->obsoletes);
631 writedeps(repo, fp, "Con:", SOLVABLE_CONFLICTS, s, s->conflicts);
632 writedeps(repo, fp, "Rec:", SOLVABLE_RECOMMENDS, s, s->recommends);
633 writedeps(repo, fp, "Sup:", SOLVABLE_SUPPLEMENTS, s, s->supplements);
634 writedeps(repo, fp, "Sug:", SOLVABLE_SUGGESTS, s, s->suggests);
635 writedeps(repo, fp, "Enh:", SOLVABLE_ENHANCES, s, s->enhances);
637 tmp = solvable_lookup_str(s, SOLVABLE_GROUP);
639 fprintf(fp, "=Grp: %s\n", tmp);
640 tmp = solvable_lookup_str(s, SOLVABLE_LICENSE);
642 fprintf(fp, "=Lic: %s\n", tmp);
645 fprintf(fp, "=Vnd: %s\n", pool_id2str(pool, s->vendor));
647 type = solvable_lookup_type(s, SOLVABLE_SOURCENAME);
650 if (type != REPOKEY_TYPE_VOID)
651 name = solvable_lookup_str(s, SOLVABLE_SOURCENAME);
652 type = solvable_lookup_type(s, SOLVABLE_SOURCEEVR);
655 if (type != REPOKEY_TYPE_VOID)
656 evr = solvable_lookup_str(s, SOLVABLE_SOURCEEVR);
657 release = strrchr(evr, '-');
659 release = evr + strlen(evr);
660 fprintf(fp, "=Src: %s %.*s %s %s\n", name, release - evr, evr, *release && release[1] ? release + 1 : "0", solvable_lookup_str(s, SOLVABLE_SOURCEARCH));
664 ti = solvable_lookup_num(s, SOLVABLE_BUILDTIME, 0);
666 fprintf(fp, "=Tim: %u\n", ti);
668 tmp = solvable_get_location(s, &medianr);
671 const char *base = strrchr(tmp, '/');
673 fprintf(fp, "=Loc: %d %s\n", medianr, tmp);
674 else if (strlen(arch) == base - tmp && !strncmp(tmp, arch, base - tmp))
675 fprintf(fp, "=Loc: %d %s\n", medianr, base + 1);
677 fprintf(fp, "=Loc: %d %s %.*s\n", medianr, base + 1, base - tmp, tmp);