Introduce install/remove iterators.
These iterator constructors lets you pass in two sets and creates
an iterator for the packages to remove or the packages to install.
The iterators will step through the packages in a sequence that respects
the pre, post, preun and postun modifiers.
Right now, the install order isn't actually implemented, this patch just
implements the API changes and updates the applications.
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_property(struct razor_importer *importer,
62 struct razor_property *p;
65 p = array_add(&importer->set->properties, sizeof *p);
66 p->name = hashtable_tokenize(&importer->table, name);
68 p->version = hashtable_tokenize(&importer->table, version);
69 list_set_ptr(&p->packages, importer->package -
70 (struct razor_package *) importer->set->packages.data);
72 r = array_add(&importer->properties, sizeof *r);
73 *r = p - (struct razor_property *) importer->set->properties.data;
75 if (((flags & RAZOR_PROPERTY_TYPE_MASK) == RAZOR_PROPERTY_REQUIRES) &&
77 r = array_add(&importer->file_requires, sizeof *r);
83 razor_importer_add_file(struct razor_importer *importer, const char *name)
85 struct import_entry *e;
87 e = array_add(&importer->files, sizeof *e);
89 e->package = importer->package -
90 (struct razor_package *) importer->set->packages.data;
91 e->name = strdup(name);
94 struct razor_importer *
95 razor_importer_create(void)
97 struct razor_importer *importer;
99 importer = zalloc(sizeof *importer);
100 importer->set = razor_set_create();
101 hashtable_init(&importer->table, &importer->set->string_pool);
106 /* Destroy an importer without creating the set. */
108 razor_importer_destroy(struct razor_importer *importer)
110 /* FIXME: write this */
114 compare_packages(const void *p1, const void *p2, void *data)
116 const struct razor_package *pkg1 = p1, *pkg2 = p2;
117 struct razor_set *set = data;
118 char *pool = set->string_pool.data;
120 /* FIXME: what if the flags are different? */
121 if (pkg1->name == pkg2->name)
122 return razor_versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
124 return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
128 compare_properties(const void *p1, const void *p2, void *data)
130 const struct razor_property *prop1 = p1, *prop2 = p2;
131 struct razor_set *set = data;
132 char *pool = set->string_pool.data;
134 if (prop1->name != prop2->name)
135 return strcmp(&pool[prop1->name], &pool[prop2->name]);
136 else if (prop1->flags != prop2->flags)
137 return prop1->flags - prop2->flags;
139 return razor_versioncmp(&pool[prop1->version], &pool[prop2->version]);
143 uniqueify_properties(struct razor_set *set)
145 struct razor_property *rp, *up, *rp_end;
146 struct array *pkgs, *p;
148 uint32_t *map, *rmap;
149 int i, count, unique;
151 count = set->properties.size / sizeof(struct razor_property);
152 map = razor_qsort_with_data(set->properties.data,
154 sizeof(struct razor_property),
158 rp_end = set->properties.data + set->properties.size;
159 rmap = malloc(count * sizeof *map);
160 pkgs = zalloc(count * sizeof *pkgs);
161 for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
162 if (rp->name != up->name ||
163 rp->flags != up->flags ||
164 rp->version != up->version) {
167 up->flags = rp->flags;
168 up->version = rp->version;
171 unique = up - (struct razor_property *) set->properties.data;
172 rmap[map[i]] = unique;
173 r = array_add(&pkgs[unique], sizeof *r);
180 set->properties.size = (void *) up - set->properties.data;
182 for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
183 list_set_array(&rp->packages, &set->package_pool, p, 0);
193 compare_filenames(const void *p1, const void *p2, void *data)
195 const struct import_entry *e1 = p1;
196 const struct import_entry *e2 = p2;
197 const char *n1 = e1->name;
198 const char *n2 = e2->name;
200 /* Need to make sure that the contents of a directory
201 * are sorted immediately after it. So "foo/bar" has to
202 * sort before "foo.conf"
204 * FIXME: this is about 60% slower than strcmp
208 return *n2 == '/' ? 1 : -1;
210 return *n1 == '/' ? -1 : 1;
223 count_entries(struct import_directory *d)
225 struct import_directory *p, *end;
228 end = d->files.data + d->files.size;
232 d->count += p->count + 1;
238 serialize_files(struct razor_set *set,
239 struct import_directory *d, struct array *array)
241 struct import_directory *p, *end;
242 struct razor_entry *e = NULL;
246 end = d->files.data + d->files.size;
247 s = array->size / sizeof *e + d->files.size / sizeof *p;
249 e = array_add(array, sizeof *e);
252 e->start = p->count > 0 ? s : 0;
255 list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
256 array_release(&p->packages);
260 e->flags |= RAZOR_ENTRY_LAST;
263 end = d->files.data + d->files.size;
265 serialize_files(set, p, array);
271 remap_property_package_links(struct array *properties, uint32_t *rmap)
273 struct razor_property *p, *end;
275 end = properties->data + properties->size;
276 for (p = properties->data; p < end; p++)
277 list_remap_head(&p->packages, rmap);
281 build_file_tree(struct razor_importer *importer)
283 int count, i, length;
284 struct import_entry *filenames;
288 struct import_directory *d, root;
289 struct razor_entry *e;
291 count = importer->files.size / sizeof (struct import_entry);
292 razor_qsort_with_data(importer->files.data,
294 sizeof (struct import_entry),
298 root.name = hashtable_tokenize(&importer->table, "");
299 array_init(&root.files);
300 array_init(&root.packages);
303 filenames = importer->files.data;
304 for (i = 0; i < count; i++) {
305 f = filenames[i].name;
312 end = strchr(f, '/');
316 memcpy(dirname, f, length);
317 dirname[length] ='\0';
318 name = hashtable_tokenize(&importer->table, dirname);
319 if (d->last == NULL || d->last->name != name) {
320 d->last = array_add(&d->files, sizeof *d);
321 d->last->name = name;
322 d->last->last = NULL;
323 array_init(&d->last->files);
324 array_init(&d->last->packages);
332 r = array_add(&d->packages, sizeof *r);
333 *r = filenames[i].package;
334 free(filenames[i].name);
337 count_entries(&root);
338 e = importer->set->files.data;
340 e->flags = RAZOR_ENTRY_LAST;
341 e->start = importer->files.size ? 1 : 0;
342 list_set_empty(&e->packages);
344 serialize_files(importer->set, &root, &importer->set->files);
346 array_release(&importer->files);
350 list_to_array(struct list *list, struct array *array)
355 item = array_add(array, sizeof *item);
357 list = list_next(list);
362 compare_file_requires(const void *p1, const void *p2, void *data)
364 uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
365 const char *pool = data;
367 return strcmp(&pool[*f1], &pool[*f2]);
371 find_file_provides(struct razor_importer *importer)
373 struct razor_property *prop;
374 struct razor_entry *top, *entry;
375 struct razor_package *packages;
376 struct array pkgprops;
378 uint32_t *req, *req_start, *req_end;
379 uint32_t *map, *newprop;
382 pool = importer->set->string_pool.data;
383 packages = importer->set->packages.data;
384 top = importer->set->files.data;
386 req = req_start = importer->file_requires.data;
387 req_end = importer->file_requires.data + importer->file_requires.size;
388 map = razor_qsort_with_data(req, req_end - req, sizeof *req,
389 compare_file_requires, pool);
392 for (req = req_start; req < req_end; req++) {
393 if (req > req_start && req[0] == req[-1])
395 entry = razor_set_find_entry(importer->set, top, &pool[*req]);
399 for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
400 prop = array_add(&importer->set->properties, sizeof *prop);
403 RAZOR_PROPERTY_PROVIDES | RAZOR_PROPERTY_EQUAL;
404 prop->version = hashtable_tokenize(&importer->table, "");
405 list_set_ptr(&prop->packages, pkg->data);
407 /* Update property list of pkg */
408 array_init(&pkgprops);
409 list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
410 newprop = array_add(&pkgprops, sizeof *newprop);
411 *newprop = prop - (struct razor_property *)importer->set->properties.data;
412 list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
413 array_release(&pkgprops);
417 array_release(&importer->file_requires);
421 build_package_file_lists(struct razor_set *set, uint32_t *rmap)
423 struct razor_package *p, *packages;
425 struct razor_entry *e, *end;
430 count = set->packages.size / sizeof *p;
431 pkgs = zalloc(count * sizeof *pkgs);
433 end = set->files.data + set->files.size;
434 for (e = set->files.data; e < end; e++) {
435 list_remap_head(&e->packages, rmap);
436 r = list_first(&e->packages, &set->package_pool);
438 q = array_add(&pkgs[r->data], sizeof *q);
439 *q = e - (struct razor_entry *) set->files.data;
444 packages = set->packages.data;
445 for (i = 0; i < count; i++) {
446 list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
447 array_release(&pkgs[i]);
453 razor_importer_finish(struct razor_importer *importer)
455 struct razor_set *set;
456 uint32_t *map, *rmap;
459 build_file_tree(importer);
460 find_file_provides(importer);
462 map = uniqueify_properties(importer->set);
463 list_remap_pool(&importer->set->property_pool, map);
466 count = importer->set->packages.size / sizeof(struct razor_package);
467 map = razor_qsort_with_data(importer->set->packages.data,
469 sizeof(struct razor_package),
473 rmap = malloc(count * sizeof *rmap);
474 for (i = 0; i < count; i++)
478 list_remap_pool(&importer->set->package_pool, rmap);
479 build_package_file_lists(importer->set, rmap);
480 remap_property_package_links(&importer->set->properties, rmap);
484 hashtable_release(&importer->table);