Imported Upstream version 0.6.35
[platform/upstream/libsolv.git] / tools / common_write.c
index e12e82f..577b1ab 100644 (file)
@@ -6,8 +6,6 @@
  */
 
 #include <sys/types.h>
-#include <limits.h>
-#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "repo.h"
 #include "repo_write.h"
 #include "common_write.h"
+#include "solvversion.h"
+
+/* toolversion history
+ * 1.0: initial tool version
+ * 1.1: changed PRODUCT_ENDOFLIFE parsing
+*/
 
 static Id verticals[] = {
   SOLVABLE_AUTHORS,
@@ -25,6 +29,8 @@ static Id verticals[] = {
   SOLVABLE_EULA,
   SOLVABLE_DISKUSAGE,
   SOLVABLE_FILELIST,
+  SOLVABLE_CHANGELOG_AUTHOR,
+  SOLVABLE_CHANGELOG_TEXT,
   0
 };
 
@@ -39,17 +45,32 @@ static char *languagetags[] = {
 
 static int test_separate = 0;
 
+struct keyfilter_data {
+  char **languages;
+  int nlanguages;
+  int haveaddedfileprovides;
+  int haveexternal;
+};
+
 static int
 keyfilter_solv(Repo *data, Repokey *key, void *kfdata)
 {
+  struct keyfilter_data *kd = kfdata;
   int i;
   const char *keyname;
+
   if (test_separate && key->storage != KEY_STORAGE_SOLVABLE)
     return KEY_STORAGE_DROPPED;
+  if (!kd->haveaddedfileprovides && key->name == REPOSITORY_ADDEDFILEPROVIDES)
+    return KEY_STORAGE_DROPPED;
+  if (!kd->haveexternal && key->name == REPOSITORY_EXTERNAL)
+    return KEY_STORAGE_DROPPED;
+  if (key->name == SUSETAGS_SHARE_NAME || key->name == SUSETAGS_SHARE_EVR || key->name == SUSETAGS_SHARE_ARCH)
+    return KEY_STORAGE_DROPPED;
   for (i = 0; verticals[i]; i++)
     if (key->name == verticals[i])
       return KEY_STORAGE_VERTICAL_OFFSET;
-  keyname = id2str(data->pool, key->name);
+  keyname = pool_id2str(data->pool, key->name);
   for (i = 0; languagetags[i] != 0; i++)
     if (!strncmp(keyname, languagetags[i], strlen(languagetags[i])))
       return KEY_STORAGE_VERTICAL_OFFSET;
@@ -63,10 +84,13 @@ keyfilter_attr(Repo *data, Repokey *key, void *kfdata)
   const char *keyname;
   if (key->storage == KEY_STORAGE_SOLVABLE)
     return KEY_STORAGE_DROPPED;
+  /* those must only be in the main solv file */
+  if (key->name == REPOSITORY_EXTERNAL || key->name == REPOSITORY_ADDEDFILEPROVIDES || key->name == REPOSITORY_TOOLVERSION)
+    return KEY_STORAGE_DROPPED;
   for (i = 0; verticals[i]; i++)
     if (key->name == verticals[i])
       return KEY_STORAGE_VERTICAL_OFFSET;
-  keyname = id2str(data->pool, key->name);
+  keyname = pool_id2str(data->pool, key->name);
   for (i = 0; languagetags[i] != 0; i++)
     if (!strncmp(keyname, languagetags[i], strlen(languagetags[i])))
       return KEY_STORAGE_VERTICAL_OFFSET;
@@ -76,22 +100,21 @@ keyfilter_attr(Repo *data, Repokey *key, void *kfdata)
 static int
 keyfilter_language(Repo *repo, Repokey *key, void *kfdata)
 {
+  Pool *pool = repo->pool;
   const char *name, *p;
-  char *lang = kfdata, *bname;
+  char *lang = kfdata;
   int i;
-  Id id;
 
-  name = id2str(repo->pool, key->name);
+  name = pool_id2str(repo->pool, key->name);
   p = strrchr(name, ':');
   if (!p || strcmp(p + 1, lang) != 0)
     return KEY_STORAGE_DROPPED;
-  /* find base name id */
-  bname = strdup(name);
-  bname[p - name] = 0;
-  id = str2id(repo->pool, bname, 1);
   for (i = 0; verticals[i]; i++)
-    if (id == verticals[i])
-      return KEY_STORAGE_VERTICAL_OFFSET;
+    {
+      const char *vname = pool_id2str(pool, verticals[i]);
+      if (!strncmp(name, vname, p - name) && vname[p - name] == 0)
+       return KEY_STORAGE_VERTICAL_OFFSET;
+    }
   return KEY_STORAGE_INCORE;
 }
 
@@ -119,22 +142,22 @@ keyfilter_FL(Repo *repo, Repokey *key, void *kfdata)
   return KEY_STORAGE_INCORE;
 }
 
-struct keyfilter_other_data {
-  char **languages;
-  int nlanguages;
-};
-
 static int
 keyfilter_other(Repo *repo, Repokey *key, void *kfdata)
 {
   const char *name, *p;
-  struct keyfilter_other_data *kd = kfdata;
+  struct keyfilter_data *kd = kfdata;
   int i;
 
+  if (!kd->haveaddedfileprovides && key->name == REPOSITORY_ADDEDFILEPROVIDES)
+    return KEY_STORAGE_DROPPED;
+  if (!kd->haveexternal && key->name == REPOSITORY_EXTERNAL)
+    return KEY_STORAGE_DROPPED;
+
   if (key->name == SOLVABLE_FILELIST || key->name == SOLVABLE_DISKUSAGE)
     return KEY_STORAGE_DROPPED;
 
-  name = id2str(repo->pool, key->name);
+  name = pool_id2str(repo->pool, key->name);
   p = strrchr(name, ':');
   if (p)
     {
@@ -156,41 +179,65 @@ keyfilter_other(Repo *repo, Repokey *key, void *kfdata)
 
 #define REPODATAFILE_BLOCK 15
 
-int
+static void
+write_info(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Repodata *info, const char *location)
+{
+  Id h;
+  Queue keyq;
+
+  queue_init(&keyq);
+  if (repo_write_filtered(repo, fp, keyfilter, kfdata, &keyq) != 0)
+    {
+      fprintf(stderr, "repo_write failed\n");
+      exit(1);
+    }
+  h = repodata_new_handle(info);
+  if (keyq.count)
+    repodata_set_idarray(info, h, REPOSITORY_KEYS, &keyq);
+  queue_free(&keyq);
+  repodata_set_str(info, h, REPOSITORY_LOCATION, location);
+  repodata_add_flexarray(info, SOLVID_META, REPOSITORY_EXTERNAL, h);
+}
+
+void
 tool_write(Repo *repo, const char *basename, const char *attrname)
 {
   Repodata *data;
+  Repodata *info = 0;
   Repokey *key;
-  Repodatafile *fileinfos = 0;
-  int nfileinfos = 0;
   char **languages = 0;
   int nlanguages = 0;
   int i, j, k, l;
+  struct keyfilter_data kd;
+  Queue addedfileprovides;
 
-  fileinfos = sat_zextend(fileinfos, nfileinfos, 1, sizeof(Repodatafile), REPODATAFILE_BLOCK);
-  pool_addfileprovides_ids(repo->pool, 0, &fileinfos[nfileinfos].addedfileprovides);
-  for (i = 0; i < 32; i++)
-    if (repo->rpmdbcookie[i])
-      break;
-  if (i < 32)
-    fileinfos[nfileinfos].rpmdbcookie = repo->rpmdbcookie;
-  if (fileinfos[nfileinfos].addedfileprovides || fileinfos[nfileinfos].rpmdbcookie)
-    nfileinfos++;
+  memset(&kd, 0, sizeof(kd));
+  info = repo_add_repodata(repo, 0);
+  repodata_set_str(info, SOLVID_META, REPOSITORY_TOOLVERSION, LIBSOLV_TOOLVERSION);
+  queue_init(&addedfileprovides);
+  pool_addfileprovides_queue(repo->pool, &addedfileprovides, 0);
+  if (addedfileprovides.count)
+    {
+      kd.haveaddedfileprovides = 1;
+      repodata_set_idarray(info, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, &addedfileprovides);
+    }
+  queue_free(&addedfileprovides);
+
+  pool_freeidhashes(repo->pool);       /* free some mem */
 
   if (basename)
     {
-      struct keyfilter_other_data kd;
       char fn[4096];
       FILE *fp;
       int has_DU = 0;
       int has_FL = 0;
 
       /* find languages and other info */
-      for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
+      FOR_REPODATAS(repo, i, data)
        {
          for (j = 1, key = data->keys + j; j < data->nkeys; j++, key++)
            {
-             const char *keyname = id2str(repo->pool, key->name);
+             const char *keyname = pool_id2str(repo->pool, key->name);
              if (key->name == SOLVABLE_DISKUSAGE)
                has_DU = 1;
              if (key->name == SOLVABLE_FILELIST)
@@ -208,11 +255,10 @@ tool_write(Repo *repo, const char *basename, const char *attrname)
                  break;
              if (k < nlanguages)
                continue;
-             languages = sat_realloc2(languages, nlanguages + 1, sizeof(char *));
+             languages = solv_realloc2(languages, nlanguages + 1, sizeof(char *));
              languages[nlanguages++] = strdup(keyname + l);
            }
        }
-      fileinfos = sat_zextend(fileinfos, nfileinfos, nlanguages + 2, sizeof(Repodatafile), REPODATAFILE_BLOCK);
       /* write language subfiles */
       for (i = 0; i < nlanguages; i++)
         {
@@ -222,10 +268,9 @@ tool_write(Repo *repo, const char *basename, const char *attrname)
              perror(fn);
              exit(1);
            }
-          repo_write(repo, fp, keyfilter_language, languages[i], fileinfos + nfileinfos, 0);
-         fileinfos[nfileinfos].location = strdup(fn);
+         write_info(repo, fp, keyfilter_language, languages[i], info, fn);
          fclose(fp);
-         nfileinfos++;
+         kd.haveexternal = 1;
         }
       /* write DU subfile */
       if (has_DU)
@@ -236,10 +281,9 @@ tool_write(Repo *repo, const char *basename, const char *attrname)
              perror(fn);
              exit(1);
            }
-         repo_write(repo, fp, keyfilter_DU, 0, fileinfos + nfileinfos, 0);
-         fileinfos[nfileinfos].location = strdup(fn);
+         write_info(repo, fp, keyfilter_DU, 0, info, fn);
          fclose(fp);
-         nfileinfos++;
+         kd.haveexternal = 1;
        }
       /* write filelist */
       if (has_FL)
@@ -250,10 +294,9 @@ tool_write(Repo *repo, const char *basename, const char *attrname)
              perror(fn);
              exit(1);
            }
-         repo_write(repo, fp, keyfilter_FL, 0, fileinfos + nfileinfos, 0);
-         fileinfos[nfileinfos].location = strdup(fn);
+         write_info(repo, fp, keyfilter_FL, 0, info, fn);
          fclose(fp);
-         nfileinfos++;
+         kd.haveexternal = 1;
        }
       /* write everything else */
       sprintf(fn, "%s.solv", basename);
@@ -264,37 +307,36 @@ tool_write(Repo *repo, const char *basename, const char *attrname)
        }
       kd.languages = languages;
       kd.nlanguages = nlanguages;
-      repo_write(repo, fp, keyfilter_other, &kd, nfileinfos ? fileinfos : 0, nfileinfos);
-      fclose(fp);
-      for (i = 0; i < nlanguages; i++)
-       free(languages[i]);
-      sat_free(languages);
-      for (i = 0; i < nfileinfos; i++)
+      repodata_internalize(info);
+      if (repo_write_filtered(repo, fp, keyfilter_other, &kd, 0) != 0)
        {
-         sat_free(fileinfos[i].addedfileprovides);
-         sat_free(fileinfos[i].location);
-         sat_free(fileinfos[i].keys);
+         fprintf(stderr, "repo_write failed\n");
+         exit(1);
        }
-      sat_free(fileinfos);
-      return 0;
+      if (fclose(fp) != 0)
+       {
+         perror("fclose");
+         exit(1);
+       }
+      for (i = 0; i < nlanguages; i++)
+       free(languages[i]);
+      solv_free(languages);
+      repodata_free(info);
     }
   if (attrname)
     {
-      fileinfos = sat_zextend(fileinfos, nfileinfos, 1, sizeof(Repodatafile), REPODATAFILE_BLOCK);
+      FILE *fp;
       test_separate = 1;
-      FILE *fp = fopen (attrname, "w");
-      repo_write(repo, fp, keyfilter_attr, 0, fileinfos + nfileinfos, 0);
-      fileinfos[nfileinfos].location = strdup(attrname);
+      fp = fopen(attrname, "w");
+      write_info(repo, fp, keyfilter_attr, 0, info, attrname);
       fclose(fp);
-      nfileinfos++;
+      kd.haveexternal = 1;
     }
-  repo_write(repo, stdout, keyfilter_solv, 0, nfileinfos ? fileinfos : 0, nfileinfos);
-  for (i = 0; i < nfileinfos; i++)
+  repodata_internalize(info);
+  if (repo_write_filtered(repo, stdout, keyfilter_solv, &kd, 0) != 0)
     {
-      sat_free(fileinfos[i].addedfileprovides);
-      sat_free(fileinfos[i].location);
-      sat_free(fileinfos[i].keys);
+      fprintf(stderr, "repo_write failed\n");
+      exit(1);
     }
-  sat_free(fileinfos);
-  return 0;
+  repodata_free(info);
 }