Imported Upstream version 0.6.23
[platform/upstream/libsolv.git] / ext / repo_content.c
index b398297..b12c4cd 100644 (file)
@@ -2,6 +2,8 @@
  * repo_content.c
  *
  * Parses 'content' file into .solv
+ * A 'content' file is the repomd.xml of the susetags format
+ *
  * See http://en.opensuse.org/Standards/YaST2_Repository_Metadata/content for a description
  * of the syntax
  *
 #include "pool.h"
 #include "repo.h"
 #include "util.h"
+#include "chksum.h"
 #include "repo_content.h"
 #define DISABLE_SPLIT
+#define DISABLE_JOIN2
 #include "tools_util.h"
 
 /* split off a word, return null terminated pointer to it.
@@ -89,7 +93,7 @@ join(struct parsedata *pd, const char *s1, const char *s2, const char *s3)
   if (l > pd->tmpl)
     {
       pd->tmpl = l + 256;
-      pd->tmp = sat_realloc(pd->tmp, pd->tmpl);
+      pd->tmp = solv_realloc(pd->tmp, pd->tmpl);
     }
   p = pd->tmp;
   if (s1)
@@ -107,6 +111,7 @@ join(struct parsedata *pd, const char *s1, const char *s2, const char *s3)
       strcpy(p, s3);
       p += strlen(s3);
     }
+  *p = 0;
   return pd->tmp;
 }
 
@@ -128,7 +133,7 @@ adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, char *line, Id ma
          dependencies sometimes.  */
       if (!strncmp (name, "package:", 8))
         name += 8;
-      id = str2id(pool, name, 1);
+      id = pool_str2id(pool, name, 1);
       if (*line == '<' || *line == '>' || *line == '=')        /* rel follows */
        {
          char *rel = splitword(&line);
@@ -137,18 +142,18 @@ adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, char *line, Id ma
 
          if (!rel || !evr)
            {
-             pool_debug(pool, SAT_FATAL, "repo_content: bad relation '%s %s'\n", name, rel);
-             exit(1);
+             pool_debug(pool, SOLV_ERROR, "repo_content: bad relation '%s %s'\n", name, rel);
+             continue;
            }
          for (flags = 0; flags < 6; flags++)
            if (!strcmp(rel, flagtab[flags]))
              break;
          if (flags == 6)
            {
-             pool_debug(pool, SAT_FATAL, "repo_content: unknown relation '%s'\n", rel);
-             exit(1);
+             pool_debug(pool, SOLV_ERROR, "repo_content: unknown relation '%s'\n", rel);
+             continue;
            }
-         id = rel2id(pool, id, str2id(pool, evr, 1), flags + 1, 1);
+         id = pool_rel2id(pool, id, pool_str2id(pool, evr, 1), flags + 1, 1);
        }
       olddeps = repo_addid_dep(pd->repo, olddeps, id, marker);
     }
@@ -192,7 +197,7 @@ add_multiple_urls(Repodata *data, Id handle, char *value, Id type)
  *
  */
 
-void
+int
 repo_add_content(Repo *repo, FILE *fp, int flags)
 {
   Pool *pool = repo->pool;
@@ -205,8 +210,10 @@ repo_add_content(Repo *repo, FILE *fp, int flags)
   int contentstyle = 0;
   char *descrdir = 0;
   char *datadir = 0;
+  char *defvendor = 0;
 
   int i = 0;
+  int res = 0;
 
   /* architectures
      we use the first architecture in BASEARCHS or noarch
@@ -217,25 +224,16 @@ repo_add_content(Repo *repo, FILE *fp, int flags)
   unsigned int numotherarchs = 0;
   Id *otherarchs = 0;
 
-  if (!(flags & REPO_REUSE_REPODATA))
-    data = repo_add_repodata(repo, 0);
-  else
-    data = repo_last_repodata(repo);
-
   memset(&pd, 0, sizeof(pd));
-  line = sat_malloc(1024);
+  line = solv_malloc(1024);
   aline = 1024;
 
-  if (repo->nrepodata)
-    /* use last repodata */
-    data = repo->repodata + repo->nrepodata - 1;
-  else
-    data = repo_add_repodata(repo, 0);
-
   pd.repo = repo;
   linep = line;
   s = 0;
 
+  data = repo_add_repodata(repo, flags);
+
   for (;;)
     {
       char *key, *value;
@@ -244,7 +242,7 @@ repo_add_content(Repo *repo, FILE *fp, int flags)
       if (linep - line + 16 > aline)
        {
          aline = linep - line;
-         line = sat_realloc(line, aline + 512);
+         line = solv_realloc(line, aline + 512);
          linep = line + aline;
          aline += 512;
        }
@@ -272,23 +270,59 @@ repo_add_content(Repo *repo, FILE *fp, int flags)
 #define code10 (contentstyle == 10)
 #define code11 (contentstyle == 11)
 
+
          if (istag ("CONTENTSTYLE"))
            {
+             if (contentstyle)
+               pool_debug(pool, SOLV_ERROR, "repo_content: 'CONTENTSTYLE' must be first line of 'content'\n");
              contentstyle = atoi(value);
              continue;
            }
          if (!contentstyle)
            contentstyle = 10;
 
+         /* repository tags */
+          /* we also replicate some of them into the product solvables
+           * to be backward compatible */
+
+         if (istag ("REPOID"))
+           {
+             repodata_add_poolstr_array(data, SOLVID_META, REPOSITORY_REPOID, value);
+             continue;
+           }
+         if (istag ("REPOKEYWORDS"))
+           {
+             add_multiple_strings(data, SOLVID_META, REPOSITORY_KEYWORDS, value);
+             continue;
+           }
+         if (istag ("DISTRO"))
+           {
+             Id dh = repodata_new_handle(data);
+             char *p;
+             /* like with createrepo --distro */
+             if ((p = strchr(value, ',')) != 0)
+               {
+                 *p++ = 0;
+                 if (*value)
+                   repodata_set_poolstr(data, dh, REPOSITORY_PRODUCT_CPEID, value);
+               }
+             else
+               p = value;
+             if (*p)
+               repodata_set_str(data, dh, REPOSITORY_PRODUCT_LABEL, p);
+             repodata_add_flexarray(data, SOLVID_META, REPOSITORY_DISTROS, dh);
+             continue;
+           }
+
          if (istag ("DESCRDIR"))
            {
              if (descrdir)
                free(descrdir);
              else
-               repo_set_str(repo, SOLVID_META, SUSETAGS_DESCRDIR, value);
+               repodata_set_str(data, SOLVID_META, SUSETAGS_DESCRDIR, value);
              if (s)
-               repo_set_str(repo, s - pool->solvables, SUSETAGS_DESCRDIR, value);
-             descrdir = strdup(value);
+               repodata_set_str(data, s - pool->solvables, SUSETAGS_DESCRDIR, value);
+             descrdir = solv_strdup(value);
              continue;
            }
          if (istag ("DATADIR"))
@@ -296,20 +330,59 @@ repo_add_content(Repo *repo, FILE *fp, int flags)
              if (datadir)
                free(datadir);
              else
-               repo_set_str(repo, SOLVID_META, SUSETAGS_DATADIR, value);
+               repodata_set_str(data, SOLVID_META, SUSETAGS_DATADIR, value);
+             if (s)
+               repodata_set_str(data, s - pool->solvables, SUSETAGS_DATADIR, value);
+             datadir = solv_strdup(value);
+             continue;
+           }
+         if (istag ("VENDOR"))
+           {
+             if (defvendor)
+               free(defvendor);
+             else
+               repodata_set_poolstr(data, SOLVID_META, SUSETAGS_DEFAULTVENDOR, value);
              if (s)
-               repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, value);
-             datadir = strdup(value);
+               s->vendor = pool_str2id(pool, value, 1);
+             defvendor = solv_strdup(value);
              continue;
            }
 
-         /* XXX: add those to SOLVID_META, too */
-         if (istag ("META"))
-           continue;
-         if (istag ("HASH"))
-           continue;
-         if (istag ("KEY"))
-           continue;
+         if (istag ("META") || istag ("HASH") || istag ("KEY"))
+           {
+             char *checksumtype, *checksum;
+             Id fh, type;
+             int l;
+
+             if ((checksumtype = splitword(&value)) == 0)
+               continue;
+             if ((checksum = splitword(&value)) == 0)
+               continue;
+             if (!*value)
+               continue;
+             type = solv_chksum_str2type(checksumtype);
+             if (!type)
+               {
+                 pool_error(pool, -1, "%s: unknown checksum type '%s'", value, checksumtype);
+                 res = 1;
+                 continue;
+               }
+              l = solv_chksum_len(type);
+             if (strlen(checksum) != 2 * l)
+               {
+                 pool_error(pool, -1, "%s: invalid checksum length for %s", value, checksumtype);
+                 res = 1;
+                 continue;
+               }
+             fh = repodata_new_handle(data);
+             repodata_set_poolstr(data, fh, SUSETAGS_FILE_TYPE, key);
+             repodata_set_str(data, fh, SUSETAGS_FILE_NAME, value);
+             repodata_set_checksum(data, fh, SUSETAGS_FILE_CHECKSUM, type, checksum);
+             repodata_add_flexarray(data, SOLVID_META, SUSETAGS_FILE, fh);
+             continue;
+           }
+
+         /* product tags */
 
          if ((code10 && istag ("PRODUCT"))
              || (code11 && istag ("NAME")))
@@ -318,7 +391,7 @@ repo_add_content(Repo *repo, FILE *fp, int flags)
                {
                  /* this solvable was created without seeing a
                     PRODUCT entry, just set the name and continue */
-                 s->name = str2id(pool, join(&pd, "product", ":", value), 1);
+                 s->name = pool_str2id(pool, join(&pd, "product", ":", value), 1);
                  continue;
                }
              if (s)
@@ -326,20 +399,23 @@ repo_add_content(Repo *repo, FILE *fp, int flags)
                  /* finish old solvable */
                  if (!s->arch)
                    s->arch = ARCH_NOARCH;
-                 if (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->evr)
+                   s->evr = ID_EMPTY;
+                 if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
+                   s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
                  if (code10)
-                   s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
+                   repo_rewrite_suse_deps(s, 0);
                }
              /* create new solvable */
              s = pool_id2solvable(pool, repo_add_solvable(repo));
-             repodata_extend(data, s - pool->solvables);
              handle = s - pool->solvables;
-             s->name = str2id(pool, join(&pd, "product", ":", value), 1);
+             s->name = pool_str2id(pool, join(&pd, "product", ":", value), 1);
              if (datadir)
-               repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, datadir);
+               repodata_set_str(data, s - pool->solvables, SUSETAGS_DATADIR, datadir);
              if (descrdir)
-               repo_set_str(repo, s - pool->solvables, SUSETAGS_DESCRDIR, descrdir);
+               repodata_set_str(data, s - pool->solvables, SUSETAGS_DESCRDIR, descrdir);
+             if (defvendor)
+               s->vendor = pool_str2id(pool, defvendor, 1);
              continue;
            }
 
@@ -348,89 +424,81 @@ repo_add_content(Repo *repo, FILE *fp, int flags)
          if (!s)
            {
              s = pool_id2solvable(pool, repo_add_solvable(repo));
-             repodata_extend(data, s - pool->solvables);
              handle = s - pool->solvables;
            }
 
          if (istag ("VERSION"))
-            pd.tmpvers = strdup(value);
+            pd.tmpvers = solv_strdup(value);
           else if (istag ("RELEASE"))
-            pd.tmprel = strdup(value);
+            pd.tmprel = solv_strdup(value);
          else if (code11 && istag ("DISTRIBUTION"))
-           repo_set_str(repo, s - pool->solvables, SOLVABLE_DISTRIBUTION, value);
+           repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_DISTRIBUTION, value);
          else if (istag ("UPDATEURLS"))
-           add_multiple_urls(data, handle, value, str2id(pool, "update", 1));
+           add_multiple_urls(data, handle, value, pool_str2id(pool, "update", 1));
          else if (istag ("EXTRAURLS"))
-           add_multiple_urls(data, handle, value, str2id(pool, "extra", 1));
+           add_multiple_urls(data, handle, value, pool_str2id(pool, "extra", 1));
          else if (istag ("OPTIONALURLS"))
-           add_multiple_urls(data, handle, value, str2id(pool, "optional", 1));
+           add_multiple_urls(data, handle, value, pool_str2id(pool, "optional", 1));
          else if (istag ("RELNOTESURL"))
-           add_multiple_urls(data, handle, value, str2id(pool, "releasenotes", 1));
+           add_multiple_urls(data, handle, value, pool_str2id(pool, "releasenotes", 1));
          else if (istag ("SHORTLABEL"))
-           repo_set_str(repo, s - pool->solvables, PRODUCT_SHORTLABEL, value);
+           repodata_set_str(data, s - pool->solvables, PRODUCT_SHORTLABEL, value);
          else if (istag ("LABEL")) /* LABEL is the products SUMMARY. */
-           repo_set_str(repo, s - pool->solvables, SOLVABLE_SUMMARY, value);
+           repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, value);
          else if (!strncmp (key, "LABEL.", 6))
-           repo_set_str(repo, s - pool->solvables, pool_id2langid(pool, SOLVABLE_SUMMARY, key + 6, 1), value);
+           repodata_set_str(data, s - pool->solvables, pool_id2langid(pool, SOLVABLE_SUMMARY, key + 6, 1), value);
          else if (istag ("FLAGS"))
            add_multiple_strings(data, handle, PRODUCT_FLAGS, value);
-         else if (istag ("VENDOR"))
-           s->vendor = str2id(pool, value, 1);
+         else if (istag ("VENDOR"))    /* actually already handled above */
+           s->vendor = pool_str2id(pool, value, 1);
           else if (istag ("BASEARCHS"))
             {
               char *arch;
 
              if ((arch = splitword(&value)) != 0)
                {
-                 s->arch = str2id(pool, arch, 1);
+                 s->arch = pool_str2id(pool, arch, 1);
                  while ((arch = splitword(&value)) != 0)
                    {
-                      otherarchs = sat_extend(otherarchs, numotherarchs, 1, sizeof(Id), 7);
-                      otherarchs[numotherarchs++] = str2id(pool, arch, 1);
+                      otherarchs = solv_extend(otherarchs, numotherarchs, 1, sizeof(Id), 7);
+                      otherarchs[numotherarchs++] = pool_str2id(pool, arch, 1);
                    }
                }
             }
+         if (!code10)
+           continue;
 
          /*
           * Every tag below is Code10 only
           *
           */
 
-         else if (code10 && istag ("CONTENTSTYLE"))
-           /* CONTENTSTYLE must be first line */
-           pool_debug(pool, SAT_ERROR, "repo_content: 'CONTENTSTYLE' must be first line of 'content'\n");
-         else if (code10 && istag ("DISTPRODUCT"))
-           /* DISTPRODUCT is for registration and Yast, not for the solver. */
-           repo_set_str(repo, s - pool->solvables, PRODUCT_DISTPRODUCT, value);
-         else if (code10 && istag ("DISTVERSION"))
-           /* DISTVERSION is for registration and Yast, not for the solver. */
-           repo_set_str(repo, s - pool->solvables, PRODUCT_DISTVERSION, value);
-         else if (code10 && istag ("ARCH"))
+         if (istag ("ARCH"))
            /* Theoretically we want to have the best arch of the given
               modifiers which still is compatible with the system
               arch.  We don't know the latter here, though.  */
            s->arch = ARCH_NOARCH;
-         else if (code10 && istag ("PREREQUIRES"))
+         else if (istag ("PREREQUIRES"))
            s->requires = adddep(pool, &pd, s->requires, value, SOLVABLE_PREREQMARKER);
-         else if (code10 && istag ("REQUIRES"))
+         else if (istag ("REQUIRES"))
            s->requires = adddep(pool, &pd, s->requires, value, -SOLVABLE_PREREQMARKER);
-         else if (code10 && istag ("PROVIDES"))
+         else if (istag ("PROVIDES"))
            s->provides = adddep(pool, &pd, s->provides, value, 0);
-         else if (code10 && istag ("CONFLICTS"))
+         else if (istag ("CONFLICTS"))
            s->conflicts = adddep(pool, &pd, s->conflicts, value, 0);
-         else if (code10 && istag ("OBSOLETES"))
+         else if (istag ("OBSOLETES"))
            s->obsoletes = adddep(pool, &pd, s->obsoletes, value, 0);
-         else if (code10 && istag ("RECOMMENDS"))
+         else if (istag ("RECOMMENDS"))
            s->recommends = adddep(pool, &pd, s->recommends, value, 0);
-         else if (code10 && istag ("SUGGESTS"))
+         else if (istag ("SUGGESTS"))
            s->suggests = adddep(pool, &pd, s->suggests, value, 0);
-         else if (code10 && istag ("SUPPLEMENTS"))
+         else if (istag ("SUPPLEMENTS"))
            s->supplements = adddep(pool, &pd, s->supplements, value, 0);
-         else if (code10 && istag ("ENHANCES"))
+         else if (istag ("ENHANCES"))
            s->enhances = adddep(pool, &pd, s->enhances, value, 0);
          /* FRESHENS doesn't seem to exist.  */
-         else if (code10 && istag ("TYPE"))
-           repo_set_str(repo, s - pool->solvables, PRODUCT_TYPE, value);
+         else if (istag ("TYPE"))
+           repodata_set_str(data, s - pool->solvables, PRODUCT_TYPE, value);
 
          /* XXX do something about LINGUAS and ARCH?
           * <ma>: Don't think so. zypp does not use or propagate them.
@@ -438,66 +506,63 @@ repo_add_content(Repo *repo, FILE *fp, int flags)
 #undef istag
        }
       else
-       pool_debug(pool, SAT_ERROR, "repo_content: malformed line: %s\n", line);
+       pool_debug(pool, SOLV_ERROR, "repo_content: malformed line: %s\n", line);
     }
 
   if (datadir)
     free(datadir);
   if (descrdir)
     free(descrdir);
+  if (defvendor)
+    free(defvendor);
 
-  if (!s || !s->name)
+  if (s && !s->name)
     {
-      pool_debug(pool, SAT_FATAL, "repo_content: 'content' incomplete, no product solvable created!\n");
-      exit(1);
+      pool_debug(pool, SOLV_ERROR, "repo_content: 'content' incomplete, no product solvable created!\n");
+      repo_free_solvable(repo, s - pool->solvables, 1);
+      s = 0;
     }
-
-  if (pd.tmpvers)
+  if (s)
     {
       if (pd.tmprel)
-        s->evr = makeevr(pool, join2(pd.tmpvers, "-", pd.tmprel));
+       s->evr = makeevr(pool, join(&pd, pd.tmpvers, "-", pd.tmprel));
       else
-        s->evr = makeevr(pool, pd.tmpvers);
-    }
-  else if (pd.tmprel)
-    {
-      s->evr = makeevr(pool, join2("", "-", pd.tmprel));
-    }
-  pd.tmpvers = sat_free((void *)pd.tmpvers);
-  pd.tmprel = sat_free((void *)pd.tmprel);
-
-  if (!s->arch)
-    s->arch = ARCH_NOARCH;
-  if (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);
+       s->evr = makeevr(pool, pd.tmpvers);
+      pd.tmpvers = solv_free((void *)pd.tmpvers);
+      pd.tmprel = solv_free((void *)pd.tmprel);
+
+      if (!s->arch)
+       s->arch = ARCH_NOARCH;
+      if (!s->evr)
+       s->evr = ID_EMPTY;
+      if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
+        s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
       if (code10)
-       s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
-    }
+       repo_rewrite_suse_deps(s, 0);
 
-  /* now for every other arch, clone the product except the architecture */
-  for (i = 0; i < numotherarchs; ++i)
-    {
-      Solvable *p = pool_id2solvable(pool, repo_add_solvable(repo));
-      repodata_extend(data, p - pool->solvables);
-      p->name = s->name;
-      p->evr = s->evr;
-      p->vendor = s->vendor;
-      p->arch = otherarchs[i];
-
-      /* self provides */
-      if (p->arch != ARCH_SRC && p->arch != ARCH_NOSRC)
-          p->provides = repo_addid_dep(repo, p->provides, rel2id(pool, p->name, p->evr, REL_EQ, 1), 0);
-
-      /* now merge the attributes */
-      repodata_merge_attrs(data, p - pool->solvables, s - pool->solvables);
+      /* now for every other arch, clone the product except the architecture */
+      for (i = 0; i < numotherarchs; ++i)
+       {
+         Solvable *p = pool_id2solvable(pool, repo_add_solvable(repo));
+         p->name = s->name;
+         p->evr = s->evr;
+         p->vendor = s->vendor;
+         p->arch = otherarchs[i];
+
+         /* self provides */
+         if (s->name && p->arch != ARCH_SRC && p->arch != ARCH_NOSRC)
+             p->provides = repo_addid_dep(repo, p->provides, pool_rel2id(pool, p->name, p->evr, REL_EQ, 1), 0);
+
+         /* now merge the attributes */
+         repodata_merge_attrs(data, p - pool->solvables, s - pool->solvables);
+       }
     }
 
   if (pd.tmp)
-    sat_free(pd.tmp);
-  sat_free(line);
-  sat_free(otherarchs);
-  join_freemem();
+    solv_free(pd.tmp);
+  solv_free(line);
+  solv_free(otherarchs);
   if (!(flags & REPO_NO_INTERNALIZE))
     repodata_internalize(data);
+  return res;
 }