2 * Copyright (c) 2019, SUSE LLC.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
17 #include "solv_jsonparser.h"
19 #include "repo_conda.h"
31 parse_deps(struct parsedata *pd, struct solv_jsonparser *jp, Offset *depp)
34 while (type > 0 && (type = jsonparser_parse(jp)) > 0 && type != JP_ARRAY_END)
36 if (type == JP_STRING)
38 Id id = pool_conda_matchspec(pd->pool, jp->value);
40 *depp = repo_addid_dep(pd->repo, *depp, id, 0);
43 type = jsonparser_skip(jp, type);
49 parse_otherdeps(struct parsedata *pd, struct solv_jsonparser *jp, Id handle, Id keyname)
52 while (type > 0 && (type = jsonparser_parse(jp)) > 0 && type != JP_ARRAY_END)
54 if (type == JP_STRING)
56 Id id = pool_conda_matchspec(pd->pool, jp->value);
58 repodata_add_idarray(pd->data, handle, keyname, id);
61 type = jsonparser_skip(jp, type);
67 parse_trackfeatures_array(struct parsedata *pd, struct solv_jsonparser *jp, Id handle)
70 while (type > 0 && (type = jsonparser_parse(jp)) > 0 && type != JP_ARRAY_END)
72 if (type == JP_STRING)
74 char *p = jp->value, *pe;
75 while (*p == ' ' || *p == '\t')
79 for (pe = p + strlen(p) - 1; pe > p; pe--)
80 if (*pe != ' ' && *pe != '\t')
82 repodata_add_idarray(pd->data, handle, SOLVABLE_TRACK_FEATURES, pool_strn2id(pd->pool, p, pe - p + 1, 1));
85 type = jsonparser_skip(jp, type);
91 parse_trackfeatures_string(struct parsedata *pd, const char *p, Id handle)
96 if (*p == ' ' || *p == '\t' || *p == ',')
99 while (*pe && *pe != ' ' && *pe != '\t' && *pe != ',')
101 repodata_add_idarray(pd->data, handle, SOLVABLE_TRACK_FEATURES, pool_strn2id(pd->pool, p, pe - p, 1));
107 swap_solvables(Pool *pool, Repodata *data, Id pa, Id pb)
111 tmp = pool->solvables[pa];
112 pool->solvables[pa] = pool->solvables[pb];
113 pool->solvables[pb] = tmp;
114 repodata_swap_attrs(data, pa, pb);
118 fn2data(struct parsedata *pd, const char *fn, Id *fntypep, int create)
120 size_t l = strlen(fn), extl = 0;
122 if (l > 6 && !strcmp(fn + l - 6, ".conda"))
124 else if (l > 8 && !strcmp(fn + l - 8, ".tar.bz2"))
128 fnid = stringpool_strn2id(&pd->fnpool, fn, l - extl, create);
131 if (fnid * 2 + 2 > pd->fndata.count)
132 queue_insertn(&pd->fndata, pd->fndata.count, fnid * 2 + 2 - pd->fndata.count, 0);
134 *fntypep = extl == 8 ? 1 : 2; /* 1: legacy .tar.bz2 2: .conda */
135 return pd->fndata.elements + 2 * fnid;
139 parse_package(struct parsedata *pd, struct solv_jsonparser *jp, char *kfn)
141 int type = JP_OBJECT;
142 Pool *pool= pd->pool;
143 Repodata *data = pd->data;
148 Id *fndata = 0, fntype = 0;
150 handle = repo_add_solvable(pd->repo);
151 s = pool_id2solvable(pool, handle);
152 while (type > 0 && (type = jsonparser_parse(jp)) > 0 && type != JP_OBJECT_END)
154 if (type == JP_STRING && !strcmp(jp->key, "build"))
155 repodata_add_poolstr_array(data, handle, SOLVABLE_BUILDFLAVOR, jp->value);
156 else if (type == JP_NUMBER && !strcmp(jp->key, "build_number"))
157 repodata_set_str(data, handle, SOLVABLE_BUILDVERSION, jp->value);
158 else if (type == JP_ARRAY && !strcmp(jp->key, "depends"))
159 type = parse_deps(pd, jp, &s->requires);
160 else if (type == JP_ARRAY && !strcmp(jp->key, "requires"))
161 type = parse_deps(pd, jp, &s->requires);
162 else if (type == JP_ARRAY && !strcmp(jp->key, "constrains"))
163 type = parse_otherdeps(pd, jp, handle, SOLVABLE_CONSTRAINS);
164 else if (type == JP_STRING && !strcmp(jp->key, "license"))
165 repodata_add_poolstr_array(data, handle, SOLVABLE_LICENSE, jp->value);
166 else if (type == JP_STRING && !strcmp(jp->key, "md5"))
167 repodata_set_checksum(data, handle, SOLVABLE_PKGID, REPOKEY_TYPE_MD5, jp->value);
168 else if (type == JP_STRING && !strcmp(jp->key, "sha256"))
169 repodata_set_checksum(data, handle, SOLVABLE_CHECKSUM, REPOKEY_TYPE_SHA256, jp->value);
170 else if (type == JP_STRING && !strcmp(jp->key, "name"))
171 s->name = pool_str2id(pool, jp->value, 1);
172 else if (type == JP_STRING && !strcmp(jp->key, "version"))
173 s->evr= pool_str2id(pool, jp->value, 1);
174 else if (type == JP_STRING && !strcmp(jp->key, "fn") && !fn)
175 fn = solv_strdup(jp->value);
176 else if (type == JP_STRING && !strcmp(jp->key, "subdir") && !subdir)
177 subdir = solv_strdup(jp->value);
178 else if (type == JP_NUMBER && !strcmp(jp->key, "size"))
179 repodata_set_num(data, handle, SOLVABLE_DOWNLOADSIZE, strtoull(jp->value, 0, 10));
180 else if (type == JP_NUMBER && !strcmp(jp->key, "timestamp"))
182 unsigned long long ts = strtoull(jp->value, 0, 10);
183 if (ts > 253402300799ULL)
185 repodata_set_num(data, handle, SOLVABLE_BUILDTIME, ts);
187 else if (type == JP_STRING && !strcmp(jp->key, "track_features"))
188 parse_trackfeatures_string(pd, jp->value, handle);
189 else if (type == JP_ARRAY && !strcmp(jp->key, "track_features"))
190 type = parse_trackfeatures_array(pd, jp, handle);
192 type = jsonparser_skip(jp, type);
196 repodata_set_location(data, handle, 0, subdir, fn ? fn : kfn);
197 fndata = fn2data(pd, fn ? fn : kfn, &fntype, 1);
204 s->provides = repo_addid_dep(pd->repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
208 /* deal with legacy package entries */
209 if (fndata[0] && fndata[0] > fntype)
211 /* ignore this package */
212 repo_free_solvable(pd->repo, handle, 1);
215 if (fndata[0] && fndata[0] < fntype)
217 /* replace old package */
218 swap_solvables(pool, data, handle, fndata[1]);
219 repo_free_solvable(pd->repo, handle, 1);
229 parse_packages(struct parsedata *pd, struct solv_jsonparser *jp)
231 int type = JP_OBJECT;
232 while (type > 0 && (type = jsonparser_parse(jp)) > 0 && type != JP_OBJECT_END)
234 if (type == JP_OBJECT)
236 char *fn = solv_strdup(jp->key);
237 type = parse_package(pd, jp, fn);
241 type = jsonparser_skip(jp, type);
247 parse_packages2(struct parsedata *pd, struct solv_jsonparser *jp)
250 while (type > 0 && (type = jsonparser_parse(jp)) > 0 && type != JP_ARRAY_END)
252 if (type == JP_OBJECT)
253 type = parse_package(pd, jp, 0);
255 type = jsonparser_skip(jp, type);
261 parse_main(struct parsedata *pd, struct solv_jsonparser *jp, int flags)
263 int type = JP_OBJECT;
264 while (type > 0 && (type = jsonparser_parse(jp)) > 0 && type != JP_OBJECT_END)
266 if (type == JP_OBJECT && !strcmp("packages", jp->key))
267 type = parse_packages(pd, jp);
268 else if (type == JP_ARRAY && !strcmp("packages", jp->key))
269 type = parse_packages2(pd, jp);
270 else if (type == JP_OBJECT && !strcmp("packages.conda", jp->key) && !(flags & CONDA_ADD_USE_ONLY_TAR_BZ2))
271 type = parse_packages(pd, jp);
272 else if (type == JP_ARRAY && !strcmp("packages.conda", jp->key) && !(flags & CONDA_ADD_USE_ONLY_TAR_BZ2))
273 type = parse_packages2(pd, jp);
275 type = jsonparser_skip(jp, type);
281 repo_add_conda(Repo *repo, FILE *fp, int flags)
283 Pool *pool = repo->pool;
284 struct solv_jsonparser jp;
289 data = repo_add_repodata(repo, flags);
291 memset(&pd, 0, sizeof(pd));
295 stringpool_init_empty(&pd.fnpool);
296 queue_init(&pd.fndata);
298 jsonparser_init(&jp, fp);
299 if ((type = jsonparser_parse(&jp)) != JP_OBJECT)
300 ret = pool_error(pool, -1, "repository does not start with an object");
301 else if ((type = parse_main(&pd, &jp, flags)) != JP_OBJECT_END)
302 ret = pool_error(pool, -1, "parse error line %d", jp.line);
303 jsonparser_free(&jp);
305 queue_free(&pd.fndata);
306 stringpool_free(&pd.fnpool);
307 if (!(flags & REPO_NO_INTERNALIZE))
308 repodata_internalize(data);