1.1 --- a/razor.c Sun Jun 15 23:15:59 2008 -0400
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,2611 +0,0 @@
1.4 -/*
1.5 - * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
1.6 - * Copyright (C) 2008 Red Hat, Inc
1.7 - *
1.8 - * This program is free software; you can redistribute it and/or modify
1.9 - * it under the terms of the GNU General Public License as published by
1.10 - * the Free Software Foundation; either version 2 of the License, or
1.11 - * (at your option) any later version.
1.12 - *
1.13 - * This program is distributed in the hope that it will be useful,
1.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.16 - * GNU General Public License for more details.
1.17 - *
1.18 - * You should have received a copy of the GNU General Public License along
1.19 - * with this program; if not, write to the Free Software Foundation, Inc.,
1.20 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1.21 - */
1.22 -
1.23 -#define _GNU_SOURCE
1.24 -
1.25 -#include <stdlib.h>
1.26 -#include <stddef.h>
1.27 -#include <stdint.h>
1.28 -#include <stdio.h>
1.29 -#include <string.h>
1.30 -#include <sys/types.h>
1.31 -#include <sys/stat.h>
1.32 -#include <sys/mman.h>
1.33 -#include <unistd.h>
1.34 -#include <fcntl.h>
1.35 -#include <errno.h>
1.36 -#include <ctype.h>
1.37 -#include <fnmatch.h>
1.38 -
1.39 -#include "razor.h"
1.40 -#include "razor-internal.h"
1.41 -#include "types.h"
1.42 -
1.43 -struct razor_set_section {
1.44 - uint32_t type;
1.45 - uint32_t offset;
1.46 - uint32_t size;
1.47 -};
1.48 -
1.49 -struct razor_set_header {
1.50 - uint32_t magic;
1.51 - uint32_t version;
1.52 - struct razor_set_section sections[0];
1.53 -};
1.54 -
1.55 -#define RAZOR_MAGIC 0x7a7a7a7a
1.56 -#define RAZOR_VERSION 1
1.57 -
1.58 -#define RAZOR_STRING_POOL 0
1.59 -#define RAZOR_PACKAGES 1
1.60 -#define RAZOR_PROPERTIES 2
1.61 -#define RAZOR_FILES 3
1.62 -#define RAZOR_PACKAGE_POOL 4
1.63 -#define RAZOR_PROPERTY_POOL 5
1.64 -#define RAZOR_FILE_POOL 6
1.65 -
1.66 -struct razor_package {
1.67 - uint name : 24;
1.68 - uint flags : 8;
1.69 - uint32_t version;
1.70 - uint32_t arch;
1.71 - struct list_head properties;
1.72 - struct list_head files;
1.73 -};
1.74 -
1.75 -struct razor_property {
1.76 - uint name : 24;
1.77 - uint flags : 6;
1.78 - enum razor_property_type type : 2;
1.79 - enum razor_version_relation relation : 32;
1.80 - uint32_t version;
1.81 - struct list_head packages;
1.82 -};
1.83 -
1.84 -struct razor_entry {
1.85 - uint name : 24;
1.86 - uint flags : 8;
1.87 - uint32_t start;
1.88 - struct list_head packages;
1.89 -};
1.90 -
1.91 -#define RAZOR_ENTRY_LAST 0x80
1.92 -
1.93 -struct razor_set {
1.94 - struct array string_pool;
1.95 - struct array packages;
1.96 - struct array properties;
1.97 - struct array files;
1.98 - struct array package_pool;
1.99 - struct array property_pool;
1.100 - struct array file_pool;
1.101 - struct razor_set_header *header;
1.102 -};
1.103 -
1.104 -struct import_entry {
1.105 - uint32_t package;
1.106 - char *name;
1.107 -};
1.108 -
1.109 -struct import_directory {
1.110 - uint32_t name, count;
1.111 - struct array files;
1.112 - struct array packages;
1.113 - struct import_directory *last;
1.114 -};
1.115 -
1.116 -struct razor_importer {
1.117 - struct razor_set *set;
1.118 - struct hashtable table;
1.119 - struct razor_package *package;
1.120 - struct array properties;
1.121 - struct array files;
1.122 - struct array file_requires;
1.123 -};
1.124 -
1.125 -static void *
1.126 -zalloc(size_t size)
1.127 -{
1.128 - void *p;
1.129 -
1.130 - p = malloc(size);
1.131 - memset(p, 0, size);
1.132 -
1.133 - return p;
1.134 -}
1.135 -
1.136 -struct razor_set_section razor_sections[] = {
1.137 - { RAZOR_STRING_POOL, offsetof(struct razor_set, string_pool) },
1.138 - { RAZOR_PACKAGES, offsetof(struct razor_set, packages) },
1.139 - { RAZOR_PROPERTIES, offsetof(struct razor_set, properties) },
1.140 - { RAZOR_FILES, offsetof(struct razor_set, files) },
1.141 - { RAZOR_PACKAGE_POOL, offsetof(struct razor_set, package_pool) },
1.142 - { RAZOR_PROPERTY_POOL, offsetof(struct razor_set, property_pool) },
1.143 - { RAZOR_FILE_POOL, offsetof(struct razor_set, file_pool) },
1.144 -};
1.145 -
1.146 -struct razor_set *
1.147 -razor_set_create(void)
1.148 -{
1.149 - struct razor_set *set;
1.150 - struct razor_entry *e;
1.151 - char *empty;
1.152 -
1.153 - set = zalloc(sizeof *set);
1.154 -
1.155 - e = array_add(&set->files, sizeof *e);
1.156 - empty = array_add(&set->string_pool, 1);
1.157 - *empty = '\0';
1.158 - e->name = 0;
1.159 - e->flags = RAZOR_ENTRY_LAST;
1.160 - e->start = 0;
1.161 - list_set_empty(&e->packages);
1.162 -
1.163 - return set;
1.164 -}
1.165 -
1.166 -struct razor_set *
1.167 -razor_set_open(const char *filename)
1.168 -{
1.169 - struct razor_set *set;
1.170 - struct razor_set_section *s;
1.171 - struct stat stat;
1.172 - struct array *array;
1.173 - int fd;
1.174 -
1.175 - set = zalloc(sizeof *set);
1.176 - fd = open(filename, O_RDONLY);
1.177 - if (fstat(fd, &stat) < 0)
1.178 - return NULL;
1.179 - set->header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1.180 - if (set->header == MAP_FAILED) {
1.181 - free(set);
1.182 - return NULL;
1.183 - }
1.184 -
1.185 - for (s = set->header->sections; ~s->type; s++) {
1.186 - if (s->type >= ARRAY_SIZE(razor_sections))
1.187 - continue;
1.188 - if (s->type != razor_sections[s->type].type)
1.189 - continue;
1.190 - array = (void *) set + razor_sections[s->type].offset;
1.191 - array->data = (void *) set->header + s->offset;
1.192 - array->size = s->size;
1.193 - array->alloc = s->size;
1.194 - }
1.195 - close(fd);
1.196 -
1.197 - return set;
1.198 -}
1.199 -
1.200 -void
1.201 -razor_set_destroy(struct razor_set *set)
1.202 -{
1.203 - unsigned int size;
1.204 - struct array *a;
1.205 - int i;
1.206 -
1.207 - if (set->header) {
1.208 - for (i = 0; set->header->sections[i].type; i++)
1.209 - ;
1.210 - size = set->header->sections[i].type;
1.211 - munmap(set->header, size);
1.212 - } else {
1.213 - for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
1.214 - a = (void *) set + razor_sections[i].offset;
1.215 - free(a->data);
1.216 - }
1.217 - }
1.218 -
1.219 - free(set);
1.220 -}
1.221 -
1.222 -int
1.223 -razor_set_write_to_fd(struct razor_set *set, int fd)
1.224 -{
1.225 - char data[4096];
1.226 - struct razor_set_header *header = (struct razor_set_header *) data;
1.227 - struct array *a;
1.228 - uint32_t offset;
1.229 - int i;
1.230 -
1.231 - memset(data, 0, sizeof data);
1.232 - header->magic = RAZOR_MAGIC;
1.233 - header->version = RAZOR_VERSION;
1.234 - offset = sizeof data;
1.235 -
1.236 - for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
1.237 - if (razor_sections[i].type != i)
1.238 - continue;
1.239 - a = (void *) set + razor_sections[i].offset;
1.240 - header->sections[i].type = i;
1.241 - header->sections[i].offset = offset;
1.242 - header->sections[i].size = a->size;
1.243 - offset += ALIGN(a->size, 4096);
1.244 - }
1.245 -
1.246 - header->sections[i].type = ~0;
1.247 - header->sections[i].offset = 0;
1.248 - header->sections[i].size = 0;
1.249 -
1.250 - razor_write(fd, data, sizeof data);
1.251 - memset(data, 0, sizeof data);
1.252 - for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
1.253 - if (razor_sections[i].type != i)
1.254 - continue;
1.255 - a = (void *) set + razor_sections[i].offset;
1.256 - razor_write(fd, a->data, a->size);
1.257 - razor_write(fd, data, ALIGN(a->size, 4096) - a->size);
1.258 - }
1.259 -
1.260 - return 0;
1.261 -}
1.262 -
1.263 -int
1.264 -razor_set_write(struct razor_set *set, const char *filename)
1.265 -{
1.266 - int fd, status;
1.267 -
1.268 - fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
1.269 - if (fd < 0)
1.270 - return -1;
1.271 -
1.272 - status = razor_set_write_to_fd(set, fd);
1.273 - if (status) {
1.274 - close(fd);
1.275 - return status;
1.276 - }
1.277 -
1.278 - return close(fd);
1.279 -}
1.280 -
1.281 -void
1.282 -razor_build_evr(char *evr_buf, int size, const char *epoch,
1.283 - const char *version, const char *release)
1.284 -{
1.285 - int len;
1.286 -
1.287 - if (!version || !*version) {
1.288 - *evr_buf = '\0';
1.289 - return;
1.290 - }
1.291 -
1.292 - if (epoch && *epoch && strcmp(epoch, "0") != 0) {
1.293 - len = snprintf(evr_buf, size, "%s:", epoch);
1.294 - evr_buf += len;
1.295 - size -= len;
1.296 - }
1.297 - len = snprintf(evr_buf, size, "%s", version);
1.298 - evr_buf += len;
1.299 - size -= len;
1.300 - if (release && *release)
1.301 - snprintf(evr_buf, size, "-%s", release);
1.302 -}
1.303 -
1.304 -void
1.305 -razor_importer_begin_package(struct razor_importer *importer,
1.306 - const char *name,
1.307 - const char *version,
1.308 - const char *arch)
1.309 -{
1.310 - struct razor_package *p;
1.311 -
1.312 - p = array_add(&importer->set->packages, sizeof *p);
1.313 - p->name = hashtable_tokenize(&importer->table, name);
1.314 - p->flags = 0;
1.315 - p->version = hashtable_tokenize(&importer->table, version);
1.316 - p->arch = hashtable_tokenize(&importer->table, arch);
1.317 -
1.318 - importer->package = p;
1.319 - array_init(&importer->properties);
1.320 -}
1.321 -
1.322 -void
1.323 -razor_importer_finish_package(struct razor_importer *importer)
1.324 -{
1.325 - list_set_array(&importer->package->properties,
1.326 - &importer->set->property_pool,
1.327 - &importer->properties,
1.328 - 1);
1.329 -
1.330 - array_release(&importer->properties);
1.331 -}
1.332 -
1.333 -void
1.334 -razor_importer_add_property(struct razor_importer *importer,
1.335 - const char *name,
1.336 - enum razor_version_relation relation,
1.337 - const char *version,
1.338 - enum razor_property_type type)
1.339 -{
1.340 - struct razor_property *p;
1.341 - uint32_t *r;
1.342 -
1.343 - p = array_add(&importer->set->properties, sizeof *p);
1.344 - p->name = hashtable_tokenize(&importer->table, name);
1.345 - p->flags = 0;
1.346 - p->type = type;
1.347 - p->relation = relation;
1.348 - p->version = hashtable_tokenize(&importer->table, version);
1.349 - list_set_ptr(&p->packages, importer->package -
1.350 - (struct razor_package *) importer->set->packages.data);
1.351 -
1.352 - r = array_add(&importer->properties, sizeof *r);
1.353 - *r = p - (struct razor_property *) importer->set->properties.data;
1.354 -
1.355 - if (type == RAZOR_PROPERTY_REQUIRES && *name == '/') {
1.356 - r = array_add(&importer->file_requires, sizeof *r);
1.357 - *r = p->name;
1.358 - }
1.359 -}
1.360 -
1.361 -void
1.362 -razor_importer_add_file(struct razor_importer *importer, const char *name)
1.363 -{
1.364 - struct import_entry *e;
1.365 -
1.366 - e = array_add(&importer->files, sizeof *e);
1.367 -
1.368 - e->package = importer->package -
1.369 - (struct razor_package *) importer->set->packages.data;
1.370 - e->name = strdup(name);
1.371 -}
1.372 -
1.373 -struct razor_importer *
1.374 -razor_importer_new(void)
1.375 -{
1.376 - struct razor_importer *importer;
1.377 -
1.378 - importer = zalloc(sizeof *importer);
1.379 - importer->set = razor_set_create();
1.380 - hashtable_init(&importer->table, &importer->set->string_pool);
1.381 -
1.382 - return importer;
1.383 -}
1.384 -
1.385 -/* Destroy an importer without creating the set. */
1.386 -void
1.387 -razor_importer_destroy(struct razor_importer *importer)
1.388 -{
1.389 - /* FIXME: write this */
1.390 -}
1.391 -
1.392 -static int
1.393 -versioncmp(const char *s1, const char *s2)
1.394 -{
1.395 - const char *p1, *p2;
1.396 - long n1, n2;
1.397 - int res;
1.398 -
1.399 - n1 = strtol(s1, (char **) &p1, 10);
1.400 - n2 = strtol(s2, (char **) &p2, 10);
1.401 -
1.402 - /* Epoch; if one but not the other has an epoch set, default
1.403 - * the epoch-less version to 0. */
1.404 - res = (*p1 == ':') - (*p2 == ':');
1.405 - if (res < 0) {
1.406 - n1 = 0;
1.407 - p1 = s1;
1.408 - p2++;
1.409 - } else if (res > 0) {
1.410 - p1++;
1.411 - n2 = 0;
1.412 - p2 = s2;
1.413 - }
1.414 -
1.415 - if (n1 != n2)
1.416 - return n1 - n2;
1.417 - while (*p1 && *p2) {
1.418 - if (*p1 != *p2)
1.419 - return *p1 - *p2;
1.420 - p1++;
1.421 - p2++;
1.422 - if (isdigit(*p1) && isdigit(*p2))
1.423 - return versioncmp(p1, p2);
1.424 - }
1.425 -
1.426 - return *p1 - *p2;
1.427 -}
1.428 -
1.429 -static int
1.430 -compare_packages(const void *p1, const void *p2, void *data)
1.431 -{
1.432 - const struct razor_package *pkg1 = p1, *pkg2 = p2;
1.433 - struct razor_set *set = data;
1.434 - char *pool = set->string_pool.data;
1.435 -
1.436 - /* FIXME: what if the flags are different? */
1.437 - if (pkg1->name == pkg2->name)
1.438 - return versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
1.439 - else
1.440 - return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
1.441 -}
1.442 -
1.443 -static int
1.444 -compare_properties(const void *p1, const void *p2, void *data)
1.445 -{
1.446 - const struct razor_property *prop1 = p1, *prop2 = p2;
1.447 - struct razor_set *set = data;
1.448 - char *pool = set->string_pool.data;
1.449 -
1.450 - if (prop1->name != prop2->name)
1.451 - return strcmp(&pool[prop1->name], &pool[prop2->name]);
1.452 - else if (prop1->type != prop2->type)
1.453 - return prop1->type - prop2->type;
1.454 - else if (prop1->relation != prop2->relation)
1.455 - return prop1->relation - prop2->relation;
1.456 - else
1.457 - return versioncmp(&pool[prop1->version], &pool[prop2->version]);
1.458 -}
1.459 -
1.460 -static uint32_t *
1.461 -uniqueify_properties(struct razor_set *set)
1.462 -{
1.463 - struct razor_property *rp, *up, *rp_end;
1.464 - struct array *pkgs, *p;
1.465 - struct list_head *r;
1.466 - uint32_t *map, *rmap;
1.467 - int i, count, unique;
1.468 -
1.469 - count = set->properties.size / sizeof(struct razor_property);
1.470 - map = razor_qsort_with_data(set->properties.data,
1.471 - count,
1.472 - sizeof(struct razor_property),
1.473 - compare_properties,
1.474 - set);
1.475 -
1.476 - rp_end = set->properties.data + set->properties.size;
1.477 - rmap = malloc(count * sizeof *map);
1.478 - pkgs = zalloc(count * sizeof *pkgs);
1.479 - for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
1.480 - if (rp->name != up->name || rp->type != up->type ||
1.481 - rp->relation != up->relation || rp->version != up->version) {
1.482 - up++;
1.483 - up->name = rp->name;
1.484 - up->flags = 0;
1.485 - up->type = rp->type;
1.486 - up->relation = rp->relation;
1.487 - up->version = rp->version;
1.488 - }
1.489 -
1.490 - unique = up - (struct razor_property *) set->properties.data;
1.491 - rmap[map[i]] = unique;
1.492 - r = array_add(&pkgs[unique], sizeof *r);
1.493 - *r = rp->packages;
1.494 - }
1.495 - free(map);
1.496 -
1.497 - if (up != rp)
1.498 - up++;
1.499 - set->properties.size = (void *) up - set->properties.data;
1.500 - rp_end = up;
1.501 - for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
1.502 - list_set_array(&rp->packages, &set->package_pool, p, 0);
1.503 - array_release(p);
1.504 - }
1.505 -
1.506 - free(pkgs);
1.507 -
1.508 - return rmap;
1.509 -}
1.510 -
1.511 -static int
1.512 -compare_filenames(const void *p1, const void *p2, void *data)
1.513 -{
1.514 - const struct import_entry *e1 = p1;
1.515 - const struct import_entry *e2 = p2;
1.516 - const char *n1 = e1->name;
1.517 - const char *n2 = e2->name;
1.518 -
1.519 - /* Need to make sure that the contents of a directory
1.520 - * are sorted immediately after it. So "foo/bar" has to
1.521 - * sort before "foo.conf"
1.522 - *
1.523 - * FIXME: this is about 60% slower than strcmp
1.524 - */
1.525 - while (*n1 && *n2) {
1.526 - if (*n1 < *n2)
1.527 - return *n2 == '/' ? 1 : -1;
1.528 - else if (*n1 > *n2)
1.529 - return *n1 == '/' ? -1 : 1;
1.530 - n1++;
1.531 - n2++;
1.532 - }
1.533 - if (*n1)
1.534 - return 1;
1.535 - else if (*n2)
1.536 - return -1;
1.537 - else
1.538 - return 0;
1.539 -}
1.540 -
1.541 -static void
1.542 -count_entries(struct import_directory *d)
1.543 -{
1.544 - struct import_directory *p, *end;
1.545 -
1.546 - p = d->files.data;
1.547 - end = d->files.data + d->files.size;
1.548 - d->count = 0;
1.549 - while (p < end) {
1.550 - count_entries(p);
1.551 - d->count += p->count + 1;
1.552 - p++;
1.553 - }
1.554 -}
1.555 -
1.556 -static void
1.557 -serialize_files(struct razor_set *set,
1.558 - struct import_directory *d, struct array *array)
1.559 -{
1.560 - struct import_directory *p, *end;
1.561 - struct razor_entry *e = NULL;
1.562 - uint32_t s;
1.563 -
1.564 - p = d->files.data;
1.565 - end = d->files.data + d->files.size;
1.566 - s = array->size / sizeof *e + d->files.size / sizeof *p;
1.567 - while (p < end) {
1.568 - e = array_add(array, sizeof *e);
1.569 - e->name = p->name;
1.570 - e->flags = 0;
1.571 - e->start = p->count > 0 ? s : 0;
1.572 - s += p->count;
1.573 -
1.574 - list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
1.575 - array_release(&p->packages);
1.576 - p++;
1.577 - }
1.578 - if (e != NULL)
1.579 - e->flags |= RAZOR_ENTRY_LAST;
1.580 -
1.581 - p = d->files.data;
1.582 - end = d->files.data + d->files.size;
1.583 - while (p < end) {
1.584 - serialize_files(set, p, array);
1.585 - p++;
1.586 - }
1.587 -}
1.588 -
1.589 -static void
1.590 -remap_property_package_links(struct array *properties, uint32_t *rmap)
1.591 -{
1.592 - struct razor_property *p, *end;
1.593 -
1.594 - end = properties->data + properties->size;
1.595 - for (p = properties->data; p < end; p++)
1.596 - list_remap_head(&p->packages, rmap);
1.597 -}
1.598 -
1.599 -static void
1.600 -build_file_tree(struct razor_importer *importer)
1.601 -{
1.602 - int count, i, length;
1.603 - struct import_entry *filenames;
1.604 - char *f, *end;
1.605 - uint32_t name, *r;
1.606 - char dirname[256];
1.607 - struct import_directory *d, root;
1.608 - struct razor_entry *e;
1.609 -
1.610 - count = importer->files.size / sizeof (struct import_entry);
1.611 - razor_qsort_with_data(importer->files.data,
1.612 - count,
1.613 - sizeof (struct import_entry),
1.614 - compare_filenames,
1.615 - NULL);
1.616 -
1.617 - root.name = hashtable_tokenize(&importer->table, "");
1.618 - array_init(&root.files);
1.619 - array_init(&root.packages);
1.620 - root.last = NULL;
1.621 -
1.622 - filenames = importer->files.data;
1.623 - for (i = 0; i < count; i++) {
1.624 - f = filenames[i].name;
1.625 - if (*f != '/')
1.626 - continue;
1.627 - f++;
1.628 -
1.629 - d = &root;
1.630 - while (*f) {
1.631 - end = strchr(f, '/');
1.632 - if (end == NULL)
1.633 - end = f + strlen(f);
1.634 - length = end - f;
1.635 - memcpy(dirname, f, length);
1.636 - dirname[length] ='\0';
1.637 - name = hashtable_tokenize(&importer->table, dirname);
1.638 - if (d->last == NULL || d->last->name != name) {
1.639 - d->last = array_add(&d->files, sizeof *d);
1.640 - d->last->name = name;
1.641 - d->last->last = NULL;
1.642 - array_init(&d->last->files);
1.643 - array_init(&d->last->packages);
1.644 - }
1.645 - d = d->last;
1.646 - f = end + 1;
1.647 - if (*end == '\0')
1.648 - break;
1.649 - }
1.650 -
1.651 - r = array_add(&d->packages, sizeof *r);
1.652 - *r = filenames[i].package;
1.653 - free(filenames[i].name);
1.654 - }
1.655 -
1.656 - count_entries(&root);
1.657 - e = importer->set->files.data;
1.658 - e->name = root.name;
1.659 - e->flags = RAZOR_ENTRY_LAST;
1.660 - e->start = importer->files.size ? 1 : 0;
1.661 - list_set_empty(&e->packages);
1.662 -
1.663 - serialize_files(importer->set, &root, &importer->set->files);
1.664 -
1.665 - array_release(&importer->files);
1.666 -}
1.667 -
1.668 -static struct razor_entry *
1.669 -find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern);
1.670 -
1.671 -static void
1.672 -list_to_array(struct list *list, struct array *array)
1.673 -{
1.674 - uint32_t *item;
1.675 -
1.676 - while (list) {
1.677 - item = array_add(array, sizeof *item);
1.678 - *item = list->data;
1.679 - list = list_next(list);
1.680 - }
1.681 -}
1.682 -
1.683 -static int
1.684 -compare_file_requires(const void *p1, const void *p2, void *data)
1.685 -{
1.686 - uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
1.687 - const char *pool = data;
1.688 -
1.689 - return strcmp(&pool[*f1], &pool[*f2]);
1.690 -}
1.691 -
1.692 -static void
1.693 -find_file_provides(struct razor_importer *importer)
1.694 -{
1.695 - struct razor_property *prop;
1.696 - struct razor_entry *top, *entry;
1.697 - struct razor_package *packages;
1.698 - struct array pkgprops;
1.699 - struct list *pkg;
1.700 - uint32_t *req, *req_start, *req_end;
1.701 - uint32_t *map, *newprop;
1.702 - char *pool;
1.703 -
1.704 - pool = importer->set->string_pool.data;
1.705 - packages = importer->set->packages.data;
1.706 - top = importer->set->files.data;
1.707 -
1.708 - req = req_start = importer->file_requires.data;
1.709 - req_end = importer->file_requires.data + importer->file_requires.size;
1.710 - map = razor_qsort_with_data(req, req_end - req, sizeof *req,
1.711 - compare_file_requires, pool);
1.712 - free(map);
1.713 -
1.714 - for (req = req_start; req < req_end; req++) {
1.715 - if (req > req_start && req[0] == req[-1])
1.716 - continue;
1.717 - entry = find_entry(importer->set, top, &pool[*req]);
1.718 - if (!entry)
1.719 - continue;
1.720 -
1.721 - for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
1.722 - prop = array_add(&importer->set->properties, sizeof *prop);
1.723 - prop->name = *req;
1.724 - prop->type = RAZOR_PROPERTY_PROVIDES;
1.725 - prop->relation = RAZOR_VERSION_EQUAL;
1.726 - prop->version = hashtable_tokenize(&importer->table, "");
1.727 - list_set_ptr(&prop->packages, pkg->data);
1.728 -
1.729 - /* Update property list of pkg */
1.730 - array_init(&pkgprops);
1.731 - list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
1.732 - newprop = array_add(&pkgprops, sizeof *newprop);
1.733 - *newprop = prop - (struct razor_property *)importer->set->properties.data;
1.734 - list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
1.735 - array_release(&pkgprops);
1.736 - }
1.737 - }
1.738 -
1.739 - array_release(&importer->file_requires);
1.740 -}
1.741 -
1.742 -static void
1.743 -build_package_file_lists(struct razor_set *set, uint32_t *rmap)
1.744 -{
1.745 - struct razor_package *p, *packages;
1.746 - struct array *pkgs;
1.747 - struct razor_entry *e, *end;
1.748 - struct list *r;
1.749 - uint32_t *q;
1.750 - int i, count;
1.751 -
1.752 - count = set->packages.size / sizeof *p;
1.753 - pkgs = zalloc(count * sizeof *pkgs);
1.754 -
1.755 - end = set->files.data + set->files.size;
1.756 - for (e = set->files.data; e < end; e++) {
1.757 - list_remap_head(&e->packages, rmap);
1.758 - r = list_first(&e->packages, &set->package_pool);
1.759 - while (r) {
1.760 - q = array_add(&pkgs[r->data], sizeof *q);
1.761 - *q = e - (struct razor_entry *) set->files.data;
1.762 - r = list_next(r);
1.763 - }
1.764 - }
1.765 -
1.766 - packages = set->packages.data;
1.767 - for (i = 0; i < count; i++) {
1.768 - list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
1.769 - array_release(&pkgs[i]);
1.770 - }
1.771 - free(pkgs);
1.772 -}
1.773 -
1.774 -struct razor_set *
1.775 -razor_importer_finish(struct razor_importer *importer)
1.776 -{
1.777 - struct razor_set *set;
1.778 - uint32_t *map, *rmap;
1.779 - int i, count;
1.780 -
1.781 - build_file_tree(importer);
1.782 - find_file_provides(importer);
1.783 -
1.784 - map = uniqueify_properties(importer->set);
1.785 - list_remap_pool(&importer->set->property_pool, map);
1.786 - free(map);
1.787 -
1.788 - count = importer->set->packages.size / sizeof(struct razor_package);
1.789 - map = razor_qsort_with_data(importer->set->packages.data,
1.790 - count,
1.791 - sizeof(struct razor_package),
1.792 - compare_packages,
1.793 - importer->set);
1.794 -
1.795 - rmap = malloc(count * sizeof *rmap);
1.796 - for (i = 0; i < count; i++)
1.797 - rmap[map[i]] = i;
1.798 - free(map);
1.799 -
1.800 - list_remap_pool(&importer->set->package_pool, rmap);
1.801 - build_package_file_lists(importer->set, rmap);
1.802 - remap_property_package_links(&importer->set->properties, rmap);
1.803 - free(rmap);
1.804 -
1.805 - set = importer->set;
1.806 - hashtable_release(&importer->table);
1.807 - free(importer);
1.808 -
1.809 - return set;
1.810 -}
1.811 -
1.812 -struct razor_package_iterator {
1.813 - struct razor_set *set;
1.814 - struct razor_package *package, *end;
1.815 - struct list *index;
1.816 - int free_index;
1.817 -};
1.818 -
1.819 -static struct razor_package_iterator *
1.820 -razor_package_iterator_create_with_index(struct razor_set *set,
1.821 - struct list *index)
1.822 -{
1.823 - struct razor_package_iterator *pi;
1.824 -
1.825 - pi = zalloc(sizeof *pi);
1.826 - pi->set = set;
1.827 - pi->index = index;
1.828 -
1.829 - return pi;
1.830 -}
1.831 -
1.832 -struct razor_package_iterator *
1.833 -razor_package_iterator_create(struct razor_set *set)
1.834 -{
1.835 - struct razor_package_iterator *pi;
1.836 -
1.837 - pi = zalloc(sizeof *pi);
1.838 - pi->set = set;
1.839 - pi->end = set->packages.data + set->packages.size;
1.840 - pi->package = set->packages.data;
1.841 -
1.842 - return pi;
1.843 -}
1.844 -
1.845 -static void
1.846 -razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
1.847 - struct razor_set *set,
1.848 - struct razor_property *property)
1.849 -{
1.850 - memset(pi, 0, sizeof *pi);
1.851 - pi->set = set;
1.852 - pi->index = list_first(&property->packages, &set->package_pool);
1.853 -}
1.854 -
1.855 -struct razor_package_iterator *
1.856 -razor_package_iterator_create_for_property(struct razor_set *set,
1.857 - struct razor_property *property)
1.858 -{
1.859 - struct list *index;
1.860 -
1.861 - index = list_first(&property->packages, &set->package_pool);
1.862 - return razor_package_iterator_create_with_index(set, index);
1.863 -}
1.864 -
1.865 -int
1.866 -razor_package_iterator_next(struct razor_package_iterator *pi,
1.867 - struct razor_package **package,
1.868 - const char **name,
1.869 - const char **version,
1.870 - const char **arch)
1.871 -{
1.872 - char *pool;
1.873 - int valid;
1.874 - struct razor_package *p, *packages;
1.875 -
1.876 - if (pi->package) {
1.877 - p = pi->package++;
1.878 - valid = p < pi->end;
1.879 - } else if (pi->index) {
1.880 - packages = pi->set->packages.data;
1.881 - p = &packages[pi->index->data];
1.882 - pi->index = list_next(pi->index);
1.883 - valid = 1;
1.884 - } else
1.885 - valid = 0;
1.886 -
1.887 - if (valid) {
1.888 - pool = pi->set->string_pool.data;
1.889 - *package = p;
1.890 - *name = &pool[p->name];
1.891 - *version = &pool[p->version];
1.892 - *arch = &pool[p->arch];
1.893 - } else {
1.894 - *package = NULL;
1.895 - }
1.896 -
1.897 - return valid;
1.898 -}
1.899 -
1.900 -void
1.901 -razor_package_iterator_destroy(struct razor_package_iterator *pi)
1.902 -{
1.903 - if (pi->free_index)
1.904 - free(pi->index);
1.905 -
1.906 - free(pi);
1.907 -}
1.908 -
1.909 -struct razor_package *
1.910 -razor_set_get_package(struct razor_set *set, const char *package)
1.911 -{
1.912 - struct razor_package_iterator *pi;
1.913 - struct razor_package *p;
1.914 - const char *name, *version, *arch;
1.915 -
1.916 - pi = razor_package_iterator_create(set);
1.917 - while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
1.918 - if (strcmp(package, name) == 0)
1.919 - break;
1.920 - }
1.921 - razor_package_iterator_destroy(pi);
1.922 -
1.923 - return p;
1.924 -}
1.925 -
1.926 -struct razor_property_iterator {
1.927 - struct razor_set *set;
1.928 - struct razor_property *property, *end;
1.929 - struct list *index;
1.930 -};
1.931 -
1.932 -struct razor_property_iterator *
1.933 -razor_property_iterator_create(struct razor_set *set,
1.934 - struct razor_package *package)
1.935 -{
1.936 - struct razor_property_iterator *pi;
1.937 -
1.938 - pi = zalloc(sizeof *pi);
1.939 - pi->set = set;
1.940 -
1.941 - if (package) {
1.942 - pi->index = list_first(&package->properties,
1.943 - &set->property_pool);
1.944 - } else {
1.945 - pi->property = set->properties.data;
1.946 - pi->end = set->properties.data + set->properties.size;
1.947 - }
1.948 -
1.949 - return pi;
1.950 -}
1.951 -
1.952 -int
1.953 -razor_property_iterator_next(struct razor_property_iterator *pi,
1.954 - struct razor_property **property,
1.955 - const char **name,
1.956 - enum razor_version_relation *relation,
1.957 - const char **version,
1.958 - enum razor_property_type *type)
1.959 -{
1.960 - char *pool;
1.961 - int valid;
1.962 - struct razor_property *p, *properties;
1.963 -
1.964 - if (pi->property) {
1.965 - p = pi->property++;
1.966 - valid = p < pi->end;
1.967 - } else if (pi->index) {
1.968 - properties = pi->set->properties.data;
1.969 - p = &properties[pi->index->data];
1.970 - pi->index = list_next(pi->index);
1.971 - valid = 1;
1.972 - } else
1.973 - valid = 0;
1.974 -
1.975 - if (valid) {
1.976 - pool = pi->set->string_pool.data;
1.977 - *property = p;
1.978 - *name = &pool[p->name];
1.979 - *relation = p->relation;
1.980 - *version = &pool[p->version];
1.981 - *type = p->type;
1.982 - } else {
1.983 - *property = NULL;
1.984 - }
1.985 -
1.986 - return valid;
1.987 -}
1.988 -
1.989 -void
1.990 -razor_property_iterator_destroy(struct razor_property_iterator *pi)
1.991 -{
1.992 - free(pi);
1.993 -}
1.994 -
1.995 -static struct razor_entry *
1.996 -find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern)
1.997 -{
1.998 - struct razor_entry *e;
1.999 - const char *n, *pool = set->string_pool.data;
1.1000 - int len;
1.1001 -
1.1002 - e = (struct razor_entry *) set->files.data + dir->start;
1.1003 - do {
1.1004 - n = pool + e->name;
1.1005 - if (strcmp(pattern + 1, n) == 0)
1.1006 - return e;
1.1007 - len = strlen(n);
1.1008 - if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
1.1009 - pattern[len + 1] == '/') {
1.1010 - return find_entry(set, e, pattern + len + 1);
1.1011 - }
1.1012 - } while (!((e++)->flags & RAZOR_ENTRY_LAST));
1.1013 -
1.1014 - return NULL;
1.1015 -}
1.1016 -
1.1017 -static void
1.1018 -list_dir(struct razor_set *set, struct razor_entry *dir,
1.1019 - char *prefix, const char *pattern)
1.1020 -{
1.1021 - struct razor_entry *e;
1.1022 - const char *n, *pool = set->string_pool.data;
1.1023 -
1.1024 - e = (struct razor_entry *) set->files.data + dir->start;
1.1025 - do {
1.1026 - n = pool + e->name;
1.1027 - if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
1.1028 - continue;
1.1029 - printf("%s/%s\n", prefix, n);
1.1030 - if (e->start) {
1.1031 - char *sub = prefix + strlen (prefix);
1.1032 - *sub = '/';
1.1033 - strcpy (sub + 1, n);
1.1034 - list_dir(set, e, prefix, pattern);
1.1035 - *sub = '\0';
1.1036 - }
1.1037 - } while (!((e++)->flags & RAZOR_ENTRY_LAST));
1.1038 -}
1.1039 -
1.1040 -void
1.1041 -razor_set_list_files(struct razor_set *set, const char *pattern)
1.1042 -{
1.1043 - struct razor_entry *e;
1.1044 - char buffer[512], *p, *base;
1.1045 -
1.1046 - if (pattern == NULL || !strcmp (pattern, "/")) {
1.1047 - buffer[0] = '\0';
1.1048 - list_dir(set, set->files.data, buffer, NULL);
1.1049 - return;
1.1050 - }
1.1051 -
1.1052 - strcpy(buffer, pattern);
1.1053 - e = find_entry(set, set->files.data, buffer);
1.1054 - if (e && e->start > 0) {
1.1055 - base = NULL;
1.1056 - } else {
1.1057 - p = strrchr(buffer, '/');
1.1058 - if (p) {
1.1059 - *p = '\0';
1.1060 - base = p + 1;
1.1061 - } else {
1.1062 - base = NULL;
1.1063 - }
1.1064 - }
1.1065 - e = find_entry(set, set->files.data, buffer);
1.1066 - if (e->start != 0)
1.1067 - list_dir(set, e, buffer, base);
1.1068 -}
1.1069 -
1.1070 -struct razor_package_iterator *
1.1071 -razor_package_iterator_create_for_file(struct razor_set *set,
1.1072 - const char *filename)
1.1073 -{
1.1074 - struct razor_entry *entry;
1.1075 - struct list *index;
1.1076 -
1.1077 - entry = find_entry(set, set->files.data, filename);
1.1078 - if (entry == NULL)
1.1079 - return NULL;
1.1080 -
1.1081 - index = list_first(&entry->packages, &set->package_pool);
1.1082 - return razor_package_iterator_create_with_index(set, index);
1.1083 -}
1.1084 -
1.1085 -static struct list *
1.1086 -list_package_files(struct razor_set *set, struct list *r,
1.1087 - struct razor_entry *dir, uint32_t end,
1.1088 - char *prefix)
1.1089 -{
1.1090 - struct razor_entry *e, *f, *entries;
1.1091 - uint32_t next, file;
1.1092 - char *pool;
1.1093 - int len;
1.1094 -
1.1095 - entries = (struct razor_entry *) set->files.data;
1.1096 - pool = set->string_pool.data;
1.1097 -
1.1098 - e = entries + dir->start;
1.1099 - do {
1.1100 - if (entries + r->data == e) {
1.1101 - printf("%s/%s\n", prefix, pool + e->name);
1.1102 - r = list_next(r);
1.1103 - if (!r)
1.1104 - return NULL;
1.1105 - if (r->data >= end)
1.1106 - return r;
1.1107 - }
1.1108 - } while (!((e++)->flags & RAZOR_ENTRY_LAST));
1.1109 -
1.1110 - e = entries + dir->start;
1.1111 - do {
1.1112 - if (e->start == 0)
1.1113 - continue;
1.1114 -
1.1115 - if (e->flags & RAZOR_ENTRY_LAST)
1.1116 - next = end;
1.1117 - else {
1.1118 - f = e + 1;
1.1119 - while (f->start == 0 && !(f->flags & RAZOR_ENTRY_LAST))
1.1120 - f++;
1.1121 - if (f->start == 0)
1.1122 - next = end;
1.1123 - else
1.1124 - next = f->start;
1.1125 - }
1.1126 -
1.1127 - file = r->data;
1.1128 - if (e->start <= file && file < next) {
1.1129 - len = strlen(prefix);
1.1130 - prefix[len] = '/';
1.1131 - strcpy(prefix + len + 1, pool + e->name);
1.1132 - r = list_package_files(set, r, e, next, prefix);
1.1133 - prefix[len] = '\0';
1.1134 - }
1.1135 - } while (!((e++)->flags & RAZOR_ENTRY_LAST) && r != NULL);
1.1136 -
1.1137 - return r;
1.1138 -}
1.1139 -
1.1140 -void
1.1141 -razor_set_list_package_files(struct razor_set *set, const char *name)
1.1142 -{
1.1143 - struct razor_package *package;
1.1144 - struct list *r;
1.1145 - uint32_t end;
1.1146 - char buffer[512];
1.1147 -
1.1148 - package = razor_set_get_package(set, name);
1.1149 -
1.1150 - r = list_first(&package->files, &set->file_pool);
1.1151 - end = set->files.size / sizeof (struct razor_entry);
1.1152 - buffer[0] = '\0';
1.1153 - list_package_files(set, r, set->files.data, end, buffer);
1.1154 -}
1.1155 -
1.1156 -#define UPSTREAM_SOURCE 0x80
1.1157 -
1.1158 -struct source {
1.1159 - struct razor_set *set;
1.1160 - uint32_t *property_map;
1.1161 - uint32_t *file_map;
1.1162 -};
1.1163 -
1.1164 -struct razor_merger {
1.1165 - struct razor_set *set;
1.1166 - struct hashtable table;
1.1167 - struct source source1;
1.1168 - struct source source2;
1.1169 -};
1.1170 -
1.1171 -static struct razor_merger *
1.1172 -razor_merger_create(struct razor_set *set1, struct razor_set *set2)
1.1173 -{
1.1174 - struct razor_merger *merger;
1.1175 - int count;
1.1176 - size_t size;
1.1177 -
1.1178 - merger = zalloc(sizeof *merger);
1.1179 - merger->set = razor_set_create();
1.1180 - hashtable_init(&merger->table, &merger->set->string_pool);
1.1181 -
1.1182 - merger->source1.set = set1;
1.1183 - count = set1->properties.size / sizeof (struct razor_property);
1.1184 - size = count * sizeof merger->source1.property_map[0];
1.1185 - merger->source1.property_map = zalloc(size);
1.1186 - count = set1->files.size / sizeof (struct razor_entry);
1.1187 - size = count * sizeof merger->source1.file_map[0];
1.1188 - merger->source1.file_map = zalloc(size);
1.1189 -
1.1190 - merger->source2.set = set2;
1.1191 - count = set2->properties.size / sizeof (struct razor_property);
1.1192 - size = count * sizeof merger->source2.property_map[0];
1.1193 - merger->source2.property_map = zalloc(size);
1.1194 - count = set2->files.size / sizeof (struct razor_entry);
1.1195 - size = count * sizeof merger->source2.file_map[0];
1.1196 - merger->source2.file_map = zalloc(size);
1.1197 -
1.1198 - return merger;
1.1199 -}
1.1200 -
1.1201 -static void
1.1202 -razor_merger_add_package(struct razor_merger *merger,
1.1203 - struct razor_package *package)
1.1204 -{
1.1205 - char *pool;
1.1206 - struct list *r;
1.1207 - struct razor_package *p;
1.1208 - struct razor_set *set1;
1.1209 - struct source *source;
1.1210 - uint32_t flags;
1.1211 -
1.1212 - set1 = merger->source1.set;
1.1213 - if (set1->packages.data <= (void *) package &&
1.1214 - (void *) package < set1->packages.data + set1->packages.size) {
1.1215 - source = &merger->source1;
1.1216 - flags = 0;
1.1217 - } else {
1.1218 - source = &merger->source2;
1.1219 - flags = UPSTREAM_SOURCE;
1.1220 - }
1.1221 -
1.1222 - pool = source->set->string_pool.data;
1.1223 - p = array_add(&merger->set->packages, sizeof *p);
1.1224 - p->name = hashtable_tokenize(&merger->table, &pool[package->name]);
1.1225 - p->flags = flags;
1.1226 - p->version = hashtable_tokenize(&merger->table,
1.1227 - &pool[package->version]);
1.1228 - p->arch = hashtable_tokenize(&merger->table,
1.1229 - &pool[package->arch]);
1.1230 -
1.1231 - p->properties = package->properties;
1.1232 - r = list_first(&package->properties, &source->set->property_pool);
1.1233 - while (r) {
1.1234 - source->property_map[r->data] = 1;
1.1235 - r = list_next(r);
1.1236 - }
1.1237 -
1.1238 - p->files = package->files;
1.1239 - r = list_first(&package->files, &source->set->file_pool);
1.1240 - while (r) {
1.1241 - source->file_map[r->data] = 1;
1.1242 - r = list_next(r);
1.1243 - }
1.1244 -}
1.1245 -
1.1246 -static uint32_t
1.1247 -add_property(struct razor_merger *merger,
1.1248 - const char *name, enum razor_version_relation relation,
1.1249 - const char *version, int type)
1.1250 -{
1.1251 - struct razor_property *p;
1.1252 -
1.1253 - p = array_add(&merger->set->properties, sizeof *p);
1.1254 - p->name = hashtable_tokenize(&merger->table, name);
1.1255 - p->flags = 0;
1.1256 - p->type = type;
1.1257 - p->relation = relation;
1.1258 - p->version = hashtable_tokenize(&merger->table, version);
1.1259 -
1.1260 - return p - (struct razor_property *) merger->set->properties.data;
1.1261 -}
1.1262 -
1.1263 -static void
1.1264 -merge_properties(struct razor_merger *merger)
1.1265 -{
1.1266 - struct razor_property *p1, *p2;
1.1267 - struct razor_set *set1, *set2;
1.1268 - uint32_t *map1, *map2;
1.1269 - int i, j, cmp, count1, count2;
1.1270 - char *pool1, *pool2;
1.1271 -
1.1272 - set1 = merger->source1.set;
1.1273 - set2 = merger->source2.set;
1.1274 - map1 = merger->source1.property_map;
1.1275 - map2 = merger->source2.property_map;
1.1276 -
1.1277 - i = 0;
1.1278 - j = 0;
1.1279 - pool1 = set1->string_pool.data;
1.1280 - pool2 = set2->string_pool.data;
1.1281 -
1.1282 - count1 = set1->properties.size / sizeof *p1;
1.1283 - count2 = set2->properties.size / sizeof *p2;
1.1284 - while (i < count1 || j < count2) {
1.1285 - if (i < count1 && map1[i] == 0) {
1.1286 - i++;
1.1287 - continue;
1.1288 - }
1.1289 - if (j < count2 && map2[j] == 0) {
1.1290 - j++;
1.1291 - continue;
1.1292 - }
1.1293 - p1 = (struct razor_property *) set1->properties.data + i;
1.1294 - p2 = (struct razor_property *) set2->properties.data + j;
1.1295 - if (i < count1 && j < count2)
1.1296 - cmp = strcmp(&pool1[p1->name], &pool2[p2->name]);
1.1297 - else if (i < count1)
1.1298 - cmp = -1;
1.1299 - else
1.1300 - cmp = 1;
1.1301 - if (cmp == 0)
1.1302 - cmp = p1->type - p2->type;
1.1303 - if (cmp == 0)
1.1304 - cmp = p1->relation - p2->relation;
1.1305 - if (cmp == 0)
1.1306 - cmp = versioncmp(&pool1[p1->version],
1.1307 - &pool2[p2->version]);
1.1308 - if (cmp < 0) {
1.1309 - map1[i++] = add_property(merger,
1.1310 - &pool1[p1->name],
1.1311 - p1->relation,
1.1312 - &pool1[p1->version],
1.1313 - p1->type);
1.1314 - } else if (cmp > 0) {
1.1315 - map2[j++] = add_property(merger,
1.1316 - &pool2[p2->name],
1.1317 - p2->relation,
1.1318 - &pool2[p2->version],
1.1319 - p2->type);
1.1320 - } else {
1.1321 - map1[i++] = map2[j++] = add_property(merger,
1.1322 - &pool1[p1->name],
1.1323 - p1->relation,
1.1324 - &pool1[p1->version],
1.1325 - p1->type);
1.1326 - }
1.1327 - }
1.1328 -}
1.1329 -
1.1330 -static void
1.1331 -emit_properties(struct list_head *properties, struct array *source_pool,
1.1332 - uint32_t *map, struct array *pool)
1.1333 -{
1.1334 - uint32_t r;
1.1335 - struct list *p, *q;
1.1336 -
1.1337 - r = pool->size / sizeof *q;
1.1338 - p = list_first(properties, source_pool);
1.1339 - while (p) {
1.1340 - q = array_add(pool, sizeof *q);
1.1341 - q->data = map[p->data];
1.1342 - q->flags = p->flags;
1.1343 - p = list_next(p);
1.1344 - }
1.1345 -
1.1346 - list_set_ptr(properties, r);
1.1347 -}
1.1348 -
1.1349 -static uint32_t
1.1350 -add_file(struct razor_merger *merger, const char *name)
1.1351 -{
1.1352 - struct razor_entry *e;
1.1353 -
1.1354 - e = array_add(&merger->set->files, sizeof *e);
1.1355 - e->name = hashtable_tokenize(&merger->table, name);
1.1356 - e->flags = 0;
1.1357 - e->start = 0;
1.1358 -
1.1359 - return e - (struct razor_entry *)merger->set->files.data;
1.1360 -}
1.1361 -
1.1362 -/* FIXME. Blah */
1.1363 -static int
1.1364 -fix_file_map(uint32_t *map,
1.1365 - struct razor_entry *files,
1.1366 - struct razor_entry *top)
1.1367 -{
1.1368 - uint32_t e;
1.1369 - int found_file = 0;
1.1370 -
1.1371 - e = top->start;
1.1372 - do {
1.1373 - if (files[e].start)
1.1374 - fix_file_map(map, files, &files[e]);
1.1375 - if (map[e])
1.1376 - found_file = 1;
1.1377 - } while (!(files[e++].flags & RAZOR_ENTRY_LAST));
1.1378 -
1.1379 - if (found_file)
1.1380 - map[top - files] = 1;
1.1381 - return found_file;
1.1382 -}
1.1383 -
1.1384 -struct merge_directory {
1.1385 - uint32_t merged, dir1, dir2;
1.1386 -};
1.1387 -
1.1388 -static void
1.1389 -merge_one_directory(struct razor_merger *merger, struct merge_directory *md)
1.1390 -{
1.1391 - struct razor_entry *root1, *root2, *mroot, *e1, *e2;
1.1392 - struct razor_set *set1, *set2;
1.1393 - struct array merge_stack;
1.1394 - struct merge_directory *child_md, *end_md;
1.1395 - uint32_t *map1, *map2, start, last;
1.1396 - int cmp;
1.1397 - char *pool1, *pool2;
1.1398 -
1.1399 - set1 = merger->source1.set;
1.1400 - set2 = merger->source2.set;
1.1401 - map1 = merger->source1.file_map;
1.1402 - map2 = merger->source2.file_map;
1.1403 - pool1 = set1->string_pool.data;
1.1404 - pool2 = set2->string_pool.data;
1.1405 - root1 = (struct razor_entry *) set1->files.data;
1.1406 - root2 = (struct razor_entry *) set2->files.data;
1.1407 -
1.1408 - array_init(&merge_stack);
1.1409 -
1.1410 - start = merger->set->files.size / sizeof (struct razor_entry);
1.1411 - last = 0;
1.1412 - e1 = md->dir1 ? root1 + md->dir1 : NULL;
1.1413 - e2 = md->dir2 ? root2 + md->dir2 : NULL;
1.1414 - while (e1 || e2) {
1.1415 - if (!e2 && !map1[e1 - root1]) {
1.1416 - if ((e1++)->flags & RAZOR_ENTRY_LAST)
1.1417 - e1 = NULL;
1.1418 - continue;
1.1419 - }
1.1420 - if (!e1 && !map2[e2 - root2]) {
1.1421 - if ((e2++)->flags & RAZOR_ENTRY_LAST)
1.1422 - e2 = NULL;
1.1423 - continue;
1.1424 - }
1.1425 - if (e1 && !map1[e1 - root1] &&
1.1426 - e2 && !map1[e2 - root2]) {
1.1427 - if ((e1++)->flags & RAZOR_ENTRY_LAST)
1.1428 - e1 = NULL;
1.1429 - if ((e2++)->flags & RAZOR_ENTRY_LAST)
1.1430 - e2 = NULL;
1.1431 - continue;
1.1432 - }
1.1433 -
1.1434 - if (!e1)
1.1435 - cmp = 1;
1.1436 - else if (!e2)
1.1437 - cmp = -1;
1.1438 - else {
1.1439 - cmp = strcmp (&pool1[e1->name],
1.1440 - &pool2[e2->name]);
1.1441 - }
1.1442 -
1.1443 - if (cmp < 0) {
1.1444 - if (map1[e1 - root1]) {
1.1445 - map1[e1 - root1] = last =
1.1446 - add_file(merger, &pool1[e1->name]);
1.1447 - if (e1->start) {
1.1448 - child_md = array_add(&merge_stack, sizeof (struct merge_directory));
1.1449 - child_md->merged = last;
1.1450 - child_md->dir1 = e1->start;
1.1451 - child_md->dir2 = 0;
1.1452 - }
1.1453 - }
1.1454 - if ((e1++)->flags & RAZOR_ENTRY_LAST)
1.1455 - e1 = NULL;
1.1456 - } else if (cmp > 0) {
1.1457 - if (map2[e2 - root2]) {
1.1458 - map2[e2 - root2] = last =
1.1459 - add_file(merger, &pool2[e2->name]);
1.1460 - if (e2->start) {
1.1461 - child_md = array_add(&merge_stack, sizeof (struct merge_directory));
1.1462 - child_md->merged = last;
1.1463 - child_md->dir1 = 0;
1.1464 - child_md->dir2 = e2->start;
1.1465 - }
1.1466 - }
1.1467 - if ((e2++)->flags & RAZOR_ENTRY_LAST)
1.1468 - e2 = NULL;
1.1469 - } else {
1.1470 - map1[e1 - root1] = map2[e2- root2] = last =
1.1471 - add_file(merger, &pool1[e1->name]);
1.1472 - if (e1->start || e2->start) {
1.1473 - child_md = array_add(&merge_stack, sizeof (struct merge_directory));
1.1474 - child_md->merged = last;
1.1475 - child_md->dir1 = e1->start;
1.1476 - child_md->dir2 = e2->start;
1.1477 - }
1.1478 - if ((e1++)->flags & RAZOR_ENTRY_LAST)
1.1479 - e1 = NULL;
1.1480 - if ((e2++)->flags & RAZOR_ENTRY_LAST)
1.1481 - e2 = NULL;
1.1482 - }
1.1483 - }
1.1484 -
1.1485 - mroot = (struct razor_entry *)merger->set->files.data;
1.1486 - if (last) {
1.1487 - mroot[last].flags = RAZOR_ENTRY_LAST;
1.1488 - mroot[md->merged].start = start;
1.1489 - } else
1.1490 - mroot[md->merged].start = 0;
1.1491 -
1.1492 - end_md = merge_stack.data + merge_stack.size;
1.1493 - for (child_md = merge_stack.data; child_md < end_md; child_md++)
1.1494 - merge_one_directory(merger, child_md);
1.1495 - array_release(&merge_stack);
1.1496 -}
1.1497 -
1.1498 -static void
1.1499 -merge_files(struct razor_merger *merger)
1.1500 -{
1.1501 - struct razor_entry *root;
1.1502 - struct merge_directory md;
1.1503 - uint32_t *map1, *map2;
1.1504 -
1.1505 - map1 = merger->source1.file_map;
1.1506 - map2 = merger->source2.file_map;
1.1507 -
1.1508 - md.merged = 0;
1.1509 -
1.1510 - if (merger->source1.set->files.size) {
1.1511 - root = (struct razor_entry *) merger->source1.set->files.data;
1.1512 - if (root->start)
1.1513 - fix_file_map(map1, root, root);
1.1514 - md.dir1 = root->start;
1.1515 - } else
1.1516 - md.dir1 = 0;
1.1517 -
1.1518 - if (merger->source2.set->files.size) {
1.1519 - root = (struct razor_entry *) merger->source2.set->files.data;
1.1520 - if (root->start)
1.1521 - fix_file_map(map2, root, root);
1.1522 - md.dir2 = root->start;
1.1523 - } else
1.1524 - md.dir2 = 0;
1.1525 -
1.1526 - merge_one_directory(merger, &md);
1.1527 -}
1.1528 -
1.1529 -static void
1.1530 -emit_files(struct list_head *files, struct array *source_pool,
1.1531 - uint32_t *map, struct array *pool)
1.1532 -{
1.1533 - uint32_t r;
1.1534 - struct list *p, *q;
1.1535 -
1.1536 - r = pool->size / sizeof *q;
1.1537 - p = list_first(files, source_pool);
1.1538 - while (p) {
1.1539 - q = array_add(pool, sizeof *q);
1.1540 - q->data = map[p->data];
1.1541 - q->flags = p->flags;
1.1542 - p = list_next(p);
1.1543 - }
1.1544 -
1.1545 - list_set_ptr(files, r);
1.1546 -}
1.1547 -
1.1548 -/* Rebuild property->packages maps. We can't just remap these, as a
1.1549 - * property may have lost or gained a number of packages. Allocate an
1.1550 - * array per property and loop through the packages and add them to
1.1551 - * the arrays for their properties. */
1.1552 -static void
1.1553 -rebuild_property_package_lists(struct razor_set *set)
1.1554 -{
1.1555 - struct array *pkgs, *a;
1.1556 - struct razor_package *pkg, *pkg_end;
1.1557 - struct razor_property *prop, *prop_end;
1.1558 - struct list *r;
1.1559 - uint32_t *q;
1.1560 - int count;
1.1561 -
1.1562 - count = set->properties.size / sizeof (struct razor_property);
1.1563 - pkgs = zalloc(count * sizeof *pkgs);
1.1564 - pkg_end = set->packages.data + set->packages.size;
1.1565 -
1.1566 - for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
1.1567 - r = list_first(&pkg->properties, &set->property_pool);
1.1568 - while (r) {
1.1569 - q = array_add(&pkgs[r->data], sizeof *q);
1.1570 - *q = pkg - (struct razor_package *) set->packages.data;
1.1571 - r = list_next(r);
1.1572 - }
1.1573 - }
1.1574 -
1.1575 - prop_end = set->properties.data + set->properties.size;
1.1576 - a = pkgs;
1.1577 - for (prop = set->properties.data; prop < prop_end; prop++, a++) {
1.1578 - list_set_array(&prop->packages, &set->package_pool, a, 0);
1.1579 - array_release(a);
1.1580 - }
1.1581 - free(pkgs);
1.1582 -}
1.1583 -
1.1584 -static void
1.1585 -rebuild_file_package_lists(struct razor_set *set)
1.1586 -{
1.1587 - struct array *pkgs, *a;
1.1588 - struct razor_package *pkg, *pkg_end;
1.1589 - struct razor_entry *entry, *entry_end;
1.1590 - struct list *r;
1.1591 - uint32_t *q;
1.1592 - int count;
1.1593 -
1.1594 - count = set->files.size / sizeof (struct razor_entry);
1.1595 - pkgs = zalloc(count * sizeof *pkgs);
1.1596 - pkg_end = set->packages.data + set->packages.size;
1.1597 -
1.1598 - for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
1.1599 - r = list_first(&pkg->files, &set->file_pool);
1.1600 - while (r) {
1.1601 - q = array_add(&pkgs[r->data], sizeof *q);
1.1602 - *q = pkg - (struct razor_package *) set->packages.data;
1.1603 - r = list_next(r);
1.1604 - }
1.1605 - }
1.1606 -
1.1607 - entry_end = set->files.data + set->files.size;
1.1608 - a = pkgs;
1.1609 - for (entry = set->files.data; entry < entry_end; entry++, a++) {
1.1610 - list_set_array(&entry->packages, &set->package_pool, a, 0);
1.1611 - array_release(a);
1.1612 - }
1.1613 - free(pkgs);
1.1614 -}
1.1615 -
1.1616 -static struct razor_set *
1.1617 -razor_merger_finish(struct razor_merger *merger)
1.1618 -{
1.1619 - struct razor_set *result;
1.1620 - struct razor_package *p, *pend;
1.1621 -
1.1622 - /* As we built the package list, we filled out a bitvector of
1.1623 - * the properties that are referenced by the packages in the
1.1624 - * new set. Now we do a parallel loop through the properties
1.1625 - * and emit those marked in the bit vector to the new set. In
1.1626 - * the process, we update the bit vector to actually map from
1.1627 - * indices in the old property list to indices in the new
1.1628 - * property list for both sets. */
1.1629 -
1.1630 - merge_properties(merger);
1.1631 - merge_files(merger);
1.1632 -
1.1633 - /* Now we loop through the packages again and emit the
1.1634 - * property lists, remapped to point to the new properties. */
1.1635 -
1.1636 - pend = merger->set->packages.data + merger->set->packages.size;
1.1637 - for (p = merger->set->packages.data; p < pend; p++) {
1.1638 - struct source *src;
1.1639 -
1.1640 - if (p->flags & UPSTREAM_SOURCE)
1.1641 - src = &merger->source2;
1.1642 - else
1.1643 - src = &merger->source1;
1.1644 -
1.1645 - emit_properties(&p->properties,
1.1646 - &src->set->property_pool,
1.1647 - src->property_map,
1.1648 - &merger->set->property_pool);
1.1649 - emit_files(&p->files,
1.1650 - &src->set->file_pool,
1.1651 - src->file_map,
1.1652 - &merger->set->file_pool);
1.1653 - p->flags &= ~UPSTREAM_SOURCE;
1.1654 - }
1.1655 -
1.1656 - rebuild_property_package_lists(merger->set);
1.1657 - rebuild_file_package_lists(merger->set);
1.1658 -
1.1659 - result = merger->set;
1.1660 - hashtable_release(&merger->table);
1.1661 - free(merger);
1.1662 -
1.1663 - return result;
1.1664 -}
1.1665 -
1.1666 -/* The diff order matters. We should sort the packages so that a
1.1667 - * REMOVE of a package comes before the INSTALL, and so that all
1.1668 - * requires for a package have been installed before the package.
1.1669 - **/
1.1670 -
1.1671 -void
1.1672 -razor_set_diff(struct razor_set *set, struct razor_set *upstream,
1.1673 - razor_package_callback_t callback, void *data)
1.1674 -{
1.1675 - struct razor_package_iterator *pi1, *pi2;
1.1676 - struct razor_package *p1, *p2;
1.1677 - const char *name1, *name2, *version1, *version2, *arch1, *arch2;
1.1678 - int res;
1.1679 -
1.1680 - pi1 = razor_package_iterator_create(set);
1.1681 - pi2 = razor_package_iterator_create(upstream);
1.1682 -
1.1683 - razor_package_iterator_next(pi1, &p1, &name1, &version1, &arch1);
1.1684 - razor_package_iterator_next(pi2, &p2, &name2, &version2, &arch2);
1.1685 -
1.1686 - while (p1 || p2) {
1.1687 - if (p1 && p2) {
1.1688 - res = strcmp(name1, name2);
1.1689 - if (res == 0)
1.1690 - res = versioncmp(version1, version2);
1.1691 - } else {
1.1692 - res = 0;
1.1693 - }
1.1694 -
1.1695 - if (p2 == NULL || res < 0)
1.1696 - callback(name1, version1, NULL, arch1, data);
1.1697 - else if (p1 == NULL || res > 0)
1.1698 - callback(name2, NULL, version2, arch2, data);
1.1699 -
1.1700 - if (p1 != NULL && res <= 0)
1.1701 - razor_package_iterator_next(pi1, &p1,
1.1702 - &name1, &version1, &arch1);
1.1703 - if (p2 != NULL && res >= 0)
1.1704 - razor_package_iterator_next(pi2, &p2,
1.1705 - &name2, &version2, &arch2);
1.1706 - }
1.1707 -
1.1708 - razor_package_iterator_destroy(pi1);
1.1709 - razor_package_iterator_destroy(pi2);
1.1710 -}
1.1711 -
1.1712 -static int
1.1713 -provider_satisfies_requirement(struct razor_property *provider,
1.1714 - const char *provider_strings,
1.1715 - enum razor_version_relation relation,
1.1716 - const char *required)
1.1717 -{
1.1718 - int cmp, len;
1.1719 - const char *provided = &provider_strings[provider->version];
1.1720 -
1.1721 - if (!*required)
1.1722 - return 1;
1.1723 - if (!*provided) {
1.1724 - if (relation >= RAZOR_VERSION_EQUAL)
1.1725 - return 1;
1.1726 - else
1.1727 - return 0;
1.1728 - }
1.1729 -
1.1730 - cmp = versioncmp(provided, required);
1.1731 -
1.1732 - switch (relation) {
1.1733 - case RAZOR_VERSION_LESS:
1.1734 - return cmp < 0;
1.1735 -
1.1736 - case RAZOR_VERSION_LESS_OR_EQUAL:
1.1737 - if (cmp <= 0)
1.1738 - return 1;
1.1739 - /* fall through: FIXME, make sure this is correct */
1.1740 -
1.1741 - case RAZOR_VERSION_EQUAL:
1.1742 - if (cmp == 0)
1.1743 - return 1;
1.1744 -
1.1745 - /* "foo == 1.1" is satisfied by "foo 1.1-2" */
1.1746 - len = strlen(required);
1.1747 - if (!strncmp(required, provided, len) && provided[len] == '-')
1.1748 - return 1;
1.1749 - return 0;
1.1750 -
1.1751 - case RAZOR_VERSION_GREATER_OR_EQUAL:
1.1752 - return cmp >= 0;
1.1753 -
1.1754 - case RAZOR_VERSION_GREATER:
1.1755 - return cmp > 0;
1.1756 - }
1.1757 -
1.1758 - /* shouldn't happen */
1.1759 - return 0;
1.1760 -}
1.1761 -
1.1762 -#define TRANS_PACKAGE_PRESENT 1
1.1763 -#define TRANS_PACKAGE_UPDATE 2
1.1764 -#define TRANS_PROPERTY_SATISFIED 0x80000000
1.1765 -
1.1766 -struct transaction_set {
1.1767 - struct razor_set *set;
1.1768 - uint32_t *packages;
1.1769 - uint32_t *properties;
1.1770 -};
1.1771 -
1.1772 -struct razor_transaction {
1.1773 - int package_count, errors;
1.1774 - struct transaction_set system, upstream;
1.1775 - int changes;
1.1776 -};
1.1777 -
1.1778 -static void
1.1779 -transaction_set_init(struct transaction_set *ts, struct razor_set *set)
1.1780 -{
1.1781 - int count;
1.1782 -
1.1783 - ts->set = set;
1.1784 - count = set->packages.size / sizeof (struct razor_package);
1.1785 - ts->packages = zalloc(count * sizeof *ts->packages);
1.1786 - count = set->properties.size / sizeof (struct razor_property);
1.1787 - ts->properties = zalloc(count * sizeof *ts->properties);
1.1788 -}
1.1789 -
1.1790 -static void
1.1791 -transaction_set_release(struct transaction_set *ts)
1.1792 -{
1.1793 - free(ts->packages);
1.1794 - free(ts->properties);
1.1795 -}
1.1796 -
1.1797 -static void
1.1798 -transaction_set_install_package(struct transaction_set *ts,
1.1799 - struct razor_package *package)
1.1800 -{
1.1801 - struct razor_package *pkgs;
1.1802 - struct list *prop;
1.1803 - int i;
1.1804 -
1.1805 - pkgs = ts->set->packages.data;
1.1806 - i = package - pkgs;
1.1807 - if (ts->packages[i] == TRANS_PACKAGE_PRESENT)
1.1808 - return;
1.1809 -
1.1810 - ts->packages[i] = TRANS_PACKAGE_PRESENT;
1.1811 -
1.1812 - prop = list_first(&package->properties, &ts->set->property_pool);
1.1813 - while (prop) {
1.1814 - ts->properties[prop->data]++;
1.1815 - prop = list_next(prop);
1.1816 - }
1.1817 -}
1.1818 -
1.1819 -static void
1.1820 -transaction_set_remove_package(struct transaction_set *ts,
1.1821 - struct razor_package *package)
1.1822 -{
1.1823 - struct razor_package *pkgs;
1.1824 - struct list *prop;
1.1825 - int i;
1.1826 -
1.1827 - pkgs = ts->set->packages.data;
1.1828 - i = package - pkgs;
1.1829 - if (ts->packages[i] == 0)
1.1830 - return;
1.1831 -
1.1832 - ts->packages[i] = 0;
1.1833 -
1.1834 - prop = list_first(&package->properties, &ts->set->property_pool);
1.1835 - while (prop) {
1.1836 - ts->properties[prop->data]--;
1.1837 - prop = list_next(prop);
1.1838 - }
1.1839 -}
1.1840 -
1.1841 -struct razor_transaction *
1.1842 -razor_transaction_create(struct razor_set *system, struct razor_set *upstream)
1.1843 -{
1.1844 - struct razor_transaction *trans;
1.1845 - struct razor_package *p, *spkgs, *pend;
1.1846 -
1.1847 - trans = zalloc(sizeof *trans);
1.1848 - transaction_set_init(&trans->system, system);
1.1849 - transaction_set_init(&trans->upstream, upstream);
1.1850 -
1.1851 - spkgs = trans->system.set->packages.data;
1.1852 - pend = trans->system.set->packages.data +
1.1853 - trans->system.set->packages.size;
1.1854 - for (p = spkgs; p < pend; p++)
1.1855 - transaction_set_install_package(&trans->system, p);
1.1856 -
1.1857 - return trans;
1.1858 -}
1.1859 -
1.1860 -void
1.1861 -razor_transaction_install_package(struct razor_transaction *trans,
1.1862 - struct razor_package *package)
1.1863 -{
1.1864 - transaction_set_install_package(&trans->upstream, package);
1.1865 - trans->changes++;
1.1866 -}
1.1867 -
1.1868 -void
1.1869 -razor_transaction_remove_package(struct razor_transaction *trans,
1.1870 - struct razor_package *package)
1.1871 -{
1.1872 - transaction_set_remove_package(&trans->system, package);
1.1873 - trans->changes++;
1.1874 -}
1.1875 -
1.1876 -void
1.1877 -razor_transaction_update_package(struct razor_transaction *trans,
1.1878 - struct razor_package *package)
1.1879 -{
1.1880 - struct razor_package *spkgs, *upkgs, *end;
1.1881 -
1.1882 - spkgs = trans->system.set->packages.data;
1.1883 - upkgs = trans->upstream.set->packages.data;
1.1884 - end = trans->system.set->packages.data +
1.1885 - trans->system.set->packages.size;
1.1886 - if (spkgs <= package && package < end)
1.1887 - trans->system.packages[package - spkgs] |= TRANS_PACKAGE_UPDATE;
1.1888 - else
1.1889 - trans->upstream.packages[package - upkgs] |= TRANS_PACKAGE_UPDATE;
1.1890 -}
1.1891 -
1.1892 -struct prop_iter {
1.1893 - struct razor_property *p, *start, *end;
1.1894 - const char *pool;
1.1895 - uint32_t *present;
1.1896 -};
1.1897 -
1.1898 -static void
1.1899 -prop_iter_init(struct prop_iter *pi, struct transaction_set *ts)
1.1900 -{
1.1901 - pi->p = ts->set->properties.data;
1.1902 - pi->start = ts->set->properties.data;
1.1903 - pi->end = ts->set->properties.data + ts->set->properties.size;
1.1904 - pi->pool = ts->set->string_pool.data;
1.1905 - pi->present = ts->properties;
1.1906 -}
1.1907 -
1.1908 -static int
1.1909 -prop_iter_next(struct prop_iter *pi,
1.1910 - enum razor_property_type type, struct razor_property **p)
1.1911 -{
1.1912 - while (pi->p < pi->end) {
1.1913 - if ((pi->present[pi->p - pi->start] & ~TRANS_PROPERTY_SATISFIED) &&
1.1914 - pi->p->type == type) {
1.1915 - *p = pi->p++;
1.1916 - return 1;
1.1917 - }
1.1918 - pi->p++;
1.1919 - }
1.1920 -
1.1921 - return 0;
1.1922 -}
1.1923 -
1.1924 -static struct razor_property *
1.1925 -prop_iter_seek_to(struct prop_iter *pi,
1.1926 - enum razor_property_type type, const char *match)
1.1927 -{
1.1928 - uint32_t name;
1.1929 -
1.1930 - while (pi->p < pi->end && strcmp(&pi->pool[pi->p->name], match) < 0)
1.1931 - pi->p++;
1.1932 -
1.1933 - if (pi->p == pi->end || strcmp(&pi->pool[pi->p->name], match) > 0)
1.1934 - return NULL;
1.1935 -
1.1936 - name = pi->p->name;
1.1937 - while (pi->p < pi->end &&
1.1938 - pi->p->name == name &&
1.1939 - pi->p->type != type)
1.1940 - pi->p++;
1.1941 -
1.1942 - if (pi->p == pi->end || pi->p->name != name)
1.1943 - return NULL;
1.1944 -
1.1945 - return pi->p;
1.1946 -}
1.1947 -
1.1948 -/* Remove packages from set that provide any of the matching (same
1.1949 - * name and type) providers from ppi onwards that match the
1.1950 - * requirement that rpi points to. */
1.1951 -static void
1.1952 -remove_matching_providers(struct razor_transaction *trans,
1.1953 - struct prop_iter *ppi,
1.1954 - enum razor_version_relation relation,
1.1955 - const char *version)
1.1956 -{
1.1957 - struct razor_property *p;
1.1958 - struct razor_package *pkg, *pkgs;
1.1959 - struct razor_package_iterator pkg_iter;
1.1960 - struct razor_set *set;
1.1961 - const char *n, *v, *a;
1.1962 -
1.1963 - if (ppi->present == trans->system.properties)
1.1964 - set = trans->system.set;
1.1965 - else
1.1966 - set = trans->upstream.set;
1.1967 -
1.1968 - pkgs = (struct razor_package *) set->packages.data;
1.1969 - for (p = ppi->p;
1.1970 - p < ppi->end &&
1.1971 - p->name == ppi->p->name &&
1.1972 - p->type == ppi->p->type;
1.1973 - p++) {
1.1974 - if (!ppi->present[p - ppi->start])
1.1975 - continue;
1.1976 - if (!provider_satisfies_requirement(p, ppi->pool,
1.1977 - relation, version))
1.1978 - continue;
1.1979 -
1.1980 - razor_package_iterator_init_for_property(&pkg_iter, set, p);
1.1981 - while (razor_package_iterator_next(&pkg_iter,
1.1982 - &pkg, &n, &v, &a)) {
1.1983 - fprintf(stderr, "removing %s-%s\n", n, v);
1.1984 - razor_transaction_remove_package(trans, pkg);
1.1985 - }
1.1986 - }
1.1987 -}
1.1988 -
1.1989 -static void
1.1990 -flag_matching_providers(struct razor_transaction *trans,
1.1991 - struct prop_iter *ppi,
1.1992 - struct razor_property *r,
1.1993 - struct prop_iter *rpi,
1.1994 - unsigned int flag)
1.1995 -{
1.1996 - struct razor_property *p;
1.1997 - struct razor_package *pkg, *pkgs;
1.1998 - struct razor_package_iterator pkg_iter;
1.1999 - struct razor_set *set;
1.2000 - const char *name, *version, *arch;
1.2001 - uint32_t *flags;
1.2002 -
1.2003 - if (ppi->present == trans->system.properties) {
1.2004 - set = trans->system.set;
1.2005 - flags = trans->system.packages;
1.2006 - } else {
1.2007 - set = trans->upstream.set;
1.2008 - flags = trans->upstream.packages;
1.2009 - }
1.2010 -
1.2011 - pkgs = (struct razor_package *) set->packages.data;
1.2012 - for (p = ppi->p;
1.2013 - p < ppi->end &&
1.2014 - p->name == ppi->p->name &&
1.2015 - p->type == ppi->p->type;
1.2016 - p++) {
1.2017 - if (!ppi->present[p - ppi->start])
1.2018 - continue;
1.2019 - if (!provider_satisfies_requirement(p, ppi->pool,
1.2020 - r->relation,
1.2021 - &rpi->pool[r->version]))
1.2022 - continue;
1.2023 -
1.2024 - razor_package_iterator_init_for_property(&pkg_iter, set, p);
1.2025 - while (razor_package_iterator_next(&pkg_iter, &pkg,
1.2026 - &name, &version, &arch)) {
1.2027 -
1.2028 - fprintf(stderr, "flagging %s-%s for providing %s matching %s %s\n",
1.2029 - name, version,
1.2030 - ppi->pool + p->name,
1.2031 - rpi->pool + r->name,
1.2032 - rpi->pool + r->version);
1.2033 - flags[pkg - pkgs] |= flag;
1.2034 - }
1.2035 - }
1.2036 -}
1.2037 -
1.2038 -static struct razor_package *
1.2039 -pick_matching_provider(struct razor_set *set,
1.2040 - struct prop_iter *ppi,
1.2041 - enum razor_version_relation relation,
1.2042 - const char *version)
1.2043 -{
1.2044 - struct razor_property *p;
1.2045 - struct razor_package *pkgs;
1.2046 - struct list *i;
1.2047 -
1.2048 - /* This is where we decide which pkgs to pull in to satisfy a
1.2049 - * requirement. There may be several different providers
1.2050 - * (different versions) and each version of a provider may
1.2051 - * come from a number of packages. We pick the first package
1.2052 - * from the first provider that matches. */
1.2053 -
1.2054 - pkgs = set->packages.data;
1.2055 - for (p = ppi->p;
1.2056 - p < ppi->end &&
1.2057 - p->name == ppi->p->name &&
1.2058 - p->type == ppi->p->type &&
1.2059 - ppi->present[p - ppi->start] == 0;
1.2060 - p++) {
1.2061 - if (!provider_satisfies_requirement(p, ppi->pool,
1.2062 - relation, version))
1.2063 - continue;
1.2064 -
1.2065 - i = list_first(&p->packages, &set->package_pool);
1.2066 -
1.2067 - return &pkgs[i->data];
1.2068 - }
1.2069 -
1.2070 - return NULL;
1.2071 -}
1.2072 -
1.2073 -static void
1.2074 -remove_obsoleted_packages(struct razor_transaction *trans)
1.2075 -{
1.2076 - struct razor_property *up;
1.2077 - struct razor_package *spkgs;
1.2078 - struct prop_iter spi, upi;
1.2079 -
1.2080 - spkgs = trans->system.set->packages.data;
1.2081 - prop_iter_init(&spi, &trans->system);
1.2082 - prop_iter_init(&upi, &trans->upstream);
1.2083 -
1.2084 - while (prop_iter_next(&upi, RAZOR_PROPERTY_OBSOLETES, &up)) {
1.2085 - if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
1.2086 - &upi.pool[up->name]))
1.2087 - continue;
1.2088 - remove_matching_providers(trans, &spi, up->relation,
1.2089 - &upi.pool[up->version]);
1.2090 - }
1.2091 -}
1.2092 -
1.2093 -static int
1.2094 -any_provider_satisfies_requirement(struct prop_iter *ppi,
1.2095 - enum razor_version_relation relation,
1.2096 - const char *version)
1.2097 -{
1.2098 - struct razor_property *p;
1.2099 -
1.2100 - for (p = ppi->p;
1.2101 - p < ppi->end &&
1.2102 - p->name == ppi->p->name &&
1.2103 - p->type == ppi->p->type;
1.2104 - p++) {
1.2105 - if (ppi->present[p - ppi->start] > 0 &&
1.2106 - provider_satisfies_requirement(p, ppi->pool,
1.2107 - relation, version))
1.2108 - return 1;
1.2109 - }
1.2110 -
1.2111 - return 0;
1.2112 -}
1.2113 -
1.2114 -static void
1.2115 -clear_requires_flags(struct transaction_set *ts)
1.2116 -{
1.2117 - struct razor_property *p;
1.2118 - const char *pool;
1.2119 - int i, count;
1.2120 -
1.2121 - count = ts->set->properties.size / sizeof *p;
1.2122 - p = ts->set->properties.data;
1.2123 - pool = ts->set->string_pool.data;
1.2124 - for (i = 0; i < count; i++) {
1.2125 - ts->properties[i] &= ~TRANS_PROPERTY_SATISFIED;
1.2126 - if (strncmp(&pool[p[i].name], "rpmlib(", 7) == 0)
1.2127 - ts->properties[i] |= TRANS_PROPERTY_SATISFIED;
1.2128 - }
1.2129 -}
1.2130 -
1.2131 -static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
1.2132 -
1.2133 -static void
1.2134 -mark_satisfied_requires(struct razor_transaction *trans,
1.2135 - struct transaction_set *rts,
1.2136 - struct transaction_set *pts)
1.2137 -{
1.2138 - struct prop_iter rpi, ppi;
1.2139 - struct razor_property *rp;
1.2140 -
1.2141 - prop_iter_init(&rpi, rts);
1.2142 - prop_iter_init(&ppi, pts);
1.2143 -
1.2144 - while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
1.2145 - if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES,
1.2146 - &rpi.pool[rp->name]))
1.2147 - continue;
1.2148 -
1.2149 - if (any_provider_satisfies_requirement(&ppi, rp->relation,
1.2150 - &rpi.pool[rp->version]))
1.2151 - rpi.present[rp - rpi.start] |= TRANS_PROPERTY_SATISFIED;
1.2152 - }
1.2153 -}
1.2154 -
1.2155 -static void
1.2156 -mark_all_satisfied_requires(struct razor_transaction *trans)
1.2157 -{
1.2158 - clear_requires_flags(&trans->system);
1.2159 - clear_requires_flags(&trans->upstream);
1.2160 - mark_satisfied_requires(trans, &trans->system, &trans->system);
1.2161 - mark_satisfied_requires(trans, &trans->system, &trans->upstream);
1.2162 - mark_satisfied_requires(trans, &trans->upstream, &trans->system);
1.2163 - mark_satisfied_requires(trans, &trans->upstream, &trans->upstream);
1.2164 -}
1.2165 -
1.2166 -static void
1.2167 -update_unsatisfied_packages(struct razor_transaction *trans)
1.2168 -{
1.2169 - struct razor_package *spkgs, *pkg;
1.2170 - struct razor_property *sp;
1.2171 - struct prop_iter spi;
1.2172 - struct razor_package_iterator pkg_iter;
1.2173 - const char *name, *version, *arch;
1.2174 -
1.2175 - spkgs = trans->system.set->packages.data;
1.2176 - prop_iter_init(&spi, &trans->system);
1.2177 -
1.2178 - while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
1.2179 - if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
1.2180 - continue;
1.2181 -
1.2182 - razor_package_iterator_init_for_property(&pkg_iter,
1.2183 - trans->system.set,
1.2184 - sp);
1.2185 - while (razor_package_iterator_next(&pkg_iter, &pkg,
1.2186 - &name, &version, &arch)) {
1.2187 - fprintf(stderr, "updating %s because %s %s %s "
1.2188 - "isn't satisfied\n",
1.2189 - name, spi.pool + sp->name,
1.2190 - relation_string[sp->relation],
1.2191 - spi.pool + sp->version);
1.2192 - trans->system.packages[pkg - spkgs] |=
1.2193 - TRANS_PACKAGE_UPDATE;
1.2194 - }
1.2195 - }
1.2196 -}
1.2197 -
1.2198 -void
1.2199 -razor_transaction_update_all(struct razor_transaction *trans)
1.2200 -{
1.2201 - struct razor_package *p;
1.2202 - int i, count;
1.2203 -
1.2204 - count = trans->system.set->packages.size / sizeof *p;
1.2205 - for (i = 0; i < count; i++)
1.2206 - trans->system.packages[i] |= TRANS_PACKAGE_UPDATE;
1.2207 -}
1.2208 -
1.2209 -static void
1.2210 -update_conflicted_packages(struct razor_transaction *trans)
1.2211 -{
1.2212 - struct razor_package *pkg, *spkgs;
1.2213 - struct razor_property *up, *sp;
1.2214 - struct prop_iter spi, upi;
1.2215 - struct razor_package_iterator pkg_iter;
1.2216 - const char *name, *version, *arch;
1.2217 -
1.2218 - spkgs = trans->system.set->packages.data;
1.2219 - prop_iter_init(&spi, &trans->system);
1.2220 - prop_iter_init(&upi, &trans->upstream);
1.2221 -
1.2222 - while (prop_iter_next(&spi, RAZOR_PROPERTY_CONFLICTS, &sp)) {
1.2223 - if (!prop_iter_seek_to(&upi, RAZOR_PROPERTY_PROVIDES,
1.2224 - &spi.pool[sp->name]))
1.2225 - continue;
1.2226 -
1.2227 - if (!any_provider_satisfies_requirement(&upi, sp->relation,
1.2228 - &spi.pool[sp->version]))
1.2229 - continue;
1.2230 -
1.2231 - razor_package_iterator_init_for_property(&pkg_iter,
1.2232 - trans->system.set,
1.2233 - sp);
1.2234 - while (razor_package_iterator_next(&pkg_iter, &pkg,
1.2235 - &name, &version, &arch)) {
1.2236 - fprintf(stderr, "updating %s %s because it conflicts with %s",
1.2237 - name, version, spi.pool + sp->name);
1.2238 - trans->system.packages[pkg - spkgs] |=
1.2239 - TRANS_PACKAGE_UPDATE;
1.2240 - }
1.2241 - }
1.2242 -
1.2243 - prop_iter_init(&spi, &trans->system);
1.2244 - prop_iter_init(&upi, &trans->upstream);
1.2245 -
1.2246 - while (prop_iter_next(&upi, RAZOR_PROPERTY_CONFLICTS, &up)) {
1.2247 - sp = prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
1.2248 - &upi.pool[upi.p->name]);
1.2249 -
1.2250 - if (sp)
1.2251 - flag_matching_providers(trans, &spi, up, &upi,
1.2252 - TRANS_PACKAGE_UPDATE);
1.2253 - }
1.2254 -}
1.2255 -
1.2256 -static void
1.2257 -pull_in_requirements(struct razor_transaction *trans,
1.2258 - struct prop_iter *rpi, struct prop_iter *ppi)
1.2259 -{
1.2260 - struct razor_property *rp, *pp;
1.2261 - struct razor_package *pkg, *upkgs;
1.2262 -
1.2263 - upkgs = trans->upstream.set->packages.data;
1.2264 - while (prop_iter_next(rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
1.2265 - if (rpi->present[rp - rpi->start] & TRANS_PROPERTY_SATISFIED)
1.2266 - continue;
1.2267 -
1.2268 - pp = prop_iter_seek_to(ppi, RAZOR_PROPERTY_PROVIDES,
1.2269 - &rpi->pool[rp->name]);
1.2270 - if (pp == NULL)
1.2271 - continue;
1.2272 - pkg = pick_matching_provider(trans->upstream.set,
1.2273 - ppi, rp->relation,
1.2274 - &rpi->pool[rp->version]);
1.2275 - if (pkg == NULL)
1.2276 - continue;
1.2277 -
1.2278 - rpi->present[rp - rpi->start] |= TRANS_PROPERTY_SATISFIED;
1.2279 -
1.2280 - fprintf(stderr, "pulling in %s which provides %s %s %s "
1.2281 - "to satisfy %s %s %s\n",
1.2282 - ppi->pool + pkg->name,
1.2283 - ppi->pool + pp->name,
1.2284 - relation_string[pp->relation],
1.2285 - ppi->pool + pp->version,
1.2286 - &rpi->pool[rp->name],
1.2287 - relation_string[rp->relation],
1.2288 - &rpi->pool[rp->version]);
1.2289 -
1.2290 - trans->upstream.packages[pkg - upkgs] |= TRANS_PACKAGE_UPDATE;
1.2291 - }
1.2292 -}
1.2293 -
1.2294 -static void
1.2295 -pull_in_all_requirements(struct razor_transaction *trans)
1.2296 -{
1.2297 - struct prop_iter rpi, ppi;
1.2298 -
1.2299 - prop_iter_init(&rpi, &trans->system);
1.2300 - prop_iter_init(&ppi, &trans->upstream);
1.2301 - pull_in_requirements(trans, &rpi, &ppi);
1.2302 -
1.2303 - prop_iter_init(&rpi, &trans->upstream);
1.2304 - prop_iter_init(&ppi, &trans->upstream);
1.2305 - pull_in_requirements(trans, &rpi, &ppi);
1.2306 -}
1.2307 -
1.2308 -static void
1.2309 -flush_scheduled_system_updates(struct razor_transaction *trans)
1.2310 -{
1.2311 - struct razor_package_iterator *pi;
1.2312 - struct razor_package *p, *pkg, *spkgs;
1.2313 - struct prop_iter ppi;
1.2314 - const char *name, *version, *arch;
1.2315 -
1.2316 - spkgs = trans->system.set->packages.data;
1.2317 - pi = razor_package_iterator_create(trans->system.set);
1.2318 - prop_iter_init(&ppi, &trans->upstream);
1.2319 -
1.2320 - while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
1.2321 - if (!(trans->system.packages[p - spkgs] & TRANS_PACKAGE_UPDATE))
1.2322 - continue;
1.2323 -
1.2324 - if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES, name))
1.2325 - continue;
1.2326 -
1.2327 - pkg = pick_matching_provider(trans->upstream.set, &ppi,
1.2328 - RAZOR_VERSION_GREATER, version);
1.2329 - if (pkg == NULL)
1.2330 - continue;
1.2331 -
1.2332 - fprintf(stderr, "updating %s-%s to %s-%s\n",
1.2333 - name, version,
1.2334 - &ppi.pool[pkg->name], &ppi.pool[pkg->version]);
1.2335 -
1.2336 - razor_transaction_remove_package(trans, p);
1.2337 - razor_transaction_install_package(trans, pkg);
1.2338 - }
1.2339 -
1.2340 - razor_package_iterator_destroy(pi);
1.2341 -}
1.2342 -
1.2343 -static void
1.2344 -flush_scheduled_upstream_updates(struct razor_transaction *trans)
1.2345 -{
1.2346 - struct razor_package_iterator *pi;
1.2347 - struct razor_package *p, *upkgs;
1.2348 - struct prop_iter spi;
1.2349 - const char *name, *version, *arch;
1.2350 -
1.2351 - upkgs = trans->upstream.set->packages.data;
1.2352 - pi = razor_package_iterator_create(trans->upstream.set);
1.2353 - prop_iter_init(&spi, &trans->system);
1.2354 -
1.2355 - while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
1.2356 - if (!(trans->upstream.packages[p - upkgs] & TRANS_PACKAGE_UPDATE))
1.2357 - continue;
1.2358 -
1.2359 - if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES, name))
1.2360 - continue;
1.2361 - remove_matching_providers(trans, &spi,
1.2362 - RAZOR_VERSION_LESS, version);
1.2363 - razor_transaction_install_package(trans, p);
1.2364 - fprintf(stderr, "installing %s-%s\n", name, version);
1.2365 - }
1.2366 -}
1.2367 -
1.2368 -int
1.2369 -razor_transaction_resolve(struct razor_transaction *trans)
1.2370 -{
1.2371 - int last = 0;
1.2372 -
1.2373 - flush_scheduled_system_updates(trans);
1.2374 -
1.2375 - while (last < trans->changes) {
1.2376 - last = trans->changes;
1.2377 - remove_obsoleted_packages(trans);
1.2378 - mark_all_satisfied_requires(trans);
1.2379 - update_unsatisfied_packages(trans);
1.2380 - update_conflicted_packages(trans);
1.2381 - pull_in_all_requirements(trans);
1.2382 - flush_scheduled_system_updates(trans);
1.2383 - flush_scheduled_upstream_updates(trans);
1.2384 - }
1.2385 -
1.2386 - return trans->changes;
1.2387 -}
1.2388 -
1.2389 -static void
1.2390 -describe_unsatisfied(struct razor_set *set, struct razor_property *rp)
1.2391 -{
1.2392 - struct razor_package_iterator pi;
1.2393 - struct razor_package *pkg;
1.2394 - const char *name, *version, *arch, *pool;
1.2395 -
1.2396 - pool = set->string_pool.data;
1.2397 - if (pool[rp->version] == '\0') {
1.2398 - razor_package_iterator_init_for_property(&pi, set, rp);
1.2399 - while (razor_package_iterator_next(&pi, &pkg,
1.2400 - &name, &version, &arch))
1.2401 - fprintf(stderr, "%s is needed by %s-%s.%s\n",
1.2402 - &pool[rp->name],
1.2403 - name, version, arch);
1.2404 - } else {
1.2405 - razor_package_iterator_init_for_property(&pi, set, rp);
1.2406 - while (razor_package_iterator_next(&pi, &pkg,
1.2407 - &name, &version, &arch))
1.2408 - fprintf(stderr, "%s %s %s is needed by %s-%s.%s\n",
1.2409 - &pool[rp->name],
1.2410 - relation_string[rp->relation],
1.2411 - &pool[rp->version],
1.2412 - name, version, arch);
1.2413 - }
1.2414 -}
1.2415 -
1.2416 -int
1.2417 -razor_transaction_describe(struct razor_transaction *trans)
1.2418 -{
1.2419 - struct prop_iter rpi;
1.2420 - struct razor_property *rp;
1.2421 - int unsatisfied;
1.2422 -
1.2423 - flush_scheduled_system_updates(trans);
1.2424 - flush_scheduled_upstream_updates(trans);
1.2425 - mark_all_satisfied_requires(trans);
1.2426 -
1.2427 - unsatisfied = 0;
1.2428 - prop_iter_init(&rpi, &trans->system);
1.2429 - while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
1.2430 - if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
1.2431 - describe_unsatisfied(trans->system.set, rp);
1.2432 - unsatisfied++;
1.2433 - }
1.2434 - }
1.2435 -
1.2436 - prop_iter_init(&rpi, &trans->upstream);
1.2437 - while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
1.2438 - if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
1.2439 - describe_unsatisfied(trans->upstream.set, rp);
1.2440 - unsatisfied++;
1.2441 - }
1.2442 - }
1.2443 -
1.2444 - return unsatisfied;
1.2445 -}
1.2446 -
1.2447 -int
1.2448 -razor_transaction_unsatisfied_property(struct razor_transaction *trans,
1.2449 - const char *name,
1.2450 - enum razor_version_relation rel,
1.2451 - const char *version,
1.2452 - enum razor_property_type type)
1.2453 -{
1.2454 - struct prop_iter pi;
1.2455 - struct razor_property *p;
1.2456 -
1.2457 - prop_iter_init(&pi, &trans->system);
1.2458 - while (prop_iter_next(&pi, type, &p)) {
1.2459 - if (!(trans->system.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
1.2460 - p->relation == rel &&
1.2461 - strcmp(&pi.pool[p->name], name) == 0 &&
1.2462 - strcmp(&pi.pool[p->version], version) == 0)
1.2463 -
1.2464 - return 1;
1.2465 - }
1.2466 -
1.2467 - prop_iter_init(&pi, &trans->upstream);
1.2468 - while (prop_iter_next(&pi, type, &p)) {
1.2469 - if (!(trans->upstream.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
1.2470 - p->relation == rel &&
1.2471 - strcmp(&pi.pool[p->name], name) == 0 &&
1.2472 - strcmp(&pi.pool[p->version], version) == 0)
1.2473 -
1.2474 - return 1;
1.2475 - }
1.2476 -
1.2477 - return 0;
1.2478 -}
1.2479 -
1.2480 -struct razor_set *
1.2481 -razor_transaction_finish(struct razor_transaction *trans)
1.2482 -{
1.2483 - struct razor_merger *merger;
1.2484 - struct razor_package *u, *uend, *upkgs, *s, *send, *spkgs;
1.2485 - char *upool, *spool;
1.2486 - int cmp;
1.2487 -
1.2488 - s = trans->system.set->packages.data;
1.2489 - spkgs = trans->system.set->packages.data;
1.2490 - send = trans->system.set->packages.data +
1.2491 - trans->system.set->packages.size;
1.2492 - spool = trans->system.set->string_pool.data;
1.2493 -
1.2494 - u = trans->upstream.set->packages.data;
1.2495 - upkgs = trans->upstream.set->packages.data;
1.2496 - uend = trans->upstream.set->packages.data +
1.2497 - trans->upstream.set->packages.size;
1.2498 - upool = trans->upstream.set->string_pool.data;
1.2499 -
1.2500 - merger = razor_merger_create(trans->system.set, trans->upstream.set);
1.2501 - while (s < send || u < uend) {
1.2502 - if (s < send && u < uend)
1.2503 - cmp = strcmp(&spool[s->name], &upool[u->name]);
1.2504 - else if (s < send)
1.2505 - cmp = -1;
1.2506 - else
1.2507 - cmp = 1;
1.2508 -
1.2509 - if (cmp < 0) {
1.2510 - if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
1.2511 - razor_merger_add_package(merger, s);
1.2512 - s++;
1.2513 - } else if (cmp == 0) {
1.2514 - if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
1.2515 - razor_merger_add_package(merger, s);
1.2516 - if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
1.2517 - razor_merger_add_package(merger, u);
1.2518 -
1.2519 - s++;
1.2520 - u++;
1.2521 - } else {
1.2522 - if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
1.2523 - razor_merger_add_package(merger, u);
1.2524 - u++;
1.2525 - }
1.2526 - }
1.2527 -
1.2528 - razor_transaction_destroy(trans);
1.2529 -
1.2530 - return razor_merger_finish(merger);
1.2531 -}
1.2532 -
1.2533 -void
1.2534 -razor_transaction_destroy(struct razor_transaction *trans)
1.2535 -{
1.2536 - transaction_set_release(&trans->system);
1.2537 - transaction_set_release(&trans->upstream);
1.2538 - free(trans);
1.2539 -}
1.2540 -
1.2541 -struct razor_package_query {
1.2542 - struct razor_set *set;
1.2543 - char *vector;
1.2544 - int count;
1.2545 -};
1.2546 -
1.2547 -struct razor_package_query *
1.2548 -razor_package_query_create(struct razor_set *set)
1.2549 -{
1.2550 - struct razor_package_query *pq;
1.2551 - int count;
1.2552 -
1.2553 - pq = zalloc(sizeof *pq);
1.2554 - pq->set = set;
1.2555 - count = set->packages.size / sizeof(struct razor_package);
1.2556 - pq->vector = zalloc(count * sizeof(char));
1.2557 -
1.2558 - return pq;
1.2559 -}
1.2560 -
1.2561 -void
1.2562 -razor_package_query_add_package(struct razor_package_query *pq,
1.2563 - struct razor_package *p)
1.2564 -{
1.2565 - struct razor_package *packages;
1.2566 -
1.2567 - packages = pq->set->packages.data;
1.2568 - pq->count += pq->vector[p - packages] ^ 1;
1.2569 - pq->vector[p - packages] = 1;
1.2570 -}
1.2571 -
1.2572 -void
1.2573 -razor_package_query_add_iterator(struct razor_package_query *pq,
1.2574 - struct razor_package_iterator *pi)
1.2575 -{
1.2576 - struct razor_package *packages, *p;
1.2577 - const char *name, *version, *arch;
1.2578 -
1.2579 - packages = pq->set->packages.data;
1.2580 - while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
1.2581 - pq->count += pq->vector[p - packages] ^ 1;
1.2582 - pq->vector[p - packages] = 1;
1.2583 - }
1.2584 -}
1.2585 -
1.2586 -struct razor_package_iterator *
1.2587 -razor_package_query_finish(struct razor_package_query *pq)
1.2588 -{
1.2589 - struct razor_package_iterator *pi;
1.2590 - struct razor_set *set;
1.2591 - struct list *index;
1.2592 - int i, j, count;
1.2593 -
1.2594 - set = pq->set;
1.2595 - count = set->packages.size / sizeof(struct razor_package);
1.2596 - index = zalloc(pq->count * sizeof *index);
1.2597 -
1.2598 - for (i = 0, j = 0; i < count; i++) {
1.2599 - if (!pq->vector[i])
1.2600 - continue;
1.2601 -
1.2602 - index[j].data = i;
1.2603 - if (j == pq->count - 1)
1.2604 - index[j].flags = 0x80;
1.2605 - j++;
1.2606 - }
1.2607 -
1.2608 - free(pq);
1.2609 -
1.2610 - pi = razor_package_iterator_create_with_index(set, index);
1.2611 - pi->free_index = 1;
1.2612 -
1.2613 - return pi;
1.2614 -}