From: Michael Schroeder Date: Wed, 14 Jan 2015 12:07:58 +0000 (+0100) Subject: add parser for rpm rich deps X-Git-Tag: 0.6.9~23 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=434eaa3a26fe498cc2a7aab319c1c2d9df395a44;p=thirdparty%2Flibsolv.git add parser for rpm rich deps This is work in progress, the rpm format may still change. Also, THEN/ELSE ops are not yet supported. --- diff --git a/ext/CMakeLists.txt b/ext/CMakeLists.txt index 5f017f2a..bdf949d5 100644 --- a/ext/CMakeLists.txt +++ b/ext/CMakeLists.txt @@ -43,6 +43,11 @@ IF (ENABLE_SUSEREPO) repo_susetags.h repo_zyppdb.h) ENDIF (ENABLE_SUSEREPO) +IF (ENABLE_COMPLEX_DEPS AND (ENABLE_SUSEREPO OR ENABLE_RPMMD OR ENABLE_RPMDB)) + SET (libsolvext_SRCS ${libsolvext_SRCS} + pool_parserpmrichdep.c) +ENDIF (ENABLE_COMPLEX_DEPS AND (ENABLE_SUSEREPO OR ENABLE_RPMMD OR ENABLE_RPMDB)) + IF (SUSE) SET (libsolvext_SRCS ${libsolvext_SRCS} repo_autopattern.c) diff --git a/ext/pool_parserpmrichdep.c b/ext/pool_parserpmrichdep.c new file mode 100644 index 00000000..742823a9 --- /dev/null +++ b/ext/pool_parserpmrichdep.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2015, SUSE Inc. + * + * This program is licensed under the BSD license, read LICENSE.BSD + * for further information + */ + +/* this is used by repo_rpmmd, repo_rpmdb, and repo_susetags */ + +#include + +#include "pool.h" +#include "pool_parserpmrichdep.h" + +#define REL_THEN 0 +#define REL_ELSE 0 + +static struct RichOpComp { + const char *n; + int l; + Id fl; +} RichOps[] = { + { "&&", 2, REL_AND }, + { "&", 1, REL_AND }, + { "AND", 3, REL_AND }, + { "||", 2, REL_OR }, + { "|", 1, REL_OR }, + { "OR", 2, REL_OR }, + { "IF", 2, REL_COND }, + { "THEN", 4, REL_THEN }, + { "?", 1, REL_THEN }, + { "ELSE", 4, REL_ELSE }, + { ":", 1, REL_ELSE }, + { NULL, 0, 0}, +}; + +static Id +parseRichDep(Pool *pool, const char **depp, Id chainfl) +{ + const char *p = *depp; + const char *n; + Id id, evr; + int fl, bl; + struct RichOpComp *op; + + if (!chainfl && *p++ != '(') + return 0; + while (*p == ' ') + p++; + if (*p == ')') + return 0; + if (*p == '(') + { + id = parseRichDep(pool, &p, 0); + if (!id) + return 0; + } + else + { + n = p; + bl = 0; + while (*p && !(*p == ' ' || *p == ',' || (*p == ')' && bl-- <= 0))) + if (*p++ == '(') + bl++; + if (n == p) + return 0; + id = pool_strn2id(pool, n, p - n, 1); + while (*p == ' ') + p++; + if (*p) + { + fl = 0; + for (;; p++) + { + if (*p == '<') + fl |= REL_LT; + else if (*p == '=') + fl |= REL_EQ; + else if (*p == '>') + fl |= REL_GT; + else + break; + } + if (fl) + { + while (*p == ' ') + p++; + n = p; + bl = 0; + while (*p && !(*p == ' ' || *p == ',' || (*p == ')' && bl-- <= 0))) + if (*p++ == '(') + bl++; + if (p - n > 2 && n[0] == '0' && n[1] == ':') + n += 2; /* strip zero epoch */ + if (n == p) + return 0; + id = pool_rel2id(pool, id, pool_strn2id(pool, n, p - n, 1), fl, 1); + } + } + } + while (*p == ' ') + p++; + if (!*p) + return 0; + if (*p == ')') + { + *depp = p + 1; + return id; + } + n = p; + while (*p && *p != ' ') + p++; + for (op = RichOps; op->n; op++) + if (p - n == op->l && !strncmp(n, op->n, op->l)) + break; + fl = op->fl; + if (!fl) + return 0; + if (chainfl == REL_THEN && fl == REL_ELSE) + chainfl = 0; + if (chainfl && fl != chainfl) + return 0; + evr = parseRichDep(pool, &p, fl); + if (!evr) + return 0; + *depp = p; + return pool_rel2id(pool, id, evr, fl, 1); +} + +Id +pool_parserpmrichdep(Pool *pool, const char *dep) +{ + Id id = parseRichDep(pool, &dep, 0); + if (id && *dep) + id = 0; + return id; +} + diff --git a/ext/pool_parserpmrichdep.h b/ext/pool_parserpmrichdep.h new file mode 100644 index 00000000..09dce2c9 --- /dev/null +++ b/ext/pool_parserpmrichdep.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2014, SUSE Inc. + * + * This program is licensed under the BSD license, read LICENSE.BSD + * for further information + */ + +#ifndef POOL_PARSERPMRICHDEP_H +#define POOL_PARSERPMRICHDEP_H + +#include "pool.h" + +extern Id pool_parserpmrichdep(Pool *pool, const char *dep); + +#endif diff --git a/ext/repo_rpmdb.c b/ext/repo_rpmdb.c index b4541c39..5627d4d8 100644 --- a/ext/repo_rpmdb.c +++ b/ext/repo_rpmdb.c @@ -47,6 +47,9 @@ #include "chksum.h" #include "repo_rpmdb.h" #include "repo_solv.h" +#ifdef ENABLE_COMPLEX_DEPS +#include "pool_parserpmrichdep.h" +#endif /* 3: added triggers */ /* 4: fixed triggers */ @@ -147,6 +150,7 @@ #define DEP_STRONG (1 << 27) #define DEP_PRE_IN ((1 << 6) | (1 << 9) | (1 << 10)) #define DEP_PRE_UN ((1 << 6) | (1 << 11) | (1 << 12)) +#define DEP_RICH (1 << 29) #define FILEFLAG_GHOST (1 << 6) @@ -404,7 +408,6 @@ setutf8string(Repodata *repodata, Id handle, Id tag, const char *str) repodata_set_str(repodata, handle, tag, str); } - /* * strong: 0: ignore strongness * 1: filter to strong @@ -512,6 +515,7 @@ makedeps(Pool *pool, Repo *repo, RpmHead *rpmhead, int tagn, int tagv, int tagf, ida = repo->idarraydata + olddeps; for (i = 0; ; i++) { + Id id; if (i == nc) { if (haspre != 1) @@ -532,9 +536,21 @@ makedeps(Pool *pool, Repo *repo, RpmHead *rpmhead, int tagn, int tagv, int tagf, if ((flags & RPM_ADD_NO_RPMLIBREQS) != 0) if (!strncmp(n[i], "rpmlib(", 7)) continue; +#ifdef ENABLE_COMPLEX_DEPS + if ((flags & (DEP_RICH | DEP_LESS | DEP_EQUAL | DEP_GREATER)) == DEP_RICH && n[i][0] == '(') + { + id = pool_parserpmrichdep(pool, n[i]); + if (id) + *ida++ = id; + else + cc--; + continue; + } +#endif + id = pool_str2id(pool, n[i], 1); if (f[i] & (DEP_LESS|DEP_GREATER|DEP_EQUAL)) { - Id name, evr; + Id evr; int fl = 0; if ((f[i] & DEP_LESS) != 0) fl |= REL_LT; @@ -542,15 +558,13 @@ makedeps(Pool *pool, Repo *repo, RpmHead *rpmhead, int tagn, int tagv, int tagf, fl |= REL_EQ; if ((f[i] & DEP_GREATER) != 0) fl |= REL_GT; - name = pool_str2id(pool, n[i], 1); if (v[i][0] == '0' && v[i][1] == ':' && v[i][2]) evr = pool_str2id(pool, v[i] + 2, 1); else evr = pool_str2id(pool, v[i], 1); - *ida++ = pool_rel2id(pool, name, evr, fl, 1); + id = pool_rel2id(pool, id, evr, fl, 1); } - else - *ida++ = pool_str2id(pool, n[i], 1); + *ida++ = id; } *ida++ = 0; repo->idarraysize += cc + 1; diff --git a/ext/repo_rpmmd.c b/ext/repo_rpmmd.c index 21dd9130..4272b6f1 100644 --- a/ext/repo_rpmmd.c +++ b/ext/repo_rpmmd.c @@ -19,7 +19,9 @@ #include "tools_util.h" #include "repo_rpmmd.h" #include "chksum.h" - +#ifdef ENABLE_COMPLEX_DEPS +#include "pool_parserpmrichdep.h" +#endif enum state { STATE_START, @@ -466,7 +468,7 @@ static char *flagtab[] = { static unsigned int adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, const char **atts, int isreq) { - Id id, name, marker; + Id id, marker; const char *n, *f, *k; const char **a; @@ -496,10 +498,18 @@ adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, const char **atts pd->acontent = l + 256; } sprintf(pd->content, "%s:%s", k, n); - name = pool_str2id(pool, pd->content, 1); + id = pool_str2id(pool, pd->content, 1); + } +#ifdef ENABLE_COMPLEX_DEPS + else if (!f && n[0] == '(') + { + id = pool_parserpmrichdep(pool, n); + if (!id) + return olddeps; } +#endif else - name = pool_str2id(pool, (char *)n, 1); + id = pool_str2id(pool, (char *)n, 1); if (f) { Id evr = makeevr_atts(pool, pd, atts); @@ -508,10 +518,8 @@ adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, const char **atts if (!strcmp(f, flagtab[flags])) break; flags = flags < 6 ? flags + 1 : 0; - id = pool_rel2id(pool, name, evr, flags, 1); + id = pool_rel2id(pool, id, evr, flags, 1); } - else - id = name; #if 0 fprintf(stderr, "new dep %s\n", pool_dep2str(pool, id)); #endif diff --git a/ext/repo_susetags.c b/ext/repo_susetags.c index 440e2d51..a96ba974 100644 --- a/ext/repo_susetags.c +++ b/ext/repo_susetags.c @@ -18,6 +18,9 @@ #include "chksum.h" #include "tools_util.h" #include "repo_susetags.h" +#ifdef ENABLE_COMPLEX_DEPS +#include "pool_parserpmrichdep.h" +#endif struct datashare { Id name; @@ -87,6 +90,17 @@ adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, char *line, Id ma /* A file dependency. Do not try to parse it */ id = pool_str2id(pool, line + 6, 1); } +#ifdef ENABLE_COMPLEX_DEPS + else if (line[6] == '(') + { + id = pool_parserpmrichdep(pool, line + 6); + if (!id) + { + pd->ret = pool_error(pool, -1, "susetags: line %d: bad dependency: '%s'\n", pd->lineno, line); + return olddeps; + } + } +#endif else { i = split(line + 6, sp, 4); /* name, , evr, ? */