support splitting of cross-kind dependencies for patterns
authorKlaus Kaempf <kkaempf@suse.de>
Fri, 15 Feb 2008 16:07:21 +0000 (16:07 +0000)
committerKlaus Kaempf <kkaempf@suse.de>
Fri, 15 Feb 2008 16:07:21 +0000 (16:07 +0000)
(experimental, disabled by default)

This prepares for handling all the 'kind' stuff in the application
layer. Parsing repos and creating .solv files _is_ part of the
application layer.

tools/repo_susetags.c
tools/repo_susetags.h
tools/susetags2solv.c
tools/tools_util.h

index 1f9b8be..5b29b71 100644 (file)
@@ -52,8 +52,8 @@ adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, char *line, Id ma
   Id id, evrid;
   char *sp[4];
 
-  i = split(line + 5, sp, 4); /* name, ?, evr, ? */
-  if (i != 1 && i != 3) /* expect either 'name' or 'name' '-' 'evr' */
+  i = split(line + 5, sp, 4); /* name, <op>, evr, ? */
+  if (i != 1 && i != 3) /* expect either 'name' or 'name' <op> 'evr' */
     {
       fprintf(stderr, "Bad dependency line: %s\n", line);
       exit(1);
@@ -78,6 +78,7 @@ adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, char *line, Id ma
   return repo_addid_dep(pd->repo, olddeps, id, marker);
 }
 
+
 /*
  * add_location
  * 
@@ -365,10 +366,27 @@ tag_from_string (char *cs)
  * repo_add_susetags
  * Parse susetags file passed in fp, fill solvables into repo
  * 
+ * susetags is key,value based
+ *  for short values
+ *    =key: value
+ *  is used
+ *  for long (multi-line) values,
+ *    +key:
+ *    value
+ *    value
+ *    -key:
+ *  is used
+ *
+ * See http://en.opensuse.org/Standards/YaST2_Repository_Metadata
+ * and http://en.opensuse.org/Standards/YaST2_Repository_Metadata/packages
+ * and http://en.opensuse.org/Standards/YaST2_Repository_Metadata/pattern
+ * 
+ * Assumptions:
+ *   All keys have 3 characters and end in ':'
  */
 
 void
-repo_add_susetags(Repo *repo, FILE *fp, Id vendor)
+repo_add_susetags(Repo *repo, FILE *fp, Id vendor, int flags)
 {
   Pool *pool = repo->pool;
   char *line, *linep;
@@ -396,31 +414,44 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor)
   linep = line;
   s = 0;
 
+  /*
+   * read complete file
+   * 
+   * collect values in 'struct parsedata pd'
+   * then build .solv (and .attr) file
+   */
+  
   for (;;)
     {
       unsigned tag;
-      if (linep - line + 16 > aline)
+      if (linep - line + 16 > aline)              /* (re-)alloc buffer */
        {
          aline = linep - line;
          line = realloc(line, aline + 512);
          linep = line + aline;
          aline += 512;
        }
-      if (!fgets(linep, aline - (linep - line), fp))
+      if (!fgets(linep, aline - (linep - line), fp)) /* read line */
        break;
       linep += strlen(linep);
       if (linep == line || linep[-1] != '\n')
         continue;
       *--linep = 0;
+      
       if (intag)
        {
-         int isend = linep[-intag - 2] == '-' && linep[-1] == ':' && !strncmp(linep - 1 - intag, line + 1, intag) && (linep == line + 1 + intag + 1 + 1 + 1 + intag + 1 || linep[-intag - 3] == '\n');
-         if (cummulate && !isend)
+         /* check for multi-line value tags (+Key:/-Key:) */
+         
+         int is_end = (linep[-intag - 2] == '-')
+                     && (linep[-1] == ':')
+                     && !strncmp(linep - 1 - intag, line + 1, intag)
+                     && (linep == line + 1 + intag + 1 + 1 + 1 + intag + 1 || linep[-intag - 3] == '\n');
+         if (cummulate && !is_end)
            {
              *linep++ = '\n';
              continue;
            }
-         if (cummulate && isend)
+         if (cummulate && is_end)
            {
              linep[-intag - 2] = 0;
              if (linep[-intag - 3] == '\n')
@@ -428,18 +459,19 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor)
              linep = line;
              intag = 0;
            }
-         if (!cummulate && isend)
+         if (!cummulate && is_end)
            {
              intag = 0;
              linep = line;
              continue;
            }
-         if (!cummulate && !isend)
+         if (!cummulate && !is_end)
            linep = line + intag + 3;
        }
       else
        linep = line;
-      if (!intag && line[0] == '+' && line[1] && line[1] != ':')
+
+      if (!intag && line[0] == '+' && line[1] && line[1] != ':') /* start of +Key:/-Key: tag */
        {
          char *tagend = strchr(line, ':');
          if (!tagend)
@@ -449,8 +481,13 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor)
            }
          intag = tagend - (line + 1);
          cummulate = 0;
-         switch (tag_from_string (line))
+         switch (tag_from_string (line))       /* check if accumulation is needed */
            {
+             case CTAG('+', 'P', 'r', 'q'):
+             case CTAG('+', 'P', 'r', 'c'):
+             case CTAG('+', 'P', 's', 'g'):
+               if (!pd.kind || !(flags & SUSETAGS_KINDS_SEPARATELY))
+                 break;
              case CTAG('+', 'D', 'e', 's'):
              case CTAG('+', 'E', 'u', 'l'):
              case CTAG('+', 'I', 'n', 's'):
@@ -459,7 +496,7 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor)
                if (line[4] == ':')
                  cummulate = 1;
            }
-         line[0] = '=';
+         line[0] = '=';                       /* handle lines between +Key:/-Key: as =Key: */
          line[intag + 2] = ' ';
          linep = line + intag + 3;
          continue;
@@ -471,6 +508,13 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor)
       tag = tag_from_string (line);
 
 
+      /*
+       * start of (next) package or pattern
+       *
+       * =Pkg: <name> <version> <release> <architecture>
+       * (=Pat: ...)
+       */
+      
       if ((tag == CTAG('=', 'P', 'k', 'g')
           || tag == CTAG('=', 'P', 'a', 't')))
        {
@@ -492,9 +536,18 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor)
                commit_diskusage (&pd, last_found_pack);
            }
 
+         /*
+          * define kind
+          */
+         
          pd.kind = 0;
          if (line[3] == 't')
            pd.kind = "pattern";
+
+         /*
+          * parse nevra
+          */
+         
           if (split(line + 5, sp, 5) != 4)
            {
              fprintf(stderr, "Bad line: %s\n", line);
@@ -567,46 +620,86 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor)
        }
       switch (tag)
         {
-         case CTAG('=', 'P', 'r', 'v'):
+         case CTAG('=', 'P', 'r', 'v'):                                        /* provides */
            s->provides = adddep(pool, &pd, s->provides, line, 0, pd.kind);
            continue;
-          case CTAG('=', 'R', 'e', 'q'):
+         case CTAG('=', 'R', 'e', 'q'):                                        /* requires */
            s->requires = adddep(pool, &pd, s->requires, line, -SOLVABLE_PREREQMARKER, pd.kind);
            continue;
-          case CTAG('=', 'P', 'r', 'q'):
-           if (pd.kind)
-             s->requires = adddep(pool, &pd, s->requires, line, 0, 0); /* Huh? No PreReq for non-packages ? */
+          case CTAG('=', 'P', 'r', 'q'):                                        /* pre-requires / packages required */
+           if (pd.kind) {
+             if (flags & SUSETAGS_KINDS_SEPARATELY)
+               repodata_set_poolstr(data, last_found_pack, id_must, line + 6);
+             else
+               s->requires = adddep(pool, &pd, s->requires, line, 0, 0);           /* patterns: a required package */
+           }
            else
-             s->requires = adddep(pool, &pd, s->requires, line, SOLVABLE_PREREQMARKER, 0);
+             s->requires = adddep(pool, &pd, s->requires, line, SOLVABLE_PREREQMARKER, 0); /* package: pre-requires */
            continue;
-         case CTAG('=', 'O', 'b', 's'):
+         case CTAG('=', 'O', 'b', 's'):                                        /* obsoletes */
            s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, pd.kind);
            continue;
-          case CTAG('=', 'C', 'o', 'n'):
+          case CTAG('=', 'C', 'o', 'n'):                                        /* conflicts */
            s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, pd.kind);
            continue;
-          case CTAG('=', 'R', 'e', 'c'):
+          case CTAG('=', 'R', 'e', 'c'):                                        /* recommends */
            s->recommends = adddep(pool, &pd, s->recommends, line, 0, pd.kind);
            continue;
-          case CTAG('=', 'S', 'u', 'p'):
+          case CTAG('=', 'S', 'u', 'p'):                                        /* supplements */
            s->supplements = adddep(pool, &pd, s->supplements, line, 0, pd.kind);
            continue;
-          case CTAG('=', 'E', 'n', 'h'):
+          case CTAG('=', 'E', 'n', 'h'):                                        /* enhances */
            s->enhances = adddep(pool, &pd, s->enhances, line, 0, pd.kind);
            continue;
-          case CTAG('=', 'S', 'u', 'g'):
+          case CTAG('=', 'S', 'u', 'g'):                                        /* suggests */
            s->suggests = adddep(pool, &pd, s->suggests, line, 0, pd.kind);
            continue;
-          case CTAG('=', 'F', 'r', 'e'):
+          case CTAG('=', 'F', 'r', 'e'):                                        /* freshens */
            s->freshens = adddep(pool, &pd, s->freshens, line, 0, pd.kind);
            continue;
-          case CTAG('=', 'P', 'r', 'c'):
-           s->recommends = adddep(pool, &pd, s->recommends, line, 0, 0);
+          case CTAG('=', 'P', 'r', 'c'):                                        /* packages recommended */
+           if (flags & SUSETAGS_KINDS_SEPARATELY)
+             repodata_set_poolstr(data, last_found_pack, id_should, line + 6);
+           else
+             s->recommends = adddep(pool, &pd, s->recommends, line, 0, 0);
+           continue;
+          case CTAG('=', 'P', 's', 'g'):                                        /* packages suggested */
+           if (flags & SUSETAGS_KINDS_SEPARATELY)
+             repodata_set_poolstr(data, last_found_pack, id_may, line + 6);
+           else
+             s->suggests = adddep(pool, &pd, s->suggests, line, 0, 0);
+           continue;
+          case CTAG('=', 'P', 'c', 'n'):                                        /* pattern: package conflicts */
+           if (flags & SUSETAGS_KINDS_SEPARATELY)
+             fprintf (stderr, "Unsupported: pattern -> package conflicts\n");
+           else
+             s->conflicts = adddep(pool, &pd, s->conflicts, line, 0, 0);
+           continue;
+         case CTAG('=', 'P', 'o', 'b'):                                        /* pattern: package obsoletes */
+           if (flags & SUSETAGS_KINDS_SEPARATELY)
+             fprintf (stderr, "Unsupported: pattern -> package obsoletes\n");
+           else
+             s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, 0);
+           continue;
+          case CTAG('=', 'P', 'f', 'r'):                                        /* pattern: package freshens */
+           if (flags & SUSETAGS_KINDS_SEPARATELY)
+             fprintf (stderr, "Unsupported: pattern -> package freshens\n");
+           else
+             s->freshens = adddep(pool, &pd, s->freshens, line, 0, 0);
+           continue;
+          case CTAG('=', 'P', 's', 'p'):                                        /* pattern: package supplements */
+           if (flags & SUSETAGS_KINDS_SEPARATELY)
+             fprintf (stderr, "Unsupported: pattern -> package supplements\n");
+           else
+             s->supplements = adddep(pool, &pd, s->supplements, line, 0, 0);
            continue;
-          case CTAG('=', 'P', 's', 'g'):
-           s->suggests = adddep(pool, &pd, s->suggests, line, 0, 0);
+          case CTAG('=', 'P', 'e', 'n'):                                        /* pattern: package enhances */
+           if (flags & SUSETAGS_KINDS_SEPARATELY)
+             fprintf (stderr, "Unsupported: pattern -> package enhances\n");
+           else
+             s->enhances = adddep(pool, &pd, s->enhances, line, 0, 0);
            continue;
-          case CTAG('=', 'V', 'e', 'r'):
+          case CTAG('=', 'V', 'e', 'r'):                                        /* - version - */
            last_found_pack = 0;
            indesc++;
            continue;
@@ -689,10 +782,17 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor)
          case CTAG('=', 'D', 'i', 'r'):
            add_dirline (&pd, line + 6);
            continue;
+
+         default:
+           break;
        }
-    }
+
+    } /* for(;;) */
+
+  /* add versioned 'self-provides' */
   if (s && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
     s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
+
   if (s)
     s->supplements = repo_fix_legacy(repo, s->provides, s->supplements);
 
@@ -713,6 +813,9 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor)
     }
 #endif
 
+  /* Shared attributes
+   *  (e.g. multiple binaries built from same source)
+   */
   if (pd.nshare)
     {
       int i, last_found;
index 432ca8f..4c6c8d4 100644 (file)
@@ -9,4 +9,6 @@
  * if <attrname> given, write attributes as '<attrname>.attr'
  */
 
-extern void repo_add_susetags(Repo *repo, FILE *fp, Id vendor);
+#define SUSETAGS_KINDS_SEPARATELY 1
+
+extern void repo_add_susetags(Repo *repo, FILE *fp, Id vendor, int flags);
index 434687f..226c325 100644 (file)
@@ -27,8 +27,9 @@ usage(const char *err)
           "susetags2solv [-a][-s][-c <content>][-h]\n"
          "  reads a 'susetags' repository from <stdin> and writes a .solv file to <stdout>\n"
          "  -a : with attributes\n"
-         "  -c <contenfile> : parse given contentfile (for product information)\n"
+         "  -c <contentfile> : parse given contentfile (for product information)\n"
          "  -h : print help & exit\n"
+         "  -k : don't mix kinds (experimental!)\n"
          "  -n <name>: save attributes as <name>.attr\n"
         );
    exit(0);
@@ -40,6 +41,7 @@ main(int argc, char **argv)
   const char *contentfile = 0;
   const char *attrname = 0;
   Id vendor = 0;
+  int flags = 0;
   argv++;
   argc--;
   while (argc--)
@@ -70,6 +72,9 @@ main(int argc, char **argv)
                else
                  usage("argument required for '-c'");
                break;
+             case 'k':
+               flags |= SUSETAGS_KINDS_SEPARATELY;
+             break;
              default : break;
            }
       argv++;
@@ -102,7 +107,7 @@ main(int argc, char **argv)
        attrname = newname;
       }
     }
-  repo_add_susetags(repo, stdin, vendor);
+  repo_add_susetags(repo, stdin, vendor, flags);
   tool_write(repo, 0, attrname);
   pool_free(pool);
   exit(0);
index cbd8ba4..7689b71 100644 (file)
@@ -134,7 +134,9 @@ join2(const char *s1, const char *s2, const char *s3)
 //   return pd->tmp;
 // }
 
-// packages
+/* key Ids */
+
+/* packages */
 static Id id_authors;
 static Id id_description;
 static Id id_diskusage;
@@ -165,6 +167,11 @@ static Id id_installonly;
 
 static Id id_isvisible;
 
+/* experimental */
+static Id id_must;
+static Id id_should;
+static Id id_may;
+
 static void init_attr_ids(Pool *pool)
 {
   id_size = str2id(pool, "size", 1);;
@@ -195,6 +202,11 @@ static void init_attr_ids(Pool *pool)
   id_time = str2id(pool, "time", 1);
 
   id_isvisible = str2id(pool, "isvisible", 1);
+
+  id_must = str2id(pool, "must", 1);
+  id_should = str2id(pool, "should", 1);
+  id_may = str2id(pool, "may", 1);
+
 }
 
 /* util function to set a translated string */
@@ -205,5 +217,4 @@ void repodata_set_tstr(Repodata *data, Id rid, const char *attrname, const char
   repodata_set_str(data, rid, attrid, str);
 }
 
-#endif
-
+#endif /* SATSOLVER_TOOLS_UTIL_H */