]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
add parser for rpm rich deps
authorMichael Schroeder <mls@suse.de>
Wed, 14 Jan 2015 12:07:58 +0000 (13:07 +0100)
committerMichael Schroeder <mls@suse.de>
Wed, 14 Jan 2015 12:07:58 +0000 (13:07 +0100)
This is work in progress, the rpm format may still change. Also,
THEN/ELSE ops are not yet supported.

ext/CMakeLists.txt
ext/pool_parserpmrichdep.c [new file with mode: 0644]
ext/pool_parserpmrichdep.h [new file with mode: 0644]
ext/repo_rpmdb.c
ext/repo_rpmmd.c
ext/repo_susetags.c

index 5f017f2ac602d6fa022d723ed89ae7de3efbbf14..bdf949d51189de096755085d71647bbdd271bc06 100644 (file)
@@ -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 (file)
index 0000000..742823a
--- /dev/null
@@ -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 <stdio.h>
+
+#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 (file)
index 0000000..09dce2c
--- /dev/null
@@ -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
index b4541c39910a7f7a3d361b0528ac5afa1dd4fbbd..5627d4d8b83f683697c9245a9863ae5be8c31bd2 100644 (file)
@@ -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 */
 #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;
index 21dd9130768e775adf6661ac25b1f732e66b4a85..4272b6f15718897ce980ac86ddcc269443fc7554 100644 (file)
@@ -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
index 440e2d51deb16166ff78e5076e26d0b0cdf1a083..a96ba974c77bec5e1cfca23212fb75c845162026 100644 (file)
@@ -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, <op>, evr, ? */