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