]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
Add repo_add_conda() and conda2solv
authorMichael Schroeder <mls@suse.de>
Thu, 4 Apr 2019 14:23:39 +0000 (16:23 +0200)
committerMichael Schroeder <mls@suse.de>
Thu, 4 Apr 2019 14:23:39 +0000 (16:23 +0200)
ext/CMakeLists.txt
ext/libsolvext.ver
ext/repo_conda.c [new file with mode: 0644]
ext/repo_conda.h [new file with mode: 0644]
ext/solv_jsonparser.c
ext/solv_jsonparser.h
src/libsolv.ver
tools/CMakeLists.txt
tools/conda2solv.c [new file with mode: 0644]

index 6dd28b1aeaa4bf81150bb94c37a56a05e3fbf840..d044403598d12006aaeaca3f76a8930d1d4fba39 100644 (file)
@@ -116,6 +116,13 @@ IF (ENABLE_APPDATA)
        repo_appdata.h)
 ENDIF (ENABLE_APPDATA)
 
+IF (ENABLE_CONDA)
+    SET (libsolvext_SRCS ${libsolvext_SRCS}
+       repo_conda.c)
+    SET (libsolvext_HEADERS ${libsolvext_HEADERS}
+       repo_conda.h)
+ENDIF (ENABLE_CONDA)
+
 IF (ENABLE_RPMMD OR ENABLE_SUSEREPO)
     SET (libsolvext_SRCS ${libsolvext_SRCS}
        repodata_diskusage.c)
@@ -126,6 +133,11 @@ IF (ENABLE_RPMMD OR ENABLE_SUSEREPO OR ENABLE_APPDATA OR ENABLE_COMPS OR ENABLE_
        solv_xmlparser.c)
 ENDIF (ENABLE_RPMMD OR ENABLE_SUSEREPO OR ENABLE_APPDATA OR ENABLE_COMPS OR ENABLE_HELIXREPO OR ENABLE_MDKREPO)
 
+IF (ENABLE_CONDA)
+    SET (libsolvext_SRCS ${libsolvext_SRCS}
+       solv_jsonparser.c)
+ENDIF (ENABLE_CONDA)
+
 IF (ENABLE_ZCHUNK_COMPRESSION)
     SET (libsolvext_SRCS ${libsolvext_SRCS}
        solv_zchunk.c)
index 4896e855ff854f946e8c1617a1c5f0dad96d5cbb..ef028f0f71c06d5bcf7872c0b870ec5385c4ec7d 100644 (file)
@@ -10,6 +10,7 @@ SOLV_1.0 {
                repo_add_arch_repo;
                repo_add_autopattern;
                repo_add_code11_products;
+               repo_add_conda;
                repo_add_content;
                repo_add_comps;
                repo_add_cudf;
diff --git a/ext/repo_conda.c b/ext/repo_conda.c
new file mode 100644 (file)
index 0000000..4f76c8f
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2019, SUSE LLC.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pool.h"
+#include "repo.h"
+#include "chksum.h"
+#include "solv_jsonparser.h"
+#include "conda.h"
+#include "repo_conda.h"
+
+struct parsedata {
+  Pool *pool;
+  Repo *repo;
+  Repodata *data;
+};
+
+static int
+parse_deps(struct parsedata *pd, struct solv_jsonparser *jp, Offset *depp)
+{
+  int type = JP_ARRAY;
+  while (type > 0 && (type = jsonparser_parse(jp)) > 0 && type != JP_ARRAY_END)
+    {
+      if (type == JP_STRING)
+       {
+         Id id = pool_conda_matchspec(pd->pool, jp->value);
+         if (id)
+           *depp = repo_addid_dep(pd->repo, *depp, id, 0);
+       }
+      else
+       type = jsonparser_skip(jp, type);
+    }
+  return type;
+}
+
+static int
+parse_package(struct parsedata *pd, struct solv_jsonparser *jp, char *kfn)
+{
+  int type = JP_OBJECT;
+  Pool *pool= pd->pool;
+  Repodata *data = pd->data;
+  Solvable *s;
+  Id handle = repo_add_solvable(pd->repo);
+  s = pool_id2solvable(pool, handle);
+  char *fn = 0;
+  char *subdir = 0;
+
+  while (type > 0 && (type = jsonparser_parse(jp)) > 0 && type != JP_OBJECT_END)
+    {
+      if (type == JP_STRING && !strcmp(jp->key, "build"))
+       repodata_add_poolstr_array(data, handle, SOLVABLE_BUILDFLAVOR, jp->value);
+      else if (type == JP_STRING && !strcmp(jp->key, "build_number"))
+       repodata_set_str(data, handle, SOLVABLE_BUILDVERSION, jp->value);
+      else if (type == JP_ARRAY && !strcmp(jp->key, "depends"))
+       type = parse_deps(pd, jp, &s->requires);
+      else if (type == JP_ARRAY && !strcmp(jp->key, "requires"))
+       type = parse_deps(pd, jp, &s->requires);
+      else if (type == JP_STRING && !strcmp(jp->key, "license"))
+       repodata_add_poolstr_array(data, handle, SOLVABLE_LICENSE, jp->value);
+      else if (type == JP_STRING && !strcmp(jp->key, "md5"))
+       repodata_set_checksum(data, handle, SOLVABLE_PKGID, REPOKEY_TYPE_MD5, jp->value);
+      else if (type == JP_STRING && !strcmp(jp->key, "sha256"))
+       repodata_set_checksum(data, handle, SOLVABLE_CHECKSUM, REPOKEY_TYPE_SHA256, jp->value);
+      else if (type == JP_STRING && !strcmp(jp->key, "name"))
+       s->name = pool_str2id(pool, jp->value, 1);
+      else if (type == JP_STRING && !strcmp(jp->key, "version"))
+       s->evr= pool_str2id(pool, jp->value, 1);
+      else if (type == JP_STRING && !strcmp(jp->key, "fn") && !fn)
+       fn = solv_strdup(jp->value);
+      else if (type == JP_STRING && !strcmp(jp->key, "subdir") && !subdir)
+       subdir = solv_strdup(jp->value);
+      else if (type == JP_NUMBER && !strcmp(jp->key, "size"))
+       repodata_set_num(data, handle, SOLVABLE_DOWNLOADSIZE, strtoull(jp->value, 0, 10));
+      else if (type == JP_NUMBER && !strcmp(jp->key, "timestamp"))
+       {
+         unsigned long long ts = strtoull(jp->value, 0, 10);
+         if (ts > 253402300799ULL)
+           ts /= 1000;
+         repodata_set_num(data, handle, SOLVABLE_BUILDTIME, ts);
+       }
+      else
+       type = jsonparser_skip(jp, type);
+    }
+  if (fn || kfn)
+    repodata_set_location(data, handle, 0, subdir, fn ? fn : kfn);
+  solv_free(fn);
+  solv_free(subdir);
+  if (!s->evr)
+    s->evr = 1;
+  if (s->name)
+    s->provides = repo_addid_dep(pd->repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
+  return type;
+}
+
+static int
+parse_packages(struct parsedata *pd, struct solv_jsonparser *jp)
+{
+  int type = JP_OBJECT;
+  while (type > 0 && (type = jsonparser_parse(jp)) > 0 && type != JP_OBJECT_END)
+    {
+      if (type == JP_OBJECT)
+       {
+         char *fn = solv_strdup(jp->key);
+         type = parse_package(pd, jp, fn);
+         solv_free(fn);
+       }
+      else
+       type = jsonparser_skip(jp, type);
+    }
+  return type;
+}
+
+static int
+parse_packages2(struct parsedata *pd, struct solv_jsonparser *jp)
+{
+  int type = JP_ARRAY;
+  while (type > 0 && (type = jsonparser_parse(jp)) > 0 && type != JP_ARRAY_END)
+    {
+      if (type == JP_OBJECT)
+       type = parse_package(pd, jp, 0);
+      else
+       type = jsonparser_skip(jp, type);
+    }
+  return type;
+}
+
+static int
+parse_main(struct parsedata *pd, struct solv_jsonparser *jp)
+{
+  int type = JP_OBJECT;
+  while (type > 0 && (type = jsonparser_parse(jp)) > 0 && type != JP_OBJECT_END)
+    {
+      if (type == JP_OBJECT && !strcmp("packages", jp->key))
+       type = parse_packages(pd, jp);
+      if (type == JP_ARRAY && !strcmp("packages", jp->key))
+       type = parse_packages2(pd, jp);
+      else
+       type = jsonparser_skip(jp, type);
+    }
+  return type;
+}
+
+int
+repo_add_conda(Repo *repo, FILE *fp, int flags)
+{
+  Pool *pool = repo->pool;
+  struct solv_jsonparser jp;
+  struct parsedata pd;
+  Repodata *data;
+  int type, ret = 0;
+
+  data = repo_add_repodata(repo, flags);
+
+  memset(&pd, 0, sizeof(pd));
+  pd.pool = pool;
+  pd.repo = repo;
+  pd.data = data;
+
+  jsonparser_init(&jp, fp);
+  if ((type = jsonparser_parse(&jp)) != JP_OBJECT)
+    ret = pool_error(pool, -1, "repository does not start with an object");
+  else if ((type = parse_main(&pd, &jp)) != JP_OBJECT_END)
+    ret = pool_error(pool, -1, "parse error line %d", jp.line);
+  jsonparser_free(&jp);
+
+  if (!(flags & REPO_NO_INTERNALIZE))
+    repodata_internalize(data);
+
+  return ret;
+}
+
diff --git a/ext/repo_conda.h b/ext/repo_conda.h
new file mode 100644 (file)
index 0000000..7e90a3d
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * Copyright (c) 2019, SUSE LLC
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+extern int repo_add_conda(Repo *repo, FILE *fp, int flags);
index 053ee6f46c2df8ab1af0515895e7393fcc1a264f..ae044e63f0438535aa67a1b01af1ef0cae2b9bb3 100644 (file)
@@ -15,7 +15,7 @@
 #include "util.h"
 #include "solv_jsonparser.h"
 
-struct solv_jsonparser *
+void
 jsonparser_init(struct solv_jsonparser *jp, FILE *fp)
 {
   memset(jp, 0, sizeof(*jp));
@@ -24,7 +24,6 @@ jsonparser_init(struct solv_jsonparser *jp, FILE *fp)
   jp->line = jp->nextline = 1;
   jp->nextc = ' ';
   queue_init(&jp->stateq);
-  return jp;
 }
 
 struct solv_jsonparser *
index d58d9e3abf744868596e8c6b36fbba9822a77236..e0274f9c9070d3af327196c6da0e19171c1a67e4 100644 (file)
@@ -41,7 +41,7 @@ struct solv_jsonparser {
 #define JP_ARRAY       8
 #define JP_ARRAY_END   9
 
-struct solv_jsonparser *jsonparser_init(struct solv_jsonparser *jp, FILE *fp);
+void jsonparser_init(struct solv_jsonparser *jp, FILE *fp);
 struct solv_jsonparser *jsonparser_free(struct solv_jsonparser *jp);
 int jsonparser_parse(struct solv_jsonparser *jp);
 int jsonparser_skip(struct solv_jsonparser *jp, int type);
index d983b5410ed9de783731150a726073e61bc72f85..eafe3e6885e97b149c4e5af14d8baff97c8e2653 100644 (file)
@@ -449,4 +449,5 @@ SOLV_1.2 {
 SOLV_1.3 {
                repodata_set_kv;
                solv_setcloexec;
+               pool_conda_matchspec;
 } SOLV_1.2;
index 0d677f691a80c4c4f05d43bc1277f76a4d3c805a..e2aa4f1acb0b08bf204c80d2d77a2db0d1b0d127 100644 (file)
@@ -98,6 +98,13 @@ TARGET_LINK_LIBRARIES (appdata2solv toolstuff libsolvext libsolv ${SYSTEM_LIBRAR
 SET (tools_list ${tools_list} appdata2solv)
 ENDIF (ENABLE_APPDATA)
 
+IF (ENABLE_CONDA)
+ADD_EXECUTABLE (conda2solv conda2solv.c)
+TARGET_LINK_LIBRARIES (conda2solv toolstuff libsolvext libsolv ${SYSTEM_LIBRARIES})
+
+SET (tools_list ${tools_list} conda2solv)
+ENDIF (ENABLE_CONDA)
+
 ADD_EXECUTABLE (dumpsolv dumpsolv.c )
 TARGET_LINK_LIBRARIES (dumpsolv libsolv)
 
diff --git a/tools/conda2solv.c b/tools/conda2solv.c
new file mode 100644 (file)
index 0000000..2b8f3c4
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019, SUSE LLC
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+/*
+ * conda2solv.c
+ *
+ * parse a conda repository file
+ *
+ * reads from stdin
+ * writes to stdout
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pool.h"
+#include "repo.h"
+#include "repo_conda.h"
+#include "solv_xfopen.h"
+#include "common_write.h"
+
+
+static void
+usage(int status)
+{
+  fprintf(stderr, "\nUsage:\n"
+          "conda2solv\n"
+          "  reads a 'synthesis' repository from <stdin> and writes a .solv file to <stdout>\n"
+          "  -h : print help & exit\n"
+         );
+   exit(status);
+}
+
+int
+main(int argc, char **argv)
+{
+  Pool *pool;
+  Repo *repo;
+  int c;
+
+  while ((c = getopt(argc, argv, "h")) >= 0)
+    {
+      switch(c)
+       {
+       case 'h':
+         usage(0);
+         break;
+       default:
+         usage(1);
+         break;
+       }
+    }
+  pool = pool_create();
+  repo = repo_create(pool, "<stdin>");
+  if (repo_add_conda(repo, stdin, 0))
+    {
+      fprintf(stderr, "conda2solv: %s\n", pool_errstr(pool));
+      exit(1);
+    }
+  repo_internalize(repo);
+  tool_write(repo, stdout);
+  pool_free(pool);
+  exit(0);
+}