2 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
3 * Copyright (C) 2008 Red Hat, Inc
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "razor-internal.h"
27 razor_importer_begin_package(struct razor_importer *importer,
32 struct razor_package *p;
34 p = array_add(&importer->set->packages, sizeof *p);
35 p->name = hashtable_tokenize(&importer->table, name);
37 p->version = hashtable_tokenize(&importer->table, version);
38 p->arch = hashtable_tokenize(&importer->table, arch);
40 importer->package = p;
41 array_init(&importer->properties);
46 razor_importer_finish_package(struct razor_importer *importer)
48 list_set_array(&importer->package->properties,
49 &importer->set->property_pool,
50 &importer->properties,
53 array_release(&importer->properties);
57 razor_importer_add_details(struct razor_importer *importer,
59 const char *description,
63 importer->package->summary = hashtable_tokenize(&importer->details_table, summary);
64 importer->package->description = hashtable_tokenize(&importer->details_table, description);
65 importer->package->url = hashtable_tokenize(&importer->details_table, url);
66 importer->package->license = hashtable_tokenize(&importer->details_table, license);
70 razor_importer_add_property(struct razor_importer *importer,
75 struct razor_property *p;
78 p = array_add(&importer->set->properties, sizeof *p);
79 p->name = hashtable_tokenize(&importer->table, name);
81 p->version = hashtable_tokenize(&importer->table, version);
82 list_set_ptr(&p->packages, importer->package -
83 (struct razor_package *) importer->set->packages.data);
85 r = array_add(&importer->properties, sizeof *r);
86 *r = p - (struct razor_property *) importer->set->properties.data;
88 if (((flags & RAZOR_PROPERTY_TYPE_MASK) == RAZOR_PROPERTY_REQUIRES) &&
90 r = array_add(&importer->file_requires, sizeof *r);
96 razor_importer_add_file(struct razor_importer *importer, const char *name)
98 struct import_entry *e;
100 e = array_add(&importer->files, sizeof *e);
102 e->package = importer->package -
103 (struct razor_package *) importer->set->packages.data;
104 e->name = strdup(name);
107 struct razor_importer *
108 razor_importer_new(void)
110 struct razor_importer *importer;
112 importer = zalloc(sizeof *importer);
113 importer->set = razor_set_create();
114 hashtable_init(&importer->table, &importer->set->string_pool);
115 hashtable_init(&importer->details_table,
116 &importer->set->details_string_pool);
117 hashtable_init(&importer->file_table,
118 &importer->set->file_string_pool);
123 /* Destroy an importer without creating the set. */
125 razor_importer_destroy(struct razor_importer *importer)
127 /* FIXME: write this */
131 compare_packages(const void *p1, const void *p2, void *data)
133 const struct razor_package *pkg1 = p1, *pkg2 = p2;
134 struct razor_set *set = data;
135 char *pool = set->string_pool.data;
137 /* FIXME: what if the flags are different? */
138 if (pkg1->name == pkg2->name)
139 return razor_versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
141 return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
145 compare_properties(const void *p1, const void *p2, void *data)
147 const struct razor_property *prop1 = p1, *prop2 = p2;
148 struct razor_set *set = data;
149 char *pool = set->string_pool.data;
151 if (prop1->name != prop2->name)
152 return strcmp(&pool[prop1->name], &pool[prop2->name]);
153 else if (prop1->flags != prop2->flags)
154 return prop1->flags - prop2->flags;
156 return razor_versioncmp(&pool[prop1->version], &pool[prop2->version]);
160 uniqueify_properties(struct razor_set *set)
162 struct razor_property *rp, *up, *rp_end;
163 struct array *pkgs, *p;
165 uint32_t *map, *rmap;
166 int i, count, unique;
168 count = set->properties.size / sizeof(struct razor_property);
169 map = razor_qsort_with_data(set->properties.data,
171 sizeof(struct razor_property),
175 rp_end = set->properties.data + set->properties.size;
176 rmap = malloc(count * sizeof *map);
177 pkgs = zalloc(count * sizeof *pkgs);
178 for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
179 if (rp->name != up->name ||
180 rp->flags != up->flags ||
181 rp->version != up->version) {
184 up->flags = rp->flags;
185 up->version = rp->version;
188 unique = up - (struct razor_property *) set->properties.data;
189 rmap[map[i]] = unique;
190 r = array_add(&pkgs[unique], sizeof *r);
197 set->properties.size = (void *) up - set->properties.data;
199 for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
200 list_set_array(&rp->packages, &set->package_pool, p, 0);
210 compare_filenames(const void *p1, const void *p2, void *data)
212 const struct import_entry *e1 = p1;
213 const struct import_entry *e2 = p2;
214 const char *n1 = e1->name;
215 const char *n2 = e2->name;
217 /* Need to make sure that the contents of a directory
218 * are sorted immediately after it. So "foo/bar" has to
219 * sort before "foo.conf"
221 * FIXME: this is about 60% slower than strcmp
225 return *n2 == '/' ? 1 : -1;
227 return *n1 == '/' ? -1 : 1;
240 count_entries(struct import_directory *d)
242 struct import_directory *p, *end;
245 end = d->files.data + d->files.size;
249 d->count += p->count + 1;
255 serialize_files(struct razor_set *set,
256 struct import_directory *d, struct array *array)
258 struct import_directory *p, *end;
259 struct razor_entry *e = NULL;
263 end = d->files.data + d->files.size;
264 s = array->size / sizeof *e + d->files.size / sizeof *p;
266 e = array_add(array, sizeof *e);
269 e->start = p->count > 0 ? s : 0;
272 list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
273 array_release(&p->packages);
277 e->flags |= RAZOR_ENTRY_LAST;
280 end = d->files.data + d->files.size;
282 serialize_files(set, p, array);
288 remap_property_package_links(struct array *properties, uint32_t *rmap)
290 struct razor_property *p, *end;
292 end = properties->data + properties->size;
293 for (p = properties->data; p < end; p++)
294 list_remap_head(&p->packages, rmap);
298 build_file_tree(struct razor_importer *importer)
300 int count, i, length;
301 struct import_entry *filenames;
305 struct import_directory *d, root;
306 struct razor_entry *e;
308 count = importer->files.size / sizeof (struct import_entry);
309 razor_qsort_with_data(importer->files.data,
311 sizeof (struct import_entry),
315 root.name = hashtable_tokenize(&importer->table, "");
316 array_init(&root.files);
317 array_init(&root.packages);
320 filenames = importer->files.data;
321 for (i = 0; i < count; i++) {
322 f = filenames[i].name;
329 end = strchr(f, '/');
333 memcpy(dirname, f, length);
334 dirname[length] ='\0';
335 name = hashtable_tokenize(&importer->table, dirname);
336 if (d->last == NULL || d->last->name != name) {
337 d->last = array_add(&d->files, sizeof *d);
338 d->last->name = name;
339 d->last->last = NULL;
340 array_init(&d->last->files);
341 array_init(&d->last->packages);
349 r = array_add(&d->packages, sizeof *r);
350 *r = filenames[i].package;
351 free(filenames[i].name);
354 count_entries(&root);
355 e = importer->set->files.data;
357 e->flags = RAZOR_ENTRY_LAST;
358 e->start = importer->files.size ? 1 : 0;
359 list_set_empty(&e->packages);
361 serialize_files(importer->set, &root, &importer->set->files);
363 array_release(&importer->files);
367 list_to_array(struct list *list, struct array *array)
372 item = array_add(array, sizeof *item);
374 list = list_next(list);
379 compare_file_requires(const void *p1, const void *p2, void *data)
381 uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
382 const char *pool = data;
384 return strcmp(&pool[*f1], &pool[*f2]);
388 find_file_provides(struct razor_importer *importer)
390 struct razor_property *prop;
391 struct razor_entry *top, *entry;
392 struct razor_package *packages;
393 struct array pkgprops;
395 uint32_t *req, *req_start, *req_end;
396 uint32_t *map, *newprop;
399 pool = importer->set->string_pool.data;
400 packages = importer->set->packages.data;
401 top = importer->set->files.data;
403 req = req_start = importer->file_requires.data;
404 req_end = importer->file_requires.data + importer->file_requires.size;
405 map = razor_qsort_with_data(req, req_end - req, sizeof *req,
406 compare_file_requires, pool);
409 for (req = req_start; req < req_end; req++) {
410 if (req > req_start && req[0] == req[-1])
412 entry = razor_set_find_entry(importer->set, top, &pool[*req]);
416 for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
417 prop = array_add(&importer->set->properties, sizeof *prop);
420 RAZOR_PROPERTY_PROVIDES | RAZOR_PROPERTY_EQUAL;
421 prop->version = hashtable_tokenize(&importer->table, "");
422 list_set_ptr(&prop->packages, pkg->data);
424 /* Update property list of pkg */
425 array_init(&pkgprops);
426 list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
427 newprop = array_add(&pkgprops, sizeof *newprop);
428 *newprop = prop - (struct razor_property *)importer->set->properties.data;
429 list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
430 array_release(&pkgprops);
434 array_release(&importer->file_requires);
438 build_package_file_lists(struct razor_set *set, uint32_t *rmap)
440 struct razor_package *p, *packages;
442 struct razor_entry *e, *end;
447 count = set->packages.size / sizeof *p;
448 pkgs = zalloc(count * sizeof *pkgs);
450 end = set->files.data + set->files.size;
451 for (e = set->files.data; e < end; e++) {
452 list_remap_head(&e->packages, rmap);
453 r = list_first(&e->packages, &set->package_pool);
455 q = array_add(&pkgs[r->data], sizeof *q);
456 *q = e - (struct razor_entry *) set->files.data;
461 packages = set->packages.data;
462 for (i = 0; i < count; i++) {
463 list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
464 array_release(&pkgs[i]);
470 razor_importer_finish(struct razor_importer *importer)
472 struct razor_set *set;
473 uint32_t *map, *rmap;
476 build_file_tree(importer);
477 find_file_provides(importer);
479 map = uniqueify_properties(importer->set);
480 list_remap_pool(&importer->set->property_pool, map);
483 count = importer->set->packages.size / sizeof(struct razor_package);
484 map = razor_qsort_with_data(importer->set->packages.data,
486 sizeof(struct razor_package),
490 rmap = malloc(count * sizeof *rmap);
491 for (i = 0; i < count; i++)
495 list_remap_pool(&importer->set->package_pool, rmap);
496 build_package_file_lists(importer->set, rmap);
497 remap_property_package_links(&importer->set->properties, rmap);
501 hashtable_release(&importer->table);