Record the time of dependencies (post, pre, postun, preun).
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.
27 #include <sys/types.h>
37 #include "razor-internal.h"
40 struct razor_set_section {
46 struct razor_set_header {
49 struct razor_set_section sections[0];
52 #define RAZOR_MAGIC 0x7a7a7a7a
53 #define RAZOR_VERSION 1
55 #define RAZOR_STRING_POOL 0
56 #define RAZOR_PACKAGES 1
57 #define RAZOR_PROPERTIES 2
59 #define RAZOR_PACKAGE_POOL 4
60 #define RAZOR_PROPERTY_POOL 5
61 #define RAZOR_FILE_POOL 6
63 struct razor_package {
68 struct list_head properties;
69 struct list_head files;
72 struct razor_property {
76 struct list_head packages;
83 struct list_head packages;
86 #define RAZOR_ENTRY_LAST 0x80
89 struct array string_pool;
90 struct array packages;
91 struct array properties;
93 struct array package_pool;
94 struct array property_pool;
95 struct array file_pool;
96 struct razor_set_header *header;
104 struct import_directory {
105 uint32_t name, count;
107 struct array packages;
108 struct import_directory *last;
111 struct razor_importer {
112 struct razor_set *set;
113 struct hashtable table;
114 struct razor_package *package;
115 struct array properties;
117 struct array file_requires;
131 struct razor_set_section razor_sections[] = {
132 { RAZOR_STRING_POOL, offsetof(struct razor_set, string_pool) },
133 { RAZOR_PACKAGES, offsetof(struct razor_set, packages) },
134 { RAZOR_PROPERTIES, offsetof(struct razor_set, properties) },
135 { RAZOR_FILES, offsetof(struct razor_set, files) },
136 { RAZOR_PACKAGE_POOL, offsetof(struct razor_set, package_pool) },
137 { RAZOR_PROPERTY_POOL, offsetof(struct razor_set, property_pool) },
138 { RAZOR_FILE_POOL, offsetof(struct razor_set, file_pool) },
142 razor_set_create(void)
144 struct razor_set *set;
145 struct razor_entry *e;
148 set = zalloc(sizeof *set);
150 e = array_add(&set->files, sizeof *e);
151 empty = array_add(&set->string_pool, 1);
154 e->flags = RAZOR_ENTRY_LAST;
156 list_set_empty(&e->packages);
162 razor_set_open(const char *filename)
164 struct razor_set *set;
165 struct razor_set_section *s;
170 set = zalloc(sizeof *set);
171 fd = open(filename, O_RDONLY);
172 if (fstat(fd, &stat) < 0)
174 set->header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
175 if (set->header == MAP_FAILED) {
180 for (s = set->header->sections; ~s->type; s++) {
181 if (s->type >= ARRAY_SIZE(razor_sections))
183 if (s->type != razor_sections[s->type].type)
185 array = (void *) set + razor_sections[s->type].offset;
186 array->data = (void *) set->header + s->offset;
187 array->size = s->size;
188 array->alloc = s->size;
196 razor_set_destroy(struct razor_set *set)
203 for (i = 0; set->header->sections[i].type; i++)
205 size = set->header->sections[i].type;
206 munmap(set->header, size);
208 for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
209 a = (void *) set + razor_sections[i].offset;
218 razor_set_write_to_fd(struct razor_set *set, int fd)
221 struct razor_set_header *header = (struct razor_set_header *) data;
226 memset(data, 0, sizeof data);
227 header->magic = RAZOR_MAGIC;
228 header->version = RAZOR_VERSION;
229 offset = sizeof data;
231 for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
232 if (razor_sections[i].type != i)
234 a = (void *) set + razor_sections[i].offset;
235 header->sections[i].type = i;
236 header->sections[i].offset = offset;
237 header->sections[i].size = a->size;
238 offset += ALIGN(a->size, 4096);
241 header->sections[i].type = ~0;
242 header->sections[i].offset = 0;
243 header->sections[i].size = 0;
245 razor_write(fd, data, sizeof data);
246 memset(data, 0, sizeof data);
247 for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
248 if (razor_sections[i].type != i)
250 a = (void *) set + razor_sections[i].offset;
251 razor_write(fd, a->data, a->size);
252 razor_write(fd, data, ALIGN(a->size, 4096) - a->size);
259 razor_set_write(struct razor_set *set, const char *filename)
263 fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
267 status = razor_set_write_to_fd(set, fd);
277 razor_build_evr(char *evr_buf, int size, const char *epoch,
278 const char *version, const char *release)
282 if (!version || !*version) {
287 if (epoch && *epoch && strcmp(epoch, "0") != 0) {
288 len = snprintf(evr_buf, size, "%s:", epoch);
292 len = snprintf(evr_buf, size, "%s", version);
295 if (release && *release)
296 snprintf(evr_buf, size, "-%s", release);
300 razor_importer_begin_package(struct razor_importer *importer,
305 struct razor_package *p;
307 p = array_add(&importer->set->packages, sizeof *p);
308 p->name = hashtable_tokenize(&importer->table, name);
310 p->version = hashtable_tokenize(&importer->table, version);
311 p->arch = hashtable_tokenize(&importer->table, arch);
313 importer->package = p;
314 array_init(&importer->properties);
319 razor_importer_finish_package(struct razor_importer *importer)
321 list_set_array(&importer->package->properties,
322 &importer->set->property_pool,
323 &importer->properties,
326 array_release(&importer->properties);
330 razor_importer_add_property(struct razor_importer *importer,
335 struct razor_property *p;
338 p = array_add(&importer->set->properties, sizeof *p);
339 p->name = hashtable_tokenize(&importer->table, name);
341 p->version = hashtable_tokenize(&importer->table, version);
342 list_set_ptr(&p->packages, importer->package -
343 (struct razor_package *) importer->set->packages.data);
345 r = array_add(&importer->properties, sizeof *r);
346 *r = p - (struct razor_property *) importer->set->properties.data;
348 if (((flags & RAZOR_PROPERTY_TYPE_MASK) == RAZOR_PROPERTY_REQUIRES) &&
350 r = array_add(&importer->file_requires, sizeof *r);
356 razor_importer_add_file(struct razor_importer *importer, const char *name)
358 struct import_entry *e;
360 e = array_add(&importer->files, sizeof *e);
362 e->package = importer->package -
363 (struct razor_package *) importer->set->packages.data;
364 e->name = strdup(name);
367 struct razor_importer *
368 razor_importer_new(void)
370 struct razor_importer *importer;
372 importer = zalloc(sizeof *importer);
373 importer->set = razor_set_create();
374 hashtable_init(&importer->table, &importer->set->string_pool);
379 /* Destroy an importer without creating the set. */
381 razor_importer_destroy(struct razor_importer *importer)
383 /* FIXME: write this */
387 versioncmp(const char *s1, const char *s2)
393 n1 = strtol(s1, (char **) &p1, 10);
394 n2 = strtol(s2, (char **) &p2, 10);
396 /* Epoch; if one but not the other has an epoch set, default
397 * the epoch-less version to 0. */
398 res = (*p1 == ':') - (*p2 == ':');
403 } else if (res > 0) {
416 if (isdigit(*p1) && isdigit(*p2))
417 return versioncmp(p1, p2);
424 compare_packages(const void *p1, const void *p2, void *data)
426 const struct razor_package *pkg1 = p1, *pkg2 = p2;
427 struct razor_set *set = data;
428 char *pool = set->string_pool.data;
430 /* FIXME: what if the flags are different? */
431 if (pkg1->name == pkg2->name)
432 return versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
434 return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
438 compare_properties(const void *p1, const void *p2, void *data)
440 const struct razor_property *prop1 = p1, *prop2 = p2;
441 struct razor_set *set = data;
442 char *pool = set->string_pool.data;
444 if (prop1->name != prop2->name)
445 return strcmp(&pool[prop1->name], &pool[prop2->name]);
446 else if (prop1->flags != prop2->flags)
447 return prop1->flags - prop2->flags;
449 return versioncmp(&pool[prop1->version], &pool[prop2->version]);
453 uniqueify_properties(struct razor_set *set)
455 struct razor_property *rp, *up, *rp_end;
456 struct array *pkgs, *p;
458 uint32_t *map, *rmap;
459 int i, count, unique;
461 count = set->properties.size / sizeof(struct razor_property);
462 map = razor_qsort_with_data(set->properties.data,
464 sizeof(struct razor_property),
468 rp_end = set->properties.data + set->properties.size;
469 rmap = malloc(count * sizeof *map);
470 pkgs = zalloc(count * sizeof *pkgs);
471 for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
472 if (rp->name != up->name ||
473 rp->flags != up->flags ||
474 rp->version != up->version) {
477 up->flags = rp->flags;
478 up->version = rp->version;
481 unique = up - (struct razor_property *) set->properties.data;
482 rmap[map[i]] = unique;
483 r = array_add(&pkgs[unique], sizeof *r);
490 set->properties.size = (void *) up - set->properties.data;
492 for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
493 list_set_array(&rp->packages, &set->package_pool, p, 0);
503 compare_filenames(const void *p1, const void *p2, void *data)
505 const struct import_entry *e1 = p1;
506 const struct import_entry *e2 = p2;
507 const char *n1 = e1->name;
508 const char *n2 = e2->name;
510 /* Need to make sure that the contents of a directory
511 * are sorted immediately after it. So "foo/bar" has to
512 * sort before "foo.conf"
514 * FIXME: this is about 60% slower than strcmp
518 return *n2 == '/' ? 1 : -1;
520 return *n1 == '/' ? -1 : 1;
533 count_entries(struct import_directory *d)
535 struct import_directory *p, *end;
538 end = d->files.data + d->files.size;
542 d->count += p->count + 1;
548 serialize_files(struct razor_set *set,
549 struct import_directory *d, struct array *array)
551 struct import_directory *p, *end;
552 struct razor_entry *e = NULL;
556 end = d->files.data + d->files.size;
557 s = array->size / sizeof *e + d->files.size / sizeof *p;
559 e = array_add(array, sizeof *e);
562 e->start = p->count > 0 ? s : 0;
565 list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
566 array_release(&p->packages);
570 e->flags |= RAZOR_ENTRY_LAST;
573 end = d->files.data + d->files.size;
575 serialize_files(set, p, array);
581 remap_property_package_links(struct array *properties, uint32_t *rmap)
583 struct razor_property *p, *end;
585 end = properties->data + properties->size;
586 for (p = properties->data; p < end; p++)
587 list_remap_head(&p->packages, rmap);
591 build_file_tree(struct razor_importer *importer)
593 int count, i, length;
594 struct import_entry *filenames;
598 struct import_directory *d, root;
599 struct razor_entry *e;
601 count = importer->files.size / sizeof (struct import_entry);
602 razor_qsort_with_data(importer->files.data,
604 sizeof (struct import_entry),
608 root.name = hashtable_tokenize(&importer->table, "");
609 array_init(&root.files);
610 array_init(&root.packages);
613 filenames = importer->files.data;
614 for (i = 0; i < count; i++) {
615 f = filenames[i].name;
622 end = strchr(f, '/');
626 memcpy(dirname, f, length);
627 dirname[length] ='\0';
628 name = hashtable_tokenize(&importer->table, dirname);
629 if (d->last == NULL || d->last->name != name) {
630 d->last = array_add(&d->files, sizeof *d);
631 d->last->name = name;
632 d->last->last = NULL;
633 array_init(&d->last->files);
634 array_init(&d->last->packages);
642 r = array_add(&d->packages, sizeof *r);
643 *r = filenames[i].package;
644 free(filenames[i].name);
647 count_entries(&root);
648 e = importer->set->files.data;
650 e->flags = RAZOR_ENTRY_LAST;
651 e->start = importer->files.size ? 1 : 0;
652 list_set_empty(&e->packages);
654 serialize_files(importer->set, &root, &importer->set->files);
656 array_release(&importer->files);
659 static struct razor_entry *
660 find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern);
663 list_to_array(struct list *list, struct array *array)
668 item = array_add(array, sizeof *item);
670 list = list_next(list);
675 compare_file_requires(const void *p1, const void *p2, void *data)
677 uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
678 const char *pool = data;
680 return strcmp(&pool[*f1], &pool[*f2]);
684 find_file_provides(struct razor_importer *importer)
686 struct razor_property *prop;
687 struct razor_entry *top, *entry;
688 struct razor_package *packages;
689 struct array pkgprops;
691 uint32_t *req, *req_start, *req_end;
692 uint32_t *map, *newprop;
695 pool = importer->set->string_pool.data;
696 packages = importer->set->packages.data;
697 top = importer->set->files.data;
699 req = req_start = importer->file_requires.data;
700 req_end = importer->file_requires.data + importer->file_requires.size;
701 map = razor_qsort_with_data(req, req_end - req, sizeof *req,
702 compare_file_requires, pool);
705 for (req = req_start; req < req_end; req++) {
706 if (req > req_start && req[0] == req[-1])
708 entry = find_entry(importer->set, top, &pool[*req]);
712 for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
713 prop = array_add(&importer->set->properties, sizeof *prop);
716 RAZOR_PROPERTY_PROVIDES | RAZOR_PROPERTY_EQUAL;
717 prop->version = hashtable_tokenize(&importer->table, "");
718 list_set_ptr(&prop->packages, pkg->data);
720 /* Update property list of pkg */
721 array_init(&pkgprops);
722 list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
723 newprop = array_add(&pkgprops, sizeof *newprop);
724 *newprop = prop - (struct razor_property *)importer->set->properties.data;
725 list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
726 array_release(&pkgprops);
730 array_release(&importer->file_requires);
734 build_package_file_lists(struct razor_set *set, uint32_t *rmap)
736 struct razor_package *p, *packages;
738 struct razor_entry *e, *end;
743 count = set->packages.size / sizeof *p;
744 pkgs = zalloc(count * sizeof *pkgs);
746 end = set->files.data + set->files.size;
747 for (e = set->files.data; e < end; e++) {
748 list_remap_head(&e->packages, rmap);
749 r = list_first(&e->packages, &set->package_pool);
751 q = array_add(&pkgs[r->data], sizeof *q);
752 *q = e - (struct razor_entry *) set->files.data;
757 packages = set->packages.data;
758 for (i = 0; i < count; i++) {
759 list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
760 array_release(&pkgs[i]);
766 razor_importer_finish(struct razor_importer *importer)
768 struct razor_set *set;
769 uint32_t *map, *rmap;
772 build_file_tree(importer);
773 find_file_provides(importer);
775 map = uniqueify_properties(importer->set);
776 list_remap_pool(&importer->set->property_pool, map);
779 count = importer->set->packages.size / sizeof(struct razor_package);
780 map = razor_qsort_with_data(importer->set->packages.data,
782 sizeof(struct razor_package),
786 rmap = malloc(count * sizeof *rmap);
787 for (i = 0; i < count; i++)
791 list_remap_pool(&importer->set->package_pool, rmap);
792 build_package_file_lists(importer->set, rmap);
793 remap_property_package_links(&importer->set->properties, rmap);
797 hashtable_release(&importer->table);
803 struct razor_package_iterator {
804 struct razor_set *set;
805 struct razor_package *package, *end;
810 static struct razor_package_iterator *
811 razor_package_iterator_create_with_index(struct razor_set *set,
814 struct razor_package_iterator *pi;
816 pi = zalloc(sizeof *pi);
823 struct razor_package_iterator *
824 razor_package_iterator_create(struct razor_set *set)
826 struct razor_package_iterator *pi;
828 pi = zalloc(sizeof *pi);
830 pi->end = set->packages.data + set->packages.size;
831 pi->package = set->packages.data;
837 razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
838 struct razor_set *set,
839 struct razor_property *property)
841 memset(pi, 0, sizeof *pi);
843 pi->index = list_first(&property->packages, &set->package_pool);
846 struct razor_package_iterator *
847 razor_package_iterator_create_for_property(struct razor_set *set,
848 struct razor_property *property)
852 index = list_first(&property->packages, &set->package_pool);
853 return razor_package_iterator_create_with_index(set, index);
857 razor_package_iterator_next(struct razor_package_iterator *pi,
858 struct razor_package **package,
860 const char **version,
865 struct razor_package *p, *packages;
870 } else if (pi->index) {
871 packages = pi->set->packages.data;
872 p = &packages[pi->index->data];
873 pi->index = list_next(pi->index);
879 pool = pi->set->string_pool.data;
881 *name = &pool[p->name];
882 *version = &pool[p->version];
883 *arch = &pool[p->arch];
892 razor_package_iterator_destroy(struct razor_package_iterator *pi)
900 struct razor_package *
901 razor_set_get_package(struct razor_set *set, const char *package)
903 struct razor_package_iterator *pi;
904 struct razor_package *p;
905 const char *name, *version, *arch;
907 pi = razor_package_iterator_create(set);
908 while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
909 if (strcmp(package, name) == 0)
912 razor_package_iterator_destroy(pi);
917 struct razor_property_iterator {
918 struct razor_set *set;
919 struct razor_property *property, *end;
923 struct razor_property_iterator *
924 razor_property_iterator_create(struct razor_set *set,
925 struct razor_package *package)
927 struct razor_property_iterator *pi;
929 pi = zalloc(sizeof *pi);
933 pi->index = list_first(&package->properties,
934 &set->property_pool);
936 pi->property = set->properties.data;
937 pi->end = set->properties.data + set->properties.size;
944 razor_property_iterator_next(struct razor_property_iterator *pi,
945 struct razor_property **property,
948 const char **version)
952 struct razor_property *p, *properties;
957 } else if (pi->index) {
958 properties = pi->set->properties.data;
959 p = &properties[pi->index->data];
960 pi->index = list_next(pi->index);
966 pool = pi->set->string_pool.data;
968 *name = &pool[p->name];
970 *version = &pool[p->version];
979 razor_property_iterator_destroy(struct razor_property_iterator *pi)
984 static struct razor_entry *
985 find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern)
987 struct razor_entry *e;
988 const char *n, *pool = set->string_pool.data;
991 e = (struct razor_entry *) set->files.data + dir->start;
994 if (strcmp(pattern + 1, n) == 0)
997 if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
998 pattern[len + 1] == '/') {
999 return find_entry(set, e, pattern + len + 1);
1001 } while (!((e++)->flags & RAZOR_ENTRY_LAST));
1007 list_dir(struct razor_set *set, struct razor_entry *dir,
1008 char *prefix, const char *pattern)
1010 struct razor_entry *e;
1011 const char *n, *pool = set->string_pool.data;
1013 e = (struct razor_entry *) set->files.data + dir->start;
1016 if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
1018 printf("%s/%s\n", prefix, n);
1020 char *sub = prefix + strlen (prefix);
1022 strcpy (sub + 1, n);
1023 list_dir(set, e, prefix, pattern);
1026 } while (!((e++)->flags & RAZOR_ENTRY_LAST));
1030 razor_set_list_files(struct razor_set *set, const char *pattern)
1032 struct razor_entry *e;
1033 char buffer[512], *p, *base;
1035 if (pattern == NULL || !strcmp (pattern, "/")) {
1037 list_dir(set, set->files.data, buffer, NULL);
1041 strcpy(buffer, pattern);
1042 e = find_entry(set, set->files.data, buffer);
1043 if (e && e->start > 0) {
1046 p = strrchr(buffer, '/');
1054 e = find_entry(set, set->files.data, buffer);
1056 list_dir(set, e, buffer, base);
1059 struct razor_package_iterator *
1060 razor_package_iterator_create_for_file(struct razor_set *set,
1061 const char *filename)
1063 struct razor_entry *entry;
1066 entry = find_entry(set, set->files.data, filename);
1070 index = list_first(&entry->packages, &set->package_pool);
1071 return razor_package_iterator_create_with_index(set, index);
1074 static struct list *
1075 list_package_files(struct razor_set *set, struct list *r,
1076 struct razor_entry *dir, uint32_t end,
1079 struct razor_entry *e, *f, *entries;
1080 uint32_t next, file;
1084 entries = (struct razor_entry *) set->files.data;
1085 pool = set->string_pool.data;
1087 e = entries + dir->start;
1089 if (entries + r->data == e) {
1090 printf("%s/%s\n", prefix, pool + e->name);
1097 } while (!((e++)->flags & RAZOR_ENTRY_LAST));
1099 e = entries + dir->start;
1104 if (e->flags & RAZOR_ENTRY_LAST)
1108 while (f->start == 0 && !(f->flags & RAZOR_ENTRY_LAST))
1117 if (e->start <= file && file < next) {
1118 len = strlen(prefix);
1120 strcpy(prefix + len + 1, pool + e->name);
1121 r = list_package_files(set, r, e, next, prefix);
1124 } while (!((e++)->flags & RAZOR_ENTRY_LAST) && r != NULL);
1130 razor_set_list_package_files(struct razor_set *set, const char *name)
1132 struct razor_package *package;
1137 package = razor_set_get_package(set, name);
1139 r = list_first(&package->files, &set->file_pool);
1140 end = set->files.size / sizeof (struct razor_entry);
1142 list_package_files(set, r, set->files.data, end, buffer);
1145 #define UPSTREAM_SOURCE 0x80
1148 struct razor_set *set;
1149 uint32_t *property_map;
1153 struct razor_merger {
1154 struct razor_set *set;
1155 struct hashtable table;
1156 struct source source1;
1157 struct source source2;
1160 static struct razor_merger *
1161 razor_merger_create(struct razor_set *set1, struct razor_set *set2)
1163 struct razor_merger *merger;
1167 merger = zalloc(sizeof *merger);
1168 merger->set = razor_set_create();
1169 hashtable_init(&merger->table, &merger->set->string_pool);
1171 merger->source1.set = set1;
1172 count = set1->properties.size / sizeof (struct razor_property);
1173 size = count * sizeof merger->source1.property_map[0];
1174 merger->source1.property_map = zalloc(size);
1175 count = set1->files.size / sizeof (struct razor_entry);
1176 size = count * sizeof merger->source1.file_map[0];
1177 merger->source1.file_map = zalloc(size);
1179 merger->source2.set = set2;
1180 count = set2->properties.size / sizeof (struct razor_property);
1181 size = count * sizeof merger->source2.property_map[0];
1182 merger->source2.property_map = zalloc(size);
1183 count = set2->files.size / sizeof (struct razor_entry);
1184 size = count * sizeof merger->source2.file_map[0];
1185 merger->source2.file_map = zalloc(size);
1191 razor_merger_add_package(struct razor_merger *merger,
1192 struct razor_package *package)
1196 struct razor_package *p;
1197 struct razor_set *set1;
1198 struct source *source;
1201 set1 = merger->source1.set;
1202 if (set1->packages.data <= (void *) package &&
1203 (void *) package < set1->packages.data + set1->packages.size) {
1204 source = &merger->source1;
1207 source = &merger->source2;
1208 flags = UPSTREAM_SOURCE;
1211 pool = source->set->string_pool.data;
1212 p = array_add(&merger->set->packages, sizeof *p);
1213 p->name = hashtable_tokenize(&merger->table, &pool[package->name]);
1215 p->version = hashtable_tokenize(&merger->table,
1216 &pool[package->version]);
1217 p->arch = hashtable_tokenize(&merger->table,
1218 &pool[package->arch]);
1220 p->properties = package->properties;
1221 r = list_first(&package->properties, &source->set->property_pool);
1223 source->property_map[r->data] = 1;
1227 p->files = package->files;
1228 r = list_first(&package->files, &source->set->file_pool);
1230 source->file_map[r->data] = 1;
1236 add_property(struct razor_merger *merger,
1237 const char *name, uint32_t flags, const char *version)
1239 struct razor_property *p;
1241 p = array_add(&merger->set->properties, sizeof *p);
1242 p->name = hashtable_tokenize(&merger->table, name);
1244 p->version = hashtable_tokenize(&merger->table, version);
1246 return p - (struct razor_property *) merger->set->properties.data;
1250 merge_properties(struct razor_merger *merger)
1252 struct razor_property *p1, *p2;
1253 struct razor_set *set1, *set2;
1254 uint32_t *map1, *map2;
1255 int i, j, cmp, count1, count2;
1256 char *pool1, *pool2;
1258 set1 = merger->source1.set;
1259 set2 = merger->source2.set;
1260 map1 = merger->source1.property_map;
1261 map2 = merger->source2.property_map;
1265 pool1 = set1->string_pool.data;
1266 pool2 = set2->string_pool.data;
1268 count1 = set1->properties.size / sizeof *p1;
1269 count2 = set2->properties.size / sizeof *p2;
1270 while (i < count1 || j < count2) {
1271 if (i < count1 && map1[i] == 0) {
1275 if (j < count2 && map2[j] == 0) {
1279 p1 = (struct razor_property *) set1->properties.data + i;
1280 p2 = (struct razor_property *) set2->properties.data + j;
1281 if (i < count1 && j < count2)
1282 cmp = strcmp(&pool1[p1->name], &pool2[p2->name]);
1283 else if (i < count1)
1288 cmp = p1->flags - p2->flags;
1290 cmp = versioncmp(&pool1[p1->version],
1291 &pool2[p2->version]);
1293 map1[i++] = add_property(merger,
1296 &pool1[p1->version]);
1297 } else if (cmp > 0) {
1298 map2[j++] = add_property(merger,
1301 &pool2[p2->version]);
1303 map1[i++] = map2[j++] =
1304 add_property(merger,
1307 &pool1[p1->version]);
1313 emit_properties(struct list_head *properties, struct array *source_pool,
1314 uint32_t *map, struct array *pool)
1319 r = pool->size / sizeof *q;
1320 p = list_first(properties, source_pool);
1322 q = array_add(pool, sizeof *q);
1323 q->data = map[p->data];
1324 q->flags = p->flags;
1328 list_set_ptr(properties, r);
1332 add_file(struct razor_merger *merger, const char *name)
1334 struct razor_entry *e;
1336 e = array_add(&merger->set->files, sizeof *e);
1337 e->name = hashtable_tokenize(&merger->table, name);
1341 return e - (struct razor_entry *)merger->set->files.data;
1346 fix_file_map(uint32_t *map,
1347 struct razor_entry *files,
1348 struct razor_entry *top)
1356 fix_file_map(map, files, &files[e]);
1359 } while (!(files[e++].flags & RAZOR_ENTRY_LAST));
1362 map[top - files] = 1;
1366 struct merge_directory {
1367 uint32_t merged, dir1, dir2;
1371 merge_one_directory(struct razor_merger *merger, struct merge_directory *md)
1373 struct razor_entry *root1, *root2, *mroot, *e1, *e2;
1374 struct razor_set *set1, *set2;
1375 struct array merge_stack;
1376 struct merge_directory *child_md, *end_md;
1377 uint32_t *map1, *map2, start, last;
1379 char *pool1, *pool2;
1381 set1 = merger->source1.set;
1382 set2 = merger->source2.set;
1383 map1 = merger->source1.file_map;
1384 map2 = merger->source2.file_map;
1385 pool1 = set1->string_pool.data;
1386 pool2 = set2->string_pool.data;
1387 root1 = (struct razor_entry *) set1->files.data;
1388 root2 = (struct razor_entry *) set2->files.data;
1390 array_init(&merge_stack);
1392 start = merger->set->files.size / sizeof (struct razor_entry);
1394 e1 = md->dir1 ? root1 + md->dir1 : NULL;
1395 e2 = md->dir2 ? root2 + md->dir2 : NULL;
1397 if (!e2 && !map1[e1 - root1]) {
1398 if ((e1++)->flags & RAZOR_ENTRY_LAST)
1402 if (!e1 && !map2[e2 - root2]) {
1403 if ((e2++)->flags & RAZOR_ENTRY_LAST)
1407 if (e1 && !map1[e1 - root1] &&
1408 e2 && !map1[e2 - root2]) {
1409 if ((e1++)->flags & RAZOR_ENTRY_LAST)
1411 if ((e2++)->flags & RAZOR_ENTRY_LAST)
1421 cmp = strcmp (&pool1[e1->name],
1426 if (map1[e1 - root1]) {
1427 map1[e1 - root1] = last =
1428 add_file(merger, &pool1[e1->name]);
1430 child_md = array_add(&merge_stack, sizeof (struct merge_directory));
1431 child_md->merged = last;
1432 child_md->dir1 = e1->start;
1436 if ((e1++)->flags & RAZOR_ENTRY_LAST)
1438 } else if (cmp > 0) {
1439 if (map2[e2 - root2]) {
1440 map2[e2 - root2] = last =
1441 add_file(merger, &pool2[e2->name]);
1443 child_md = array_add(&merge_stack, sizeof (struct merge_directory));
1444 child_md->merged = last;
1446 child_md->dir2 = e2->start;
1449 if ((e2++)->flags & RAZOR_ENTRY_LAST)
1452 map1[e1 - root1] = map2[e2- root2] = last =
1453 add_file(merger, &pool1[e1->name]);
1454 if (e1->start || e2->start) {
1455 child_md = array_add(&merge_stack, sizeof (struct merge_directory));
1456 child_md->merged = last;
1457 child_md->dir1 = e1->start;
1458 child_md->dir2 = e2->start;
1460 if ((e1++)->flags & RAZOR_ENTRY_LAST)
1462 if ((e2++)->flags & RAZOR_ENTRY_LAST)
1467 mroot = (struct razor_entry *)merger->set->files.data;
1469 mroot[last].flags = RAZOR_ENTRY_LAST;
1470 mroot[md->merged].start = start;
1472 mroot[md->merged].start = 0;
1474 end_md = merge_stack.data + merge_stack.size;
1475 for (child_md = merge_stack.data; child_md < end_md; child_md++)
1476 merge_one_directory(merger, child_md);
1477 array_release(&merge_stack);
1481 merge_files(struct razor_merger *merger)
1483 struct razor_entry *root;
1484 struct merge_directory md;
1485 uint32_t *map1, *map2;
1487 map1 = merger->source1.file_map;
1488 map2 = merger->source2.file_map;
1492 if (merger->source1.set->files.size) {
1493 root = (struct razor_entry *) merger->source1.set->files.data;
1495 fix_file_map(map1, root, root);
1496 md.dir1 = root->start;
1500 if (merger->source2.set->files.size) {
1501 root = (struct razor_entry *) merger->source2.set->files.data;
1503 fix_file_map(map2, root, root);
1504 md.dir2 = root->start;
1508 merge_one_directory(merger, &md);
1512 emit_files(struct list_head *files, struct array *source_pool,
1513 uint32_t *map, struct array *pool)
1518 r = pool->size / sizeof *q;
1519 p = list_first(files, source_pool);
1521 q = array_add(pool, sizeof *q);
1522 q->data = map[p->data];
1523 q->flags = p->flags;
1527 list_set_ptr(files, r);
1530 /* Rebuild property->packages maps. We can't just remap these, as a
1531 * property may have lost or gained a number of packages. Allocate an
1532 * array per property and loop through the packages and add them to
1533 * the arrays for their properties. */
1535 rebuild_property_package_lists(struct razor_set *set)
1537 struct array *pkgs, *a;
1538 struct razor_package *pkg, *pkg_end;
1539 struct razor_property *prop, *prop_end;
1544 count = set->properties.size / sizeof (struct razor_property);
1545 pkgs = zalloc(count * sizeof *pkgs);
1546 pkg_end = set->packages.data + set->packages.size;
1548 for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
1549 r = list_first(&pkg->properties, &set->property_pool);
1551 q = array_add(&pkgs[r->data], sizeof *q);
1552 *q = pkg - (struct razor_package *) set->packages.data;
1557 prop_end = set->properties.data + set->properties.size;
1559 for (prop = set->properties.data; prop < prop_end; prop++, a++) {
1560 list_set_array(&prop->packages, &set->package_pool, a, 0);
1567 rebuild_file_package_lists(struct razor_set *set)
1569 struct array *pkgs, *a;
1570 struct razor_package *pkg, *pkg_end;
1571 struct razor_entry *entry, *entry_end;
1576 count = set->files.size / sizeof (struct razor_entry);
1577 pkgs = zalloc(count * sizeof *pkgs);
1578 pkg_end = set->packages.data + set->packages.size;
1580 for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
1581 r = list_first(&pkg->files, &set->file_pool);
1583 q = array_add(&pkgs[r->data], sizeof *q);
1584 *q = pkg - (struct razor_package *) set->packages.data;
1589 entry_end = set->files.data + set->files.size;
1591 for (entry = set->files.data; entry < entry_end; entry++, a++) {
1592 list_set_array(&entry->packages, &set->package_pool, a, 0);
1598 static struct razor_set *
1599 razor_merger_finish(struct razor_merger *merger)
1601 struct razor_set *result;
1602 struct razor_package *p, *pend;
1604 /* As we built the package list, we filled out a bitvector of
1605 * the properties that are referenced by the packages in the
1606 * new set. Now we do a parallel loop through the properties
1607 * and emit those marked in the bit vector to the new set. In
1608 * the process, we update the bit vector to actually map from
1609 * indices in the old property list to indices in the new
1610 * property list for both sets. */
1612 merge_properties(merger);
1613 merge_files(merger);
1615 /* Now we loop through the packages again and emit the
1616 * property lists, remapped to point to the new properties. */
1618 pend = merger->set->packages.data + merger->set->packages.size;
1619 for (p = merger->set->packages.data; p < pend; p++) {
1622 if (p->flags & UPSTREAM_SOURCE)
1623 src = &merger->source2;
1625 src = &merger->source1;
1627 emit_properties(&p->properties,
1628 &src->set->property_pool,
1630 &merger->set->property_pool);
1631 emit_files(&p->files,
1632 &src->set->file_pool,
1634 &merger->set->file_pool);
1635 p->flags &= ~UPSTREAM_SOURCE;
1638 rebuild_property_package_lists(merger->set);
1639 rebuild_file_package_lists(merger->set);
1641 result = merger->set;
1642 hashtable_release(&merger->table);
1648 /* The diff order matters. We should sort the packages so that a
1649 * REMOVE of a package comes before the INSTALL, and so that all
1650 * requires for a package have been installed before the package.
1654 razor_set_diff(struct razor_set *set, struct razor_set *upstream,
1655 razor_package_callback_t callback, void *data)
1657 struct razor_package_iterator *pi1, *pi2;
1658 struct razor_package *p1, *p2;
1659 const char *name1, *name2, *version1, *version2, *arch1, *arch2;
1662 pi1 = razor_package_iterator_create(set);
1663 pi2 = razor_package_iterator_create(upstream);
1665 razor_package_iterator_next(pi1, &p1, &name1, &version1, &arch1);
1666 razor_package_iterator_next(pi2, &p2, &name2, &version2, &arch2);
1670 res = strcmp(name1, name2);
1672 res = versioncmp(version1, version2);
1677 if (p2 == NULL || res < 0)
1678 callback(name1, version1, NULL, arch1, data);
1679 else if (p1 == NULL || res > 0)
1680 callback(name2, NULL, version2, arch2, data);
1682 if (p1 != NULL && res <= 0)
1683 razor_package_iterator_next(pi1, &p1,
1684 &name1, &version1, &arch1);
1685 if (p2 != NULL && res >= 0)
1686 razor_package_iterator_next(pi2, &p2,
1687 &name2, &version2, &arch2);
1690 razor_package_iterator_destroy(pi1);
1691 razor_package_iterator_destroy(pi2);
1695 provider_satisfies_requirement(struct razor_property *provider,
1696 const char *provider_strings,
1698 const char *required)
1701 const char *provided = &provider_strings[provider->version];
1706 if (flags & RAZOR_PROPERTY_LESS)
1712 cmp = versioncmp(provided, required);
1714 switch (flags & RAZOR_PROPERTY_RELATION_MASK) {
1715 case RAZOR_PROPERTY_LESS:
1718 case RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL:
1721 /* fall through: FIXME, make sure this is correct */
1723 case RAZOR_PROPERTY_EQUAL:
1727 /* "foo == 1.1" is satisfied by "foo 1.1-2" */
1728 len = strlen(required);
1729 if (!strncmp(required, provided, len) && provided[len] == '-')
1733 case RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL:
1736 case RAZOR_PROPERTY_GREATER:
1740 /* shouldn't happen */
1744 #define TRANS_PACKAGE_PRESENT 1
1745 #define TRANS_PACKAGE_UPDATE 2
1746 #define TRANS_PROPERTY_SATISFIED 0x80000000
1748 struct transaction_set {
1749 struct razor_set *set;
1751 uint32_t *properties;
1754 struct razor_transaction {
1755 int package_count, errors;
1756 struct transaction_set system, upstream;
1761 transaction_set_init(struct transaction_set *ts, struct razor_set *set)
1766 count = set->packages.size / sizeof (struct razor_package);
1767 ts->packages = zalloc(count * sizeof *ts->packages);
1768 count = set->properties.size / sizeof (struct razor_property);
1769 ts->properties = zalloc(count * sizeof *ts->properties);
1773 transaction_set_release(struct transaction_set *ts)
1776 free(ts->properties);
1780 transaction_set_install_package(struct transaction_set *ts,
1781 struct razor_package *package)
1783 struct razor_package *pkgs;
1787 pkgs = ts->set->packages.data;
1789 if (ts->packages[i] == TRANS_PACKAGE_PRESENT)
1792 ts->packages[i] = TRANS_PACKAGE_PRESENT;
1794 prop = list_first(&package->properties, &ts->set->property_pool);
1796 ts->properties[prop->data]++;
1797 prop = list_next(prop);
1802 transaction_set_remove_package(struct transaction_set *ts,
1803 struct razor_package *package)
1805 struct razor_package *pkgs;
1809 pkgs = ts->set->packages.data;
1811 if (ts->packages[i] == 0)
1814 ts->packages[i] = 0;
1816 prop = list_first(&package->properties, &ts->set->property_pool);
1818 ts->properties[prop->data]--;
1819 prop = list_next(prop);
1823 struct razor_transaction *
1824 razor_transaction_create(struct razor_set *system, struct razor_set *upstream)
1826 struct razor_transaction *trans;
1827 struct razor_package *p, *spkgs, *pend;
1829 trans = zalloc(sizeof *trans);
1830 transaction_set_init(&trans->system, system);
1831 transaction_set_init(&trans->upstream, upstream);
1833 spkgs = trans->system.set->packages.data;
1834 pend = trans->system.set->packages.data +
1835 trans->system.set->packages.size;
1836 for (p = spkgs; p < pend; p++)
1837 transaction_set_install_package(&trans->system, p);
1843 razor_transaction_install_package(struct razor_transaction *trans,
1844 struct razor_package *package)
1846 transaction_set_install_package(&trans->upstream, package);
1851 razor_transaction_remove_package(struct razor_transaction *trans,
1852 struct razor_package *package)
1854 transaction_set_remove_package(&trans->system, package);
1859 razor_transaction_update_package(struct razor_transaction *trans,
1860 struct razor_package *package)
1862 struct razor_package *spkgs, *upkgs, *end;
1864 spkgs = trans->system.set->packages.data;
1865 upkgs = trans->upstream.set->packages.data;
1866 end = trans->system.set->packages.data +
1867 trans->system.set->packages.size;
1868 if (spkgs <= package && package < end)
1869 trans->system.packages[package - spkgs] |= TRANS_PACKAGE_UPDATE;
1871 trans->upstream.packages[package - upkgs] |= TRANS_PACKAGE_UPDATE;
1875 struct razor_property *p, *start, *end;
1881 prop_iter_init(struct prop_iter *pi, struct transaction_set *ts)
1883 pi->p = ts->set->properties.data;
1884 pi->start = ts->set->properties.data;
1885 pi->end = ts->set->properties.data + ts->set->properties.size;
1886 pi->pool = ts->set->string_pool.data;
1887 pi->present = ts->properties;
1891 prop_iter_next(struct prop_iter *pi, uint32_t flags, struct razor_property **p)
1893 while (pi->p < pi->end) {
1894 if ((pi->present[pi->p - pi->start] & ~TRANS_PROPERTY_SATISFIED) &&
1895 (pi->p->flags & RAZOR_PROPERTY_TYPE_MASK) == flags) {
1905 static struct razor_property *
1906 prop_iter_seek_to(struct prop_iter *pi,
1907 uint32_t flags, const char *match)
1911 while (pi->p < pi->end && strcmp(&pi->pool[pi->p->name], match) < 0)
1914 if (pi->p == pi->end || strcmp(&pi->pool[pi->p->name], match) > 0)
1918 while (pi->p < pi->end &&
1919 pi->p->name == name &&
1920 (pi->p->flags & RAZOR_PROPERTY_TYPE_MASK) != flags)
1923 if (pi->p == pi->end || pi->p->name != name)
1929 /* Remove packages from set that provide any of the matching (same
1930 * name and type) providers from ppi onwards that match the
1931 * requirement that rpi points to. */
1933 remove_matching_providers(struct razor_transaction *trans,
1934 struct prop_iter *ppi,
1936 const char *version)
1938 struct razor_property *p;
1939 struct razor_package *pkg, *pkgs;
1940 struct razor_package_iterator pkg_iter;
1941 struct razor_set *set;
1942 const char *n, *v, *a;
1945 if (ppi->present == trans->system.properties)
1946 set = trans->system.set;
1948 set = trans->upstream.set;
1950 pkgs = (struct razor_package *) set->packages.data;
1951 type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
1954 p->name == ppi->p->name &&
1955 (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
1957 if (!ppi->present[p - ppi->start])
1959 if (!provider_satisfies_requirement(p, ppi->pool,
1963 razor_package_iterator_init_for_property(&pkg_iter, set, p);
1964 while (razor_package_iterator_next(&pkg_iter,
1965 &pkg, &n, &v, &a)) {
1966 fprintf(stderr, "removing %s-%s\n", n, v);
1967 razor_transaction_remove_package(trans, pkg);
1973 flag_matching_providers(struct razor_transaction *trans,
1974 struct prop_iter *ppi,
1975 struct razor_property *r,
1976 struct prop_iter *rpi,
1979 struct razor_property *p;
1980 struct razor_package *pkg, *pkgs;
1981 struct razor_package_iterator pkg_iter;
1982 struct razor_set *set;
1983 const char *name, *version, *arch;
1984 uint32_t *flags, type;
1986 if (ppi->present == trans->system.properties) {
1987 set = trans->system.set;
1988 flags = trans->system.packages;
1990 set = trans->upstream.set;
1991 flags = trans->upstream.packages;
1994 pkgs = (struct razor_package *) set->packages.data;
1995 type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
1998 p->name == ppi->p->name &&
1999 (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
2001 if (!ppi->present[p - ppi->start])
2003 if (!provider_satisfies_requirement(p, ppi->pool,
2005 &rpi->pool[r->version]))
2008 razor_package_iterator_init_for_property(&pkg_iter, set, p);
2009 while (razor_package_iterator_next(&pkg_iter, &pkg,
2010 &name, &version, &arch)) {
2012 fprintf(stderr, "flagging %s-%s for providing %s matching %s %s\n",
2014 ppi->pool + p->name,
2015 rpi->pool + r->name,
2016 rpi->pool + r->version);
2017 flags[pkg - pkgs] |= flag;
2022 static struct razor_package *
2023 pick_matching_provider(struct razor_set *set,
2024 struct prop_iter *ppi,
2026 const char *version)
2028 struct razor_property *p;
2029 struct razor_package *pkgs;
2033 /* This is where we decide which pkgs to pull in to satisfy a
2034 * requirement. There may be several different providers
2035 * (different versions) and each version of a provider may
2036 * come from a number of packages. We pick the first package
2037 * from the first provider that matches. */
2039 pkgs = set->packages.data;
2040 type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
2043 p->name == ppi->p->name &&
2044 (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type &&
2045 ppi->present[p - ppi->start] == 0;
2047 if (!provider_satisfies_requirement(p, ppi->pool,
2051 i = list_first(&p->packages, &set->package_pool);
2053 return &pkgs[i->data];
2060 remove_obsoleted_packages(struct razor_transaction *trans)
2062 struct razor_property *up;
2063 struct razor_package *spkgs;
2064 struct prop_iter spi, upi;
2066 spkgs = trans->system.set->packages.data;
2067 prop_iter_init(&spi, &trans->system);
2068 prop_iter_init(&upi, &trans->upstream);
2070 while (prop_iter_next(&upi, RAZOR_PROPERTY_OBSOLETES, &up)) {
2071 if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
2072 &upi.pool[up->name]))
2074 remove_matching_providers(trans, &spi, up->flags,
2075 &upi.pool[up->version]);
2080 any_provider_satisfies_requirement(struct prop_iter *ppi,
2082 const char *version)
2084 struct razor_property *p;
2087 type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
2090 p->name == ppi->p->name &&
2091 (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
2093 if (ppi->present[p - ppi->start] > 0 &&
2094 provider_satisfies_requirement(p, ppi->pool,
2103 clear_requires_flags(struct transaction_set *ts)
2105 struct razor_property *p;
2109 count = ts->set->properties.size / sizeof *p;
2110 p = ts->set->properties.data;
2111 pool = ts->set->string_pool.data;
2112 for (i = 0; i < count; i++) {
2113 ts->properties[i] &= ~TRANS_PROPERTY_SATISFIED;
2114 if (strncmp(&pool[p[i].name], "rpmlib(", 7) == 0)
2115 ts->properties[i] |= TRANS_PROPERTY_SATISFIED;
2120 razor_property_relation_to_string(struct razor_property *p)
2122 switch (p->flags & RAZOR_PROPERTY_RELATION_MASK) {
2123 case RAZOR_PROPERTY_LESS:
2126 case RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL:
2129 case RAZOR_PROPERTY_EQUAL:
2132 case RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL:
2135 case RAZOR_PROPERTY_GREATER:
2144 razor_property_type_to_string(struct razor_property *p)
2146 switch (p->flags & RAZOR_PROPERTY_TYPE_MASK) {
2147 case RAZOR_PROPERTY_REQUIRES:
2149 case RAZOR_PROPERTY_PROVIDES:
2151 case RAZOR_PROPERTY_CONFLICTS:
2153 case RAZOR_PROPERTY_OBSOLETES:
2161 mark_satisfied_requires(struct razor_transaction *trans,
2162 struct transaction_set *rts,
2163 struct transaction_set *pts)
2165 struct prop_iter rpi, ppi;
2166 struct razor_property *rp;
2168 prop_iter_init(&rpi, rts);
2169 prop_iter_init(&ppi, pts);
2171 while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
2172 if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES,
2173 &rpi.pool[rp->name]))
2176 if (any_provider_satisfies_requirement(&ppi, rp->flags,
2177 &rpi.pool[rp->version]))
2178 rpi.present[rp - rpi.start] |= TRANS_PROPERTY_SATISFIED;
2183 mark_all_satisfied_requires(struct razor_transaction *trans)
2185 clear_requires_flags(&trans->system);
2186 clear_requires_flags(&trans->upstream);
2187 mark_satisfied_requires(trans, &trans->system, &trans->system);
2188 mark_satisfied_requires(trans, &trans->system, &trans->upstream);
2189 mark_satisfied_requires(trans, &trans->upstream, &trans->system);
2190 mark_satisfied_requires(trans, &trans->upstream, &trans->upstream);
2194 update_unsatisfied_packages(struct razor_transaction *trans)
2196 struct razor_package *spkgs, *pkg;
2197 struct razor_property *sp;
2198 struct prop_iter spi;
2199 struct razor_package_iterator pkg_iter;
2200 const char *name, *version, *arch;
2202 spkgs = trans->system.set->packages.data;
2203 prop_iter_init(&spi, &trans->system);
2205 while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
2206 if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
2209 razor_package_iterator_init_for_property(&pkg_iter,
2212 while (razor_package_iterator_next(&pkg_iter, &pkg,
2213 &name, &version, &arch)) {
2214 fprintf(stderr, "updating %s because %s %s %s "
2215 "isn't satisfied\n",
2216 name, spi.pool + sp->name,
2217 razor_property_relation_to_string(sp),
2218 spi.pool + sp->version);
2219 trans->system.packages[pkg - spkgs] |=
2220 TRANS_PACKAGE_UPDATE;
2226 razor_transaction_update_all(struct razor_transaction *trans)
2228 struct razor_package *p;
2231 count = trans->system.set->packages.size / sizeof *p;
2232 for (i = 0; i < count; i++)
2233 trans->system.packages[i] |= TRANS_PACKAGE_UPDATE;
2237 update_conflicted_packages(struct razor_transaction *trans)
2239 struct razor_package *pkg, *spkgs;
2240 struct razor_property *up, *sp;
2241 struct prop_iter spi, upi;
2242 struct razor_package_iterator pkg_iter;
2243 const char *name, *version, *arch;
2245 spkgs = trans->system.set->packages.data;
2246 prop_iter_init(&spi, &trans->system);
2247 prop_iter_init(&upi, &trans->upstream);
2249 while (prop_iter_next(&spi, RAZOR_PROPERTY_CONFLICTS, &sp)) {
2250 if (!prop_iter_seek_to(&upi, RAZOR_PROPERTY_PROVIDES,
2251 &spi.pool[sp->name]))
2254 if (!any_provider_satisfies_requirement(&upi, sp->flags,
2255 &spi.pool[sp->version]))
2258 razor_package_iterator_init_for_property(&pkg_iter,
2261 while (razor_package_iterator_next(&pkg_iter, &pkg,
2262 &name, &version, &arch)) {
2263 fprintf(stderr, "updating %s %s because it conflicts with %s",
2264 name, version, spi.pool + sp->name);
2265 trans->system.packages[pkg - spkgs] |=
2266 TRANS_PACKAGE_UPDATE;
2270 prop_iter_init(&spi, &trans->system);
2271 prop_iter_init(&upi, &trans->upstream);
2273 while (prop_iter_next(&upi, RAZOR_PROPERTY_CONFLICTS, &up)) {
2274 sp = prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
2275 &upi.pool[upi.p->name]);
2278 flag_matching_providers(trans, &spi, up, &upi,
2279 TRANS_PACKAGE_UPDATE);
2284 pull_in_requirements(struct razor_transaction *trans,
2285 struct prop_iter *rpi, struct prop_iter *ppi)
2287 struct razor_property *rp, *pp;
2288 struct razor_package *pkg, *upkgs;
2290 upkgs = trans->upstream.set->packages.data;
2291 while (prop_iter_next(rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
2292 if (rpi->present[rp - rpi->start] & TRANS_PROPERTY_SATISFIED)
2295 pp = prop_iter_seek_to(ppi, RAZOR_PROPERTY_PROVIDES,
2296 &rpi->pool[rp->name]);
2299 pkg = pick_matching_provider(trans->upstream.set,
2301 &rpi->pool[rp->version]);
2305 rpi->present[rp - rpi->start] |= TRANS_PROPERTY_SATISFIED;
2307 fprintf(stderr, "pulling in %s which provides %s %s %s "
2308 "to satisfy %s %s %s\n",
2309 ppi->pool + pkg->name,
2310 ppi->pool + pp->name,
2311 razor_property_relation_to_string(pp),
2312 ppi->pool + pp->version,
2313 &rpi->pool[rp->name],
2314 razor_property_relation_to_string(rp),
2315 &rpi->pool[rp->version]);
2317 trans->upstream.packages[pkg - upkgs] |= TRANS_PACKAGE_UPDATE;
2322 pull_in_all_requirements(struct razor_transaction *trans)
2324 struct prop_iter rpi, ppi;
2326 prop_iter_init(&rpi, &trans->system);
2327 prop_iter_init(&ppi, &trans->upstream);
2328 pull_in_requirements(trans, &rpi, &ppi);
2330 prop_iter_init(&rpi, &trans->upstream);
2331 prop_iter_init(&ppi, &trans->upstream);
2332 pull_in_requirements(trans, &rpi, &ppi);
2336 flush_scheduled_system_updates(struct razor_transaction *trans)
2338 struct razor_package_iterator *pi;
2339 struct razor_package *p, *pkg, *spkgs;
2340 struct prop_iter ppi;
2341 const char *name, *version, *arch;
2343 spkgs = trans->system.set->packages.data;
2344 pi = razor_package_iterator_create(trans->system.set);
2345 prop_iter_init(&ppi, &trans->upstream);
2347 while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
2348 if (!(trans->system.packages[p - spkgs] & TRANS_PACKAGE_UPDATE))
2351 if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES, name))
2354 pkg = pick_matching_provider(trans->upstream.set, &ppi,
2355 RAZOR_PROPERTY_GREATER, version);
2359 fprintf(stderr, "updating %s-%s to %s-%s\n",
2361 &ppi.pool[pkg->name], &ppi.pool[pkg->version]);
2363 razor_transaction_remove_package(trans, p);
2364 razor_transaction_install_package(trans, pkg);
2367 razor_package_iterator_destroy(pi);
2371 flush_scheduled_upstream_updates(struct razor_transaction *trans)
2373 struct razor_package_iterator *pi;
2374 struct razor_package *p, *upkgs;
2375 struct prop_iter spi;
2376 const char *name, *version, *arch;
2378 upkgs = trans->upstream.set->packages.data;
2379 pi = razor_package_iterator_create(trans->upstream.set);
2380 prop_iter_init(&spi, &trans->system);
2382 while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
2383 if (!(trans->upstream.packages[p - upkgs] & TRANS_PACKAGE_UPDATE))
2386 if (prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES, name))
2387 remove_matching_providers(trans,
2389 RAZOR_PROPERTY_LESS,
2391 razor_transaction_install_package(trans, p);
2392 fprintf(stderr, "installing %s-%s\n", name, version);
2397 razor_transaction_resolve(struct razor_transaction *trans)
2401 flush_scheduled_system_updates(trans);
2402 flush_scheduled_upstream_updates(trans);
2404 while (last < trans->changes) {
2405 last = trans->changes;
2406 remove_obsoleted_packages(trans);
2407 mark_all_satisfied_requires(trans);
2408 update_unsatisfied_packages(trans);
2409 update_conflicted_packages(trans);
2410 pull_in_all_requirements(trans);
2411 flush_scheduled_system_updates(trans);
2412 flush_scheduled_upstream_updates(trans);
2415 return trans->changes;
2419 describe_unsatisfied(struct razor_set *set, struct razor_property *rp)
2421 struct razor_package_iterator pi;
2422 struct razor_package *pkg;
2423 const char *name, *version, *arch, *pool;
2425 pool = set->string_pool.data;
2426 if (pool[rp->version] == '\0') {
2427 razor_package_iterator_init_for_property(&pi, set, rp);
2428 while (razor_package_iterator_next(&pi, &pkg,
2429 &name, &version, &arch))
2430 fprintf(stderr, "%s is needed by %s-%s.%s\n",
2432 name, version, arch);
2434 razor_package_iterator_init_for_property(&pi, set, rp);
2435 while (razor_package_iterator_next(&pi, &pkg,
2436 &name, &version, &arch))
2437 fprintf(stderr, "%s %s %s is needed by %s-%s.%s\n",
2439 razor_property_relation_to_string(rp),
2441 name, version, arch);
2446 razor_transaction_describe(struct razor_transaction *trans)
2448 struct prop_iter rpi;
2449 struct razor_property *rp;
2452 flush_scheduled_system_updates(trans);
2453 flush_scheduled_upstream_updates(trans);
2454 mark_all_satisfied_requires(trans);
2457 prop_iter_init(&rpi, &trans->system);
2458 while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
2459 if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
2460 describe_unsatisfied(trans->system.set, rp);
2465 prop_iter_init(&rpi, &trans->upstream);
2466 while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
2467 if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
2468 describe_unsatisfied(trans->upstream.set, rp);
2477 razor_transaction_unsatisfied_property(struct razor_transaction *trans,
2480 const char *version)
2482 struct prop_iter pi;
2483 struct razor_property *p;
2485 prop_iter_init(&pi, &trans->system);
2486 while (prop_iter_next(&pi, flags, &p)) {
2487 if (!(trans->system.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
2488 p->flags == flags &&
2489 strcmp(&pi.pool[p->name], name) == 0 &&
2490 strcmp(&pi.pool[p->version], version) == 0)
2495 prop_iter_init(&pi, &trans->upstream);
2496 while (prop_iter_next(&pi, flags, &p)) {
2497 if (!(trans->upstream.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
2498 p->flags == flags &&
2499 strcmp(&pi.pool[p->name], name) == 0 &&
2500 strcmp(&pi.pool[p->version], version) == 0)
2509 razor_transaction_finish(struct razor_transaction *trans)
2511 struct razor_merger *merger;
2512 struct razor_package *u, *uend, *upkgs, *s, *send, *spkgs;
2513 char *upool, *spool;
2516 s = trans->system.set->packages.data;
2517 spkgs = trans->system.set->packages.data;
2518 send = trans->system.set->packages.data +
2519 trans->system.set->packages.size;
2520 spool = trans->system.set->string_pool.data;
2522 u = trans->upstream.set->packages.data;
2523 upkgs = trans->upstream.set->packages.data;
2524 uend = trans->upstream.set->packages.data +
2525 trans->upstream.set->packages.size;
2526 upool = trans->upstream.set->string_pool.data;
2528 merger = razor_merger_create(trans->system.set, trans->upstream.set);
2529 while (s < send || u < uend) {
2530 if (s < send && u < uend)
2531 cmp = strcmp(&spool[s->name], &upool[u->name]);
2538 if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
2539 razor_merger_add_package(merger, s);
2541 } else if (cmp == 0) {
2542 if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
2543 razor_merger_add_package(merger, s);
2544 if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
2545 razor_merger_add_package(merger, u);
2550 if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
2551 razor_merger_add_package(merger, u);
2556 razor_transaction_destroy(trans);
2558 return razor_merger_finish(merger);
2562 razor_transaction_destroy(struct razor_transaction *trans)
2564 transaction_set_release(&trans->system);
2565 transaction_set_release(&trans->upstream);
2569 struct razor_package_query {
2570 struct razor_set *set;
2575 struct razor_package_query *
2576 razor_package_query_create(struct razor_set *set)
2578 struct razor_package_query *pq;
2581 pq = zalloc(sizeof *pq);
2583 count = set->packages.size / sizeof(struct razor_package);
2584 pq->vector = zalloc(count * sizeof(char));
2590 razor_package_query_add_package(struct razor_package_query *pq,
2591 struct razor_package *p)
2593 struct razor_package *packages;
2595 packages = pq->set->packages.data;
2596 pq->count += pq->vector[p - packages] ^ 1;
2597 pq->vector[p - packages] = 1;
2601 razor_package_query_add_iterator(struct razor_package_query *pq,
2602 struct razor_package_iterator *pi)
2604 struct razor_package *packages, *p;
2605 const char *name, *version, *arch;
2607 packages = pq->set->packages.data;
2608 while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
2609 pq->count += pq->vector[p - packages] ^ 1;
2610 pq->vector[p - packages] = 1;
2614 struct razor_package_iterator *
2615 razor_package_query_finish(struct razor_package_query *pq)
2617 struct razor_package_iterator *pi;
2618 struct razor_set *set;
2623 count = set->packages.size / sizeof(struct razor_package);
2624 index = zalloc(pq->count * sizeof *index);
2626 for (i = 0, j = 0; i < count; i++) {
2631 if (j == pq->count - 1)
2632 index[j].flags = 0x80;
2638 pi = razor_package_iterator_create_with_index(set, index);