1.1 --- a/razor.c Sun Jun 15 18:16:20 2008 -0400
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,3244 +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_DETAILS_MAGIC 0x7a7a7a7b
1.57 -#define RAZOR_FILES_MAGIC 0x7a7a7a7c
1.58 -#define RAZOR_VERSION 1
1.59 -
1.60 -#define RAZOR_STRING_POOL 0
1.61 -#define RAZOR_PACKAGES 1
1.62 -#define RAZOR_PROPERTIES 2
1.63 -#define RAZOR_PACKAGE_POOL 3
1.64 -#define RAZOR_PROPERTY_POOL 4
1.65 -
1.66 -#define RAZOR_DETAILS_STRING_POOL 0
1.67 -
1.68 -#define RAZOR_FILES 0
1.69 -#define RAZOR_FILE_POOL 1
1.70 -#define RAZOR_FILE_STRING_POOL 2
1.71 -
1.72 -struct razor_package {
1.73 - uint name : 24;
1.74 - uint flags : 8;
1.75 - uint32_t version;
1.76 - uint32_t arch;
1.77 - uint32_t summary;
1.78 - uint32_t description;
1.79 - uint32_t url;
1.80 - uint32_t license;
1.81 - struct list_head properties;
1.82 - struct list_head files;
1.83 -};
1.84 -
1.85 -struct razor_property {
1.86 - uint name : 24;
1.87 - uint flags : 6;
1.88 - enum razor_property_type type : 2;
1.89 - enum razor_version_relation relation : 32;
1.90 - uint32_t version;
1.91 - struct list_head packages;
1.92 -};
1.93 -
1.94 -struct razor_entry {
1.95 - uint name : 24;
1.96 - uint flags : 8;
1.97 - uint32_t start;
1.98 - struct list_head packages;
1.99 -};
1.100 -
1.101 -#define RAZOR_ENTRY_LAST 0x80
1.102 -
1.103 -struct razor_set {
1.104 - struct array string_pool;
1.105 - struct array packages;
1.106 - struct array properties;
1.107 - struct array files;
1.108 - struct array package_pool;
1.109 - struct array property_pool;
1.110 - struct array file_pool;
1.111 - struct array file_string_pool;
1.112 - struct array details_string_pool;
1.113 - struct razor_set_header *header;
1.114 - struct razor_set_header *details_header;
1.115 - struct razor_set_header *files_header;
1.116 -};
1.117 -
1.118 -struct import_entry {
1.119 - uint32_t package;
1.120 - char *name;
1.121 -};
1.122 -
1.123 -struct import_directory {
1.124 - uint32_t name, count;
1.125 - struct array files;
1.126 - struct array packages;
1.127 - struct import_directory *last;
1.128 -};
1.129 -
1.130 -struct razor_importer {
1.131 - struct razor_set *set;
1.132 - struct hashtable table;
1.133 - struct hashtable file_table;
1.134 - struct hashtable details_table;
1.135 - struct razor_package *package;
1.136 - struct array properties;
1.137 - struct array files;
1.138 - struct array file_requires;
1.139 -};
1.140 -
1.141 -static void *
1.142 -zalloc(size_t size)
1.143 -{
1.144 - void *p;
1.145 -
1.146 - p = malloc(size);
1.147 - memset(p, 0, size);
1.148 -
1.149 - return p;
1.150 -}
1.151 -
1.152 -struct razor_set_section razor_sections[] = {
1.153 - { RAZOR_STRING_POOL, offsetof(struct razor_set, string_pool) },
1.154 - { RAZOR_PACKAGES, offsetof(struct razor_set, packages) },
1.155 - { RAZOR_PROPERTIES, offsetof(struct razor_set, properties) },
1.156 - { RAZOR_PACKAGE_POOL, offsetof(struct razor_set, package_pool) },
1.157 - { RAZOR_PROPERTY_POOL, offsetof(struct razor_set, property_pool) },
1.158 -};
1.159 -
1.160 -struct razor_set_section razor_files_sections[] = {
1.161 - { RAZOR_FILES, offsetof(struct razor_set, files) },
1.162 - { RAZOR_FILE_POOL, offsetof(struct razor_set, file_pool) },
1.163 - { RAZOR_FILE_STRING_POOL, offsetof(struct razor_set, file_string_pool) },
1.164 -};
1.165 -
1.166 -struct razor_set_section razor_details_sections[] = {
1.167 - { RAZOR_DETAILS_STRING_POOL, offsetof(struct razor_set, details_string_pool) },
1.168 -};
1.169 -
1.170 -struct razor_set *
1.171 -razor_set_create(void)
1.172 -{
1.173 - struct razor_set *set;
1.174 - struct razor_entry *e;
1.175 - char *empty;
1.176 -
1.177 - set = zalloc(sizeof *set);
1.178 -
1.179 - e = array_add(&set->files, sizeof *e);
1.180 - empty = array_add(&set->string_pool, 1);
1.181 - *empty = '\0';
1.182 - empty = array_add(&set->file_string_pool, 1);
1.183 - *empty = '\0';
1.184 - empty = array_add(&set->details_string_pool, 1);
1.185 - *empty = '\0';
1.186 - e->name = 0;
1.187 - e->flags = RAZOR_ENTRY_LAST;
1.188 - e->start = 0;
1.189 - list_set_empty(&e->packages);
1.190 -
1.191 - return set;
1.192 -}
1.193 -
1.194 -struct razor_set *
1.195 -razor_set_open(const char *filename)
1.196 -{
1.197 - struct razor_set *set;
1.198 - struct razor_set_section *s;
1.199 - struct stat stat;
1.200 - struct array *array;
1.201 - int fd;
1.202 -
1.203 - set = zalloc(sizeof *set);
1.204 - fd = open(filename, O_RDONLY);
1.205 - if (fstat(fd, &stat) < 0)
1.206 - return NULL;
1.207 - set->header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1.208 - if (set->header == MAP_FAILED) {
1.209 - free(set);
1.210 - return NULL;
1.211 - }
1.212 -
1.213 - for (s = set->header->sections; ~s->type; s++) {
1.214 - if (s->type >= ARRAY_SIZE(razor_sections))
1.215 - continue;
1.216 - if (s->type != razor_sections[s->type].type)
1.217 - continue;
1.218 - array = (void *) set + razor_sections[s->type].offset;
1.219 - array->data = (void *) set->header + s->offset;
1.220 - array->size = s->size;
1.221 - array->alloc = s->size;
1.222 - }
1.223 - close(fd);
1.224 -
1.225 - return set;
1.226 -}
1.227 -
1.228 -void
1.229 -razor_set_destroy(struct razor_set *set)
1.230 -{
1.231 - unsigned int size;
1.232 - struct array *a;
1.233 - int i;
1.234 -
1.235 - if (set->header) {
1.236 - for (i = 0; set->header->sections[i].type; i++)
1.237 - ;
1.238 - size = set->header->sections[i].type;
1.239 - munmap(set->header, size);
1.240 - } else {
1.241 - for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
1.242 - a = (void *) set + razor_sections[i].offset;
1.243 - free(a->data);
1.244 - }
1.245 - }
1.246 -
1.247 - if (set->details_header) {
1.248 - for (i = 0; set->details_header->sections[i].type; i++)
1.249 - ;
1.250 - size = set->details_header->sections[i].type;
1.251 - munmap(set->details_header, size);
1.252 - } else {
1.253 - for (i = 0; i < ARRAY_SIZE(razor_details_sections); i++) {
1.254 - a = (void *) set + razor_details_sections[i].offset;
1.255 - free(a->data);
1.256 - }
1.257 - }
1.258 -
1.259 - if (set->files_header) {
1.260 - for (i = 0; set->files_header->sections[i].type; i++)
1.261 - ;
1.262 - size = set->files_header->sections[i].type;
1.263 - munmap(set->files_header, size);
1.264 - } else {
1.265 - for (i = 0; i < ARRAY_SIZE(razor_files_sections); i++) {
1.266 - a = (void *) set + razor_files_sections[i].offset;
1.267 - free(a->data);
1.268 - }
1.269 - }
1.270 -
1.271 - free(set);
1.272 -}
1.273 -
1.274 -void
1.275 -razor_set_open_details(struct razor_set *set, const char *filename)
1.276 -{
1.277 - struct razor_set_section *s;
1.278 - struct stat stat;
1.279 - struct array *array;
1.280 - int fd;
1.281 -
1.282 - fd = open(filename, O_RDONLY);
1.283 - if (fstat(fd, &stat) < 0)
1.284 - return;
1.285 - set->details_header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1.286 - if (set->details_header == MAP_FAILED)
1.287 - return;
1.288 -
1.289 - for (s = set->details_header->sections; ~s->type; s++) {
1.290 - if (s->type >= ARRAY_SIZE(razor_details_sections))
1.291 - continue;
1.292 - if (s->type != razor_details_sections[s->type].type)
1.293 - continue;
1.294 - array = (void *) set + razor_details_sections[s->type].offset;
1.295 - array->data = (void *) set->details_header + s->offset;
1.296 - array->size = s->size;
1.297 - array->alloc = s->size;
1.298 - }
1.299 - close(fd);
1.300 -}
1.301 -
1.302 -void
1.303 -razor_set_open_files(struct razor_set *set, const char *filename)
1.304 -{
1.305 - struct razor_set_section *s;
1.306 - struct stat stat;
1.307 - struct array *array;
1.308 - int fd;
1.309 -
1.310 - fd = open(filename, O_RDONLY);
1.311 - if (fstat(fd, &stat) < 0)
1.312 - return;
1.313 - set->files_header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1.314 - if (set->files_header == MAP_FAILED)
1.315 - return;
1.316 -
1.317 - for (s = set->files_header->sections; ~s->type; s++) {
1.318 - if (s->type >= ARRAY_SIZE(razor_files_sections))
1.319 - continue;
1.320 - if (s->type != razor_files_sections[s->type].type)
1.321 - continue;
1.322 - array = (void *) set + razor_files_sections[s->type].offset;
1.323 - array->data = (void *) set->files_header + s->offset;
1.324 - array->size = s->size;
1.325 - array->alloc = s->size;
1.326 - }
1.327 - close(fd);
1.328 -}
1.329 -
1.330 -static int
1.331 -razor_set_write_sections_to_fd(struct razor_set *set, int fd, int magic,
1.332 - struct razor_set_section *sections,
1.333 - size_t array_size)
1.334 -{
1.335 - char data[4096];
1.336 - struct razor_set_header *header = (struct razor_set_header *) data;
1.337 - struct array *a;
1.338 - uint32_t offset;
1.339 - int i;
1.340 -
1.341 - memset(data, 0, sizeof data);
1.342 - header->magic = magic;
1.343 - header->version = RAZOR_VERSION;
1.344 - offset = sizeof data;
1.345 -
1.346 - for (i = 0; i < array_size; i++) {
1.347 - if (sections[i].type != i)
1.348 - continue;
1.349 - a = (void *) set + sections[i].offset;
1.350 - header->sections[i].type = i;
1.351 - header->sections[i].offset = offset;
1.352 - header->sections[i].size = a->size;
1.353 - offset += ALIGN(a->size, 4096);
1.354 - }
1.355 -
1.356 - header->sections[i].type = ~0;
1.357 - header->sections[i].offset = 0;
1.358 - header->sections[i].size = 0;
1.359 -
1.360 - razor_write(fd, data, sizeof data);
1.361 - memset(data, 0, sizeof data);
1.362 - for (i = 0; i < array_size; i++) {
1.363 - if (sections[i].type != i)
1.364 - continue;
1.365 - a = (void *) set + sections[i].offset;
1.366 - razor_write(fd, a->data, a->size);
1.367 - razor_write(fd, data, ALIGN(a->size, 4096) - a->size);
1.368 - }
1.369 -
1.370 - return 0;
1.371 -}
1.372 -
1.373 -int
1.374 -razor_set_write_to_fd(struct razor_set *set, int fd,
1.375 - enum razor_repo_file_type type)
1.376 -{
1.377 - switch (type) {
1.378 - case RAZOR_REPO_FILE_MAIN:
1.379 - return razor_set_write_sections_to_fd(set, fd, RAZOR_MAGIC,
1.380 - razor_sections,
1.381 - ARRAY_SIZE(razor_sections));
1.382 -
1.383 - case RAZOR_REPO_FILE_DETAILS:
1.384 - return razor_set_write_sections_to_fd(set, fd, RAZOR_DETAILS_MAGIC,
1.385 - razor_details_sections,
1.386 - ARRAY_SIZE(razor_details_sections));
1.387 - case RAZOR_REPO_FILE_FILES:
1.388 - return razor_set_write_sections_to_fd(set, fd, RAZOR_FILES_MAGIC,
1.389 - razor_files_sections,
1.390 - ARRAY_SIZE(razor_files_sections));
1.391 - default:
1.392 - return -1;
1.393 - }
1.394 -}
1.395 -
1.396 -int
1.397 -razor_set_write(struct razor_set *set, const char *filename,
1.398 - enum razor_repo_file_type type)
1.399 -{
1.400 - int fd, status;
1.401 -
1.402 - fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
1.403 - if (fd < 0)
1.404 - return -1;
1.405 -
1.406 - status = razor_set_write_to_fd(set, fd, type);
1.407 - if (status) {
1.408 - close(fd);
1.409 - return status;
1.410 - }
1.411 -
1.412 - return close(fd);
1.413 -}
1.414 -
1.415 -void
1.416 -razor_build_evr(char *evr_buf, int size, const char *epoch,
1.417 - const char *version, const char *release)
1.418 -{
1.419 - int len;
1.420 -
1.421 - if (!version || !*version) {
1.422 - *evr_buf = '\0';
1.423 - return;
1.424 - }
1.425 -
1.426 - if (epoch && *epoch && strcmp(epoch, "0") != 0) {
1.427 - len = snprintf(evr_buf, size, "%s:", epoch);
1.428 - evr_buf += len;
1.429 - size -= len;
1.430 - }
1.431 - len = snprintf(evr_buf, size, "%s", version);
1.432 - evr_buf += len;
1.433 - size -= len;
1.434 - if (release && *release)
1.435 - snprintf(evr_buf, size, "-%s", release);
1.436 -}
1.437 -
1.438 -void
1.439 -razor_importer_begin_package(struct razor_importer *importer,
1.440 - const char *name,
1.441 - const char *version,
1.442 - const char *arch)
1.443 -{
1.444 - struct razor_package *p;
1.445 -
1.446 - p = array_add(&importer->set->packages, sizeof *p);
1.447 - p->name = hashtable_tokenize(&importer->table, name);
1.448 - p->flags = 0;
1.449 - p->version = hashtable_tokenize(&importer->table, version);
1.450 - p->arch = hashtable_tokenize(&importer->table, arch);
1.451 -
1.452 - importer->package = p;
1.453 - array_init(&importer->properties);
1.454 -}
1.455 -
1.456 -void
1.457 -razor_importer_finish_package(struct razor_importer *importer)
1.458 -{
1.459 - list_set_array(&importer->package->properties,
1.460 - &importer->set->property_pool,
1.461 - &importer->properties,
1.462 - 1);
1.463 -
1.464 - array_release(&importer->properties);
1.465 -}
1.466 -
1.467 -void
1.468 -razor_importer_add_details(struct razor_importer *importer,
1.469 - const char *summary,
1.470 - const char *description,
1.471 - const char *url,
1.472 - const char *license)
1.473 -{
1.474 - importer->package->summary = hashtable_tokenize(&importer->details_table, summary);
1.475 - importer->package->description = hashtable_tokenize(&importer->details_table, description);
1.476 - importer->package->url = hashtable_tokenize(&importer->details_table, url);
1.477 - importer->package->license = hashtable_tokenize(&importer->details_table, license);
1.478 -}
1.479 -
1.480 -void
1.481 -razor_importer_add_property(struct razor_importer *importer,
1.482 - const char *name,
1.483 - enum razor_version_relation relation,
1.484 - const char *version,
1.485 - enum razor_property_type type)
1.486 -{
1.487 - struct razor_property *p;
1.488 - uint32_t *r;
1.489 -
1.490 - p = array_add(&importer->set->properties, sizeof *p);
1.491 - p->name = hashtable_tokenize(&importer->table, name);
1.492 - p->flags = 0;
1.493 - p->type = type;
1.494 - p->relation = relation;
1.495 - p->version = hashtable_tokenize(&importer->table, version);
1.496 - list_set_ptr(&p->packages, importer->package -
1.497 - (struct razor_package *) importer->set->packages.data);
1.498 -
1.499 - r = array_add(&importer->properties, sizeof *r);
1.500 - *r = p - (struct razor_property *) importer->set->properties.data;
1.501 -
1.502 - if (type == RAZOR_PROPERTY_REQUIRES && *name == '/') {
1.503 - r = array_add(&importer->file_requires, sizeof *r);
1.504 - *r = p->name;
1.505 - }
1.506 -}
1.507 -
1.508 -void
1.509 -razor_importer_add_file(struct razor_importer *importer, const char *name)
1.510 -{
1.511 - struct import_entry *e;
1.512 -
1.513 - e = array_add(&importer->files, sizeof *e);
1.514 -
1.515 - e->package = importer->package -
1.516 - (struct razor_package *) importer->set->packages.data;
1.517 - e->name = strdup(name);
1.518 -}
1.519 -
1.520 -struct razor_importer *
1.521 -razor_importer_new(void)
1.522 -{
1.523 - struct razor_importer *importer;
1.524 -
1.525 - importer = zalloc(sizeof *importer);
1.526 - importer->set = razor_set_create();
1.527 - hashtable_init(&importer->table, &importer->set->string_pool);
1.528 - hashtable_init(&importer->file_table, &importer->set->file_string_pool);
1.529 - hashtable_init(&importer->details_table, &importer->set->details_string_pool);
1.530 -
1.531 - return importer;
1.532 -}
1.533 -
1.534 -/* Destroy an importer without creating the set. */
1.535 -void
1.536 -razor_importer_destroy(struct razor_importer *importer)
1.537 -{
1.538 - /* FIXME: write this */
1.539 -}
1.540 -
1.541 -static int
1.542 -versioncmp(const char *s1, const char *s2)
1.543 -{
1.544 - const char *p1, *p2;
1.545 - long n1, n2;
1.546 - int res;
1.547 -
1.548 - n1 = strtol(s1, (char **) &p1, 10);
1.549 - n2 = strtol(s2, (char **) &p2, 10);
1.550 -
1.551 - /* Epoch; if one but not the other has an epoch set, default
1.552 - * the epoch-less version to 0. */
1.553 - res = (*p1 == ':') - (*p2 == ':');
1.554 - if (res < 0) {
1.555 - n1 = 0;
1.556 - p1 = s1;
1.557 - p2++;
1.558 - } else if (res > 0) {
1.559 - p1++;
1.560 - n2 = 0;
1.561 - p2 = s2;
1.562 - }
1.563 -
1.564 - if (n1 != n2)
1.565 - return n1 - n2;
1.566 - while (*p1 && *p2) {
1.567 - if (*p1 != *p2)
1.568 - return *p1 - *p2;
1.569 - p1++;
1.570 - p2++;
1.571 - if (isdigit(*p1) && isdigit(*p2))
1.572 - return versioncmp(p1, p2);
1.573 - }
1.574 -
1.575 - return *p1 - *p2;
1.576 -}
1.577 -
1.578 -static int
1.579 -compare_packages(const void *p1, const void *p2, void *data)
1.580 -{
1.581 - const struct razor_package *pkg1 = p1, *pkg2 = p2;
1.582 - struct razor_set *set = data;
1.583 - char *pool = set->string_pool.data;
1.584 -
1.585 - /* FIXME: what if the flags are different? */
1.586 - if (pkg1->name == pkg2->name)
1.587 - return versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
1.588 - else
1.589 - return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
1.590 -}
1.591 -
1.592 -static int
1.593 -compare_properties(const void *p1, const void *p2, void *data)
1.594 -{
1.595 - const struct razor_property *prop1 = p1, *prop2 = p2;
1.596 - struct razor_set *set = data;
1.597 - char *pool = set->string_pool.data;
1.598 -
1.599 - if (prop1->name != prop2->name)
1.600 - return strcmp(&pool[prop1->name], &pool[prop2->name]);
1.601 - else if (prop1->type != prop2->type)
1.602 - return prop1->type - prop2->type;
1.603 - else if (prop1->relation != prop2->relation)
1.604 - return prop1->relation - prop2->relation;
1.605 - else
1.606 - return versioncmp(&pool[prop1->version], &pool[prop2->version]);
1.607 -}
1.608 -
1.609 -static uint32_t *
1.610 -uniqueify_properties(struct razor_set *set)
1.611 -{
1.612 - struct razor_property *rp, *up, *rp_end;
1.613 - struct array *pkgs, *p;
1.614 - struct list_head *r;
1.615 - uint32_t *map, *rmap;
1.616 - int i, count, unique;
1.617 -
1.618 - count = set->properties.size / sizeof(struct razor_property);
1.619 - map = razor_qsort_with_data(set->properties.data,
1.620 - count,
1.621 - sizeof(struct razor_property),
1.622 - compare_properties,
1.623 - set);
1.624 -
1.625 - rp_end = set->properties.data + set->properties.size;
1.626 - rmap = malloc(count * sizeof *map);
1.627 - pkgs = zalloc(count * sizeof *pkgs);
1.628 - for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
1.629 - if (rp->name != up->name || rp->type != up->type ||
1.630 - rp->relation != up->relation || rp->version != up->version) {
1.631 - up++;
1.632 - up->name = rp->name;
1.633 - up->flags = 0;
1.634 - up->type = rp->type;
1.635 - up->relation = rp->relation;
1.636 - up->version = rp->version;
1.637 - }
1.638 -
1.639 - unique = up - (struct razor_property *) set->properties.data;
1.640 - rmap[map[i]] = unique;
1.641 - r = array_add(&pkgs[unique], sizeof *r);
1.642 - *r = rp->packages;
1.643 - }
1.644 - free(map);
1.645 -
1.646 - if (up != rp)
1.647 - up++;
1.648 - set->properties.size = (void *) up - set->properties.data;
1.649 - rp_end = up;
1.650 - for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
1.651 - list_set_array(&rp->packages, &set->package_pool, p, 0);
1.652 - array_release(p);
1.653 - }
1.654 -
1.655 - free(pkgs);
1.656 -
1.657 - return rmap;
1.658 -}
1.659 -
1.660 -static int
1.661 -compare_filenames(const void *p1, const void *p2, void *data)
1.662 -{
1.663 - const struct import_entry *e1 = p1;
1.664 - const struct import_entry *e2 = p2;
1.665 - const char *n1 = e1->name;
1.666 - const char *n2 = e2->name;
1.667 -
1.668 - /* Need to make sure that the contents of a directory
1.669 - * are sorted immediately after it. So "foo/bar" has to
1.670 - * sort before "foo.conf"
1.671 - *
1.672 - * FIXME: this is about 60% slower than strcmp
1.673 - */
1.674 - while (*n1 && *n2) {
1.675 - if (*n1 < *n2)
1.676 - return *n2 == '/' ? 1 : -1;
1.677 - else if (*n1 > *n2)
1.678 - return *n1 == '/' ? -1 : 1;
1.679 - n1++;
1.680 - n2++;
1.681 - }
1.682 - if (*n1)
1.683 - return 1;
1.684 - else if (*n2)
1.685 - return -1;
1.686 - else
1.687 - return 0;
1.688 -}
1.689 -
1.690 -static void
1.691 -count_entries(struct import_directory *d)
1.692 -{
1.693 - struct import_directory *p, *end;
1.694 -
1.695 - p = d->files.data;
1.696 - end = d->files.data + d->files.size;
1.697 - d->count = 0;
1.698 - while (p < end) {
1.699 - count_entries(p);
1.700 - d->count += p->count + 1;
1.701 - p++;
1.702 - }
1.703 -}
1.704 -
1.705 -static void
1.706 -serialize_files(struct razor_set *set,
1.707 - struct import_directory *d, struct array *array)
1.708 -{
1.709 - struct import_directory *p, *end;
1.710 - struct razor_entry *e = NULL;
1.711 - uint32_t s;
1.712 -
1.713 - p = d->files.data;
1.714 - end = d->files.data + d->files.size;
1.715 - s = array->size / sizeof *e + d->files.size / sizeof *p;
1.716 - while (p < end) {
1.717 - e = array_add(array, sizeof *e);
1.718 - e->name = p->name;
1.719 - e->flags = 0;
1.720 - e->start = p->count > 0 ? s : 0;
1.721 - s += p->count;
1.722 -
1.723 - list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
1.724 - array_release(&p->packages);
1.725 - p++;
1.726 - }
1.727 - if (e != NULL)
1.728 - e->flags |= RAZOR_ENTRY_LAST;
1.729 -
1.730 - p = d->files.data;
1.731 - end = d->files.data + d->files.size;
1.732 - while (p < end) {
1.733 - serialize_files(set, p, array);
1.734 - p++;
1.735 - }
1.736 -}
1.737 -
1.738 -static void
1.739 -remap_property_package_links(struct array *properties, uint32_t *rmap)
1.740 -{
1.741 - struct razor_property *p, *end;
1.742 -
1.743 - end = properties->data + properties->size;
1.744 - for (p = properties->data; p < end; p++)
1.745 - list_remap_head(&p->packages, rmap);
1.746 -}
1.747 -
1.748 -static void
1.749 -build_file_tree(struct razor_importer *importer)
1.750 -{
1.751 - int count, i, length;
1.752 - struct import_entry *filenames;
1.753 - char *f, *end;
1.754 - uint32_t name, *r;
1.755 - char dirname[256];
1.756 - struct import_directory *d, root;
1.757 - struct razor_entry *e;
1.758 -
1.759 - count = importer->files.size / sizeof (struct import_entry);
1.760 - razor_qsort_with_data(importer->files.data,
1.761 - count,
1.762 - sizeof (struct import_entry),
1.763 - compare_filenames,
1.764 - NULL);
1.765 -
1.766 - root.name = hashtable_tokenize(&importer->file_table, "");
1.767 - array_init(&root.files);
1.768 - array_init(&root.packages);
1.769 - root.last = NULL;
1.770 -
1.771 - filenames = importer->files.data;
1.772 - for (i = 0; i < count; i++) {
1.773 - f = filenames[i].name;
1.774 - if (*f != '/')
1.775 - continue;
1.776 - f++;
1.777 -
1.778 - d = &root;
1.779 - while (*f) {
1.780 - end = strchr(f, '/');
1.781 - if (end == NULL)
1.782 - end = f + strlen(f);
1.783 - length = end - f;
1.784 - memcpy(dirname, f, length);
1.785 - dirname[length] ='\0';
1.786 - name = hashtable_tokenize(&importer->file_table, dirname);
1.787 - if (d->last == NULL || d->last->name != name) {
1.788 - d->last = array_add(&d->files, sizeof *d);
1.789 - d->last->name = name;
1.790 - d->last->last = NULL;
1.791 - array_init(&d->last->files);
1.792 - array_init(&d->last->packages);
1.793 - }
1.794 - d = d->last;
1.795 - f = end + 1;
1.796 - if (*end == '\0')
1.797 - break;
1.798 - }
1.799 -
1.800 - r = array_add(&d->packages, sizeof *r);
1.801 - *r = filenames[i].package;
1.802 - free(filenames[i].name);
1.803 - }
1.804 -
1.805 - count_entries(&root);
1.806 - e = importer->set->files.data;
1.807 - e->name = root.name;
1.808 - e->flags = RAZOR_ENTRY_LAST;
1.809 - e->start = importer->files.size ? 1 : 0;
1.810 - list_set_empty(&e->packages);
1.811 -
1.812 - serialize_files(importer->set, &root, &importer->set->files);
1.813 -
1.814 - array_release(&importer->files);
1.815 -}
1.816 -
1.817 -static struct razor_entry *
1.818 -find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern);
1.819 -
1.820 -static void
1.821 -list_to_array(struct list *list, struct array *array)
1.822 -{
1.823 - uint32_t *item;
1.824 -
1.825 - while (list) {
1.826 - item = array_add(array, sizeof *item);
1.827 - *item = list->data;
1.828 - list = list_next(list);
1.829 - }
1.830 -}
1.831 -
1.832 -static int
1.833 -compare_file_requires(const void *p1, const void *p2, void *data)
1.834 -{
1.835 - uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
1.836 - const char *pool = data;
1.837 -
1.838 - return strcmp(&pool[*f1], &pool[*f2]);
1.839 -}
1.840 -
1.841 -static void
1.842 -find_file_provides(struct razor_importer *importer)
1.843 -{
1.844 - struct razor_property *prop;
1.845 - struct razor_entry *top, *entry;
1.846 - struct razor_package *packages;
1.847 - struct array pkgprops;
1.848 - struct list *pkg;
1.849 - uint32_t *req, *req_start, *req_end;
1.850 - uint32_t *map, *newprop;
1.851 - char *pool;
1.852 -
1.853 - pool = importer->set->string_pool.data;
1.854 - packages = importer->set->packages.data;
1.855 - top = importer->set->files.data;
1.856 -
1.857 - req = req_start = importer->file_requires.data;
1.858 - req_end = importer->file_requires.data + importer->file_requires.size;
1.859 - map = razor_qsort_with_data(req, req_end - req, sizeof *req,
1.860 - compare_file_requires, pool);
1.861 - free(map);
1.862 -
1.863 - for (req = req_start; req < req_end; req++) {
1.864 - if (req > req_start && req[0] == req[-1])
1.865 - continue;
1.866 - entry = find_entry(importer->set, top, &pool[*req]);
1.867 - if (!entry)
1.868 - continue;
1.869 -
1.870 - for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
1.871 - prop = array_add(&importer->set->properties, sizeof *prop);
1.872 - prop->name = *req;
1.873 - prop->type = RAZOR_PROPERTY_PROVIDES;
1.874 - prop->relation = RAZOR_VERSION_EQUAL;
1.875 - prop->version = hashtable_tokenize(&importer->table, "");
1.876 - list_set_ptr(&prop->packages, pkg->data);
1.877 -
1.878 - /* Update property list of pkg */
1.879 - array_init(&pkgprops);
1.880 - list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
1.881 - newprop = array_add(&pkgprops, sizeof *newprop);
1.882 - *newprop = prop - (struct razor_property *)importer->set->properties.data;
1.883 - list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
1.884 - array_release(&pkgprops);
1.885 - }
1.886 - }
1.887 -
1.888 - array_release(&importer->file_requires);
1.889 -}
1.890 -
1.891 -static void
1.892 -build_package_file_lists(struct razor_set *set, uint32_t *rmap)
1.893 -{
1.894 - struct razor_package *p, *packages;
1.895 - struct array *pkgs;
1.896 - struct razor_entry *e, *end;
1.897 - struct list *r;
1.898 - uint32_t *q;
1.899 - int i, count;
1.900 -
1.901 - count = set->packages.size / sizeof *p;
1.902 - pkgs = zalloc(count * sizeof *pkgs);
1.903 -
1.904 - end = set->files.data + set->files.size;
1.905 - for (e = set->files.data; e < end; e++) {
1.906 - list_remap_head(&e->packages, rmap);
1.907 - r = list_first(&e->packages, &set->package_pool);
1.908 - while (r) {
1.909 - q = array_add(&pkgs[r->data], sizeof *q);
1.910 - *q = e - (struct razor_entry *) set->files.data;
1.911 - r = list_next(r);
1.912 - }
1.913 - }
1.914 -
1.915 - packages = set->packages.data;
1.916 - for (i = 0; i < count; i++) {
1.917 - list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
1.918 - array_release(&pkgs[i]);
1.919 - }
1.920 - free(pkgs);
1.921 -}
1.922 -
1.923 -struct razor_set *
1.924 -razor_importer_finish(struct razor_importer *importer)
1.925 -{
1.926 - struct razor_set *set;
1.927 - uint32_t *map, *rmap;
1.928 - int i, count;
1.929 -
1.930 - build_file_tree(importer);
1.931 - find_file_provides(importer);
1.932 -
1.933 - map = uniqueify_properties(importer->set);
1.934 - list_remap_pool(&importer->set->property_pool, map);
1.935 - free(map);
1.936 -
1.937 - count = importer->set->packages.size / sizeof(struct razor_package);
1.938 - map = razor_qsort_with_data(importer->set->packages.data,
1.939 - count,
1.940 - sizeof(struct razor_package),
1.941 - compare_packages,
1.942 - importer->set);
1.943 -
1.944 - rmap = malloc(count * sizeof *rmap);
1.945 - for (i = 0; i < count; i++)
1.946 - rmap[map[i]] = i;
1.947 - free(map);
1.948 -
1.949 - list_remap_pool(&importer->set->package_pool, rmap);
1.950 - build_package_file_lists(importer->set, rmap);
1.951 - remap_property_package_links(&importer->set->properties, rmap);
1.952 - free(rmap);
1.953 -
1.954 - set = importer->set;
1.955 - hashtable_release(&importer->table);
1.956 - hashtable_release(&importer->file_table);
1.957 - hashtable_release(&importer->details_table);
1.958 - free(importer);
1.959 -
1.960 - return set;
1.961 -}
1.962 -
1.963 -struct razor_package_iterator {
1.964 - struct razor_set *set;
1.965 - struct razor_package *package, *end;
1.966 - struct list *index;
1.967 - int free_index;
1.968 -};
1.969 -
1.970 -static struct razor_package_iterator *
1.971 -razor_package_iterator_create_with_index(struct razor_set *set,
1.972 - struct list *index)
1.973 -{
1.974 - struct razor_package_iterator *pi;
1.975 -
1.976 - pi = zalloc(sizeof *pi);
1.977 - pi->set = set;
1.978 - pi->index = index;
1.979 -
1.980 - return pi;
1.981 -}
1.982 -
1.983 -struct razor_package_iterator *
1.984 -razor_package_iterator_create(struct razor_set *set)
1.985 -{
1.986 - struct razor_package_iterator *pi;
1.987 -
1.988 - pi = zalloc(sizeof *pi);
1.989 - pi->set = set;
1.990 - pi->end = set->packages.data + set->packages.size;
1.991 - pi->package = set->packages.data;
1.992 -
1.993 - return pi;
1.994 -}
1.995 -
1.996 -struct razor_package_iterator *
1.997 -razor_package_iterator_create_for_property(struct razor_set *set,
1.998 - struct razor_property *property)
1.999 -{
1.1000 - struct list *index;
1.1001 -
1.1002 - index = list_first(&property->packages, &set->package_pool);
1.1003 - return razor_package_iterator_create_with_index(set, index);
1.1004 -}
1.1005 -
1.1006 -int
1.1007 -razor_package_iterator_next(struct razor_package_iterator *pi,
1.1008 - struct razor_package **package,
1.1009 - const char **name,
1.1010 - const char **version,
1.1011 - const char **arch)
1.1012 -{
1.1013 - char *pool;
1.1014 - int valid;
1.1015 - struct razor_package *p, *packages;
1.1016 -
1.1017 - if (pi->package) {
1.1018 - p = pi->package++;
1.1019 - valid = p < pi->end;
1.1020 - } else if (pi->index) {
1.1021 - packages = pi->set->packages.data;
1.1022 - p = &packages[pi->index->data];
1.1023 - pi->index = list_next(pi->index);
1.1024 - valid = 1;
1.1025 - } else
1.1026 - valid = 0;
1.1027 -
1.1028 - if (valid) {
1.1029 - pool = pi->set->string_pool.data;
1.1030 - *package = p;
1.1031 - *name = &pool[p->name];
1.1032 - *version = &pool[p->version];
1.1033 - *arch = &pool[p->arch];
1.1034 - } else {
1.1035 - *package = NULL;
1.1036 - }
1.1037 -
1.1038 - return valid;
1.1039 -}
1.1040 -
1.1041 -void
1.1042 -razor_package_iterator_destroy(struct razor_package_iterator *pi)
1.1043 -{
1.1044 - if (pi->free_index)
1.1045 - free(pi->index);
1.1046 -
1.1047 - free(pi);
1.1048 -}
1.1049 -
1.1050 -struct razor_package *
1.1051 -razor_set_get_package(struct razor_set *set, const char *package)
1.1052 -{
1.1053 - struct razor_package_iterator *pi;
1.1054 - struct razor_package *p;
1.1055 - const char *name, *version, *arch;
1.1056 -
1.1057 - pi = razor_package_iterator_create(set);
1.1058 - while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
1.1059 - if (strcmp(package, name) == 0)
1.1060 - break;
1.1061 - }
1.1062 - razor_package_iterator_destroy(pi);
1.1063 -
1.1064 - return p;
1.1065 -}
1.1066 -
1.1067 -void
1.1068 -razor_package_get_details(struct razor_set *set, struct razor_package *package,
1.1069 - const char **summary, const char **description,
1.1070 - const char **url, const char **license)
1.1071 -{
1.1072 - const char *pool = set->details_string_pool.data;
1.1073 -
1.1074 - *summary = &pool[package->summary];
1.1075 - *description = &pool[package->description];
1.1076 - *url = &pool[package->url];
1.1077 - *license = &pool[package->license];
1.1078 -}
1.1079 -
1.1080 -struct razor_property_iterator {
1.1081 - struct razor_set *set;
1.1082 - struct razor_property *property, *end;
1.1083 - struct list *index;
1.1084 -};
1.1085 -
1.1086 -struct razor_property_iterator *
1.1087 -razor_property_iterator_create(struct razor_set *set,
1.1088 - struct razor_package *package)
1.1089 -{
1.1090 - struct razor_property_iterator *pi;
1.1091 -
1.1092 - pi = zalloc(sizeof *pi);
1.1093 - pi->set = set;
1.1094 -
1.1095 - if (package) {
1.1096 - pi->index = list_first(&package->properties,
1.1097 - &set->property_pool);
1.1098 - } else {
1.1099 - pi->property = set->properties.data;
1.1100 - pi->end = set->properties.data + set->properties.size;
1.1101 - }
1.1102 -
1.1103 - return pi;
1.1104 -}
1.1105 -
1.1106 -int
1.1107 -razor_property_iterator_next(struct razor_property_iterator *pi,
1.1108 - struct razor_property **property,
1.1109 - const char **name,
1.1110 - enum razor_version_relation *relation,
1.1111 - const char **version,
1.1112 - enum razor_property_type *type)
1.1113 -{
1.1114 - char *pool;
1.1115 - int valid;
1.1116 - struct razor_property *p, *properties;
1.1117 -
1.1118 - if (pi->property) {
1.1119 - p = pi->property++;
1.1120 - valid = p < pi->end;
1.1121 - } else if (pi->index) {
1.1122 - properties = pi->set->properties.data;
1.1123 - p = &properties[pi->index->data];
1.1124 - pi->index = list_next(pi->index);
1.1125 - valid = 1;
1.1126 - } else
1.1127 - valid = 0;
1.1128 -
1.1129 - if (valid) {
1.1130 - pool = pi->set->string_pool.data;
1.1131 - *property = p;
1.1132 - *name = &pool[p->name];
1.1133 - *relation = p->relation;
1.1134 - *version = &pool[p->version];
1.1135 - *type = p->type;
1.1136 - } else {
1.1137 - *property = NULL;
1.1138 - }
1.1139 -
1.1140 - return valid;
1.1141 -}
1.1142 -
1.1143 -void
1.1144 -razor_property_iterator_destroy(struct razor_property_iterator *pi)
1.1145 -{
1.1146 - free(pi);
1.1147 -}
1.1148 -
1.1149 -static struct razor_entry *
1.1150 -find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern)
1.1151 -{
1.1152 - struct razor_entry *e;
1.1153 - const char *n, *pool = set->file_string_pool.data;
1.1154 - int len;
1.1155 -
1.1156 - e = (struct razor_entry *) set->files.data + dir->start;
1.1157 - do {
1.1158 - n = pool + e->name;
1.1159 - if (strcmp(pattern + 1, n) == 0)
1.1160 - return e;
1.1161 - len = strlen(n);
1.1162 - if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
1.1163 - pattern[len + 1] == '/') {
1.1164 - return find_entry(set, e, pattern + len + 1);
1.1165 - }
1.1166 - } while (!((e++)->flags & RAZOR_ENTRY_LAST));
1.1167 -
1.1168 - return NULL;
1.1169 -}
1.1170 -
1.1171 -static void
1.1172 -list_dir(struct razor_set *set, struct razor_entry *dir,
1.1173 - char *prefix, const char *pattern)
1.1174 -{
1.1175 - struct razor_entry *e;
1.1176 - const char *n, *pool = set->file_string_pool.data;
1.1177 -
1.1178 - e = (struct razor_entry *) set->files.data + dir->start;
1.1179 - do {
1.1180 - n = pool + e->name;
1.1181 - if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
1.1182 - continue;
1.1183 - printf("%s/%s\n", prefix, n);
1.1184 - if (e->start) {
1.1185 - char *sub = prefix + strlen (prefix);
1.1186 - *sub = '/';
1.1187 - strcpy (sub + 1, n);
1.1188 - list_dir(set, e, prefix, pattern);
1.1189 - *sub = '\0';
1.1190 - }
1.1191 - } while (!((e++)->flags & RAZOR_ENTRY_LAST));
1.1192 -}
1.1193 -
1.1194 -void
1.1195 -razor_set_list_files(struct razor_set *set, const char *pattern)
1.1196 -{
1.1197 - struct razor_entry *e;
1.1198 - char buffer[512], *p, *base;
1.1199 -
1.1200 - if (pattern == NULL || !strcmp (pattern, "/")) {
1.1201 - buffer[0] = '\0';
1.1202 - list_dir(set, set->files.data, buffer, NULL);
1.1203 - return;
1.1204 - }
1.1205 -
1.1206 - strcpy(buffer, pattern);
1.1207 - e = find_entry(set, set->files.data, buffer);
1.1208 - if (e && e->start > 0) {
1.1209 - base = NULL;
1.1210 - } else {
1.1211 - p = strrchr(buffer, '/');
1.1212 - if (p) {
1.1213 - *p = '\0';
1.1214 - base = p + 1;
1.1215 - } else {
1.1216 - base = NULL;
1.1217 - }
1.1218 - }
1.1219 - e = find_entry(set, set->files.data, buffer);
1.1220 - if (e->start != 0)
1.1221 - list_dir(set, e, buffer, base);
1.1222 -}
1.1223 -
1.1224 -struct razor_package_iterator *
1.1225 -razor_package_iterator_create_for_file(struct razor_set *set,
1.1226 - const char *filename)
1.1227 -{
1.1228 - struct razor_entry *entry;
1.1229 - struct list *index;
1.1230 -
1.1231 - entry = find_entry(set, set->files.data, filename);
1.1232 - if (entry == NULL)
1.1233 - return NULL;
1.1234 -
1.1235 - index = list_first(&entry->packages, &set->package_pool);
1.1236 - return razor_package_iterator_create_with_index(set, index);
1.1237 -}
1.1238 -
1.1239 -static struct list *
1.1240 -list_package_files(struct razor_set *set, struct list *r,
1.1241 - struct razor_entry *dir, uint32_t end,
1.1242 - char *prefix)
1.1243 -{
1.1244 - struct razor_entry *e, *f, *entries;
1.1245 - uint32_t next, file;
1.1246 - char *pool;
1.1247 - int len;
1.1248 -
1.1249 - entries = (struct razor_entry *) set->files.data;
1.1250 - pool = set->file_string_pool.data;
1.1251 -
1.1252 - e = entries + dir->start;
1.1253 - do {
1.1254 - if (entries + r->data == e) {
1.1255 - printf("%s/%s\n", prefix, pool + e->name);
1.1256 - r = list_next(r);
1.1257 - if (!r)
1.1258 - return NULL;
1.1259 - if (r->data >= end)
1.1260 - return r;
1.1261 - }
1.1262 - } while (!((e++)->flags & RAZOR_ENTRY_LAST));
1.1263 -
1.1264 - e = entries + dir->start;
1.1265 - do {
1.1266 - if (e->start == 0)
1.1267 - continue;
1.1268 -
1.1269 - if (e->flags & RAZOR_ENTRY_LAST)
1.1270 - next = end;
1.1271 - else {
1.1272 - f = e + 1;
1.1273 - while (f->start == 0 && !(f->flags & RAZOR_ENTRY_LAST))
1.1274 - f++;
1.1275 - if (f->start == 0)
1.1276 - next = end;
1.1277 - else
1.1278 - next = f->start;
1.1279 - }
1.1280 -
1.1281 - file = r->data;
1.1282 - if (e->start <= file && file < next) {
1.1283 - len = strlen(prefix);
1.1284 - prefix[len] = '/';
1.1285 - strcpy(prefix + len + 1, pool + e->name);
1.1286 - r = list_package_files(set, r, e, next, prefix);
1.1287 - prefix[len] = '\0';
1.1288 - }
1.1289 - } while (!((e++)->flags & RAZOR_ENTRY_LAST) && r != NULL);
1.1290 -
1.1291 - return r;
1.1292 -}
1.1293 -
1.1294 -void
1.1295 -razor_set_list_package_files(struct razor_set *set, const char *name)
1.1296 -{
1.1297 - struct razor_package *package;
1.1298 - struct list *r;
1.1299 - uint32_t end;
1.1300 - char buffer[512];
1.1301 -
1.1302 - package = razor_set_get_package(set, name);
1.1303 -
1.1304 - r = list_first(&package->files, &set->file_pool);
1.1305 - end = set->files.size / sizeof (struct razor_entry);
1.1306 - buffer[0] = '\0';
1.1307 - list_package_files(set, r, set->files.data, end, buffer);
1.1308 -}
1.1309 -
1.1310 -static void
1.1311 -razor_set_validate(struct razor_set *set, struct array *unsatisfied)
1.1312 -{
1.1313 - struct razor_property *r, *p, *end;
1.1314 - uint32_t *u;
1.1315 - char *pool;
1.1316 -
1.1317 - end = set->properties.data + set->properties.size;
1.1318 - pool = set->string_pool.data;
1.1319 -
1.1320 - for (r = set->properties.data, p = r; r < end; r++) {
1.1321 - if (r->type != RAZOR_PROPERTY_REQUIRES)
1.1322 - continue;
1.1323 -
1.1324 - p = r;
1.1325 - while (p < end && p->name == r->name &&
1.1326 - p->type == r->type)
1.1327 - p++;
1.1328 -
1.1329 - /* If there is more than one version of a provides,
1.1330 - * seek to the end for the highest version. */
1.1331 - /* FIXME: This doesn't work if we have a series of
1.1332 - * requires a = 1, provides a = 1, requires a = 2,
1.1333 - * provides a = 2, as the kernel and kernel-devel
1.1334 - * does.*/
1.1335 - while (p + 1 < end && p->name == (p + 1)->name &&
1.1336 - p->type == (p + 1)->type)
1.1337 - p++;
1.1338 -
1.1339 - /* FIXME: We need to track property flags (<, <=, =
1.1340 - * etc) to properly determine if a requires is
1.1341 - * satisfied. The current code doesn't track that the
1.1342 - * requires a = 1 isn't satisfied by a = 2 provides. */
1.1343 -
1.1344 - if (p == end ||
1.1345 - p->type != RAZOR_PROPERTY_PROVIDES ||
1.1346 - r->name != p->name ||
1.1347 - versioncmp(&pool[r->version], &pool[p->version]) > 0) {
1.1348 - /* FIXME: We ignore file requires for now. */
1.1349 - if (pool[r->name] == '/')
1.1350 - continue;
1.1351 - u = array_add(unsatisfied, sizeof *u);
1.1352 - *u = r - (struct razor_property *) set->properties.data;
1.1353 - }
1.1354 - }
1.1355 -}
1.1356 -
1.1357 -void
1.1358 -razor_set_list_unsatisfied(struct razor_set *set)
1.1359 -{
1.1360 - struct array unsatisfied;
1.1361 - struct razor_property *properties, *r;
1.1362 - uint32_t *u, *end;
1.1363 - char *pool;
1.1364 -
1.1365 - array_init(&unsatisfied);
1.1366 - razor_set_validate(set, &unsatisfied);
1.1367 -
1.1368 - end = unsatisfied.data + unsatisfied.size;
1.1369 - properties = set->properties.data;
1.1370 - pool = set->string_pool.data;
1.1371 -
1.1372 - for (u = unsatisfied.data; u < end; u++) {
1.1373 - r = properties + *u;
1.1374 - if (pool[r->version] == '\0')
1.1375 - printf("%s not satisfied\n",
1.1376 - &pool[r->name]);
1.1377 - else
1.1378 - printf("%s-%s not satisfied\n",
1.1379 - &pool[r->name],
1.1380 - &pool[r->version]);
1.1381 - }
1.1382 -
1.1383 - array_release(&unsatisfied);
1.1384 -}
1.1385 -
1.1386 -#define UPSTREAM_SOURCE 0x80
1.1387 -
1.1388 -struct source {
1.1389 - struct razor_set *set;
1.1390 - uint32_t *property_map;
1.1391 - uint32_t *file_map;
1.1392 -};
1.1393 -
1.1394 -struct razor_merger {
1.1395 - struct razor_set *set;
1.1396 - struct hashtable table;
1.1397 - struct hashtable file_table;
1.1398 - struct hashtable details_table;
1.1399 - struct source source1;
1.1400 - struct source source2;
1.1401 -};
1.1402 -
1.1403 -static struct razor_merger *
1.1404 -razor_merger_create(struct razor_set *set1, struct razor_set *set2)
1.1405 -{
1.1406 - struct razor_merger *merger;
1.1407 - int count;
1.1408 - size_t size;
1.1409 -
1.1410 - merger = zalloc(sizeof *merger);
1.1411 - merger->set = razor_set_create();
1.1412 - hashtable_init(&merger->table, &merger->set->string_pool);
1.1413 - hashtable_init(&merger->file_table, &merger->set->file_string_pool);
1.1414 - hashtable_init(&merger->details_table, &merger->set->details_string_pool);
1.1415 -
1.1416 - merger->source1.set = set1;
1.1417 - count = set1->properties.size / sizeof (struct razor_property);
1.1418 - size = count * sizeof merger->source1.property_map[0];
1.1419 - merger->source1.property_map = zalloc(size);
1.1420 - count = set1->files.size / sizeof (struct razor_entry);
1.1421 - size = count * sizeof merger->source1.file_map[0];
1.1422 - merger->source1.file_map = zalloc(size);
1.1423 -
1.1424 - merger->source2.set = set2;
1.1425 - count = set2->properties.size / sizeof (struct razor_property);
1.1426 - size = count * sizeof merger->source2.property_map[0];
1.1427 - merger->source2.property_map = zalloc(size);
1.1428 - count = set2->files.size / sizeof (struct razor_entry);
1.1429 - size = count * sizeof merger->source2.file_map[0];
1.1430 - merger->source2.file_map = zalloc(size);
1.1431 -
1.1432 - return merger;
1.1433 -}
1.1434 -
1.1435 -static void
1.1436 -add_package(struct razor_merger *merger,
1.1437 - struct razor_package *package, struct source *source,
1.1438 - uint32_t flags)
1.1439 -{
1.1440 - char *pool;
1.1441 - struct list *r;
1.1442 - struct razor_package *p;
1.1443 -
1.1444 - pool = source->set->string_pool.data;
1.1445 - p = array_add(&merger->set->packages, sizeof *p);
1.1446 - p->name = hashtable_tokenize(&merger->table, &pool[package->name]);
1.1447 - p->flags = flags;
1.1448 - p->version = hashtable_tokenize(&merger->table,
1.1449 - &pool[package->version]);
1.1450 - p->arch = hashtable_tokenize(&merger->table,
1.1451 - &pool[package->arch]);
1.1452 -
1.1453 - p->properties = package->properties;
1.1454 - r = list_first(&package->properties, &source->set->property_pool);
1.1455 - while (r) {
1.1456 - source->property_map[r->data] = 1;
1.1457 - r = list_next(r);
1.1458 - }
1.1459 -
1.1460 - p->files = package->files;
1.1461 - r = list_first(&package->files, &source->set->file_pool);
1.1462 - while (r) {
1.1463 - source->file_map[r->data] = 1;
1.1464 - r = list_next(r);
1.1465 - }
1.1466 -}
1.1467 -
1.1468 -static uint32_t
1.1469 -add_property(struct razor_merger *merger,
1.1470 - const char *name, enum razor_version_relation relation,
1.1471 - const char *version, int type)
1.1472 -{
1.1473 - struct razor_property *p;
1.1474 -
1.1475 - p = array_add(&merger->set->properties, sizeof *p);
1.1476 - p->name = hashtable_tokenize(&merger->table, name);
1.1477 - p->flags = 0;
1.1478 - p->type = type;
1.1479 - p->relation = relation;
1.1480 - p->version = hashtable_tokenize(&merger->table, version);
1.1481 -
1.1482 - return p - (struct razor_property *) merger->set->properties.data;
1.1483 -}
1.1484 -
1.1485 -static void
1.1486 -merge_properties(struct razor_merger *merger)
1.1487 -{
1.1488 - struct razor_property *p1, *p2;
1.1489 - struct razor_set *set1, *set2;
1.1490 - uint32_t *map1, *map2;
1.1491 - int i, j, cmp, count1, count2;
1.1492 - char *pool1, *pool2;
1.1493 -
1.1494 - set1 = merger->source1.set;
1.1495 - set2 = merger->source2.set;
1.1496 - map1 = merger->source1.property_map;
1.1497 - map2 = merger->source2.property_map;
1.1498 -
1.1499 - i = 0;
1.1500 - j = 0;
1.1501 - pool1 = set1->string_pool.data;
1.1502 - pool2 = set2->string_pool.data;
1.1503 -
1.1504 - count1 = set1->properties.size / sizeof *p1;
1.1505 - count2 = set2->properties.size / sizeof *p2;
1.1506 - while (i < count1 || j < count2) {
1.1507 - if (i < count1 && map1[i] == 0) {
1.1508 - i++;
1.1509 - continue;
1.1510 - }
1.1511 - if (j < count2 && map2[j] == 0) {
1.1512 - j++;
1.1513 - continue;
1.1514 - }
1.1515 - p1 = (struct razor_property *) set1->properties.data + i;
1.1516 - p2 = (struct razor_property *) set2->properties.data + j;
1.1517 - if (i < count1 && j < count2)
1.1518 - cmp = strcmp(&pool1[p1->name], &pool2[p2->name]);
1.1519 - else if (i < count1)
1.1520 - cmp = -1;
1.1521 - else
1.1522 - cmp = 1;
1.1523 - if (cmp == 0)
1.1524 - cmp = p1->type - p2->type;
1.1525 - if (cmp == 0)
1.1526 - cmp = p1->relation - p2->relation;
1.1527 - if (cmp == 0)
1.1528 - cmp = versioncmp(&pool1[p1->version],
1.1529 - &pool2[p2->version]);
1.1530 - if (cmp < 0) {
1.1531 - map1[i++] = add_property(merger,
1.1532 - &pool1[p1->name],
1.1533 - p1->relation,
1.1534 - &pool1[p1->version],
1.1535 - p1->type);
1.1536 - } else if (cmp > 0) {
1.1537 - map2[j++] = add_property(merger,
1.1538 - &pool2[p2->name],
1.1539 - p2->relation,
1.1540 - &pool2[p2->version],
1.1541 - p2->type);
1.1542 - } else {
1.1543 - map1[i++] = map2[j++] = add_property(merger,
1.1544 - &pool1[p1->name],
1.1545 - p1->relation,
1.1546 - &pool1[p1->version],
1.1547 - p1->type);
1.1548 - }
1.1549 - }
1.1550 -}
1.1551 -
1.1552 -static void
1.1553 -emit_properties(struct list_head *properties, struct array *source_pool,
1.1554 - uint32_t *map, struct array *pool)
1.1555 -{
1.1556 - uint32_t r;
1.1557 - struct list *p, *q;
1.1558 -
1.1559 - r = pool->size / sizeof *q;
1.1560 - p = list_first(properties, source_pool);
1.1561 - while (p) {
1.1562 - q = array_add(pool, sizeof *q);
1.1563 - q->data = map[p->data];
1.1564 - q->flags = p->flags;
1.1565 - p = list_next(p);
1.1566 - }
1.1567 -
1.1568 - list_set_ptr(properties, r);
1.1569 -}
1.1570 -
1.1571 -static uint32_t
1.1572 -add_file(struct razor_merger *merger, const char *name)
1.1573 -{
1.1574 - struct razor_entry *e;
1.1575 -
1.1576 - e = array_add(&merger->set->files, sizeof *e);
1.1577 - e->name = hashtable_tokenize(&merger->file_table, name);
1.1578 - e->flags = 0;
1.1579 - e->start = 0;
1.1580 -
1.1581 - return e - (struct razor_entry *)merger->set->files.data;
1.1582 -}
1.1583 -
1.1584 -/* FIXME. Blah */
1.1585 -static int
1.1586 -fix_file_map(uint32_t *map,
1.1587 - struct razor_entry *files,
1.1588 - struct razor_entry *top)
1.1589 -{
1.1590 - uint32_t e;
1.1591 - int found_file = 0;
1.1592 -
1.1593 - e = top->start;
1.1594 - do {
1.1595 - if (files[e].start)
1.1596 - fix_file_map(map, files, &files[e]);
1.1597 - if (map[e])
1.1598 - found_file = 1;
1.1599 - } while (!(files[e++].flags & RAZOR_ENTRY_LAST));
1.1600 -
1.1601 - if (found_file)
1.1602 - map[top - files] = 1;
1.1603 - return found_file;
1.1604 -}
1.1605 -
1.1606 -struct merge_directory {
1.1607 - uint32_t merged, dir1, dir2;
1.1608 -};
1.1609 -
1.1610 -static void
1.1611 -merge_one_directory(struct razor_merger *merger, struct merge_directory *md)
1.1612 -{
1.1613 - struct razor_entry *root1, *root2, *mroot, *e1, *e2;
1.1614 - struct razor_set *set1, *set2;
1.1615 - struct array merge_stack;
1.1616 - struct merge_directory *child_md, *end_md;
1.1617 - uint32_t *map1, *map2, start, last;
1.1618 - int cmp;
1.1619 - char *pool1, *pool2;
1.1620 -
1.1621 - set1 = merger->source1.set;
1.1622 - set2 = merger->source2.set;
1.1623 - map1 = merger->source1.file_map;
1.1624 - map2 = merger->source2.file_map;
1.1625 - pool1 = set1->string_pool.data;
1.1626 - pool2 = set2->string_pool.data;
1.1627 - root1 = (struct razor_entry *) set1->files.data;
1.1628 - root2 = (struct razor_entry *) set2->files.data;
1.1629 -
1.1630 - array_init(&merge_stack);
1.1631 -
1.1632 - start = merger->set->files.size / sizeof (struct razor_entry);
1.1633 - last = 0;
1.1634 - e1 = md->dir1 ? root1 + md->dir1 : NULL;
1.1635 - e2 = md->dir2 ? root2 + md->dir2 : NULL;
1.1636 - while (e1 || e2) {
1.1637 - if (!e2 && !map1[e1 - root1]) {
1.1638 - if ((e1++)->flags & RAZOR_ENTRY_LAST)
1.1639 - e1 = NULL;
1.1640 - continue;
1.1641 - }
1.1642 - if (!e1 && !map2[e2 - root2]) {
1.1643 - if ((e2++)->flags & RAZOR_ENTRY_LAST)
1.1644 - e2 = NULL;
1.1645 - continue;
1.1646 - }
1.1647 - if (e1 && !map1[e1 - root1] &&
1.1648 - e2 && !map1[e2 - root2]) {
1.1649 - if ((e1++)->flags & RAZOR_ENTRY_LAST)
1.1650 - e1 = NULL;
1.1651 - if ((e2++)->flags & RAZOR_ENTRY_LAST)
1.1652 - e2 = NULL;
1.1653 - continue;
1.1654 - }
1.1655 -
1.1656 - if (!e1)
1.1657 - cmp = 1;
1.1658 - else if (!e2)
1.1659 - cmp = -1;
1.1660 - else {
1.1661 - cmp = strcmp (&pool1[e1->name],
1.1662 - &pool2[e2->name]);
1.1663 - }
1.1664 -
1.1665 - if (cmp < 0) {
1.1666 - if (map1[e1 - root1]) {
1.1667 - map1[e1 - root1] = last =
1.1668 - add_file(merger, &pool1[e1->name]);
1.1669 - if (e1->start) {
1.1670 - child_md = array_add(&merge_stack, sizeof (struct merge_directory));
1.1671 - child_md->merged = last;
1.1672 - child_md->dir1 = e1->start;
1.1673 - child_md->dir2 = 0;
1.1674 - }
1.1675 - }
1.1676 - if ((e1++)->flags & RAZOR_ENTRY_LAST)
1.1677 - e1 = NULL;
1.1678 - } else if (cmp > 0) {
1.1679 - if (map2[e2 - root2]) {
1.1680 - map2[e2 - root2] = last =
1.1681 - add_file(merger, &pool2[e2->name]);
1.1682 - if (e2->start) {
1.1683 - child_md = array_add(&merge_stack, sizeof (struct merge_directory));
1.1684 - child_md->merged = last;
1.1685 - child_md->dir1 = 0;
1.1686 - child_md->dir2 = e2->start;
1.1687 - }
1.1688 - }
1.1689 - if ((e2++)->flags & RAZOR_ENTRY_LAST)
1.1690 - e2 = NULL;
1.1691 - } else {
1.1692 - map1[e1 - root1] = map2[e2- root2] = last =
1.1693 - add_file(merger, &pool1[e1->name]);
1.1694 - if (e1->start || e2->start) {
1.1695 - child_md = array_add(&merge_stack, sizeof (struct merge_directory));
1.1696 - child_md->merged = last;
1.1697 - child_md->dir1 = e1->start;
1.1698 - child_md->dir2 = e2->start;
1.1699 - }
1.1700 - if ((e1++)->flags & RAZOR_ENTRY_LAST)
1.1701 - e1 = NULL;
1.1702 - if ((e2++)->flags & RAZOR_ENTRY_LAST)
1.1703 - e2 = NULL;
1.1704 - }
1.1705 - }
1.1706 -
1.1707 - mroot = (struct razor_entry *)merger->set->files.data;
1.1708 - if (last) {
1.1709 - mroot[last].flags = RAZOR_ENTRY_LAST;
1.1710 - mroot[md->merged].start = start;
1.1711 - } else
1.1712 - mroot[md->merged].start = 0;
1.1713 -
1.1714 - end_md = merge_stack.data + merge_stack.size;
1.1715 - for (child_md = merge_stack.data; child_md < end_md; child_md++)
1.1716 - merge_one_directory(merger, child_md);
1.1717 - array_release(&merge_stack);
1.1718 -}
1.1719 -
1.1720 -static void
1.1721 -merge_files(struct razor_merger *merger)
1.1722 -{
1.1723 - struct razor_entry *root;
1.1724 - struct merge_directory md;
1.1725 - uint32_t *map1, *map2;
1.1726 -
1.1727 - map1 = merger->source1.file_map;
1.1728 - map2 = merger->source2.file_map;
1.1729 -
1.1730 - md.merged = 0;
1.1731 -
1.1732 - if (merger->source1.set->files.size) {
1.1733 - root = (struct razor_entry *) merger->source1.set->files.data;
1.1734 - if (root->start)
1.1735 - fix_file_map(map1, root, root);
1.1736 - md.dir1 = root->start;
1.1737 - } else
1.1738 - md.dir1 = 0;
1.1739 -
1.1740 - if (merger->source2.set->files.size) {
1.1741 - root = (struct razor_entry *) merger->source2.set->files.data;
1.1742 - if (root->start)
1.1743 - fix_file_map(map2, root, root);
1.1744 - md.dir2 = root->start;
1.1745 - } else
1.1746 - md.dir2 = 0;
1.1747 -
1.1748 - merge_one_directory(merger, &md);
1.1749 -}
1.1750 -
1.1751 -static void
1.1752 -emit_files(struct list_head *files, struct array *source_pool,
1.1753 - uint32_t *map, struct array *pool)
1.1754 -{
1.1755 - uint32_t r;
1.1756 - struct list *p, *q;
1.1757 -
1.1758 - r = pool->size / sizeof *q;
1.1759 - p = list_first(files, source_pool);
1.1760 - while (p) {
1.1761 - q = array_add(pool, sizeof *q);
1.1762 - q->data = map[p->data];
1.1763 - q->flags = p->flags;
1.1764 - p = list_next(p);
1.1765 - }
1.1766 -
1.1767 - list_set_ptr(files, r);
1.1768 -}
1.1769 -
1.1770 -/* Rebuild property->packages maps. We can't just remap these, as a
1.1771 - * property may have lost or gained a number of packages. Allocate an
1.1772 - * array per property and loop through the packages and add them to
1.1773 - * the arrays for their properties. */
1.1774 -static void
1.1775 -rebuild_property_package_lists(struct razor_set *set)
1.1776 -{
1.1777 - struct array *pkgs, *a;
1.1778 - struct razor_package *pkg, *pkg_end;
1.1779 - struct razor_property *prop, *prop_end;
1.1780 - struct list *r;
1.1781 - uint32_t *q;
1.1782 - int count;
1.1783 -
1.1784 - count = set->properties.size / sizeof (struct razor_property);
1.1785 - pkgs = zalloc(count * sizeof *pkgs);
1.1786 - pkg_end = set->packages.data + set->packages.size;
1.1787 -
1.1788 - for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
1.1789 - r = list_first(&pkg->properties, &set->property_pool);
1.1790 - while (r) {
1.1791 - q = array_add(&pkgs[r->data], sizeof *q);
1.1792 - *q = pkg - (struct razor_package *) set->packages.data;
1.1793 - r = list_next(r);
1.1794 - }
1.1795 - }
1.1796 -
1.1797 - prop_end = set->properties.data + set->properties.size;
1.1798 - a = pkgs;
1.1799 - for (prop = set->properties.data; prop < prop_end; prop++, a++) {
1.1800 - list_set_array(&prop->packages, &set->package_pool, a, 0);
1.1801 - array_release(a);
1.1802 - }
1.1803 - free(pkgs);
1.1804 -}
1.1805 -
1.1806 -static void
1.1807 -rebuild_file_package_lists(struct razor_set *set)
1.1808 -{
1.1809 - struct array *pkgs, *a;
1.1810 - struct razor_package *pkg, *pkg_end;
1.1811 - struct razor_entry *entry, *entry_end;
1.1812 - struct list *r;
1.1813 - uint32_t *q;
1.1814 - int count;
1.1815 -
1.1816 - count = set->files.size / sizeof (struct razor_entry);
1.1817 - pkgs = zalloc(count * sizeof *pkgs);
1.1818 - pkg_end = set->packages.data + set->packages.size;
1.1819 -
1.1820 - for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
1.1821 - r = list_first(&pkg->files, &set->file_pool);
1.1822 - while (r) {
1.1823 - q = array_add(&pkgs[r->data], sizeof *q);
1.1824 - *q = pkg - (struct razor_package *) set->packages.data;
1.1825 - r = list_next(r);
1.1826 - }
1.1827 - }
1.1828 -
1.1829 - entry_end = set->files.data + set->files.size;
1.1830 - a = pkgs;
1.1831 - for (entry = set->files.data; entry < entry_end; entry++, a++) {
1.1832 - list_set_array(&entry->packages, &set->package_pool, a, 0);
1.1833 - array_release(a);
1.1834 - }
1.1835 - free(pkgs);
1.1836 -}
1.1837 -
1.1838 -static struct razor_set *
1.1839 -razor_merger_finish(struct razor_merger *merger)
1.1840 -{
1.1841 - struct razor_set *result;
1.1842 - struct razor_package *p, *pend;
1.1843 -
1.1844 - /* As we built the package list, we filled out a bitvector of
1.1845 - * the properties that are referenced by the packages in the
1.1846 - * new set. Now we do a parallel loop through the properties
1.1847 - * and emit those marked in the bit vector to the new set. In
1.1848 - * the process, we update the bit vector to actually map from
1.1849 - * indices in the old property list to indices in the new
1.1850 - * property list for both sets. */
1.1851 -
1.1852 - merge_properties(merger);
1.1853 - merge_files(merger);
1.1854 -
1.1855 - /* Now we loop through the packages again and emit the
1.1856 - * property lists, remapped to point to the new properties. */
1.1857 -
1.1858 - pend = merger->set->packages.data + merger->set->packages.size;
1.1859 - for (p = merger->set->packages.data; p < pend; p++) {
1.1860 - struct source *src;
1.1861 -
1.1862 - if (p->flags & UPSTREAM_SOURCE)
1.1863 - src = &merger->source2;
1.1864 - else
1.1865 - src = &merger->source1;
1.1866 -
1.1867 - emit_properties(&p->properties,
1.1868 - &src->set->property_pool,
1.1869 - src->property_map,
1.1870 - &merger->set->property_pool);
1.1871 - emit_files(&p->files,
1.1872 - &src->set->file_pool,
1.1873 - src->file_map,
1.1874 - &merger->set->file_pool);
1.1875 - p->flags &= ~UPSTREAM_SOURCE;
1.1876 - }
1.1877 -
1.1878 - rebuild_property_package_lists(merger->set);
1.1879 - rebuild_file_package_lists(merger->set);
1.1880 -
1.1881 - result = merger->set;
1.1882 - hashtable_release(&merger->table);
1.1883 - hashtable_release(&merger->file_table);
1.1884 - hashtable_release(&merger->details_table);
1.1885 - free(merger);
1.1886 -
1.1887 - return result;
1.1888 -}
1.1889 -
1.1890 -/* The diff order matters. We should sort the packages so that a
1.1891 - * REMOVE of a package comes before the INSTALL, and so that all
1.1892 - * requires for a package have been installed before the package.
1.1893 - **/
1.1894 -
1.1895 -void
1.1896 -razor_set_diff(struct razor_set *set, struct razor_set *upstream,
1.1897 - razor_package_callback_t callback, void *data)
1.1898 -{
1.1899 - struct razor_package_iterator *pi1, *pi2;
1.1900 - struct razor_package *p1, *p2;
1.1901 - const char *name1, *name2, *version1, *version2, *arch1, *arch2;
1.1902 - int res;
1.1903 -
1.1904 - pi1 = razor_package_iterator_create(set);
1.1905 - pi2 = razor_package_iterator_create(upstream);
1.1906 -
1.1907 - razor_package_iterator_next(pi1, &p1, &name1, &version1, &arch1);
1.1908 - razor_package_iterator_next(pi2, &p2, &name2, &version2, &arch2);
1.1909 -
1.1910 - while (p1 || p2) {
1.1911 - if (p1 && p2) {
1.1912 - res = strcmp(name1, name2);
1.1913 - if (res == 0)
1.1914 - res = versioncmp(version1, version2);
1.1915 - } else {
1.1916 - res = 0;
1.1917 - }
1.1918 -
1.1919 - if (p2 == NULL || res < 0)
1.1920 - callback(name1, version1, NULL, arch1, data);
1.1921 - else if (p1 == NULL || res > 0)
1.1922 - callback(name2, NULL, version2, arch2, data);
1.1923 -
1.1924 - if (p1 != NULL && res <= 0)
1.1925 - razor_package_iterator_next(pi1, &p1,
1.1926 - &name1, &version1, &arch1);
1.1927 - if (p2 != NULL && res >= 0)
1.1928 - razor_package_iterator_next(pi2, &p2,
1.1929 - &name2, &version2, &arch2);
1.1930 - }
1.1931 -
1.1932 - razor_package_iterator_destroy(pi1);
1.1933 - razor_package_iterator_destroy(pi2);
1.1934 -}
1.1935 -
1.1936 -struct razor_transaction;
1.1937 -struct razor_transaction_package;
1.1938 -struct razor_transaction_resolver;
1.1939 -
1.1940 -struct razor_transaction {
1.1941 - int package_count, errors;
1.1942 - struct razor_set *system, *upstream;
1.1943 -
1.1944 - struct bitarray syspkgs, uppkgs;
1.1945 - struct array packages;
1.1946 -};
1.1947 -
1.1948 -struct razor_transaction_package {
1.1949 - const char *name, *old_version, *new_version;
1.1950 - struct razor_package *old_package, *new_package;
1.1951 - enum razor_transaction_package_state state;
1.1952 -
1.1953 - /* dep_package is the name of the package that resulted in
1.1954 - * this entry being created (or NULL if the user requested the
1.1955 - * install/remove), with the other dep_ fields providing
1.1956 - * additional information.
1.1957 - *
1.1958 - * For INSTALL, if dep_type is REQUIRES, then dep_package
1.1959 - * required something that this package provides. If dep_type
1.1960 - * is CONFLICTS, then dep_package is a package that conflicted
1.1961 - * with an older version of this package, forcing an upgrade.
1.1962 - *
1.1963 - * For REMOVE, if dep_type is REQUIRES, then dep_package is a
1.1964 - * package that is being removed. If dep_type is OBSOLETES,
1.1965 - * then dep_package is a package that obsoletes this one.
1.1966 - *
1.1967 - * For OLD_CONFLICT or NEW_CONFLICT, dep_package is an
1.1968 - * existing package that conflicts with this one. The
1.1969 - * conflicting property comes from the already-installed
1.1970 - * package for OLD_CONFLICT, or the to-be-installed package
1.1971 - * for NEW_CONFLICT.
1.1972 - *
1.1973 - * For UNSATISFIABLE, the dep_ fields are as for an INSTALL,
1.1974 - * but the name field will be NULL.
1.1975 - */
1.1976 - const char *dep_package;
1.1977 - enum razor_property_type dep_type;
1.1978 - const char *dep_property;
1.1979 - enum razor_version_relation dep_relation;
1.1980 - const char *dep_version;
1.1981 -};
1.1982 -
1.1983 -static int
1.1984 -package_in_set(void *package, struct razor_set *set)
1.1985 -{
1.1986 - return package >= set->packages.data &&
1.1987 - package < set->packages.data + set->packages.size;
1.1988 -}
1.1989 -
1.1990 -static int
1.1991 -property_in_set(void *property, struct razor_set *set)
1.1992 -{
1.1993 - return property >= set->properties.data &&
1.1994 - property < set->properties.data + set->properties.size;
1.1995 -}
1.1996 -
1.1997 -static struct razor_package *
1.1998 -property_provider_package(struct razor_transaction *trans,
1.1999 - struct razor_property *prop,
1.2000 - int installed)
1.2001 -{
1.2002 - struct razor_set *set;
1.2003 - struct bitarray *pkgbits;
1.2004 - struct razor_package *pkgs;
1.2005 - struct list *p;
1.2006 -
1.2007 - if (installed && prop->type != RAZOR_PROPERTY_PROVIDES)
1.2008 - return NULL;
1.2009 - else if (!installed &&
1.2010 - prop->type != RAZOR_PROPERTY_PROVIDES &&
1.2011 - prop->type != RAZOR_PROPERTY_OBSOLETES)
1.2012 - return NULL;
1.2013 -
1.2014 - if (property_in_set(prop, trans->system)) {
1.2015 - set = trans->system;
1.2016 - pkgbits = &trans->syspkgs;
1.2017 - } else {
1.2018 - set = trans->upstream;
1.2019 - pkgbits = &trans->uppkgs;
1.2020 - }
1.2021 - pkgs = set->packages.data;
1.2022 -
1.2023 - for (p = list_first(&prop->packages, &set->package_pool); p; p = list_next(p)) {
1.2024 - if (bitarray_get(pkgbits, p->data) != installed)
1.2025 - continue;
1.2026 - if (prop->type == RAZOR_PROPERTY_OBSOLETES ||
1.2027 - pkgs[p->data].name == prop->name)
1.2028 - return &pkgs[p->data];
1.2029 - }
1.2030 - return NULL;
1.2031 -}
1.2032 -
1.2033 -static int
1.2034 -compare_transaction_packages(const void *one, const void *two)
1.2035 -{
1.2036 - struct razor_transaction_package **tp1 = (void *)one;
1.2037 - struct razor_transaction_package **tp2 = (void *)two;
1.2038 -
1.2039 - if (!(*tp1)->name)
1.2040 - return 1;
1.2041 - else if (!(*tp2)->name)
1.2042 - return -1;
1.2043 - else
1.2044 - return strcmp((*tp1)->name, (*tp2)->name);
1.2045 -}
1.2046 -
1.2047 -/* FIXME: merge this into the other property loop in razor_transaction_satisfy */
1.2048 -static void
1.2049 -resolve_new_packages(struct razor_transaction *trans,
1.2050 - int start, int end)
1.2051 -{
1.2052 - struct razor_property *sp, *up, *sp_end, *up_end;
1.2053 - struct razor_package *spkg, *spkgs, *upkg, *upkgs;
1.2054 - struct razor_transaction_package **packages;
1.2055 - const char *spool, *upool;
1.2056 - int i;
1.2057 -
1.2058 - sp_end = trans->system->properties.data + trans->system->properties.size;
1.2059 - spool = trans->system->string_pool.data;
1.2060 - spkgs = trans->system->packages.data;
1.2061 - up_end = trans->upstream->properties.data + trans->upstream->properties.size;
1.2062 - upool = trans->upstream->string_pool.data;
1.2063 - upkgs = trans->upstream->packages.data;
1.2064 -
1.2065 - /* FIXME, check if sorting the packages directly (rather than
1.2066 - * sorting pointers-to-packages) still results in confusing
1.2067 - * descriptions.
1.2068 - */
1.2069 - packages = calloc(end - start, sizeof *packages);
1.2070 - for (i = start; i < end; i++)
1.2071 - packages[i - start] = ((struct razor_transaction_package *)trans->packages.data) + i;
1.2072 - qsort(packages, end - start, sizeof *packages,
1.2073 - compare_transaction_packages);
1.2074 -
1.2075 - sp = trans->system->properties.data;
1.2076 - up = trans->upstream->properties.data;
1.2077 - for (i = 0; i < end - start; i++) {
1.2078 - if (!packages[i]->name ||
1.2079 - packages[i]->state >= RAZOR_PACKAGE_FIRST_ERROR_STATE)
1.2080 - continue;
1.2081 -
1.2082 - spkg = NULL;
1.2083 - while (sp < sp_end &&
1.2084 - strcmp(&spool[sp->name], packages[i]->name) < 0)
1.2085 - sp++;
1.2086 - while (sp < sp_end &&
1.2087 - strcmp(&spool[sp->name], packages[i]->name) == 0 &&
1.2088 - !(spkg = property_provider_package(trans, sp, 1)))
1.2089 - sp++;
1.2090 -
1.2091 - upkg = NULL;
1.2092 - while (up < up_end &&
1.2093 - strcmp(&upool[up->name], packages[i]->name) < 0)
1.2094 - up++;
1.2095 - while (up < up_end &&
1.2096 - strcmp(&upool[up->name], packages[i]->name) == 0 &&
1.2097 - !(upkg = property_provider_package(trans, up, 0)))
1.2098 - up++;
1.2099 -
1.2100 - if (packages[i]->state == RAZOR_PACKAGE_REMOVE ||
1.2101 - packages[i]->state == RAZOR_PACKAGE_OBSOLETED) {
1.2102 - if (spkg) {
1.2103 - packages[i]->old_package = spkg;
1.2104 - packages[i]->name = &spool[spkg->name];
1.2105 - packages[i]->old_version = &spool[spkg->version];
1.2106 - bitarray_set(&trans->syspkgs, spkg - spkgs, 0);
1.2107 - }
1.2108 - if (!packages[i]->old_package) {
1.2109 - packages[i]->name = strdup(packages[i]->name);
1.2110 - packages[i]->state |= RAZOR_PACKAGE_UNAVAILABLE_FLAG;
1.2111 - trans->errors++;
1.2112 - }
1.2113 - } else {
1.2114 - if (upkg) {
1.2115 - packages[i]->new_package = upkg;
1.2116 - packages[i]->name = &upool[upkg->name];
1.2117 - packages[i]->new_version = &upool[upkg->version];
1.2118 -
1.2119 - if (up->name != upkg->name) {
1.2120 - packages[i]->dep_package = &upool[upkg->name];
1.2121 - packages[i]->dep_type = up->type;
1.2122 - packages[i]->dep_property = &upool[up->name];
1.2123 - packages[i]->dep_relation = up->relation;
1.2124 - packages[i]->dep_version = &upool[up->version];
1.2125 - }
1.2126 -
1.2127 - if (spkg) {
1.2128 - packages[i]->old_package = spkg;
1.2129 - packages[i]->old_version = &spool[spkg->version];
1.2130 - if (versioncmp(&spool[spkg->version], &upool[up->version]) >= 0) {
1.2131 - packages[i]->state = RAZOR_PACKAGE_UP_TO_DATE;
1.2132 - trans->errors++;
1.2133 - continue;
1.2134 - }
1.2135 - bitarray_set(&trans->syspkgs, spkg - spkgs, 0);
1.2136 - }
1.2137 - bitarray_set(&trans->uppkgs, upkg - upkgs, 1);
1.2138 - }
1.2139 - if (!packages[i]->new_package) {
1.2140 - packages[i]->name = strdup(packages[i]->name);
1.2141 - packages[i]->state |= RAZOR_PACKAGE_UNAVAILABLE_FLAG;
1.2142 - trans->errors++;
1.2143 - }
1.2144 - }
1.2145 - }
1.2146 -}
1.2147 -
1.2148 -static int
1.2149 -provider_satisfies_requirement(struct razor_property *provider,
1.2150 - const char *provider_strings,
1.2151 - struct razor_property *requirement,
1.2152 - const char *requirement_strings)
1.2153 -{
1.2154 - int cmp, len;
1.2155 - const char *provided = &provider_strings[provider->version];
1.2156 - const char *required = &requirement_strings[requirement->version];
1.2157 -
1.2158 - if (!*required)
1.2159 - return 1;
1.2160 - if (!*provided) {
1.2161 - if (requirement->relation >= RAZOR_VERSION_EQUAL)
1.2162 - return 1;
1.2163 - else
1.2164 - return 0;
1.2165 - }
1.2166 -
1.2167 - cmp = versioncmp(provided, required);
1.2168 -
1.2169 - switch (requirement->relation) {
1.2170 - case RAZOR_VERSION_LESS:
1.2171 - return cmp < 0;
1.2172 -
1.2173 - case RAZOR_VERSION_LESS_OR_EQUAL:
1.2174 - if (cmp <= 0)
1.2175 - return 1;
1.2176 - /* fall through: FIXME, make sure this is correct */
1.2177 -
1.2178 - case RAZOR_VERSION_EQUAL:
1.2179 - if (cmp == 0)
1.2180 - return 1;
1.2181 -
1.2182 - /* "foo == 1.1" is satisfied by "foo 1.1-2" */
1.2183 - len = strlen(required);
1.2184 - if (!strncmp(required, provided, len) && provided[len] == '-')
1.2185 - return 1;
1.2186 - return 0;
1.2187 -
1.2188 - case RAZOR_VERSION_GREATER_OR_EQUAL:
1.2189 - return cmp >= 0;
1.2190 -
1.2191 - case RAZOR_VERSION_GREATER:
1.2192 - return cmp > 0;
1.2193 - }
1.2194 -
1.2195 - /* shouldn't happen */
1.2196 - return 0;
1.2197 -}
1.2198 -
1.2199 -static struct razor_package *
1.2200 -find_package_for_file(struct razor_set *set, struct bitarray *pkgbits,
1.2201 - const char *filename, int installed)
1.2202 -{
1.2203 - struct razor_package *pkgs = set->packages.data;
1.2204 - struct razor_entry *entry;
1.2205 - struct list *p;
1.2206 -
1.2207 - if (filename[0] != '/')
1.2208 - return 0;
1.2209 -
1.2210 - entry = find_entry(set, set->files.data, filename);
1.2211 - if (!entry)
1.2212 - return 0;
1.2213 -
1.2214 - for (p = list_first(&entry->packages, &set->package_pool); p; p = list_next(p)) {
1.2215 - if (bitarray_get(pkgbits, p->data) == installed)
1.2216 - return &pkgs[p->data];
1.2217 - }
1.2218 - return NULL;
1.2219 -}
1.2220 -
1.2221 -static struct razor_package *
1.2222 -find_installed_package_for_file(struct razor_transaction *trans,
1.2223 - const char *filename)
1.2224 -{
1.2225 - struct razor_package *pkg;
1.2226 -
1.2227 - pkg = find_package_for_file(trans->system, &trans->syspkgs,
1.2228 - filename, 1);
1.2229 - if (!pkg)
1.2230 - pkg = find_package_for_file(trans->upstream, &trans->uppkgs,
1.2231 - filename, 1);
1.2232 - return pkg;
1.2233 -}
1.2234 -
1.2235 -static struct razor_package *
1.2236 -find_uninstalled_package_for_file(struct razor_transaction *trans,
1.2237 - const char *filename)
1.2238 -{
1.2239 - struct razor_package *pkg;
1.2240 -
1.2241 - pkg = find_package_for_file(trans->upstream, &trans->uppkgs,
1.2242 - filename, 0);
1.2243 - if (!pkg)
1.2244 - pkg = find_package_for_file(trans->system, &trans->syspkgs,
1.2245 - filename, 0);
1.2246 - return pkg;
1.2247 -}
1.2248 -
1.2249 -static struct razor_property *
1.2250 -skip_to_matching_property(struct razor_transaction *trans,
1.2251 - struct razor_property *match,
1.2252 - struct razor_property *prop)
1.2253 -{
1.2254 - struct razor_set *mset, *pset;
1.2255 - const char *ppool, *mpool;
1.2256 - struct razor_property *prop_end;
1.2257 -
1.2258 - if (property_in_set(match, trans->system))
1.2259 - mset = trans->system;
1.2260 - else
1.2261 - mset = trans->upstream;
1.2262 -
1.2263 - if (property_in_set(prop, trans->system))
1.2264 - pset = trans->system;
1.2265 - else if (property_in_set(prop, trans->upstream))
1.2266 - pset = trans->upstream;
1.2267 - else
1.2268 - return prop;
1.2269 -
1.2270 - prop_end = pset->properties.data + pset->properties.size;
1.2271 - ppool = pset->string_pool.data;
1.2272 - mpool = mset->string_pool.data;
1.2273 -
1.2274 - while (prop < prop_end &&
1.2275 - strcmp(&ppool[prop->name], &mpool[match->name]) < 0)
1.2276 - prop++;
1.2277 - return prop;
1.2278 -}
1.2279 -
1.2280 -static struct razor_package *
1.2281 -find_package_matching(struct razor_transaction *trans, int installed,
1.2282 - struct razor_property *prop,
1.2283 - struct razor_property *req,
1.2284 - struct razor_set *req_set)
1.2285 -{
1.2286 - struct razor_set *set;
1.2287 - struct bitarray *pkgbits;
1.2288 - struct razor_package *pkgs;
1.2289 - struct razor_property *props, *prop_end;
1.2290 - enum razor_property_type match_type;
1.2291 - const char *pool;
1.2292 - const char *rpool;
1.2293 - int match_name = (req->type == RAZOR_PROPERTY_OBSOLETES);
1.2294 - int match;
1.2295 -
1.2296 - if (property_in_set(prop, trans->system)) {
1.2297 - set = trans->system;
1.2298 - pkgbits = &trans->syspkgs;
1.2299 - } else if (property_in_set(prop, trans->upstream)) {
1.2300 - set = trans->upstream;
1.2301 - pkgbits = &trans->uppkgs;
1.2302 - } else
1.2303 - return NULL;
1.2304 -
1.2305 - if (!req_set) {
1.2306 - if (property_in_set(req, trans->system))
1.2307 - req_set = trans->system;
1.2308 - else
1.2309 - req_set = trans->upstream;
1.2310 - }
1.2311 - rpool = req_set->string_pool.data;
1.2312 -
1.2313 - if (req->type == RAZOR_PROPERTY_PROVIDES)
1.2314 - match_type = RAZOR_PROPERTY_CONFLICTS;
1.2315 - else
1.2316 - match_type = RAZOR_PROPERTY_PROVIDES;
1.2317 -
1.2318 - pkgs = set->packages.data;
1.2319 - props = set->properties.data;
1.2320 - prop_end = set->properties.data + set->properties.size;
1.2321 - pool = set->string_pool.data;
1.2322 -
1.2323 - /* Find first matching property */
1.2324 - while (prop < prop_end &&
1.2325 - strcmp(&pool[prop->name], &rpool[req->name]) < 0)
1.2326 - prop++;
1.2327 - if (prop == prop_end ||
1.2328 - strcmp(&pool[prop->name], &rpool[req->name]) > 0)
1.2329 - return NULL;
1.2330 -
1.2331 - if (prop->type < match_type) {
1.2332 - while (prop < prop_end && prop->type != match_type)
1.2333 - prop++;
1.2334 - } else {
1.2335 - while (prop >= props && prop->type != match_type)
1.2336 - prop--;
1.2337 - while (prop > props + 1 && (prop - 1)->name == prop->name &&
1.2338 - (prop - 1)->type == match_type)
1.2339 - prop--;
1.2340 - }
1.2341 -
1.2342 - /* Scan matching properties */
1.2343 - while (prop < prop_end && prop->type == match_type &&
1.2344 - strcmp(&pool[prop->name], &rpool[req->name]) == 0) {
1.2345 - if (match_type == RAZOR_PROPERTY_PROVIDES)
1.2346 - match = provider_satisfies_requirement(prop, pool, req, rpool);
1.2347 - else
1.2348 - match = provider_satisfies_requirement(req, rpool, prop, pool);
1.2349 - if (match) {
1.2350 - struct list *pkg;
1.2351 -
1.2352 - for (pkg = list_first(&prop->packages, &set->package_pool); pkg; pkg = list_next(pkg)) {
1.2353 - if (bitarray_get(pkgbits, pkg->data) != installed)
1.2354 - continue;
1.2355 - if (!match_name ||
1.2356 - strcmp(&pool[pkgs[pkg->data].name],
1.2357 - &rpool[req->name]) == 0)
1.2358 - return &pkgs[pkg->data];
1.2359 - }
1.2360 - }
1.2361 - prop++;
1.2362 - }
1.2363 -
1.2364 - return NULL;
1.2365 -}
1.2366 -
1.2367 -static struct razor_package *
1.2368 -find_installed_package_for_property(struct razor_transaction *trans,
1.2369 - struct razor_property *sys_start,
1.2370 - struct razor_property *up_start,
1.2371 - struct razor_property *req)
1.2372 -{
1.2373 - struct razor_package *pkg;
1.2374 -
1.2375 - pkg = find_package_matching(trans, 1, sys_start, req, NULL);
1.2376 - if (!pkg)
1.2377 - pkg = find_package_matching(trans, 1, up_start, req, NULL);
1.2378 - return pkg;
1.2379 -}
1.2380 -
1.2381 -static struct razor_package *
1.2382 -find_uninstalled_package_for_property(struct razor_transaction *trans,
1.2383 - struct razor_property *sys_start,
1.2384 - struct razor_property *up_start,
1.2385 - struct razor_property *req)
1.2386 -{
1.2387 - struct razor_package *pkg;
1.2388 -
1.2389 - pkg = find_package_matching(trans, 0, up_start, req, NULL);
1.2390 - if (!pkg)
1.2391 - pkg = find_package_matching(trans, 0, sys_start, req, NULL);
1.2392 - return pkg;
1.2393 -}
1.2394 -
1.2395 -static struct razor_transaction_package *
1.2396 -find_transaction_package(struct razor_transaction *trans, const char *name)
1.2397 -{
1.2398 - struct razor_transaction_package *packages;
1.2399 - int count, i;
1.2400 -
1.2401 - packages = trans->packages.data;
1.2402 - count = trans->packages.size / sizeof *packages;
1.2403 - for (i = 0; i < count; i++) {
1.2404 - if (packages[i].name && !strcmp(packages[i].name, name))
1.2405 - return &packages[i];
1.2406 - }
1.2407 - return NULL;
1.2408 -}
1.2409 -
1.2410 -/* FIXME? */
1.2411 -static int
1.2412 -prop_is_being_installed(struct razor_transaction *trans,
1.2413 - struct razor_property *prop)
1.2414 -{
1.2415 - struct list *pkg;
1.2416 -
1.2417 - for (pkg = list_first(&prop->packages, &trans->upstream->package_pool); pkg; pkg = list_next(pkg)) {
1.2418 - if (bitarray_get(&trans->uppkgs, pkg->data))
1.2419 - return 1;
1.2420 - }
1.2421 - return 0;
1.2422 -}
1.2423 -
1.2424 -static int
1.2425 -prop_is_being_removed(struct razor_transaction *trans,
1.2426 - struct razor_property *prop)
1.2427 -{
1.2428 - struct list *pkg;
1.2429 -
1.2430 - for (pkg = list_first(&prop->packages, &trans->system->package_pool); pkg; pkg = list_next(pkg)) {
1.2431 - if (bitarray_get(&trans->syspkgs, pkg->data))
1.2432 - return 0;
1.2433 - }
1.2434 - return 1;
1.2435 -}
1.2436 -
1.2437 -static int
1.2438 -prop_is_being_updated(struct razor_transaction *trans,
1.2439 - struct razor_property *prop)
1.2440 -{
1.2441 - struct razor_package *packages = trans->system->packages.data;
1.2442 - const char *pool = trans->system->string_pool.data;
1.2443 - struct razor_transaction_package *tp;
1.2444 - struct list *pkg;
1.2445 -
1.2446 - /* Assumes prop_is_being_removed returns true */
1.2447 -
1.2448 - for (pkg = list_first(&prop->packages, &trans->system->package_pool); pkg; pkg = list_next(pkg)) {
1.2449 - tp = find_transaction_package(trans, &pool[packages[pkg->data].name]);
1.2450 - if (tp && tp->state == RAZOR_PACKAGE_REMOVE)
1.2451 - return 0;
1.2452 - }
1.2453 - return 1;
1.2454 -}
1.2455 -
1.2456 -static void
1.2457 -add_transaction_package(struct razor_transaction *trans,
1.2458 - struct razor_package *new_package,
1.2459 - struct razor_package *old_package,
1.2460 - enum razor_transaction_package_state state,
1.2461 - const char *req_package,
1.2462 - struct razor_property *req_prop)
1.2463 -{
1.2464 - struct razor_set *new_package_set, *old_package_set, *req_set;
1.2465 - struct bitarray *reqpkgbits;
1.2466 - struct razor_transaction_package *tp, *already;
1.2467 - const char *pool;
1.2468 - struct razor_package *pkgs;
1.2469 - struct list *pkg;
1.2470 - int contradiction = 0;
1.2471 -
1.2472 - if (package_in_set(new_package, trans->system))
1.2473 - new_package_set = trans->system;
1.2474 - else
1.2475 - new_package_set = trans->upstream;
1.2476 - if (package_in_set(old_package, trans->system))
1.2477 - old_package_set = trans->system;
1.2478 - else
1.2479 - old_package_set = trans->upstream;
1.2480 - if (property_in_set(req_prop, trans->system)) {
1.2481 - req_set = trans->system;
1.2482 - reqpkgbits = &trans->syspkgs;
1.2483 - } else {
1.2484 - req_set = trans->upstream;
1.2485 - reqpkgbits = &trans->uppkgs;
1.2486 - }
1.2487 -
1.2488 - if (new_package) {
1.2489 - pool = new_package_set->string_pool.data;
1.2490 - already = find_transaction_package(trans, &pool[new_package->name]);
1.2491 - if (already) {
1.2492 - if (already->new_package == new_package) {
1.2493 - /* Already taken care of */
1.2494 - return;
1.2495 - } else if (new_package_set == trans->upstream &&
1.2496 - already->state == RAZOR_PACKAGE_FORCED_UPDATE) {
1.2497 - already->new_package = new_package;
1.2498 - return;
1.2499 - } else if (new_package_set == trans->upstream) {
1.2500 - return;
1.2501 - }
1.2502 -
1.2503 - /* Oops. We lose */
1.2504 - if (state != RAZOR_PACKAGE_CONTRADICTION)
1.2505 - contradiction = 1;
1.2506 - }
1.2507 - } else if (old_package) {
1.2508 - pool = old_package_set->string_pool.data;
1.2509 - already = find_transaction_package(trans, &pool[old_package->name]);
1.2510 - if (already) {
1.2511 - if (already->old_package == old_package) {
1.2512 - /* Already taken care of */
1.2513 - return;
1.2514 - } else if (old_package_set == trans->system) {
1.2515 - already->old_package = old_package;
1.2516 - return;
1.2517 - }
1.2518 -
1.2519 - /* Oops. We lose */
1.2520 - if (state != RAZOR_PACKAGE_CONTRADICTION)
1.2521 - contradiction = 1;
1.2522 - }
1.2523 - } else
1.2524 - state = RAZOR_PACKAGE_UNSATISFIABLE;
1.2525 -
1.2526 - tp = array_add(&trans->packages, sizeof *tp);
1.2527 - memset(tp, 0, sizeof *tp);
1.2528 -
1.2529 - if (new_package) {
1.2530 - pool = new_package_set->string_pool.data;
1.2531 - tp->new_package = new_package;
1.2532 - tp->name = &pool[new_package->name];
1.2533 - tp->new_version = &pool[new_package->version];
1.2534 -
1.2535 - pkgs = new_package_set->packages.data;
1.2536 - }
1.2537 - if (old_package) {
1.2538 - pool = old_package_set->string_pool.data;
1.2539 - tp->old_package = old_package;
1.2540 - tp->name = &pool[old_package->name];
1.2541 - tp->old_version = &pool[old_package->version];
1.2542 -
1.2543 - pkgs = old_package_set->packages.data;
1.2544 - }
1.2545 -
1.2546 - tp->state = state;
1.2547 - if (state != RAZOR_PACKAGE_INSTALL &&
1.2548 - state != RAZOR_PACKAGE_FORCED_UPDATE &&
1.2549 - state != RAZOR_PACKAGE_REMOVE &&
1.2550 - state != RAZOR_PACKAGE_OBSOLETED)
1.2551 - trans->errors++;
1.2552 -
1.2553 - if (contradiction) {
1.2554 - /* Do this now, after adding tp, so that it ends up
1.2555 - * after both the INSTALL and the REMOVE in the array.
1.2556 - */
1.2557 - add_transaction_package(trans, new_package, old_package,
1.2558 - RAZOR_PACKAGE_CONTRADICTION,
1.2559 - NULL, NULL);
1.2560 - }
1.2561 -
1.2562 - if (req_package)
1.2563 - tp->dep_package = req_package;
1.2564 - if (!req_prop)
1.2565 - return;
1.2566 -
1.2567 - pool = req_set->string_pool.data;
1.2568 - pkgs = req_set->packages.data;
1.2569 - if (!req_package) {
1.2570 - for (pkg = list_first(&req_prop->packages, &req_set->package_pool); pkg; pkg = list_next(pkg)) {
1.2571 - if (bitarray_get(reqpkgbits, pkg->data))
1.2572 - break;
1.2573 - }
1.2574 - if (pkg)
1.2575 - tp->dep_package = &pool[pkgs[pkg->data].name];
1.2576 - }
1.2577 -
1.2578 - tp->dep_type = req_prop->type;
1.2579 - tp->dep_property = &pool[req_prop->name];
1.2580 - tp->dep_relation = req_prop->relation;
1.2581 - tp->dep_version = &pool[req_prop->version];
1.2582 -}
1.2583 -
1.2584 -static void
1.2585 -razor_transaction_satisfy(struct razor_transaction *trans)
1.2586 -{
1.2587 - struct razor_package *spkgs, *upkgs, *pkg;
1.2588 - struct razor_property *sp, *sprops, *sprop_end;
1.2589 - struct razor_property *up, *uprops, *uprop_end;
1.2590 - struct razor_property *sr, *ur, *first_up;
1.2591 - const char *spool, *upool, *removed_package;
1.2592 - struct list *reqpkg;
1.2593 -
1.2594 - spkgs = trans->system->packages.data;
1.2595 - sprops = trans->system->properties.data;
1.2596 - sprop_end = trans->system->properties.data + trans->system->properties.size;
1.2597 - spool = trans->system->string_pool.data;
1.2598 - upkgs = trans->upstream->packages.data;
1.2599 - uprops = trans->upstream->properties.data;
1.2600 - uprop_end = trans->upstream->properties.data + trans->upstream->properties.size;
1.2601 - upool = trans->upstream->string_pool.data;
1.2602 -
1.2603 - sp = sprops;
1.2604 - for (up = uprops; up < uprop_end; up++) {
1.2605 - /* Skip 'up' ahead to a property of a package which is
1.2606 - * to-be-installed.
1.2607 - */
1.2608 - while (up < uprop_end &&
1.2609 - !prop_is_being_installed(trans, up))
1.2610 - up++;
1.2611 - if (up == uprop_end)
1.2612 - break;
1.2613 - sp = skip_to_matching_property(trans, up, sp);
1.2614 -
1.2615 - switch (up->type) {
1.2616 - case RAZOR_PROPERTY_REQUIRES:
1.2617 - if (!strncmp(&upool[up->name], "rpmlib(", 7))
1.2618 - break;
1.2619 -
1.2620 - if (find_installed_package_for_property(trans, sp, up, up) ||
1.2621 - find_installed_package_for_file(trans, &upool[up->name])) {
1.2622 - /* Requires something that is either installed
1.2623 - * or to-be-installed.
1.2624 - */
1.2625 - break;
1.2626 - }
1.2627 -
1.2628 - /* See if we can install a new upstream provider */
1.2629 - pkg = find_uninstalled_package_for_property(trans, sp, up, up);
1.2630 - if (!pkg)
1.2631 - pkg = find_uninstalled_package_for_file(trans, &upool[up->name]);
1.2632 - add_transaction_package(trans, pkg, NULL,
1.2633 - RAZOR_PACKAGE_INSTALL,
1.2634 - NULL, up);
1.2635 - break;
1.2636 -
1.2637 - case RAZOR_PROPERTY_PROVIDES:
1.2638 - /* find_installed_package_for_property works backwards
1.2639 - * here, finding a *conflicting* installed package.
1.2640 - */
1.2641 - pkg = find_installed_package_for_property(trans, sp, up, up);
1.2642 - if (!pkg)
1.2643 - break;
1.2644 -
1.2645 - if (package_in_set(pkg, trans->system)) {
1.2646 - /* pkg CONFLICTS with what 'up' PROVIDES. Try
1.2647 - * finding an upgrade
1.2648 - */
1.2649 - add_transaction_package(trans, NULL, pkg,
1.2650 - RAZOR_PACKAGE_FORCED_UPDATE,
1.2651 - &upool[up->name], sp);
1.2652 - } else {
1.2653 - add_transaction_package(trans, NULL, pkg,
1.2654 - RAZOR_PACKAGE_CONTRADICTION,
1.2655 - NULL, up);
1.2656 - }
1.2657 - break;
1.2658 -
1.2659 - case RAZOR_PROPERTY_CONFLICTS:
1.2660 - pkg = find_installed_package_for_property(trans, sp, up, up);
1.2661 - if (!pkg)
1.2662 - break;
1.2663 -
1.2664 - if (package_in_set(pkg, trans->system)) {
1.2665 - /* Conflicts with something already installed.
1.2666 - * Try to upgrade out.
1.2667 - */
1.2668 - add_transaction_package(trans, NULL, pkg,
1.2669 - RAZOR_PACKAGE_FORCED_UPDATE,
1.2670 - NULL, up);
1.2671 - } else {
1.2672 - add_transaction_package(trans, pkg, NULL,
1.2673 - RAZOR_PACKAGE_CONTRADICTION,
1.2674 - NULL, up);
1.2675 - }
1.2676 - break;
1.2677 -
1.2678 - case RAZOR_PROPERTY_OBSOLETES:
1.2679 - pkg = find_installed_package_for_property(trans, sp, up, up);
1.2680 - if (pkg) {
1.2681 - /* If pkg is to-be-installed, this
1.2682 - * will add a CONTRADICTION error as well.
1.2683 - */
1.2684 - add_transaction_package(trans, NULL, pkg,
1.2685 - RAZOR_PACKAGE_OBSOLETED,
1.2686 - NULL, up);
1.2687 - }
1.2688 - break;
1.2689 -
1.2690 - default:
1.2691 - /* can't happen */
1.2692 - break;
1.2693 - }
1.2694 - }
1.2695 -
1.2696 - up = uprops;
1.2697 - for (sp = sprops; sp < sprop_end; sp++) {
1.2698 - /* Skip 'sp' ahead to a PROVIDES of a package which is
1.2699 - * to-be-removed.
1.2700 - */
1.2701 - while (sp < sprop_end &&
1.2702 - (sp->type != RAZOR_PROPERTY_PROVIDES ||
1.2703 - !prop_is_being_removed(trans, sp)))
1.2704 - sp++;
1.2705 - if (sp == sprop_end)
1.2706 - break;
1.2707 -
1.2708 - removed_package = &spool[spkgs[list_first(&sp->packages, &trans->system->package_pool)->data].name];
1.2709 -
1.2710 - /* Skip 'up' to match */
1.2711 - up = skip_to_matching_property(trans, sp, up);
1.2712 - ur = first_up = up;
1.2713 -
1.2714 - /* If the package is just being upgraded, we may
1.2715 - * already be installing an identical PROVIDES, so
1.2716 - * check for that.
1.2717 - */
1.2718 - while (up < uprop_end &&
1.2719 - strcmp(&spool[sp->name], &upool[up->name]) == 0 &&
1.2720 - (up->type != RAZOR_PROPERTY_PROVIDES ||
1.2721 - sp->relation != up->relation ||
1.2722 - strcmp(&spool[sp->name], &upool[up->name]) != 0))
1.2723 - up++;
1.2724 - if (up < uprop_end &&
1.2725 - up->type == RAZOR_PROPERTY_PROVIDES &&
1.2726 - strcmp(&spool[sp->name], &upool[up->name]) == 0 &&
1.2727 - sp->relation == up->relation &&
1.2728 - strcmp(&spool[sp->version], &upool[up->version]) == 0 &&
1.2729 - prop_is_being_installed(trans, up)) {
1.2730 - up = first_up;
1.2731 - continue;
1.2732 - }
1.2733 - up = first_up;
1.2734 -
1.2735 - /* For all still-installed packages that require
1.2736 - * sp->name, see if they are satisfied by any other
1.2737 - * still-installed or to-be-installed property. If
1.2738 - * not, either remove or attempt to update the
1.2739 - * package, depending on why the required property has
1.2740 - * disappeared
1.2741 - */
1.2742 - sr = sp;
1.2743 - while (sr > sprops + 1 && (sr - 1)->name == sr->name)
1.2744 - sr--;
1.2745 - for (; sr->type == RAZOR_PROPERTY_REQUIRES; sr++) {
1.2746 - if (prop_is_being_removed(trans, sr))
1.2747 - continue;
1.2748 - if (find_installed_package_for_property(trans, sp, up, sr))
1.2749 - continue;
1.2750 -
1.2751 - for (reqpkg = list_first(&sr->packages, &trans->system->package_pool); reqpkg; reqpkg = list_next(reqpkg)) {
1.2752 - if (!bitarray_get(&trans->syspkgs, reqpkg->data))
1.2753 - continue;
1.2754 - pkg = &spkgs[reqpkg->data];
1.2755 - if (prop_is_being_updated(trans, sp)) {
1.2756 - add_transaction_package(trans, NULL, pkg,
1.2757 - RAZOR_PACKAGE_FORCED_UPDATE,
1.2758 - removed_package, NULL);
1.2759 - } else {
1.2760 - add_transaction_package(trans, NULL, pkg,
1.2761 - RAZOR_PACKAGE_REMOVE,
1.2762 - removed_package, sr);
1.2763 - }
1.2764 - }
1.2765 - }
1.2766 - }
1.2767 -}
1.2768 -
1.2769 -void
1.2770 -razor_transaction_install_package(struct razor_transaction *transaction,
1.2771 - struct razor_package *package)
1.2772 -{
1.2773 - add_transaction_package(transaction, package, NULL,
1.2774 - RAZOR_PACKAGE_INSTALL, NULL, NULL);
1.2775 -}
1.2776 -
1.2777 -void
1.2778 -razor_transaction_remove_package(struct razor_transaction *transaction,
1.2779 - struct razor_package *package)
1.2780 -{
1.2781 - add_transaction_package(transaction, NULL, package,
1.2782 - RAZOR_PACKAGE_REMOVE, NULL, NULL);
1.2783 -}
1.2784 -
1.2785 -void
1.2786 -razor_transaction_update_all(struct razor_transaction *trans)
1.2787 -{
1.2788 - struct razor_package *sp, *spkgs, *send, *up, *upkgs, *uend;
1.2789 - const char *spool, *upool;
1.2790 -
1.2791 - spkgs = trans->system->packages.data;
1.2792 - send = trans->system->packages.data + trans->system->packages.size;
1.2793 - spool = trans->system->string_pool.data;
1.2794 - up = upkgs = trans->upstream->packages.data;
1.2795 - uend = trans->upstream->packages.data + trans->upstream->packages.size;
1.2796 - upool = trans->upstream->string_pool.data;
1.2797 -
1.2798 - for (sp = spkgs; sp < send; sp++) {
1.2799 - while (up < uend && strcmp(&spool[sp->name], &upool[up->name]) > 0)
1.2800 - up++;
1.2801 - if (strcmp(&spool[sp->name], &upool[up->name]) == 0 &&
1.2802 - versioncmp(&spool[sp->version], &upool[up->version]) < 0) {
1.2803 - add_transaction_package(trans, up, sp,
1.2804 - RAZOR_PACKAGE_INSTALL,
1.2805 - NULL, NULL);
1.2806 - }
1.2807 - }
1.2808 -}
1.2809 -
1.2810 -struct razor_transaction *
1.2811 -razor_transaction_create(struct razor_set *system, struct razor_set *upstream)
1.2812 -{
1.2813 - struct razor_transaction *trans;
1.2814 - int count;
1.2815 -
1.2816 - trans = zalloc(sizeof *trans);
1.2817 -
1.2818 - trans->system = system;
1.2819 - trans->upstream = upstream ? upstream : razor_set_create();
1.2820 - array_init(&trans->packages);
1.2821 - count = trans->system->packages.size / sizeof (struct razor_package);
1.2822 - bitarray_init(&trans->syspkgs, count, 1);
1.2823 - count = trans->upstream->packages.size / sizeof (struct razor_package);
1.2824 - bitarray_init(&trans->uppkgs, count, 0);
1.2825 -
1.2826 - return trans;
1.2827 -}
1.2828 -
1.2829 -static void
1.2830 -resolve_transaction(struct razor_transaction *trans)
1.2831 -{
1.2832 - int start, end;
1.2833 -
1.2834 - if (trans->package_count > 0)
1.2835 - /* Already did this, return. */
1.2836 - return;
1.2837 -
1.2838 - start = 0;
1.2839 - end = trans->packages.size / sizeof (struct razor_transaction_package);
1.2840 -
1.2841 - while (start != end) {
1.2842 - resolve_new_packages(trans, start, end);
1.2843 - if (trans->errors)
1.2844 - break;
1.2845 -
1.2846 - razor_transaction_satisfy(trans);
1.2847 -
1.2848 - start = end;
1.2849 - end = trans->packages.size / sizeof (struct razor_transaction_package);
1.2850 - }
1.2851 -
1.2852 - trans->package_count = end;
1.2853 -}
1.2854 -
1.2855 -const char * const razor_version_relations[] = {
1.2856 - /* same order as enum razor_version_relation */
1.2857 - "<", "<=", "=", ">=", ">"
1.2858 -};
1.2859 -
1.2860 -const char * const razor_property_types[] = {
1.2861 - /* same order as enum razor_property_type */
1.2862 - "requires", "provides", "conflicts with", "obsoletes"
1.2863 -};
1.2864 -
1.2865 -static void
1.2866 -print_requirement(struct razor_transaction_package *p)
1.2867 -{
1.2868 - if (p->dep_type == RAZOR_PROPERTY_CONFLICTS &&
1.2869 - !strcmp(p->dep_package, p->name)) {
1.2870 - printf(" because %s %s conflicts with %s",
1.2871 - p->name, p->old_version, p->dep_property);
1.2872 - if (*p->dep_version) {
1.2873 - printf(" %s %s",
1.2874 - razor_version_relations[p->dep_relation],
1.2875 - p->dep_version);
1.2876 - }
1.2877 - } else {
1.2878 - if (strcmp(p->name, p->dep_package) != 0)
1.2879 - printf(" for %s", p->dep_package);
1.2880 - if (*p->dep_version) {
1.2881 - printf(", which %s %s %s %s",
1.2882 - razor_property_types[p->dep_type],
1.2883 - p->dep_property,
1.2884 - razor_version_relations[p->dep_relation],
1.2885 - p->dep_version);
1.2886 - } else if (strcmp(p->dep_property, p->name) != 0) {
1.2887 - printf(", which %s %s",
1.2888 - razor_property_types[p->dep_type],
1.2889 - p->dep_property);
1.2890 - }
1.2891 - }
1.2892 -}
1.2893 -
1.2894 -int
1.2895 -razor_transaction_resolve(struct razor_transaction *trans)
1.2896 -{
1.2897 - struct razor_transaction_package *p, *pend, *tps;
1.2898 - int errors_only = 0;
1.2899 -
1.2900 - resolve_transaction(trans);
1.2901 -
1.2902 - tps = trans->packages.data;
1.2903 - pend = trans->packages.data + trans->packages.size;
1.2904 - for (p = trans->packages.data; p < pend; p++) {
1.2905 - switch (p->state) {
1.2906 - case RAZOR_PACKAGE_INSTALL:
1.2907 - if (errors_only)
1.2908 - break;
1.2909 -
1.2910 - printf("Installing %s %s", p->name, p->new_version);
1.2911 - if (p->dep_package)
1.2912 - print_requirement(p);
1.2913 - printf("\n");
1.2914 - break;
1.2915 -
1.2916 - case RAZOR_PACKAGE_FORCED_UPDATE:
1.2917 - if (errors_only)
1.2918 - break;
1.2919 -
1.2920 - printf("Updating %s to %s due to update of %s\n",
1.2921 - p->name, p->new_version, p->dep_package);
1.2922 - break;
1.2923 -
1.2924 - case RAZOR_PACKAGE_REMOVE:
1.2925 - if (errors_only)
1.2926 - break;
1.2927 - printf("Removing %s %s", p->name, p->old_version);
1.2928 - if (p->dep_package) {
1.2929 - printf(" which required %s",
1.2930 - p->dep_package);
1.2931 - if (strcmp(p->dep_property, p->dep_package) != 0)
1.2932 - printf(" for %s", p->dep_property);
1.2933 - }
1.2934 - printf("\n");
1.2935 - break;
1.2936 -
1.2937 - case RAZOR_PACKAGE_OBSOLETED:
1.2938 - if (errors_only)
1.2939 - break;
1.2940 - printf("Removing %s %s", p->name, p->old_version);
1.2941 - if (p->dep_package) {
1.2942 - printf(" which is obsoleted by %s",
1.2943 - p->dep_package);
1.2944 - }
1.2945 - printf("\n");
1.2946 - break;
1.2947 -
1.2948 - case RAZOR_PACKAGE_INSTALL_UNAVAILABLE:
1.2949 - printf("Error: can't find %s", p->name);
1.2950 - if (p->dep_package) {
1.2951 - printf(" (which is required");
1.2952 - print_requirement(p);
1.2953 - printf(")");
1.2954 - }
1.2955 - printf("\n");
1.2956 - errors_only = 1;
1.2957 - break;
1.2958 -
1.2959 - case RAZOR_PACKAGE_UPDATE_UNAVAILABLE:
1.2960 - printf("Error: can't find an updated version of %s (which must be updated due to update of %s)\n",
1.2961 - p->name, p->dep_package);
1.2962 - errors_only = 1;
1.2963 - break;
1.2964 -
1.2965 - case RAZOR_PACKAGE_REMOVE_NOT_INSTALLED:
1.2966 - printf("Error: can't remove %s: not installed\n", p->name);
1.2967 - errors_only = 1;
1.2968 - break;
1.2969 -
1.2970 - case RAZOR_PACKAGE_UP_TO_DATE:
1.2971 - printf("Error: can't update %s", p->name);
1.2972 - if (p->dep_package)
1.2973 - printf(" (which must be updated due to update of %s)", p->dep_package);
1.2974 - printf(": %s is most recent version\n", p->old_version);
1.2975 - errors_only = 1;
1.2976 - break;
1.2977 -
1.2978 - case RAZOR_PACKAGE_CONTRADICTION:
1.2979 - printf("Error: package %s is marked for both installation and removal\n", p->name);
1.2980 - errors_only = 1;
1.2981 - break;
1.2982 -
1.2983 - case RAZOR_PACKAGE_OLD_CONFLICT:
1.2984 - printf("Error: can't install %s, because installed package %s conflicts with ",
1.2985 - p->name, p->dep_package);
1.2986 - if (*p->dep_version) {
1.2987 - printf("%s %s %s",
1.2988 - p->dep_property,
1.2989 - razor_version_relations[p->dep_relation],
1.2990 - p->dep_version);
1.2991 - } else
1.2992 - printf("it");
1.2993 - printf("\n");
1.2994 -
1.2995 - errors_only = 1;
1.2996 - break;
1.2997 -
1.2998 - case RAZOR_PACKAGE_NEW_CONFLICT:
1.2999 - printf("Error: can't install %s, because it conflicts with %s",
1.3000 - p->name, p->dep_package);
1.3001 - if (*p->dep_version) {
1.3002 - printf(" %s %s",
1.3003 - razor_version_relations[p->dep_relation],
1.3004 - p->dep_version);
1.3005 - }
1.3006 - printf("\n");
1.3007 -
1.3008 - errors_only = 1;
1.3009 - break;
1.3010 -
1.3011 - case RAZOR_PACKAGE_UNSATISFIABLE:
1.3012 - printf("Error: can't find package for %s", p->dep_property);
1.3013 - if (*p->dep_version) {
1.3014 - printf(" %s %s",
1.3015 - razor_version_relations[p->dep_relation],
1.3016 - p->dep_version);
1.3017 - }
1.3018 - printf(" which is required by %s\n",
1.3019 - p->dep_package);
1.3020 - errors_only = 1;
1.3021 - break;
1.3022 -
1.3023 - default:
1.3024 - /* Shouldn't actually happen */
1.3025 - break;
1.3026 - }
1.3027 - }
1.3028 -
1.3029 - return trans->errors;
1.3030 -}
1.3031 -
1.3032 -int
1.3033 -razor_transaction_unsatisfied_property(struct razor_transaction *trans,
1.3034 - const char *name,
1.3035 - enum razor_version_relation rel,
1.3036 - const char *version)
1.3037 -{
1.3038 - struct razor_transaction_package *p, *end;
1.3039 -
1.3040 - end = trans->packages.data + trans->packages.size;
1.3041 - for (p = trans->packages.data; p < end; p++) {
1.3042 - if (p->state != RAZOR_PACKAGE_UNSATISFIABLE)
1.3043 - continue;
1.3044 - if (strcmp(name, p->dep_property) != 0 ||
1.3045 - rel != p->dep_relation ||
1.3046 - strcmp(version, p->dep_version) != 0)
1.3047 - continue;
1.3048 -
1.3049 - return 1;
1.3050 - }
1.3051 -
1.3052 - return 0;
1.3053 -}
1.3054 -
1.3055 -struct razor_set *
1.3056 -razor_transaction_finish(struct razor_transaction *trans)
1.3057 -{
1.3058 - struct array install_packages, remove_packages;
1.3059 - struct razor_merger *merger;
1.3060 - struct razor_package *pkg, *i, *iend, *r, *rend, *s, *send;
1.3061 - struct razor_set *set;
1.3062 - struct source *source1, *source2;
1.3063 - char *spool, *ipool, *rpool;
1.3064 - uint32_t *map;
1.3065 - struct razor_transaction_package *p, *end;
1.3066 - int cmp;
1.3067 -
1.3068 - /* FIXME */
1.3069 - if (trans->errors)
1.3070 - return NULL;
1.3071 -
1.3072 - /* Sort the transaction packages into two arrays */
1.3073 - array_init(&install_packages);
1.3074 - array_init(&remove_packages);
1.3075 -
1.3076 - end = trans->packages.data + trans->packages.size;
1.3077 - for (p = trans->packages.data; p < end; p++) {
1.3078 - if (p->new_package) {
1.3079 - pkg = array_add(&install_packages, sizeof *pkg);
1.3080 - *pkg = *p->new_package;
1.3081 - } else {
1.3082 - pkg = array_add(&remove_packages, sizeof *pkg);
1.3083 - *pkg = *p->old_package;
1.3084 - }
1.3085 - }
1.3086 - map = razor_qsort_with_data(install_packages.data,
1.3087 - install_packages.size / sizeof *pkg,
1.3088 - sizeof *pkg,
1.3089 - compare_packages,
1.3090 - trans->upstream);
1.3091 - free(map);
1.3092 - map = razor_qsort_with_data(remove_packages.data,
1.3093 - remove_packages.size / sizeof *pkg,
1.3094 - sizeof *pkg,
1.3095 - compare_packages,
1.3096 - trans->system);
1.3097 - free(map);
1.3098 -
1.3099 - merger = razor_merger_create(trans->system, trans->upstream);
1.3100 -
1.3101 - source1 = &merger->source1;
1.3102 - source2 = &merger->source2;
1.3103 -
1.3104 - i = install_packages.data;
1.3105 - iend = install_packages.data + install_packages.size;
1.3106 - ipool = trans->upstream->string_pool.data;
1.3107 -
1.3108 - r = remove_packages.data;
1.3109 - rend = remove_packages.data + remove_packages.size;
1.3110 - rpool = trans->system->string_pool.data;
1.3111 -
1.3112 - s = trans->system->packages.data;
1.3113 - send = trans->system->packages.data + trans->system->packages.size;
1.3114 - spool = trans->system->string_pool.data;
1.3115 -
1.3116 - while (s < send || i < iend) {
1.3117 - /* Check if s is being removed */
1.3118 - if (s < send && r < rend &&
1.3119 - s->name == r->name && s->version && r->version) {
1.3120 - s++;
1.3121 - r++;
1.3122 - continue;
1.3123 - }
1.3124 -
1.3125 - if (s < send && i < iend)
1.3126 - cmp = strcmp(&spool[s->name], &ipool[i->name]);
1.3127 - else if (s < send)
1.3128 - cmp = -1;
1.3129 - else
1.3130 - cmp = 1;
1.3131 - if (cmp < 0) {
1.3132 - add_package(merger, s, source1, 0);
1.3133 - s++;
1.3134 - } else if (cmp == 0) {
1.3135 - add_package(merger, i, source2, UPSTREAM_SOURCE);
1.3136 - s++;
1.3137 - i++;
1.3138 - } else {
1.3139 - add_package(merger, i, source2, UPSTREAM_SOURCE);
1.3140 - i++;
1.3141 - }
1.3142 - }
1.3143 -
1.3144 - array_release(&install_packages);
1.3145 - array_release(&remove_packages);
1.3146 -
1.3147 - set = razor_merger_finish(merger);
1.3148 - razor_transaction_destroy(trans);
1.3149 -
1.3150 - return set;
1.3151 -}
1.3152 -
1.3153 -void
1.3154 -razor_transaction_destroy(struct razor_transaction *trans)
1.3155 -{
1.3156 - struct razor_transaction_package *p, *end;
1.3157 -
1.3158 - end = trans->packages.data + trans->packages.size;
1.3159 - for (p = trans->packages.data; p < end; p++) {
1.3160 - if (!p->dep_package &&
1.3161 - (p->state == RAZOR_PACKAGE_INSTALL_UNAVAILABLE ||
1.3162 - p->state == RAZOR_PACKAGE_REMOVE_NOT_INSTALLED))
1.3163 - free((char *)p->name);
1.3164 - }
1.3165 -
1.3166 - array_release(&trans->packages);
1.3167 - bitarray_release(&trans->syspkgs);
1.3168 - bitarray_release(&trans->uppkgs);
1.3169 - free(trans);
1.3170 -
1.3171 - /* FIXME: free upstream if it was created as an empty set */
1.3172 -}
1.3173 -
1.3174 -struct razor_package_query {
1.3175 - struct razor_set *set;
1.3176 - char *vector;
1.3177 - int count;
1.3178 -};
1.3179 -
1.3180 -struct razor_package_query *
1.3181 -razor_package_query_create(struct razor_set *set)
1.3182 -{
1.3183 - struct razor_package_query *pq;
1.3184 - int count;
1.3185 -
1.3186 - pq = zalloc(sizeof *pq);
1.3187 - pq->set = set;
1.3188 - count = set->packages.size / sizeof(struct razor_package);
1.3189 - pq->vector = zalloc(count * sizeof(char));
1.3190 -
1.3191 - return pq;
1.3192 -}
1.3193 -
1.3194 -void
1.3195 -razor_package_query_add_package(struct razor_package_query *pq,
1.3196 - struct razor_package *p)
1.3197 -{
1.3198 - struct razor_package *packages;
1.3199 -
1.3200 - packages = pq->set->packages.data;
1.3201 - pq->count += pq->vector[p - packages] ^ 1;
1.3202 - pq->vector[p - packages] = 1;
1.3203 -}
1.3204 -
1.3205 -void
1.3206 -razor_package_query_add_iterator(struct razor_package_query *pq,
1.3207 - struct razor_package_iterator *pi)
1.3208 -{
1.3209 - struct razor_package *packages, *p;
1.3210 - const char *name, *version, *arch;
1.3211 -
1.3212 - packages = pq->set->packages.data;
1.3213 - while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
1.3214 - pq->count += pq->vector[p - packages] ^ 1;
1.3215 - pq->vector[p - packages] = 1;
1.3216 - }
1.3217 -}
1.3218 -
1.3219 -struct razor_package_iterator *
1.3220 -razor_package_query_finish(struct razor_package_query *pq)
1.3221 -{
1.3222 - struct razor_package_iterator *pi;
1.3223 - struct razor_set *set;
1.3224 - struct list *index;
1.3225 - int i, j, count;
1.3226 -
1.3227 - set = pq->set;
1.3228 - count = set->packages.size / sizeof(struct razor_package);
1.3229 - index = zalloc(pq->count * sizeof *index);
1.3230 -
1.3231 - for (i = 0, j = 0; i < count; i++) {
1.3232 - if (!pq->vector[i])
1.3233 - continue;
1.3234 -
1.3235 - index[j].data = i;
1.3236 - if (j == pq->count - 1)
1.3237 - index[j].flags = 0x80;
1.3238 - j++;
1.3239 - }
1.3240 -
1.3241 - free(pq);
1.3242 -
1.3243 - pi = razor_package_iterator_create_with_index(set, index);
1.3244 - pi->free_index = 1;
1.3245 -
1.3246 - return pi;
1.3247 -}