Autoconfify razor.
committer: Kristian H?gsberg <krh@redhat.com>
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 {
75 enum razor_property_type type : 2;
76 enum razor_version_relation relation : 32;
78 struct list_head packages;
85 struct list_head packages;
88 #define RAZOR_ENTRY_LAST 0x80
91 struct array string_pool;
92 struct array packages;
93 struct array properties;
95 struct array package_pool;
96 struct array property_pool;
97 struct array file_pool;
98 struct razor_set_header *header;
101 struct import_entry {
106 struct import_directory {
107 uint32_t name, count;
109 struct array packages;
110 struct import_directory *last;
113 struct razor_importer {
114 struct razor_set *set;
115 struct hashtable table;
116 struct razor_package *package;
117 struct array properties;
119 struct array file_requires;
133 struct razor_set_section razor_sections[] = {
134 { RAZOR_STRING_POOL, offsetof(struct razor_set, string_pool) },
135 { RAZOR_PACKAGES, offsetof(struct razor_set, packages) },
136 { RAZOR_PROPERTIES, offsetof(struct razor_set, properties) },
137 { RAZOR_FILES, offsetof(struct razor_set, files) },
138 { RAZOR_PACKAGE_POOL, offsetof(struct razor_set, package_pool) },
139 { RAZOR_PROPERTY_POOL, offsetof(struct razor_set, property_pool) },
140 { RAZOR_FILE_POOL, offsetof(struct razor_set, file_pool) },
144 razor_set_create(void)
146 struct razor_set *set;
147 struct razor_entry *e;
150 set = zalloc(sizeof *set);
152 e = array_add(&set->files, sizeof *e);
153 empty = array_add(&set->string_pool, 1);
156 e->flags = RAZOR_ENTRY_LAST;
158 list_set_empty(&e->packages);
164 razor_set_open(const char *filename)
166 struct razor_set *set;
167 struct razor_set_section *s;
172 set = zalloc(sizeof *set);
173 fd = open(filename, O_RDONLY);
174 if (fstat(fd, &stat) < 0)
176 set->header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
177 if (set->header == MAP_FAILED) {
182 for (s = set->header->sections; ~s->type; s++) {
183 if (s->type >= ARRAY_SIZE(razor_sections))
185 if (s->type != razor_sections[s->type].type)
187 array = (void *) set + razor_sections[s->type].offset;
188 array->data = (void *) set->header + s->offset;
189 array->size = s->size;
190 array->alloc = s->size;
198 razor_set_destroy(struct razor_set *set)
205 for (i = 0; set->header->sections[i].type; i++)
207 size = set->header->sections[i].type;
208 munmap(set->header, size);
210 for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
211 a = (void *) set + razor_sections[i].offset;
220 razor_set_write_to_fd(struct razor_set *set, int fd)
223 struct razor_set_header *header = (struct razor_set_header *) data;
228 memset(data, 0, sizeof data);
229 header->magic = RAZOR_MAGIC;
230 header->version = RAZOR_VERSION;
231 offset = sizeof data;
233 for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
234 if (razor_sections[i].type != i)
236 a = (void *) set + razor_sections[i].offset;
237 header->sections[i].type = i;
238 header->sections[i].offset = offset;
239 header->sections[i].size = a->size;
240 offset += ALIGN(a->size, 4096);
243 header->sections[i].type = ~0;
244 header->sections[i].offset = 0;
245 header->sections[i].size = 0;
247 razor_write(fd, data, sizeof data);
248 memset(data, 0, sizeof data);
249 for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
250 if (razor_sections[i].type != i)
252 a = (void *) set + razor_sections[i].offset;
253 razor_write(fd, a->data, a->size);
254 razor_write(fd, data, ALIGN(a->size, 4096) - a->size);
261 razor_set_write(struct razor_set *set, const char *filename)
265 fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
269 status = razor_set_write_to_fd(set, fd);
279 razor_build_evr(char *evr_buf, int size, const char *epoch,
280 const char *version, const char *release)
284 if (!version || !*version) {
289 if (epoch && *epoch && strcmp(epoch, "0") != 0) {
290 len = snprintf(evr_buf, size, "%s:", epoch);
294 len = snprintf(evr_buf, size, "%s", version);
297 if (release && *release)
298 snprintf(evr_buf, size, "-%s", release);
302 razor_importer_begin_package(struct razor_importer *importer,
307 struct razor_package *p;
309 p = array_add(&importer->set->packages, sizeof *p);
310 p->name = hashtable_tokenize(&importer->table, name);
312 p->version = hashtable_tokenize(&importer->table, version);
313 p->arch = hashtable_tokenize(&importer->table, arch);
315 importer->package = p;
316 array_init(&importer->properties);
320 razor_importer_finish_package(struct razor_importer *importer)
322 list_set_array(&importer->package->properties,
323 &importer->set->property_pool,
324 &importer->properties,
327 array_release(&importer->properties);
331 razor_importer_add_property(struct razor_importer *importer,
333 enum razor_version_relation relation,
335 enum razor_property_type type)
337 struct razor_property *p;
340 p = array_add(&importer->set->properties, sizeof *p);
341 p->name = hashtable_tokenize(&importer->table, name);
344 p->relation = relation;
345 p->version = hashtable_tokenize(&importer->table, version);
346 list_set_ptr(&p->packages, importer->package -
347 (struct razor_package *) importer->set->packages.data);
349 r = array_add(&importer->properties, sizeof *r);
350 *r = p - (struct razor_property *) importer->set->properties.data;
352 if (type == RAZOR_PROPERTY_REQUIRES && *name == '/') {
353 r = array_add(&importer->file_requires, sizeof *r);
359 razor_importer_add_file(struct razor_importer *importer, const char *name)
361 struct import_entry *e;
363 e = array_add(&importer->files, sizeof *e);
365 e->package = importer->package -
366 (struct razor_package *) importer->set->packages.data;
367 e->name = strdup(name);
370 struct razor_importer *
371 razor_importer_new(void)
373 struct razor_importer *importer;
375 importer = zalloc(sizeof *importer);
376 importer->set = razor_set_create();
377 hashtable_init(&importer->table, &importer->set->string_pool);
382 /* Destroy an importer without creating the set. */
384 razor_importer_destroy(struct razor_importer *importer)
386 /* FIXME: write this */
390 versioncmp(const char *s1, const char *s2)
396 n1 = strtol(s1, (char **) &p1, 10);
397 n2 = strtol(s2, (char **) &p2, 10);
399 /* Epoch; if one but not the other has an epoch set, default
400 * the epoch-less version to 0. */
401 res = (*p1 == ':') - (*p2 == ':');
406 } else if (res > 0) {
419 if (isdigit(*p1) && isdigit(*p2))
420 return versioncmp(p1, p2);
427 compare_packages(const void *p1, const void *p2, void *data)
429 const struct razor_package *pkg1 = p1, *pkg2 = p2;
430 struct razor_set *set = data;
431 char *pool = set->string_pool.data;
433 /* FIXME: what if the flags are different? */
434 if (pkg1->name == pkg2->name)
435 return versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
437 return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
441 compare_properties(const void *p1, const void *p2, void *data)
443 const struct razor_property *prop1 = p1, *prop2 = p2;
444 struct razor_set *set = data;
445 char *pool = set->string_pool.data;
447 if (prop1->name != prop2->name)
448 return strcmp(&pool[prop1->name], &pool[prop2->name]);
449 else if (prop1->type != prop2->type)
450 return prop1->type - prop2->type;
451 else if (prop1->relation != prop2->relation)
452 return prop1->relation - prop2->relation;
454 return versioncmp(&pool[prop1->version], &pool[prop2->version]);
458 uniqueify_properties(struct razor_set *set)
460 struct razor_property *rp, *up, *rp_end;
461 struct array *pkgs, *p;
463 uint32_t *map, *rmap;
464 int i, count, unique;
466 count = set->properties.size / sizeof(struct razor_property);
467 map = razor_qsort_with_data(set->properties.data,
469 sizeof(struct razor_property),
473 rp_end = set->properties.data + set->properties.size;
474 rmap = malloc(count * sizeof *map);
475 pkgs = zalloc(count * sizeof *pkgs);
476 for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
477 if (rp->name != up->name || rp->type != up->type ||
478 rp->relation != up->relation || rp->version != up->version) {
483 up->relation = rp->relation;
484 up->version = rp->version;
487 unique = up - (struct razor_property *) set->properties.data;
488 rmap[map[i]] = unique;
489 r = array_add(&pkgs[unique], sizeof *r);
496 set->properties.size = (void *) up - set->properties.data;
498 for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
499 list_set_array(&rp->packages, &set->package_pool, p, 0);
509 compare_filenames(const void *p1, const void *p2, void *data)
511 const struct import_entry *e1 = p1;
512 const struct import_entry *e2 = p2;
513 const char *n1 = e1->name;
514 const char *n2 = e2->name;
516 /* Need to make sure that the contents of a directory
517 * are sorted immediately after it. So "foo/bar" has to
518 * sort before "foo.conf"
520 * FIXME: this is about 60% slower than strcmp
524 return *n2 == '/' ? 1 : -1;
526 return *n1 == '/' ? -1 : 1;
539 count_entries(struct import_directory *d)
541 struct import_directory *p, *end;
544 end = d->files.data + d->files.size;
548 d->count += p->count + 1;
554 serialize_files(struct razor_set *set,
555 struct import_directory *d, struct array *array)
557 struct import_directory *p, *end;
558 struct razor_entry *e = NULL;
562 end = d->files.data + d->files.size;
563 s = array->size / sizeof *e + d->files.size / sizeof *p;
565 e = array_add(array, sizeof *e);
568 e->start = p->count > 0 ? s : 0;
571 list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
572 array_release(&p->packages);
576 e->flags |= RAZOR_ENTRY_LAST;
579 end = d->files.data + d->files.size;
581 serialize_files(set, p, array);
587 remap_property_package_links(struct array *properties, uint32_t *rmap)
589 struct razor_property *p, *end;
591 end = properties->data + properties->size;
592 for (p = properties->data; p < end; p++)
593 list_remap_head(&p->packages, rmap);
597 build_file_tree(struct razor_importer *importer)
599 int count, i, length;
600 struct import_entry *filenames;
604 struct import_directory *d, root;
605 struct razor_entry *e;
607 count = importer->files.size / sizeof (struct import_entry);
608 razor_qsort_with_data(importer->files.data,
610 sizeof (struct import_entry),
614 root.name = hashtable_tokenize(&importer->table, "");
615 array_init(&root.files);
616 array_init(&root.packages);
619 filenames = importer->files.data;
620 for (i = 0; i < count; i++) {
621 f = filenames[i].name;
628 end = strchr(f, '/');
632 memcpy(dirname, f, length);
633 dirname[length] ='\0';
634 name = hashtable_tokenize(&importer->table, dirname);
635 if (d->last == NULL || d->last->name != name) {
636 d->last = array_add(&d->files, sizeof *d);
637 d->last->name = name;
638 d->last->last = NULL;
639 array_init(&d->last->files);
640 array_init(&d->last->packages);
648 r = array_add(&d->packages, sizeof *r);
649 *r = filenames[i].package;
650 free(filenames[i].name);
653 count_entries(&root);
654 e = importer->set->files.data;
656 e->flags = RAZOR_ENTRY_LAST;
657 e->start = importer->files.size ? 1 : 0;
658 list_set_empty(&e->packages);
660 serialize_files(importer->set, &root, &importer->set->files);
662 array_release(&importer->files);
665 static struct razor_entry *
666 find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern);
669 list_to_array(struct list *list, struct array *array)
674 item = array_add(array, sizeof *item);
676 list = list_next(list);
681 compare_file_requires(const void *p1, const void *p2, void *data)
683 uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
684 const char *pool = data;
686 return strcmp(&pool[*f1], &pool[*f2]);
690 find_file_provides(struct razor_importer *importer)
692 struct razor_property *prop;
693 struct razor_entry *top, *entry;
694 struct razor_package *packages;
695 struct array pkgprops;
697 uint32_t *req, *req_start, *req_end;
698 uint32_t *map, *newprop;
701 pool = importer->set->string_pool.data;
702 packages = importer->set->packages.data;
703 top = importer->set->files.data;
705 req = req_start = importer->file_requires.data;
706 req_end = importer->file_requires.data + importer->file_requires.size;
707 map = razor_qsort_with_data(req, req_end - req, sizeof *req,
708 compare_file_requires, pool);
711 for (req = req_start; req < req_end; req++) {
712 if (req > req_start && req[0] == req[-1])
714 entry = find_entry(importer->set, top, &pool[*req]);
718 for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
719 prop = array_add(&importer->set->properties, sizeof *prop);
721 prop->type = RAZOR_PROPERTY_PROVIDES;
722 prop->relation = RAZOR_VERSION_EQUAL;
723 prop->version = hashtable_tokenize(&importer->table, "");
724 list_set_ptr(&prop->packages, pkg->data);
726 /* Update property list of pkg */
727 array_init(&pkgprops);
728 list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
729 newprop = array_add(&pkgprops, sizeof *newprop);
730 *newprop = prop - (struct razor_property *)importer->set->properties.data;
731 list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
732 array_release(&pkgprops);
736 array_release(&importer->file_requires);
740 build_package_file_lists(struct razor_set *set, uint32_t *rmap)
742 struct razor_package *p, *packages;
744 struct razor_entry *e, *end;
749 count = set->packages.size / sizeof *p;
750 pkgs = zalloc(count * sizeof *pkgs);
752 end = set->files.data + set->files.size;
753 for (e = set->files.data; e < end; e++) {
754 list_remap_head(&e->packages, rmap);
755 r = list_first(&e->packages, &set->package_pool);
757 q = array_add(&pkgs[r->data], sizeof *q);
758 *q = e - (struct razor_entry *) set->files.data;
763 packages = set->packages.data;
764 for (i = 0; i < count; i++) {
765 list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
766 array_release(&pkgs[i]);
772 razor_importer_finish(struct razor_importer *importer)
774 struct razor_set *set;
775 uint32_t *map, *rmap;
778 build_file_tree(importer);
779 find_file_provides(importer);
781 map = uniqueify_properties(importer->set);
782 list_remap_pool(&importer->set->property_pool, map);
785 count = importer->set->packages.size / sizeof(struct razor_package);
786 map = razor_qsort_with_data(importer->set->packages.data,
788 sizeof(struct razor_package),
792 rmap = malloc(count * sizeof *rmap);
793 for (i = 0; i < count; i++)
797 list_remap_pool(&importer->set->package_pool, rmap);
798 build_package_file_lists(importer->set, rmap);
799 remap_property_package_links(&importer->set->properties, rmap);
803 hashtable_release(&importer->table);
809 struct razor_package_iterator {
810 struct razor_set *set;
811 struct razor_package *package, *end;
816 static struct razor_package_iterator *
817 razor_package_iterator_create_with_index(struct razor_set *set,
820 struct razor_package_iterator *pi;
822 pi = zalloc(sizeof *pi);
829 struct razor_package_iterator *
830 razor_package_iterator_create(struct razor_set *set)
832 struct razor_package_iterator *pi;
834 pi = zalloc(sizeof *pi);
836 pi->end = set->packages.data + set->packages.size;
837 pi->package = set->packages.data;
843 razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
844 struct razor_set *set,
845 struct razor_property *property)
847 memset(pi, 0, sizeof *pi);
849 pi->index = list_first(&property->packages, &set->package_pool);
852 struct razor_package_iterator *
853 razor_package_iterator_create_for_property(struct razor_set *set,
854 struct razor_property *property)
858 index = list_first(&property->packages, &set->package_pool);
859 return razor_package_iterator_create_with_index(set, index);
863 razor_package_iterator_next(struct razor_package_iterator *pi,
864 struct razor_package **package,
866 const char **version,
871 struct razor_package *p, *packages;
876 } else if (pi->index) {
877 packages = pi->set->packages.data;
878 p = &packages[pi->index->data];
879 pi->index = list_next(pi->index);
885 pool = pi->set->string_pool.data;
887 *name = &pool[p->name];
888 *version = &pool[p->version];
889 *arch = &pool[p->arch];
898 razor_package_iterator_destroy(struct razor_package_iterator *pi)
906 struct razor_package *
907 razor_set_get_package(struct razor_set *set, const char *package)
909 struct razor_package_iterator *pi;
910 struct razor_package *p;
911 const char *name, *version, *arch;
913 pi = razor_package_iterator_create(set);
914 while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
915 if (strcmp(package, name) == 0)
918 razor_package_iterator_destroy(pi);
923 struct razor_property_iterator {
924 struct razor_set *set;
925 struct razor_property *property, *end;
929 struct razor_property_iterator *
930 razor_property_iterator_create(struct razor_set *set,
931 struct razor_package *package)
933 struct razor_property_iterator *pi;
935 pi = zalloc(sizeof *pi);
939 pi->index = list_first(&package->properties,
940 &set->property_pool);
942 pi->property = set->properties.data;
943 pi->end = set->properties.data + set->properties.size;
950 razor_property_iterator_next(struct razor_property_iterator *pi,
951 struct razor_property **property,
953 enum razor_version_relation *relation,
954 const char **version,
955 enum razor_property_type *type)
959 struct razor_property *p, *properties;
964 } else if (pi->index) {
965 properties = pi->set->properties.data;
966 p = &properties[pi->index->data];
967 pi->index = list_next(pi->index);
973 pool = pi->set->string_pool.data;
975 *name = &pool[p->name];
976 *relation = p->relation;
977 *version = &pool[p->version];
987 razor_property_iterator_destroy(struct razor_property_iterator *pi)
992 static struct razor_entry *
993 find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern)
995 struct razor_entry *e;
996 const char *n, *pool = set->string_pool.data;
999 e = (struct razor_entry *) set->files.data + dir->start;
1002 if (strcmp(pattern + 1, n) == 0)
1005 if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
1006 pattern[len + 1] == '/') {
1007 return find_entry(set, e, pattern + len + 1);
1009 } while (!((e++)->flags & RAZOR_ENTRY_LAST));
1015 list_dir(struct razor_set *set, struct razor_entry *dir,
1016 char *prefix, const char *pattern)
1018 struct razor_entry *e;
1019 const char *n, *pool = set->string_pool.data;
1021 e = (struct razor_entry *) set->files.data + dir->start;
1024 if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
1026 printf("%s/%s\n", prefix, n);
1028 char *sub = prefix + strlen (prefix);
1030 strcpy (sub + 1, n);
1031 list_dir(set, e, prefix, pattern);
1034 } while (!((e++)->flags & RAZOR_ENTRY_LAST));
1038 razor_set_list_files(struct razor_set *set, const char *pattern)
1040 struct razor_entry *e;
1041 char buffer[512], *p, *base;
1043 if (pattern == NULL || !strcmp (pattern, "/")) {
1045 list_dir(set, set->files.data, buffer, NULL);
1049 strcpy(buffer, pattern);
1050 e = find_entry(set, set->files.data, buffer);
1051 if (e && e->start > 0) {
1054 p = strrchr(buffer, '/');
1062 e = find_entry(set, set->files.data, buffer);
1064 list_dir(set, e, buffer, base);
1067 struct razor_package_iterator *
1068 razor_package_iterator_create_for_file(struct razor_set *set,
1069 const char *filename)
1071 struct razor_entry *entry;
1074 entry = find_entry(set, set->files.data, filename);
1078 index = list_first(&entry->packages, &set->package_pool);
1079 return razor_package_iterator_create_with_index(set, index);
1082 static struct list *
1083 list_package_files(struct razor_set *set, struct list *r,
1084 struct razor_entry *dir, uint32_t end,
1087 struct razor_entry *e, *f, *entries;
1088 uint32_t next, file;
1092 entries = (struct razor_entry *) set->files.data;
1093 pool = set->string_pool.data;
1095 e = entries + dir->start;
1097 if (entries + r->data == e) {
1098 printf("%s/%s\n", prefix, pool + e->name);
1105 } while (!((e++)->flags & RAZOR_ENTRY_LAST));
1107 e = entries + dir->start;
1112 if (e->flags & RAZOR_ENTRY_LAST)
1116 while (f->start == 0 && !(f->flags & RAZOR_ENTRY_LAST))
1125 if (e->start <= file && file < next) {
1126 len = strlen(prefix);
1128 strcpy(prefix + len + 1, pool + e->name);
1129 r = list_package_files(set, r, e, next, prefix);
1132 } while (!((e++)->flags & RAZOR_ENTRY_LAST) && r != NULL);
1138 razor_set_list_package_files(struct razor_set *set, const char *name)
1140 struct razor_package *package;
1145 package = razor_set_get_package(set, name);
1147 r = list_first(&package->files, &set->file_pool);
1148 end = set->files.size / sizeof (struct razor_entry);
1150 list_package_files(set, r, set->files.data, end, buffer);
1153 #define UPSTREAM_SOURCE 0x80
1156 struct razor_set *set;
1157 uint32_t *property_map;
1161 struct razor_merger {
1162 struct razor_set *set;
1163 struct hashtable table;
1164 struct source source1;
1165 struct source source2;
1168 static struct razor_merger *
1169 razor_merger_create(struct razor_set *set1, struct razor_set *set2)
1171 struct razor_merger *merger;
1175 merger = zalloc(sizeof *merger);
1176 merger->set = razor_set_create();
1177 hashtable_init(&merger->table, &merger->set->string_pool);
1179 merger->source1.set = set1;
1180 count = set1->properties.size / sizeof (struct razor_property);
1181 size = count * sizeof merger->source1.property_map[0];
1182 merger->source1.property_map = zalloc(size);
1183 count = set1->files.size / sizeof (struct razor_entry);
1184 size = count * sizeof merger->source1.file_map[0];
1185 merger->source1.file_map = zalloc(size);
1187 merger->source2.set = set2;
1188 count = set2->properties.size / sizeof (struct razor_property);
1189 size = count * sizeof merger->source2.property_map[0];
1190 merger->source2.property_map = zalloc(size);
1191 count = set2->files.size / sizeof (struct razor_entry);
1192 size = count * sizeof merger->source2.file_map[0];
1193 merger->source2.file_map = zalloc(size);
1199 razor_merger_add_package(struct razor_merger *merger,
1200 struct razor_package *package)
1204 struct razor_package *p;
1205 struct razor_set *set1;
1206 struct source *source;
1209 set1 = merger->source1.set;
1210 if (set1->packages.data <= (void *) package &&
1211 (void *) package < set1->packages.data + set1->packages.size) {
1212 source = &merger->source1;
1215 source = &merger->source2;
1216 flags = UPSTREAM_SOURCE;
1219 pool = source->set->string_pool.data;
1220 p = array_add(&merger->set->packages, sizeof *p);
1221 p->name = hashtable_tokenize(&merger->table, &pool[package->name]);
1223 p->version = hashtable_tokenize(&merger->table,
1224 &pool[package->version]);
1225 p->arch = hashtable_tokenize(&merger->table,
1226 &pool[package->arch]);
1228 p->properties = package->properties;
1229 r = list_first(&package->properties, &source->set->property_pool);
1231 source->property_map[r->data] = 1;
1235 p->files = package->files;
1236 r = list_first(&package->files, &source->set->file_pool);
1238 source->file_map[r->data] = 1;
1244 add_property(struct razor_merger *merger,
1245 const char *name, enum razor_version_relation relation,
1246 const char *version, int type)
1248 struct razor_property *p;
1250 p = array_add(&merger->set->properties, sizeof *p);
1251 p->name = hashtable_tokenize(&merger->table, name);
1254 p->relation = relation;
1255 p->version = hashtable_tokenize(&merger->table, version);
1257 return p - (struct razor_property *) merger->set->properties.data;
1261 merge_properties(struct razor_merger *merger)
1263 struct razor_property *p1, *p2;
1264 struct razor_set *set1, *set2;
1265 uint32_t *map1, *map2;
1266 int i, j, cmp, count1, count2;
1267 char *pool1, *pool2;
1269 set1 = merger->source1.set;
1270 set2 = merger->source2.set;
1271 map1 = merger->source1.property_map;
1272 map2 = merger->source2.property_map;
1276 pool1 = set1->string_pool.data;
1277 pool2 = set2->string_pool.data;
1279 count1 = set1->properties.size / sizeof *p1;
1280 count2 = set2->properties.size / sizeof *p2;
1281 while (i < count1 || j < count2) {
1282 if (i < count1 && map1[i] == 0) {
1286 if (j < count2 && map2[j] == 0) {
1290 p1 = (struct razor_property *) set1->properties.data + i;
1291 p2 = (struct razor_property *) set2->properties.data + j;
1292 if (i < count1 && j < count2)
1293 cmp = strcmp(&pool1[p1->name], &pool2[p2->name]);
1294 else if (i < count1)
1299 cmp = p1->type - p2->type;
1301 cmp = p1->relation - p2->relation;
1303 cmp = versioncmp(&pool1[p1->version],
1304 &pool2[p2->version]);
1306 map1[i++] = add_property(merger,
1309 &pool1[p1->version],
1311 } else if (cmp > 0) {
1312 map2[j++] = add_property(merger,
1315 &pool2[p2->version],
1318 map1[i++] = map2[j++] = add_property(merger,
1321 &pool1[p1->version],
1328 emit_properties(struct list_head *properties, struct array *source_pool,
1329 uint32_t *map, struct array *pool)
1334 r = pool->size / sizeof *q;
1335 p = list_first(properties, source_pool);
1337 q = array_add(pool, sizeof *q);
1338 q->data = map[p->data];
1339 q->flags = p->flags;
1343 list_set_ptr(properties, r);
1347 add_file(struct razor_merger *merger, const char *name)
1349 struct razor_entry *e;
1351 e = array_add(&merger->set->files, sizeof *e);
1352 e->name = hashtable_tokenize(&merger->table, name);
1356 return e - (struct razor_entry *)merger->set->files.data;
1361 fix_file_map(uint32_t *map,
1362 struct razor_entry *files,
1363 struct razor_entry *top)
1371 fix_file_map(map, files, &files[e]);
1374 } while (!(files[e++].flags & RAZOR_ENTRY_LAST));
1377 map[top - files] = 1;
1381 struct merge_directory {
1382 uint32_t merged, dir1, dir2;
1386 merge_one_directory(struct razor_merger *merger, struct merge_directory *md)
1388 struct razor_entry *root1, *root2, *mroot, *e1, *e2;
1389 struct razor_set *set1, *set2;
1390 struct array merge_stack;
1391 struct merge_directory *child_md, *end_md;
1392 uint32_t *map1, *map2, start, last;
1394 char *pool1, *pool2;
1396 set1 = merger->source1.set;
1397 set2 = merger->source2.set;
1398 map1 = merger->source1.file_map;
1399 map2 = merger->source2.file_map;
1400 pool1 = set1->string_pool.data;
1401 pool2 = set2->string_pool.data;
1402 root1 = (struct razor_entry *) set1->files.data;
1403 root2 = (struct razor_entry *) set2->files.data;
1405 array_init(&merge_stack);
1407 start = merger->set->files.size / sizeof (struct razor_entry);
1409 e1 = md->dir1 ? root1 + md->dir1 : NULL;
1410 e2 = md->dir2 ? root2 + md->dir2 : NULL;
1412 if (!e2 && !map1[e1 - root1]) {
1413 if ((e1++)->flags & RAZOR_ENTRY_LAST)
1417 if (!e1 && !map2[e2 - root2]) {
1418 if ((e2++)->flags & RAZOR_ENTRY_LAST)
1422 if (e1 && !map1[e1 - root1] &&
1423 e2 && !map1[e2 - root2]) {
1424 if ((e1++)->flags & RAZOR_ENTRY_LAST)
1426 if ((e2++)->flags & RAZOR_ENTRY_LAST)
1436 cmp = strcmp (&pool1[e1->name],
1441 if (map1[e1 - root1]) {
1442 map1[e1 - root1] = last =
1443 add_file(merger, &pool1[e1->name]);
1445 child_md = array_add(&merge_stack, sizeof (struct merge_directory));
1446 child_md->merged = last;
1447 child_md->dir1 = e1->start;
1451 if ((e1++)->flags & RAZOR_ENTRY_LAST)
1453 } else if (cmp > 0) {
1454 if (map2[e2 - root2]) {
1455 map2[e2 - root2] = last =
1456 add_file(merger, &pool2[e2->name]);
1458 child_md = array_add(&merge_stack, sizeof (struct merge_directory));
1459 child_md->merged = last;
1461 child_md->dir2 = e2->start;
1464 if ((e2++)->flags & RAZOR_ENTRY_LAST)
1467 map1[e1 - root1] = map2[e2- root2] = last =
1468 add_file(merger, &pool1[e1->name]);
1469 if (e1->start || e2->start) {
1470 child_md = array_add(&merge_stack, sizeof (struct merge_directory));
1471 child_md->merged = last;
1472 child_md->dir1 = e1->start;
1473 child_md->dir2 = e2->start;
1475 if ((e1++)->flags & RAZOR_ENTRY_LAST)
1477 if ((e2++)->flags & RAZOR_ENTRY_LAST)
1482 mroot = (struct razor_entry *)merger->set->files.data;
1484 mroot[last].flags = RAZOR_ENTRY_LAST;
1485 mroot[md->merged].start = start;
1487 mroot[md->merged].start = 0;
1489 end_md = merge_stack.data + merge_stack.size;
1490 for (child_md = merge_stack.data; child_md < end_md; child_md++)
1491 merge_one_directory(merger, child_md);
1492 array_release(&merge_stack);
1496 merge_files(struct razor_merger *merger)
1498 struct razor_entry *root;
1499 struct merge_directory md;
1500 uint32_t *map1, *map2;
1502 map1 = merger->source1.file_map;
1503 map2 = merger->source2.file_map;
1507 if (merger->source1.set->files.size) {
1508 root = (struct razor_entry *) merger->source1.set->files.data;
1510 fix_file_map(map1, root, root);
1511 md.dir1 = root->start;
1515 if (merger->source2.set->files.size) {
1516 root = (struct razor_entry *) merger->source2.set->files.data;
1518 fix_file_map(map2, root, root);
1519 md.dir2 = root->start;
1523 merge_one_directory(merger, &md);
1527 emit_files(struct list_head *files, struct array *source_pool,
1528 uint32_t *map, struct array *pool)
1533 r = pool->size / sizeof *q;
1534 p = list_first(files, source_pool);
1536 q = array_add(pool, sizeof *q);
1537 q->data = map[p->data];
1538 q->flags = p->flags;
1542 list_set_ptr(files, r);
1545 /* Rebuild property->packages maps. We can't just remap these, as a
1546 * property may have lost or gained a number of packages. Allocate an
1547 * array per property and loop through the packages and add them to
1548 * the arrays for their properties. */
1550 rebuild_property_package_lists(struct razor_set *set)
1552 struct array *pkgs, *a;
1553 struct razor_package *pkg, *pkg_end;
1554 struct razor_property *prop, *prop_end;
1559 count = set->properties.size / sizeof (struct razor_property);
1560 pkgs = zalloc(count * sizeof *pkgs);
1561 pkg_end = set->packages.data + set->packages.size;
1563 for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
1564 r = list_first(&pkg->properties, &set->property_pool);
1566 q = array_add(&pkgs[r->data], sizeof *q);
1567 *q = pkg - (struct razor_package *) set->packages.data;
1572 prop_end = set->properties.data + set->properties.size;
1574 for (prop = set->properties.data; prop < prop_end; prop++, a++) {
1575 list_set_array(&prop->packages, &set->package_pool, a, 0);
1582 rebuild_file_package_lists(struct razor_set *set)
1584 struct array *pkgs, *a;
1585 struct razor_package *pkg, *pkg_end;
1586 struct razor_entry *entry, *entry_end;
1591 count = set->files.size / sizeof (struct razor_entry);
1592 pkgs = zalloc(count * sizeof *pkgs);
1593 pkg_end = set->packages.data + set->packages.size;
1595 for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
1596 r = list_first(&pkg->files, &set->file_pool);
1598 q = array_add(&pkgs[r->data], sizeof *q);
1599 *q = pkg - (struct razor_package *) set->packages.data;
1604 entry_end = set->files.data + set->files.size;
1606 for (entry = set->files.data; entry < entry_end; entry++, a++) {
1607 list_set_array(&entry->packages, &set->package_pool, a, 0);
1613 static struct razor_set *
1614 razor_merger_finish(struct razor_merger *merger)
1616 struct razor_set *result;
1617 struct razor_package *p, *pend;
1619 /* As we built the package list, we filled out a bitvector of
1620 * the properties that are referenced by the packages in the
1621 * new set. Now we do a parallel loop through the properties
1622 * and emit those marked in the bit vector to the new set. In
1623 * the process, we update the bit vector to actually map from
1624 * indices in the old property list to indices in the new
1625 * property list for both sets. */
1627 merge_properties(merger);
1628 merge_files(merger);
1630 /* Now we loop through the packages again and emit the
1631 * property lists, remapped to point to the new properties. */
1633 pend = merger->set->packages.data + merger->set->packages.size;
1634 for (p = merger->set->packages.data; p < pend; p++) {
1637 if (p->flags & UPSTREAM_SOURCE)
1638 src = &merger->source2;
1640 src = &merger->source1;
1642 emit_properties(&p->properties,
1643 &src->set->property_pool,
1645 &merger->set->property_pool);
1646 emit_files(&p->files,
1647 &src->set->file_pool,
1649 &merger->set->file_pool);
1650 p->flags &= ~UPSTREAM_SOURCE;
1653 rebuild_property_package_lists(merger->set);
1654 rebuild_file_package_lists(merger->set);
1656 result = merger->set;
1657 hashtable_release(&merger->table);
1663 /* The diff order matters. We should sort the packages so that a
1664 * REMOVE of a package comes before the INSTALL, and so that all
1665 * requires for a package have been installed before the package.
1669 razor_set_diff(struct razor_set *set, struct razor_set *upstream,
1670 razor_package_callback_t callback, void *data)
1672 struct razor_package_iterator *pi1, *pi2;
1673 struct razor_package *p1, *p2;
1674 const char *name1, *name2, *version1, *version2, *arch1, *arch2;
1677 pi1 = razor_package_iterator_create(set);
1678 pi2 = razor_package_iterator_create(upstream);
1680 razor_package_iterator_next(pi1, &p1, &name1, &version1, &arch1);
1681 razor_package_iterator_next(pi2, &p2, &name2, &version2, &arch2);
1685 res = strcmp(name1, name2);
1687 res = versioncmp(version1, version2);
1692 if (p2 == NULL || res < 0)
1693 callback(name1, version1, NULL, arch1, data);
1694 else if (p1 == NULL || res > 0)
1695 callback(name2, NULL, version2, arch2, data);
1697 if (p1 != NULL && res <= 0)
1698 razor_package_iterator_next(pi1, &p1,
1699 &name1, &version1, &arch1);
1700 if (p2 != NULL && res >= 0)
1701 razor_package_iterator_next(pi2, &p2,
1702 &name2, &version2, &arch2);
1705 razor_package_iterator_destroy(pi1);
1706 razor_package_iterator_destroy(pi2);
1710 provider_satisfies_requirement(struct razor_property *provider,
1711 const char *provider_strings,
1712 enum razor_version_relation relation,
1713 const char *required)
1716 const char *provided = &provider_strings[provider->version];
1721 if (relation >= RAZOR_VERSION_EQUAL)
1727 cmp = versioncmp(provided, required);
1730 case RAZOR_VERSION_LESS:
1733 case RAZOR_VERSION_LESS_OR_EQUAL:
1736 /* fall through: FIXME, make sure this is correct */
1738 case RAZOR_VERSION_EQUAL:
1742 /* "foo == 1.1" is satisfied by "foo 1.1-2" */
1743 len = strlen(required);
1744 if (!strncmp(required, provided, len) && provided[len] == '-')
1748 case RAZOR_VERSION_GREATER_OR_EQUAL:
1751 case RAZOR_VERSION_GREATER:
1755 /* shouldn't happen */
1759 #define TRANS_PACKAGE_PRESENT 1
1760 #define TRANS_PACKAGE_UPDATE 2
1761 #define TRANS_PROPERTY_SATISFIED 0x80000000
1763 struct transaction_set {
1764 struct razor_set *set;
1766 uint32_t *properties;
1769 struct razor_transaction {
1770 int package_count, errors;
1771 struct transaction_set system, upstream;
1776 transaction_set_init(struct transaction_set *ts, struct razor_set *set)
1781 count = set->packages.size / sizeof (struct razor_package);
1782 ts->packages = zalloc(count * sizeof *ts->packages);
1783 count = set->properties.size / sizeof (struct razor_property);
1784 ts->properties = zalloc(count * sizeof *ts->properties);
1788 transaction_set_release(struct transaction_set *ts)
1791 free(ts->properties);
1795 transaction_set_install_package(struct transaction_set *ts,
1796 struct razor_package *package)
1798 struct razor_package *pkgs;
1802 pkgs = ts->set->packages.data;
1804 if (ts->packages[i] == TRANS_PACKAGE_PRESENT)
1807 ts->packages[i] = TRANS_PACKAGE_PRESENT;
1809 prop = list_first(&package->properties, &ts->set->property_pool);
1811 ts->properties[prop->data]++;
1812 prop = list_next(prop);
1817 transaction_set_remove_package(struct transaction_set *ts,
1818 struct razor_package *package)
1820 struct razor_package *pkgs;
1824 pkgs = ts->set->packages.data;
1826 if (ts->packages[i] == 0)
1829 ts->packages[i] = 0;
1831 prop = list_first(&package->properties, &ts->set->property_pool);
1833 ts->properties[prop->data]--;
1834 prop = list_next(prop);
1838 struct razor_transaction *
1839 razor_transaction_create(struct razor_set *system, struct razor_set *upstream)
1841 struct razor_transaction *trans;
1842 struct razor_package *p, *spkgs, *pend;
1844 trans = zalloc(sizeof *trans);
1845 transaction_set_init(&trans->system, system);
1846 transaction_set_init(&trans->upstream, upstream);
1848 spkgs = trans->system.set->packages.data;
1849 pend = trans->system.set->packages.data +
1850 trans->system.set->packages.size;
1851 for (p = spkgs; p < pend; p++)
1852 transaction_set_install_package(&trans->system, p);
1858 razor_transaction_install_package(struct razor_transaction *trans,
1859 struct razor_package *package)
1861 transaction_set_install_package(&trans->upstream, package);
1866 razor_transaction_remove_package(struct razor_transaction *trans,
1867 struct razor_package *package)
1869 transaction_set_remove_package(&trans->system, package);
1874 razor_transaction_update_package(struct razor_transaction *trans,
1875 struct razor_package *package)
1877 struct razor_package *spkgs, *upkgs, *end;
1879 spkgs = trans->system.set->packages.data;
1880 upkgs = trans->upstream.set->packages.data;
1881 end = trans->system.set->packages.data +
1882 trans->system.set->packages.size;
1883 if (spkgs <= package && package < end)
1884 trans->system.packages[package - spkgs] |= TRANS_PACKAGE_UPDATE;
1886 trans->upstream.packages[package - upkgs] |= TRANS_PACKAGE_UPDATE;
1890 struct razor_property *p, *start, *end;
1896 prop_iter_init(struct prop_iter *pi, struct transaction_set *ts)
1898 pi->p = ts->set->properties.data;
1899 pi->start = ts->set->properties.data;
1900 pi->end = ts->set->properties.data + ts->set->properties.size;
1901 pi->pool = ts->set->string_pool.data;
1902 pi->present = ts->properties;
1906 prop_iter_next(struct prop_iter *pi,
1907 enum razor_property_type type, struct razor_property **p)
1909 while (pi->p < pi->end) {
1910 if ((pi->present[pi->p - pi->start] & ~TRANS_PROPERTY_SATISFIED) &&
1911 pi->p->type == type) {
1921 static struct razor_property *
1922 prop_iter_seek_to(struct prop_iter *pi,
1923 enum razor_property_type type, const char *match)
1927 while (pi->p < pi->end && strcmp(&pi->pool[pi->p->name], match) < 0)
1930 if (pi->p == pi->end || strcmp(&pi->pool[pi->p->name], match) > 0)
1934 while (pi->p < pi->end &&
1935 pi->p->name == name &&
1936 pi->p->type != type)
1939 if (pi->p == pi->end || pi->p->name != name)
1945 /* Remove packages from set that provide any of the matching (same
1946 * name and type) providers from ppi onwards that match the
1947 * requirement that rpi points to. */
1949 remove_matching_providers(struct razor_transaction *trans,
1950 struct prop_iter *ppi,
1951 enum razor_version_relation relation,
1952 const char *version)
1954 struct razor_property *p;
1955 struct razor_package *pkg, *pkgs;
1956 struct razor_package_iterator pkg_iter;
1957 struct razor_set *set;
1958 const char *n, *v, *a;
1960 if (ppi->present == trans->system.properties)
1961 set = trans->system.set;
1963 set = trans->upstream.set;
1965 pkgs = (struct razor_package *) set->packages.data;
1968 p->name == ppi->p->name &&
1969 p->type == ppi->p->type;
1971 if (!ppi->present[p - ppi->start])
1973 if (!provider_satisfies_requirement(p, ppi->pool,
1977 razor_package_iterator_init_for_property(&pkg_iter, set, p);
1978 while (razor_package_iterator_next(&pkg_iter,
1979 &pkg, &n, &v, &a)) {
1980 fprintf(stderr, "removing %s-%s\n", n, v);
1981 razor_transaction_remove_package(trans, pkg);
1987 flag_matching_providers(struct razor_transaction *trans,
1988 struct prop_iter *ppi,
1989 struct razor_property *r,
1990 struct prop_iter *rpi,
1993 struct razor_property *p;
1994 struct razor_package *pkg, *pkgs;
1995 struct razor_package_iterator pkg_iter;
1996 struct razor_set *set;
1997 const char *name, *version, *arch;
2000 if (ppi->present == trans->system.properties) {
2001 set = trans->system.set;
2002 flags = trans->system.packages;
2004 set = trans->upstream.set;
2005 flags = trans->upstream.packages;
2008 pkgs = (struct razor_package *) set->packages.data;
2011 p->name == ppi->p->name &&
2012 p->type == ppi->p->type;
2014 if (!ppi->present[p - ppi->start])
2016 if (!provider_satisfies_requirement(p, ppi->pool,
2018 &rpi->pool[r->version]))
2021 razor_package_iterator_init_for_property(&pkg_iter, set, p);
2022 while (razor_package_iterator_next(&pkg_iter, &pkg,
2023 &name, &version, &arch)) {
2025 fprintf(stderr, "flagging %s-%s for providing %s matching %s %s\n",
2027 ppi->pool + p->name,
2028 rpi->pool + r->name,
2029 rpi->pool + r->version);
2030 flags[pkg - pkgs] |= flag;
2035 static struct razor_package *
2036 pick_matching_provider(struct razor_set *set,
2037 struct prop_iter *ppi,
2038 enum razor_version_relation relation,
2039 const char *version)
2041 struct razor_property *p;
2042 struct razor_package *pkgs;
2045 /* This is where we decide which pkgs to pull in to satisfy a
2046 * requirement. There may be several different providers
2047 * (different versions) and each version of a provider may
2048 * come from a number of packages. We pick the first package
2049 * from the first provider that matches. */
2051 pkgs = set->packages.data;
2054 p->name == ppi->p->name &&
2055 p->type == ppi->p->type &&
2056 ppi->present[p - ppi->start] == 0;
2058 if (!provider_satisfies_requirement(p, ppi->pool,
2062 i = list_first(&p->packages, &set->package_pool);
2064 return &pkgs[i->data];
2071 remove_obsoleted_packages(struct razor_transaction *trans)
2073 struct razor_property *up;
2074 struct razor_package *spkgs;
2075 struct prop_iter spi, upi;
2077 spkgs = trans->system.set->packages.data;
2078 prop_iter_init(&spi, &trans->system);
2079 prop_iter_init(&upi, &trans->upstream);
2081 while (prop_iter_next(&upi, RAZOR_PROPERTY_OBSOLETES, &up)) {
2082 if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
2083 &upi.pool[up->name]))
2085 remove_matching_providers(trans, &spi, up->relation,
2086 &upi.pool[up->version]);
2091 any_provider_satisfies_requirement(struct prop_iter *ppi,
2092 enum razor_version_relation relation,
2093 const char *version)
2095 struct razor_property *p;
2099 p->name == ppi->p->name &&
2100 p->type == ppi->p->type;
2102 if (ppi->present[p - ppi->start] > 0 &&
2103 provider_satisfies_requirement(p, ppi->pool,
2112 clear_requires_flags(struct transaction_set *ts)
2114 struct razor_property *p;
2118 count = ts->set->properties.size / sizeof *p;
2119 p = ts->set->properties.data;
2120 pool = ts->set->string_pool.data;
2121 for (i = 0; i < count; i++) {
2122 ts->properties[i] &= ~TRANS_PROPERTY_SATISFIED;
2123 if (strncmp(&pool[p[i].name], "rpmlib(", 7) == 0)
2124 ts->properties[i] |= TRANS_PROPERTY_SATISFIED;
2128 static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
2131 mark_satisfied_requires(struct razor_transaction *trans,
2132 struct transaction_set *rts,
2133 struct transaction_set *pts)
2135 struct prop_iter rpi, ppi;
2136 struct razor_property *rp;
2138 prop_iter_init(&rpi, rts);
2139 prop_iter_init(&ppi, pts);
2141 while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
2142 if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES,
2143 &rpi.pool[rp->name]))
2146 if (any_provider_satisfies_requirement(&ppi, rp->relation,
2147 &rpi.pool[rp->version]))
2148 rpi.present[rp - rpi.start] |= TRANS_PROPERTY_SATISFIED;
2153 mark_all_satisfied_requires(struct razor_transaction *trans)
2155 clear_requires_flags(&trans->system);
2156 clear_requires_flags(&trans->upstream);
2157 mark_satisfied_requires(trans, &trans->system, &trans->system);
2158 mark_satisfied_requires(trans, &trans->system, &trans->upstream);
2159 mark_satisfied_requires(trans, &trans->upstream, &trans->system);
2160 mark_satisfied_requires(trans, &trans->upstream, &trans->upstream);
2164 update_unsatisfied_packages(struct razor_transaction *trans)
2166 struct razor_package *spkgs, *pkg;
2167 struct razor_property *sp;
2168 struct prop_iter spi;
2169 struct razor_package_iterator pkg_iter;
2170 const char *name, *version, *arch;
2172 spkgs = trans->system.set->packages.data;
2173 prop_iter_init(&spi, &trans->system);
2175 while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
2176 if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
2179 razor_package_iterator_init_for_property(&pkg_iter,
2182 while (razor_package_iterator_next(&pkg_iter, &pkg,
2183 &name, &version, &arch)) {
2184 fprintf(stderr, "updating %s because %s %s %s "
2185 "isn't satisfied\n",
2186 name, spi.pool + sp->name,
2187 relation_string[sp->relation],
2188 spi.pool + sp->version);
2189 trans->system.packages[pkg - spkgs] |=
2190 TRANS_PACKAGE_UPDATE;
2196 razor_transaction_update_all(struct razor_transaction *trans)
2198 struct razor_package *p;
2201 count = trans->system.set->packages.size / sizeof *p;
2202 for (i = 0; i < count; i++)
2203 trans->system.packages[i] |= TRANS_PACKAGE_UPDATE;
2207 update_conflicted_packages(struct razor_transaction *trans)
2209 struct razor_package *pkg, *spkgs;
2210 struct razor_property *up, *sp;
2211 struct prop_iter spi, upi;
2212 struct razor_package_iterator pkg_iter;
2213 const char *name, *version, *arch;
2215 spkgs = trans->system.set->packages.data;
2216 prop_iter_init(&spi, &trans->system);
2217 prop_iter_init(&upi, &trans->upstream);
2219 while (prop_iter_next(&spi, RAZOR_PROPERTY_CONFLICTS, &sp)) {
2220 if (!prop_iter_seek_to(&upi, RAZOR_PROPERTY_PROVIDES,
2221 &spi.pool[sp->name]))
2224 if (!any_provider_satisfies_requirement(&upi, sp->relation,
2225 &spi.pool[sp->version]))
2228 razor_package_iterator_init_for_property(&pkg_iter,
2231 while (razor_package_iterator_next(&pkg_iter, &pkg,
2232 &name, &version, &arch)) {
2233 fprintf(stderr, "updating %s %s because it conflicts with %s",
2234 name, version, spi.pool + sp->name);
2235 trans->system.packages[pkg - spkgs] |=
2236 TRANS_PACKAGE_UPDATE;
2240 prop_iter_init(&spi, &trans->system);
2241 prop_iter_init(&upi, &trans->upstream);
2243 while (prop_iter_next(&upi, RAZOR_PROPERTY_CONFLICTS, &up)) {
2244 sp = prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
2245 &upi.pool[upi.p->name]);
2248 flag_matching_providers(trans, &spi, up, &upi,
2249 TRANS_PACKAGE_UPDATE);
2254 pull_in_requirements(struct razor_transaction *trans,
2255 struct prop_iter *rpi, struct prop_iter *ppi)
2257 struct razor_property *rp, *pp;
2258 struct razor_package *pkg, *upkgs;
2260 upkgs = trans->upstream.set->packages.data;
2261 while (prop_iter_next(rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
2262 if (rpi->present[rp - rpi->start] & TRANS_PROPERTY_SATISFIED)
2265 pp = prop_iter_seek_to(ppi, RAZOR_PROPERTY_PROVIDES,
2266 &rpi->pool[rp->name]);
2269 pkg = pick_matching_provider(trans->upstream.set,
2271 &rpi->pool[rp->version]);
2275 rpi->present[rp - rpi->start] |= TRANS_PROPERTY_SATISFIED;
2277 fprintf(stderr, "pulling in %s which provides %s %s %s "
2278 "to satisfy %s %s %s\n",
2279 ppi->pool + pkg->name,
2280 ppi->pool + pp->name,
2281 relation_string[pp->relation],
2282 ppi->pool + pp->version,
2283 &rpi->pool[rp->name],
2284 relation_string[rp->relation],
2285 &rpi->pool[rp->version]);
2287 trans->upstream.packages[pkg - upkgs] |= TRANS_PACKAGE_UPDATE;
2292 pull_in_all_requirements(struct razor_transaction *trans)
2294 struct prop_iter rpi, ppi;
2296 prop_iter_init(&rpi, &trans->system);
2297 prop_iter_init(&ppi, &trans->upstream);
2298 pull_in_requirements(trans, &rpi, &ppi);
2300 prop_iter_init(&rpi, &trans->upstream);
2301 prop_iter_init(&ppi, &trans->upstream);
2302 pull_in_requirements(trans, &rpi, &ppi);
2306 flush_scheduled_system_updates(struct razor_transaction *trans)
2308 struct razor_package_iterator *pi;
2309 struct razor_package *p, *pkg, *spkgs;
2310 struct prop_iter ppi;
2311 const char *name, *version, *arch;
2313 spkgs = trans->system.set->packages.data;
2314 pi = razor_package_iterator_create(trans->system.set);
2315 prop_iter_init(&ppi, &trans->upstream);
2317 while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
2318 if (!(trans->system.packages[p - spkgs] & TRANS_PACKAGE_UPDATE))
2321 if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES, name))
2324 pkg = pick_matching_provider(trans->upstream.set, &ppi,
2325 RAZOR_VERSION_GREATER, version);
2329 fprintf(stderr, "updating %s-%s to %s-%s\n",
2331 &ppi.pool[pkg->name], &ppi.pool[pkg->version]);
2333 razor_transaction_remove_package(trans, p);
2334 razor_transaction_install_package(trans, pkg);
2337 razor_package_iterator_destroy(pi);
2341 flush_scheduled_upstream_updates(struct razor_transaction *trans)
2343 struct razor_package_iterator *pi;
2344 struct razor_package *p, *upkgs;
2345 struct prop_iter spi;
2346 const char *name, *version, *arch;
2348 upkgs = trans->upstream.set->packages.data;
2349 pi = razor_package_iterator_create(trans->upstream.set);
2350 prop_iter_init(&spi, &trans->system);
2352 while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
2353 if (!(trans->upstream.packages[p - upkgs] & TRANS_PACKAGE_UPDATE))
2356 if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES, name))
2358 remove_matching_providers(trans, &spi,
2359 RAZOR_VERSION_LESS, version);
2360 razor_transaction_install_package(trans, p);
2361 fprintf(stderr, "installing %s-%s\n", name, version);
2366 razor_transaction_resolve(struct razor_transaction *trans)
2370 flush_scheduled_system_updates(trans);
2372 while (last < trans->changes) {
2373 last = trans->changes;
2374 remove_obsoleted_packages(trans);
2375 mark_all_satisfied_requires(trans);
2376 update_unsatisfied_packages(trans);
2377 update_conflicted_packages(trans);
2378 pull_in_all_requirements(trans);
2379 flush_scheduled_system_updates(trans);
2380 flush_scheduled_upstream_updates(trans);
2383 return trans->changes;
2387 describe_unsatisfied(struct razor_set *set, struct razor_property *rp)
2389 struct razor_package_iterator pi;
2390 struct razor_package *pkg;
2391 const char *name, *version, *arch, *pool;
2393 pool = set->string_pool.data;
2394 if (pool[rp->version] == '\0') {
2395 razor_package_iterator_init_for_property(&pi, set, rp);
2396 while (razor_package_iterator_next(&pi, &pkg,
2397 &name, &version, &arch))
2398 fprintf(stderr, "%s is needed by %s-%s.%s\n",
2400 name, version, arch);
2402 razor_package_iterator_init_for_property(&pi, set, rp);
2403 while (razor_package_iterator_next(&pi, &pkg,
2404 &name, &version, &arch))
2405 fprintf(stderr, "%s %s %s is needed by %s-%s.%s\n",
2407 relation_string[rp->relation],
2409 name, version, arch);
2414 razor_transaction_describe(struct razor_transaction *trans)
2416 struct prop_iter rpi;
2417 struct razor_property *rp;
2420 flush_scheduled_system_updates(trans);
2421 flush_scheduled_upstream_updates(trans);
2422 mark_all_satisfied_requires(trans);
2425 prop_iter_init(&rpi, &trans->system);
2426 while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
2427 if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
2428 describe_unsatisfied(trans->system.set, rp);
2433 prop_iter_init(&rpi, &trans->upstream);
2434 while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
2435 if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
2436 describe_unsatisfied(trans->upstream.set, rp);
2445 razor_transaction_unsatisfied_property(struct razor_transaction *trans,
2447 enum razor_version_relation rel,
2448 const char *version,
2449 enum razor_property_type type)
2451 struct prop_iter pi;
2452 struct razor_property *p;
2454 prop_iter_init(&pi, &trans->system);
2455 while (prop_iter_next(&pi, type, &p)) {
2456 if (!(trans->system.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
2457 p->relation == rel &&
2458 strcmp(&pi.pool[p->name], name) == 0 &&
2459 strcmp(&pi.pool[p->version], version) == 0)
2464 prop_iter_init(&pi, &trans->upstream);
2465 while (prop_iter_next(&pi, type, &p)) {
2466 if (!(trans->upstream.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
2467 p->relation == rel &&
2468 strcmp(&pi.pool[p->name], name) == 0 &&
2469 strcmp(&pi.pool[p->version], version) == 0)
2478 razor_transaction_finish(struct razor_transaction *trans)
2480 struct razor_merger *merger;
2481 struct razor_package *u, *uend, *upkgs, *s, *send, *spkgs;
2482 char *upool, *spool;
2485 s = trans->system.set->packages.data;
2486 spkgs = trans->system.set->packages.data;
2487 send = trans->system.set->packages.data +
2488 trans->system.set->packages.size;
2489 spool = trans->system.set->string_pool.data;
2491 u = trans->upstream.set->packages.data;
2492 upkgs = trans->upstream.set->packages.data;
2493 uend = trans->upstream.set->packages.data +
2494 trans->upstream.set->packages.size;
2495 upool = trans->upstream.set->string_pool.data;
2497 merger = razor_merger_create(trans->system.set, trans->upstream.set);
2498 while (s < send || u < uend) {
2499 if (s < send && u < uend)
2500 cmp = strcmp(&spool[s->name], &upool[u->name]);
2507 if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
2508 razor_merger_add_package(merger, s);
2510 } else if (cmp == 0) {
2511 if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
2512 razor_merger_add_package(merger, s);
2513 if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
2514 razor_merger_add_package(merger, u);
2519 if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
2520 razor_merger_add_package(merger, u);
2525 razor_transaction_destroy(trans);
2527 return razor_merger_finish(merger);
2531 razor_transaction_destroy(struct razor_transaction *trans)
2533 transaction_set_release(&trans->system);
2534 transaction_set_release(&trans->upstream);
2538 struct razor_package_query {
2539 struct razor_set *set;
2544 struct razor_package_query *
2545 razor_package_query_create(struct razor_set *set)
2547 struct razor_package_query *pq;
2550 pq = zalloc(sizeof *pq);
2552 count = set->packages.size / sizeof(struct razor_package);
2553 pq->vector = zalloc(count * sizeof(char));
2559 razor_package_query_add_package(struct razor_package_query *pq,
2560 struct razor_package *p)
2562 struct razor_package *packages;
2564 packages = pq->set->packages.data;
2565 pq->count += pq->vector[p - packages] ^ 1;
2566 pq->vector[p - packages] = 1;
2570 razor_package_query_add_iterator(struct razor_package_query *pq,
2571 struct razor_package_iterator *pi)
2573 struct razor_package *packages, *p;
2574 const char *name, *version, *arch;
2576 packages = pq->set->packages.data;
2577 while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
2578 pq->count += pq->vector[p - packages] ^ 1;
2579 pq->vector[p - packages] = 1;
2583 struct razor_package_iterator *
2584 razor_package_query_finish(struct razor_package_query *pq)
2586 struct razor_package_iterator *pi;
2587 struct razor_set *set;
2592 count = set->packages.size / sizeof(struct razor_package);
2593 index = zalloc(pq->count * sizeof *index);
2595 for (i = 0, j = 0; i < count; i++) {
2600 if (j == pq->count - 1)
2601 index[j].flags = 0x80;
2607 pi = razor_package_iterator_create_with_index(set, index);