- also free attrs array when freeing a solvable
[platform/upstream/libsolv.git] / tools / rpmdb2solv.c
index 81d58bd..33796ff 100644 (file)
@@ -8,6 +8,10 @@
 /*
  * rpmdb2solv
  * 
+ * Reads rpm database (and evtl. more, like product metadata) to build
+ * a .solv file of 'installed' solvables.
+ * Writes .solv to stdout
+ * 
  */
 
 #include <sys/types.h>
 #include "pool.h"
 #include "repo.h"
 #include "repo_rpmdb.h"
+#include "repo_products.h"
 #include "repo_solv.h"
 #include "common_write.h"
 
+static void
+usage(int status)
+{
+  fprintf(stderr, "\nUsage:\n"
+         "rpmdb2solv [-n] [-x] [-b <basefile>] [-p <productsdir>] [-r <root>]\n"
+         " -n : No packages, do not read rpmdb, useful to only parse products\n"
+         " -x : use extrapool\n"
+         " -b <basefile> : Write .solv to <basefile>.solv instead of stdout\n"
+         " -p <productsdir> : Scan <productsdir> for .prod files, representing installed products\n"
+         " -r <root> : Prefix rpmdb path and <productsdir> with <root>\n"
+         " -o <solv> : Write .solv to file instead of stdout\n"
+        );
+  exit(status);
+}
+
+
 int
 main(int argc, char **argv)
 {
   Pool *pool = pool_create();
   Repo *repo, *ref = 0;
-  FILE *fp;
+  Repodata *data;
   Pool *refpool;
-  int c;
-  const char *root = "/";
+  int c, percent = 0;
+  int extrapool = 0;
+  int nopacks = 0;
+  const char *root = 0;
   const char *basefile = 0;
+  const char *refname = 0;
+#ifdef ENABLE_SUSEREPO
+  char *proddir = 0;
+#endif
+  char *outfile = 0;
 
-  while ((c = getopt (argc, argv, "b:r:")) >= 0)
+  /*
+   * parse arguments
+   */
+  
+  while ((c = getopt(argc, argv, "Phnxb:r:p:o:")) >= 0)
     switch (c)
       {
+      case 'h':
+         usage(0);
+       break;
       case 'r':
         root = optarg;
         break;
       case 'b':
         basefile = optarg;
         break;
+      case 'n':
+       nopacks = 1;
+       break;
+      case 'P':
+       percent = 1;
+       break;
+      case 'p':
+#ifdef ENABLE_SUSEREPO
+       proddir = optarg;
+#endif
+       break;
+      case 'x':
+        extrapool = 1;
+        break;
+      case 'o':
+        outfile = optarg;
+        break;
       default:
-       exit(1);
+       usage(1);
       }
   
+  if (outfile && !freopen(outfile, "w", stdout))
+    {
+      perror(outfile);
+      exit(1);
+    }
+    
+  /*
+   * optional arg is old version of rpmdb solv file
+   * should make this a real option instead
+   */
+  
   if (optind < argc)
+    refname = argv[optind];
+
+  if (refname)
     {
-      refpool = pool;
-      if ((fp = fopen(argv[optind], "r")) == NULL)
+      FILE *fp;
+      if ((fp = fopen(refname, "r")) == NULL)
         {
-          perror(argv[optind]);
-          exit(1);
+          perror(refname);
         }
-      ref = repo_create(refpool, "ref");
-      repo_add_solv(ref, fp);
-      fclose(fp);
+      else
+       {
+         if (extrapool)
+           refpool = pool_create();
+         else
+           refpool = pool;
+         ref = repo_create(refpool, "ref");
+         repo_add_solv(ref, fp, 0);
+         repo_disable_paging(ref);
+         fclose(fp);
+       }
     }
 
+  /*
+   * create 'installed' repository
+   * add products
+   * add rpmdb
+   * write .solv
+   */
+
   repo = repo_create(pool, "installed");
-  repo_add_rpmdb(repo, ref, root);
+  data = repo_add_repodata(repo, 0);
+
+  if (!nopacks)
+    repo_add_rpmdb(repo, ref, root, REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE | (percent ? RPMDB_REPORT_PROGRESS : 0));
+
+#ifdef ENABLE_SUSEREPO
+  if (proddir && *proddir)
+    {
+      char *buf = proddir;
+      /* if <root> given, not '/', and proddir does not start with <root> */
+      if (root && *root)
+       {
+         int rootlen = strlen(root);
+         if (strncmp(root, proddir, rootlen))
+           {
+             buf = (char *)solv_malloc(rootlen + strlen(proddir) + 2); /* + '/' + \0 */
+             strcpy(buf, root);
+             if (root[rootlen - 1] != '/' && *proddir != '/')
+               buf[rootlen++] = '/';
+             strcpy(buf + rootlen, proddir);
+           }
+       }
+      repo_add_products(repo, buf, root, REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE);
+      if (buf != proddir)
+       solv_free(buf);
+    }
+#endif
+  repodata_internalize(data);
+
   if (ref)
     {
       if (ref->pool != pool)
@@ -74,6 +182,5 @@ main(int argc, char **argv)
 
   tool_write(repo, basefile, 0);
   pool_free(pool);
-
   exit(0);
 }