Fix old typo in file merging code.
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_create:
29 * Create a new %razor_importer.
31 * Returns: the new %razor_importer.
33 RAZOR_EXPORT struct razor_importer *
34 razor_importer_create(void)
36 struct razor_importer *importer;
38 importer = zalloc(sizeof *importer);
39 importer->set = razor_set_create();
40 hashtable_init(&importer->table, &importer->set->string_pool);
41 hashtable_init(&importer->details_table,
42 &importer->set->details_string_pool);
43 hashtable_init(&importer->file_table,
44 &importer->set->file_string_pool);
50 * razor_importer_destroy:
51 * @importer: the %razor_importer
53 * Destroy an importer without creating a %razor_set. Normally,
54 * %razor_importer_finish will create a new %razor_set and destroy the
55 * importer. If the import must be aborted without creating the set,
56 * just destroy the import using this function.
59 razor_importer_destroy(struct razor_importer *importer)
61 /* FIXME: write this */
66 * razor_importer_begin_package:
67 * @importer: the %razor_importer
68 * @name: the name of the new package
69 * @version: the version of the new package
70 * @arch: the architechture of the new package.
72 * Begin describing a new package to the importer. This creates a new
73 * package and sets the %name, %version and %arch. Subsequent calls
74 * to %razor_importer_add_details, %razor_importer_add_property and
75 * %razor_importer_add_file further describe this package and
76 * %razor_importer_finish_package marks the end of meta data for this
80 razor_importer_begin_package(struct razor_importer *importer,
85 struct razor_package *p;
87 p = array_add(&importer->set->packages, sizeof *p);
88 p->name = hashtable_tokenize(&importer->table, name);
90 p->version = hashtable_tokenize(&importer->table, version);
91 p->arch = hashtable_tokenize(&importer->table, arch);
93 importer->package = p;
94 array_init(&importer->properties);
98 * razor_importer_finish_package:
99 * @importer: the %razor_importer
101 * Tells the importer that the current package is complete.
104 razor_importer_finish_package(struct razor_importer *importer)
106 list_set_array(&importer->package->properties,
107 &importer->set->property_pool,
108 &importer->properties,
111 array_release(&importer->properties);
115 * razor_importer_add_details:
116 * @importer: the %razor_importer
117 * @summary: the package summary
118 * @description: the package description
119 * @url: the package url
120 * @license: the package license
122 * Provide additional information for the current package.
125 razor_importer_add_details(struct razor_importer *importer,
127 const char *description,
131 importer->package->summary = hashtable_tokenize(&importer->details_table, summary);
132 importer->package->description = hashtable_tokenize(&importer->details_table, description);
133 importer->package->url = hashtable_tokenize(&importer->details_table, url);
134 importer->package->license = hashtable_tokenize(&importer->details_table, license);
138 * razor_importer_add_property:
139 * @importer: the %razor_importer
140 * @name: name of the property
141 * @flags: property flags
142 * @version: version of the property or %NULL
144 * Add a property for the current package. The %flags parameter
145 * determines the type of the property and optionally the relation to
146 * the specified version and the availability constraint. See
147 * %razor_property_flags for further information about the flag
151 razor_importer_add_property(struct razor_importer *importer,
156 struct razor_property *p;
159 p = array_add(&importer->set->properties, sizeof *p);
160 p->name = hashtable_tokenize(&importer->table, name);
162 p->version = hashtable_tokenize(&importer->table, version);
163 list_set_ptr(&p->packages, importer->package -
164 (struct razor_package *) importer->set->packages.data);
166 r = array_add(&importer->properties, sizeof *r);
167 *r = p - (struct razor_property *) importer->set->properties.data;
169 if (((flags & RAZOR_PROPERTY_TYPE_MASK) == RAZOR_PROPERTY_REQUIRES) &&
171 r = array_add(&importer->file_requires, sizeof *r);
177 * razor_importer_add_file:
178 * @importer: the %razor_importer
179 * @name: name of the file
181 * Add a file to the current package.
184 razor_importer_add_file(struct razor_importer *importer, const char *name)
186 struct import_entry *e;
188 e = array_add(&importer->files, sizeof *e);
190 e->package = importer->package -
191 (struct razor_package *) importer->set->packages.data;
192 e->name = strdup(name);
196 compare_packages(const void *p1, const void *p2, void *data)
198 const struct razor_package *pkg1 = p1, *pkg2 = p2;
199 struct razor_set *set = data;
200 char *pool = set->string_pool.data;
202 /* FIXME: what if the flags are different? */
203 if (pkg1->name == pkg2->name)
204 return razor_versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
206 return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
210 compare_properties(const void *p1, const void *p2, void *data)
212 const struct razor_property *prop1 = p1, *prop2 = p2;
213 struct razor_set *set = data;
214 char *pool = set->string_pool.data;
216 if (prop1->name != prop2->name)
217 return strcmp(&pool[prop1->name], &pool[prop2->name]);
218 else if (prop1->flags != prop2->flags)
219 return prop1->flags - prop2->flags;
220 else if (prop1->version != prop2->version)
221 return razor_versioncmp(&pool[prop1->version], &pool[prop2->version]);
223 return prop1->packages.list_ptr - prop2->packages.list_ptr;
227 uniqueify_properties(struct razor_set *set)
229 struct razor_property *rp, *up, *rp_end;
230 struct array *pkgs, *p;
232 uint32_t *map, *rmap;
233 int i, count, unique;
235 count = set->properties.size / sizeof(struct razor_property);
236 map = razor_qsort_with_data(set->properties.data,
238 sizeof(struct razor_property),
242 rp_end = set->properties.data + set->properties.size;
243 rmap = malloc(count * sizeof *map);
244 pkgs = zalloc(count * sizeof *pkgs);
245 for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
246 if (rp->name != up->name ||
247 rp->flags != up->flags ||
248 rp->version != up->version) {
251 up->flags = rp->flags;
252 up->version = rp->version;
255 unique = up - (struct razor_property *) set->properties.data;
256 rmap[map[i]] = unique;
257 r = array_add(&pkgs[unique], sizeof *r);
264 set->properties.size = (void *) up - set->properties.data;
266 for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
267 list_set_array(&rp->packages, &set->package_pool, p, 0);
277 compare_filenames(const void *p1, const void *p2, void *data)
279 const struct import_entry *e1 = p1;
280 const struct import_entry *e2 = p2;
281 const char *n1 = e1->name;
282 const char *n2 = e2->name;
284 /* Need to make sure that the contents of a directory
285 * are sorted immediately after it. So "foo/bar" has to
286 * sort before "foo.conf"
288 * FIXME: this is about 60% slower than strcmp
292 return *n2 == '/' ? 1 : -1;
294 return *n1 == '/' ? -1 : 1;
307 count_entries(struct import_directory *d)
309 struct import_directory *p, *end;
312 end = d->files.data + d->files.size;
316 d->count += p->count + 1;
322 serialize_files(struct razor_set *set,
323 struct import_directory *d, struct array *array)
325 struct import_directory *p, *end;
326 struct razor_entry *e = NULL;
330 end = d->files.data + d->files.size;
331 s = array->size / sizeof *e + d->files.size / sizeof *p;
333 e = array_add(array, sizeof *e);
336 e->start = p->count > 0 ? s : 0;
339 list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
340 array_release(&p->packages);
344 e->flags |= RAZOR_ENTRY_LAST;
347 end = d->files.data + d->files.size;
349 serialize_files(set, p, array);
355 remap_property_package_links(struct array *properties, uint32_t *rmap)
357 struct razor_property *p, *end;
359 end = properties->data + properties->size;
360 for (p = properties->data; p < end; p++)
361 list_remap_head(&p->packages, rmap);
365 build_file_tree(struct razor_importer *importer)
367 int count, i, length;
368 struct import_entry *filenames;
372 struct import_directory *d, root;
373 struct razor_entry *e;
375 count = importer->files.size / sizeof (struct import_entry);
376 razor_qsort_with_data(importer->files.data,
378 sizeof (struct import_entry),
382 root.name = hashtable_tokenize(&importer->file_table, "");
383 array_init(&root.files);
384 array_init(&root.packages);
387 filenames = importer->files.data;
388 for (i = 0; i < count; i++) {
389 f = filenames[i].name;
396 end = strchr(f, '/');
400 memcpy(dirname, f, length);
401 dirname[length] ='\0';
402 name = hashtable_tokenize(&importer->file_table,
404 if (d->last == NULL || d->last->name != name) {
405 d->last = array_add(&d->files, sizeof *d);
406 d->last->name = name;
407 d->last->last = NULL;
408 array_init(&d->last->files);
409 array_init(&d->last->packages);
417 r = array_add(&d->packages, sizeof *r);
418 *r = filenames[i].package;
419 free(filenames[i].name);
422 count_entries(&root);
423 e = importer->set->files.data;
425 e->flags = RAZOR_ENTRY_LAST;
426 e->start = importer->files.size ? 1 : 0;
427 list_set_empty(&e->packages);
429 serialize_files(importer->set, &root, &importer->set->files);
431 array_release(&importer->files);
435 list_to_array(struct list *list, struct array *array)
440 item = array_add(array, sizeof *item);
442 list = list_next(list);
447 compare_file_requires(const void *p1, const void *p2, void *data)
449 uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
450 const char *pool = data;
452 return strcmp(&pool[*f1], &pool[*f2]);
456 find_file_provides(struct razor_importer *importer)
458 struct razor_property *prop;
459 struct razor_entry *top, *entry;
460 struct razor_package *packages;
461 struct array pkgprops;
463 uint32_t *req, *req_start, *req_end;
464 uint32_t *map, *newprop;
467 pool = importer->set->string_pool.data;
468 packages = importer->set->packages.data;
469 top = importer->set->files.data;
471 req = req_start = importer->file_requires.data;
472 req_end = importer->file_requires.data + importer->file_requires.size;
473 map = razor_qsort_with_data(req, req_end - req, sizeof *req,
474 compare_file_requires, pool);
477 for (req = req_start; req < req_end; req++) {
478 if (req > req_start && req[0] == req[-1])
480 entry = razor_set_find_entry(importer->set, top, &pool[*req]);
484 for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
485 prop = array_add(&importer->set->properties, sizeof *prop);
488 RAZOR_PROPERTY_PROVIDES | RAZOR_PROPERTY_EQUAL;
489 prop->version = hashtable_tokenize(&importer->table, "");
490 list_set_ptr(&prop->packages, pkg->data);
492 /* Update property list of pkg */
493 array_init(&pkgprops);
494 list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
495 newprop = array_add(&pkgprops, sizeof *newprop);
496 *newprop = prop - (struct razor_property *)importer->set->properties.data;
497 list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
498 array_release(&pkgprops);
502 array_release(&importer->file_requires);
506 build_package_file_lists(struct razor_set *set, uint32_t *rmap)
508 struct razor_package *p, *packages;
510 struct razor_entry *e, *end;
515 count = set->packages.size / sizeof *p;
516 pkgs = zalloc(count * sizeof *pkgs);
518 end = set->files.data + set->files.size;
519 for (e = set->files.data; e < end; e++) {
520 list_remap_head(&e->packages, rmap);
521 r = list_first(&e->packages, &set->package_pool);
523 q = array_add(&pkgs[r->data], sizeof *q);
524 *q = e - (struct razor_entry *) set->files.data;
529 packages = set->packages.data;
530 for (i = 0; i < count; i++) {
531 list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
532 array_release(&pkgs[i]);
538 * razor_importer_finish:
539 * @importer: the %razor_importer
541 * Finish importing packages and create the package set. This sorts
542 * and indexes all the packages, properties and files in the importer
543 * and creates a new %razor_set. After creating the new package set,
544 * the importer is destroyed.
546 * Returns: the new %razor_set
548 RAZOR_EXPORT struct razor_set *
549 razor_importer_finish(struct razor_importer *importer)
551 struct razor_set *set;
552 uint32_t *map, *rmap;
555 build_file_tree(importer);
556 find_file_provides(importer);
558 map = uniqueify_properties(importer->set);
559 list_remap_pool(&importer->set->property_pool, map);
562 count = importer->set->packages.size / sizeof(struct razor_package);
563 map = razor_qsort_with_data(importer->set->packages.data,
565 sizeof(struct razor_package),
569 rmap = malloc(count * sizeof *rmap);
570 for (i = 0; i < count; i++)
574 list_remap_pool(&importer->set->package_pool, rmap);
575 build_package_file_lists(importer->set, rmap);
576 remap_property_package_links(&importer->set->properties, rmap);
580 hashtable_release(&importer->table);
581 hashtable_release(&importer->details_table);
582 hashtable_release(&importer->file_table);