Break up the monolithic razor.c.
authorKristian H?gsberg <krh@redhat.com>
Fri Jun 20 15:10:34 2008 -0400 (2008-06-20)
changeset 248057933050c42
parent 247 63444a10fb8e
child 249 061a5b815727
child 258 29d5002bd17f
Break up the monolithic razor.c.
librazor/Makefile.am
librazor/importer.c
librazor/iterator.c
librazor/merger.c
librazor/razor-internal.h
librazor/razor-root.c
librazor/razor.c
librazor/razor.h
librazor/root.c
librazor/transaction.c
librazor/types.c
librazor/types.h
src/.gitignore
     1.1 --- a/librazor/Makefile.am	Fri Jun 20 14:18:52 2008 -0400
     1.2 +++ b/librazor/Makefile.am	Fri Jun 20 15:10:34 2008 -0400
     1.3 @@ -21,11 +21,14 @@
     1.4  	razor-internal.h				\
     1.5  	razor.h						\
     1.6  	razor.c						\
     1.7 -	razor-root.c					\
     1.8 -	types.h						\
     1.9 +	root.c						\
    1.10  	types.c						\
    1.11  	util.c						\
    1.12 -	rpm.c
    1.13 +	rpm.c						\
    1.14 +	iterator.c					\
    1.15 +	importer.c					\
    1.16 +	merger.c					\
    1.17 +	transaction.c
    1.18  
    1.19  librazor_la_LIBADD = $(ZLIB_LIBS)
    1.20  
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/librazor/importer.c	Fri Jun 20 15:10:34 2008 -0400
     2.3 @@ -0,0 +1,488 @@
     2.4 +/*
     2.5 + * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
     2.6 + * Copyright (C) 2008  Red Hat, Inc
     2.7 + *
     2.8 + * This program is free software; you can redistribute it and/or modify
     2.9 + * it under the terms of the GNU General Public License as published by
    2.10 + * the Free Software Foundation; either version 2 of the License, or
    2.11 + * (at your option) any later version.
    2.12 + *
    2.13 + * This program is distributed in the hope that it will be useful,
    2.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.16 + * GNU General Public License for more details.
    2.17 + *
    2.18 + * You should have received a copy of the GNU General Public License along
    2.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
    2.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    2.21 + */
    2.22 +
    2.23 +#define _GNU_SOURCE
    2.24 +
    2.25 +#include <string.h>
    2.26 +#include "razor-internal.h"
    2.27 +#include "razor.h"
    2.28 +
    2.29 +void
    2.30 +razor_importer_begin_package(struct razor_importer *importer,
    2.31 +			     const char *name,
    2.32 +			     const char *version,
    2.33 +			     const char *arch)
    2.34 +{
    2.35 +	struct razor_package *p;
    2.36 +
    2.37 +	p = array_add(&importer->set->packages, sizeof *p);
    2.38 +	p->name = hashtable_tokenize(&importer->table, name);
    2.39 +	p->flags = 0;
    2.40 +	p->version = hashtable_tokenize(&importer->table, version);
    2.41 +	p->arch = hashtable_tokenize(&importer->table, arch);
    2.42 +
    2.43 +	importer->package = p;
    2.44 +	array_init(&importer->properties);
    2.45 +}
    2.46 +
    2.47 +
    2.48 +void
    2.49 +razor_importer_finish_package(struct razor_importer *importer)
    2.50 +{
    2.51 +	list_set_array(&importer->package->properties,
    2.52 +		       &importer->set->property_pool,
    2.53 +		       &importer->properties,
    2.54 +		       1);
    2.55 +
    2.56 +	array_release(&importer->properties);
    2.57 +}
    2.58 +
    2.59 +void
    2.60 +razor_importer_add_property(struct razor_importer *importer,
    2.61 +			    const char *name,
    2.62 +			    uint32_t flags,
    2.63 +			    const char *version)
    2.64 +{
    2.65 +	struct razor_property *p;
    2.66 +	uint32_t *r;
    2.67 +
    2.68 +	p = array_add(&importer->set->properties, sizeof *p);
    2.69 +	p->name = hashtable_tokenize(&importer->table, name);
    2.70 +	p->flags = flags;
    2.71 +	p->version = hashtable_tokenize(&importer->table, version);
    2.72 +	list_set_ptr(&p->packages, importer->package -
    2.73 +		     (struct razor_package *) importer->set->packages.data);
    2.74 +
    2.75 +	r = array_add(&importer->properties, sizeof *r);
    2.76 +	*r = p - (struct razor_property *) importer->set->properties.data;
    2.77 +
    2.78 +	if (((flags & RAZOR_PROPERTY_TYPE_MASK) == RAZOR_PROPERTY_REQUIRES) &&
    2.79 +	    *name == '/') {
    2.80 +		r = array_add(&importer->file_requires, sizeof *r);
    2.81 +		*r = p->name;
    2.82 +	}
    2.83 +}
    2.84 +
    2.85 +void
    2.86 +razor_importer_add_file(struct razor_importer *importer, const char *name)
    2.87 +{
    2.88 +	struct import_entry *e;
    2.89 +
    2.90 +	e = array_add(&importer->files, sizeof *e);
    2.91 +
    2.92 +	e->package = importer->package -
    2.93 +		(struct razor_package *) importer->set->packages.data;
    2.94 +	e->name = strdup(name);
    2.95 +}
    2.96 +
    2.97 +struct razor_importer *
    2.98 +razor_importer_new(void)
    2.99 +{
   2.100 +	struct razor_importer *importer;
   2.101 +
   2.102 +	importer = zalloc(sizeof *importer);
   2.103 +	importer->set = razor_set_create();
   2.104 +	hashtable_init(&importer->table, &importer->set->string_pool);
   2.105 +
   2.106 +	return importer;
   2.107 +}
   2.108 +
   2.109 +/* Destroy an importer without creating the set. */
   2.110 +void
   2.111 +razor_importer_destroy(struct razor_importer *importer)
   2.112 +{
   2.113 +	/* FIXME: write this */
   2.114 +}
   2.115 +
   2.116 +static int
   2.117 +compare_packages(const void *p1, const void *p2, void *data)
   2.118 +{
   2.119 +	const struct razor_package *pkg1 = p1, *pkg2 = p2;
   2.120 +	struct razor_set *set = data;
   2.121 +	char *pool = set->string_pool.data;
   2.122 +
   2.123 +	/* FIXME: what if the flags are different? */
   2.124 +	if (pkg1->name == pkg2->name)
   2.125 +		return razor_versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
   2.126 +	else
   2.127 +		return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
   2.128 +}
   2.129 +
   2.130 +static int
   2.131 +compare_properties(const void *p1, const void *p2, void *data)
   2.132 +{
   2.133 +	const struct razor_property *prop1 = p1, *prop2 = p2;
   2.134 +	struct razor_set *set = data;
   2.135 +	char *pool = set->string_pool.data;
   2.136 +
   2.137 +	if (prop1->name != prop2->name)
   2.138 +		return strcmp(&pool[prop1->name], &pool[prop2->name]);
   2.139 +	else if (prop1->flags != prop2->flags)
   2.140 +		return prop1->flags - prop2->flags;
   2.141 +	else
   2.142 +		return razor_versioncmp(&pool[prop1->version], &pool[prop2->version]);
   2.143 +}
   2.144 +
   2.145 +static uint32_t *
   2.146 +uniqueify_properties(struct razor_set *set)
   2.147 +{
   2.148 +	struct razor_property *rp, *up, *rp_end;
   2.149 +	struct array *pkgs, *p;
   2.150 +	struct list_head *r;
   2.151 +	uint32_t *map, *rmap;
   2.152 +	int i, count, unique;
   2.153 +
   2.154 +	count = set->properties.size / sizeof(struct razor_property);
   2.155 +	map = razor_qsort_with_data(set->properties.data,
   2.156 +				    count,
   2.157 +				    sizeof(struct razor_property),
   2.158 +				    compare_properties,
   2.159 +				    set);
   2.160 +
   2.161 +	rp_end = set->properties.data + set->properties.size;
   2.162 +	rmap = malloc(count * sizeof *map);
   2.163 +	pkgs = zalloc(count * sizeof *pkgs);
   2.164 +	for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
   2.165 +		if (rp->name != up->name ||
   2.166 +		    rp->flags != up->flags ||
   2.167 +		    rp->version != up->version) {
   2.168 +			up++;
   2.169 +			up->name = rp->name;
   2.170 +			up->flags = rp->flags;
   2.171 +			up->version = rp->version;
   2.172 +		}
   2.173 +
   2.174 +		unique = up - (struct razor_property *) set->properties.data;
   2.175 +		rmap[map[i]] = unique;
   2.176 +		r = array_add(&pkgs[unique], sizeof *r);
   2.177 +		*r = rp->packages;
   2.178 +	}
   2.179 +	free(map);
   2.180 +
   2.181 +	if (up != rp)
   2.182 +		up++;
   2.183 +	set->properties.size = (void *) up - set->properties.data;
   2.184 +	rp_end = up;
   2.185 +	for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
   2.186 +		list_set_array(&rp->packages, &set->package_pool, p, 0);
   2.187 +		array_release(p);
   2.188 +	}
   2.189 +
   2.190 +	free(pkgs);
   2.191 +
   2.192 +	return rmap;
   2.193 +}
   2.194 +
   2.195 +static int
   2.196 +compare_filenames(const void *p1, const void *p2, void *data)
   2.197 +{
   2.198 +	const struct import_entry *e1 = p1;
   2.199 +	const struct import_entry *e2 = p2;
   2.200 +	const char *n1 = e1->name;
   2.201 +	const char *n2 = e2->name;
   2.202 +
   2.203 +	/* Need to make sure that the contents of a directory
   2.204 +	 * are sorted immediately after it. So "foo/bar" has to
   2.205 +	 * sort before "foo.conf"
   2.206 +	 *
   2.207 +	 * FIXME: this is about 60% slower than strcmp
   2.208 +	 */
   2.209 +	while (*n1 && *n2) {
   2.210 +		if (*n1 < *n2)
   2.211 +			return *n2 == '/' ? 1 : -1;
   2.212 +		else if (*n1 > *n2)
   2.213 +			return *n1 == '/' ? -1 : 1;
   2.214 +		n1++;
   2.215 +		n2++;
   2.216 +	}
   2.217 +	if (*n1)
   2.218 +		return 1;
   2.219 +	else if (*n2)
   2.220 +		return -1;
   2.221 +	else
   2.222 +		return 0;
   2.223 +}
   2.224 +
   2.225 +static void
   2.226 +count_entries(struct import_directory *d)
   2.227 +{
   2.228 +	struct import_directory *p, *end;
   2.229 +
   2.230 +	p = d->files.data;
   2.231 +	end = d->files.data + d->files.size;
   2.232 +	d->count = 0;
   2.233 +	while (p < end) {
   2.234 +		count_entries(p);
   2.235 +		d->count += p->count + 1;
   2.236 +		p++;
   2.237 +	}
   2.238 +}
   2.239 +
   2.240 +static void
   2.241 +serialize_files(struct razor_set *set,
   2.242 +		struct import_directory *d, struct array *array)
   2.243 +{
   2.244 +	struct import_directory *p, *end;
   2.245 +	struct razor_entry *e = NULL;
   2.246 +	uint32_t s;
   2.247 +
   2.248 +	p = d->files.data;
   2.249 +	end = d->files.data + d->files.size;
   2.250 +	s = array->size / sizeof *e + d->files.size / sizeof *p;
   2.251 +	while (p < end) {
   2.252 +		e = array_add(array, sizeof *e);
   2.253 +		e->name = p->name;
   2.254 +		e->flags = 0;
   2.255 +		e->start = p->count > 0 ? s : 0;
   2.256 +		s += p->count;
   2.257 +
   2.258 +		list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
   2.259 +		array_release(&p->packages);
   2.260 +		p++;
   2.261 +	}
   2.262 +	if (e != NULL)
   2.263 +		e->flags |= RAZOR_ENTRY_LAST;
   2.264 +
   2.265 +	p = d->files.data;
   2.266 +	end = d->files.data + d->files.size;
   2.267 +	while (p < end) {
   2.268 +		serialize_files(set, p, array);
   2.269 +		p++;
   2.270 +	}
   2.271 +}
   2.272 +
   2.273 +static void
   2.274 +remap_property_package_links(struct array *properties, uint32_t *rmap)
   2.275 +{
   2.276 +	struct razor_property *p, *end;
   2.277 +
   2.278 +	end = properties->data + properties->size;
   2.279 +	for (p = properties->data; p < end; p++)
   2.280 +		list_remap_head(&p->packages, rmap);
   2.281 +}
   2.282 +
   2.283 +static void
   2.284 +build_file_tree(struct razor_importer *importer)
   2.285 +{
   2.286 +	int count, i, length;
   2.287 +	struct import_entry *filenames;
   2.288 +	char *f, *end;
   2.289 +	uint32_t name, *r;
   2.290 +	char dirname[256];
   2.291 +	struct import_directory *d, root;
   2.292 +	struct razor_entry *e;
   2.293 +
   2.294 +	count = importer->files.size / sizeof (struct import_entry);
   2.295 +	razor_qsort_with_data(importer->files.data,
   2.296 +			      count,
   2.297 +			      sizeof (struct import_entry),
   2.298 +			      compare_filenames,
   2.299 +			      NULL);
   2.300 +
   2.301 +	root.name = hashtable_tokenize(&importer->table, "");
   2.302 +	array_init(&root.files);
   2.303 +	array_init(&root.packages);
   2.304 +	root.last = NULL;
   2.305 +
   2.306 +	filenames = importer->files.data;
   2.307 +	for (i = 0; i < count; i++) {
   2.308 +		f = filenames[i].name;
   2.309 +		if (*f != '/')
   2.310 +			continue;
   2.311 +		f++;
   2.312 +
   2.313 +		d = &root;
   2.314 +		while (*f) {
   2.315 +			end = strchr(f, '/');
   2.316 +			if (end == NULL)
   2.317 +				end = f + strlen(f);
   2.318 +			length = end - f;
   2.319 +			memcpy(dirname, f, length);
   2.320 +			dirname[length] ='\0';
   2.321 +			name = hashtable_tokenize(&importer->table, dirname);
   2.322 +			if (d->last == NULL || d->last->name != name) {
   2.323 +				d->last = array_add(&d->files, sizeof *d);
   2.324 +				d->last->name = name;
   2.325 +				d->last->last = NULL;
   2.326 +				array_init(&d->last->files);
   2.327 +				array_init(&d->last->packages);
   2.328 +			}
   2.329 +			d = d->last;
   2.330 +			f = end + 1;
   2.331 +			if (*end == '\0')
   2.332 +				break;
   2.333 +		}
   2.334 +
   2.335 +		r = array_add(&d->packages, sizeof *r);
   2.336 +		*r = filenames[i].package;
   2.337 +		free(filenames[i].name);
   2.338 +	}
   2.339 +
   2.340 +	count_entries(&root);
   2.341 +	e = importer->set->files.data;
   2.342 +	e->name = root.name;
   2.343 +	e->flags = RAZOR_ENTRY_LAST;
   2.344 +	e->start = importer->files.size ? 1 : 0;
   2.345 +	list_set_empty(&e->packages);
   2.346 +
   2.347 +	serialize_files(importer->set, &root, &importer->set->files);
   2.348 +
   2.349 +	array_release(&importer->files);
   2.350 +}
   2.351 +
   2.352 +static void
   2.353 +list_to_array(struct list *list, struct array *array)
   2.354 +{
   2.355 +	uint32_t *item;
   2.356 +
   2.357 +	while (list) {
   2.358 +		 item = array_add(array, sizeof *item);
   2.359 +		 *item = list->data;
   2.360 +		 list = list_next(list);
   2.361 +	}
   2.362 +}
   2.363 +
   2.364 +static int
   2.365 +compare_file_requires(const void *p1, const void *p2, void *data)
   2.366 +{
   2.367 +	uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
   2.368 +	const char *pool = data;
   2.369 +
   2.370 +	return strcmp(&pool[*f1], &pool[*f2]);
   2.371 +}
   2.372 +
   2.373 +static void
   2.374 +find_file_provides(struct razor_importer *importer)
   2.375 +{
   2.376 +	struct razor_property *prop;
   2.377 +	struct razor_entry *top, *entry;
   2.378 +	struct razor_package *packages;
   2.379 +	struct array pkgprops;
   2.380 +	struct list *pkg;
   2.381 +	uint32_t *req, *req_start, *req_end;
   2.382 +	uint32_t *map, *newprop;
   2.383 +	char *pool;
   2.384 +
   2.385 +	pool = importer->set->string_pool.data;
   2.386 +	packages = importer->set->packages.data;
   2.387 +	top = importer->set->files.data;
   2.388 +
   2.389 +	req = req_start = importer->file_requires.data;
   2.390 +	req_end = importer->file_requires.data + importer->file_requires.size;
   2.391 +	map = razor_qsort_with_data(req, req_end - req, sizeof *req,
   2.392 +				    compare_file_requires, pool);
   2.393 +	free(map);
   2.394 +
   2.395 +	for (req = req_start; req < req_end; req++) {
   2.396 +		if (req > req_start && req[0] == req[-1])
   2.397 +			continue;
   2.398 +		entry = razor_set_find_entry(importer->set, top, &pool[*req]);
   2.399 +		if (!entry)
   2.400 +			continue;
   2.401 +
   2.402 +		for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
   2.403 +			prop = array_add(&importer->set->properties, sizeof *prop);
   2.404 +			prop->name = *req;
   2.405 +			prop->flags =
   2.406 +				RAZOR_PROPERTY_PROVIDES | RAZOR_PROPERTY_EQUAL;
   2.407 +			prop->version = hashtable_tokenize(&importer->table, "");
   2.408 +			list_set_ptr(&prop->packages, pkg->data);
   2.409 +
   2.410 +			/* Update property list of pkg */
   2.411 +			array_init(&pkgprops);
   2.412 +			list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
   2.413 +			newprop = array_add(&pkgprops, sizeof *newprop);
   2.414 +			*newprop = prop - (struct razor_property *)importer->set->properties.data;
   2.415 +			list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
   2.416 +			array_release(&pkgprops);
   2.417 +		}
   2.418 +	}
   2.419 +
   2.420 +	array_release(&importer->file_requires);
   2.421 +}
   2.422 +
   2.423 +static void
   2.424 +build_package_file_lists(struct razor_set *set, uint32_t *rmap)
   2.425 +{
   2.426 +	struct razor_package *p, *packages;
   2.427 +	struct array *pkgs;
   2.428 +	struct razor_entry *e, *end;
   2.429 +	struct list *r;
   2.430 +	uint32_t *q;
   2.431 +	int i, count;
   2.432 +
   2.433 +	count = set->packages.size / sizeof *p;
   2.434 +	pkgs = zalloc(count * sizeof *pkgs);
   2.435 +
   2.436 +	end = set->files.data + set->files.size;
   2.437 +	for (e = set->files.data; e < end; e++) {
   2.438 +		list_remap_head(&e->packages, rmap);
   2.439 +		r = list_first(&e->packages, &set->package_pool);
   2.440 +		while (r) {
   2.441 +			q = array_add(&pkgs[r->data], sizeof *q);
   2.442 +			*q = e - (struct razor_entry *) set->files.data;
   2.443 +			r = list_next(r);
   2.444 +		}
   2.445 +	}
   2.446 +
   2.447 +	packages = set->packages.data;
   2.448 +	for (i = 0; i < count; i++) {
   2.449 +		list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
   2.450 +		array_release(&pkgs[i]);
   2.451 +	}
   2.452 +	free(pkgs);
   2.453 +}
   2.454 +
   2.455 +struct razor_set *
   2.456 +razor_importer_finish(struct razor_importer *importer)
   2.457 +{
   2.458 +	struct razor_set *set;
   2.459 +	uint32_t *map, *rmap;
   2.460 +	int i, count;
   2.461 +
   2.462 +	build_file_tree(importer);
   2.463 +	find_file_provides(importer);
   2.464 +
   2.465 +	map = uniqueify_properties(importer->set);
   2.466 +	list_remap_pool(&importer->set->property_pool, map);
   2.467 +	free(map);
   2.468 +
   2.469 +	count = importer->set->packages.size / sizeof(struct razor_package);
   2.470 +	map = razor_qsort_with_data(importer->set->packages.data,
   2.471 +				    count,
   2.472 +				    sizeof(struct razor_package),
   2.473 +				    compare_packages,
   2.474 +				    importer->set);
   2.475 +
   2.476 +	rmap = malloc(count * sizeof *rmap);
   2.477 +	for (i = 0; i < count; i++)
   2.478 +		rmap[map[i]] = i;
   2.479 +	free(map);
   2.480 +
   2.481 +	list_remap_pool(&importer->set->package_pool, rmap);
   2.482 +	build_package_file_lists(importer->set, rmap);
   2.483 +	remap_property_package_links(&importer->set->properties, rmap);
   2.484 +	free(rmap);
   2.485 +
   2.486 +	set = importer->set;
   2.487 +	hashtable_release(&importer->table);
   2.488 +	free(importer);
   2.489 +
   2.490 +	return set;
   2.491 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/librazor/iterator.c	Fri Jun 20 15:10:34 2008 -0400
     3.3 @@ -0,0 +1,265 @@
     3.4 +/*
     3.5 + * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
     3.6 + * Copyright (C) 2008  Red Hat, Inc
     3.7 + *
     3.8 + * This program is free software; you can redistribute it and/or modify
     3.9 + * it under the terms of the GNU General Public License as published by
    3.10 + * the Free Software Foundation; either version 2 of the License, or
    3.11 + * (at your option) any later version.
    3.12 + *
    3.13 + * This program is distributed in the hope that it will be useful,
    3.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.16 + * GNU General Public License for more details.
    3.17 + *
    3.18 + * You should have received a copy of the GNU General Public License along
    3.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
    3.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    3.21 + */
    3.22 +
    3.23 +#define _GNU_SOURCE
    3.24 +
    3.25 +#include <string.h>
    3.26 +#include "razor-internal.h"
    3.27 +#include "razor.h"
    3.28 +
    3.29 +static struct razor_package_iterator *
    3.30 +razor_package_iterator_create_with_index(struct razor_set *set,
    3.31 +					 struct list *index)
    3.32 +{
    3.33 +	struct razor_package_iterator *pi;
    3.34 +
    3.35 +	pi = zalloc(sizeof *pi);
    3.36 +	pi->set = set;
    3.37 +	pi->index = index;
    3.38 +
    3.39 +	return pi;
    3.40 +}
    3.41 +
    3.42 +struct razor_package_iterator *
    3.43 +razor_package_iterator_create(struct razor_set *set)
    3.44 +{
    3.45 +	struct razor_package_iterator *pi;
    3.46 +
    3.47 +	pi = zalloc(sizeof *pi);
    3.48 +	pi->set = set;
    3.49 +	pi->end = set->packages.data + set->packages.size;
    3.50 +	pi->package = set->packages.data;
    3.51 +
    3.52 +	return pi;
    3.53 +}
    3.54 +
    3.55 +void
    3.56 +razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
    3.57 +					 struct razor_set *set,
    3.58 +					 struct razor_property *property)
    3.59 +{
    3.60 +	memset(pi, 0, sizeof *pi);
    3.61 +	pi->set = set;
    3.62 +	pi->index = list_first(&property->packages, &set->package_pool);
    3.63 +}
    3.64 +
    3.65 +struct razor_package_iterator *
    3.66 +razor_package_iterator_create_for_property(struct razor_set *set,
    3.67 +					   struct razor_property *property)
    3.68 +{
    3.69 +	struct list *index;
    3.70 +
    3.71 +	index = list_first(&property->packages, &set->package_pool);
    3.72 +	return razor_package_iterator_create_with_index(set, index);
    3.73 +}
    3.74 +
    3.75 +struct razor_package_iterator *
    3.76 +razor_package_iterator_create_for_file(struct razor_set *set,
    3.77 +				       const char *filename)
    3.78 +{
    3.79 +	struct razor_entry *entry;
    3.80 +	struct list *index;
    3.81 +
    3.82 +	entry = razor_set_find_entry(set, set->files.data, filename);
    3.83 +	if (entry == NULL)
    3.84 +		return NULL;
    3.85 +
    3.86 +	index = list_first(&entry->packages, &set->package_pool);
    3.87 +	return razor_package_iterator_create_with_index(set, index);
    3.88 +}
    3.89 +
    3.90 +int
    3.91 +razor_package_iterator_next(struct razor_package_iterator *pi,
    3.92 +			    struct razor_package **package,
    3.93 +			    const char **name,
    3.94 +			    const char **version,
    3.95 +			    const char **arch)
    3.96 +{
    3.97 +	char *pool;
    3.98 +	int valid;
    3.99 +	struct razor_package *p, *packages;
   3.100 +
   3.101 +	if (pi->package) {
   3.102 +		p = pi->package++;
   3.103 +		valid = p < pi->end;
   3.104 +	} else if (pi->index) {
   3.105 +		packages = pi->set->packages.data;
   3.106 +		p = &packages[pi->index->data];
   3.107 +		pi->index = list_next(pi->index);
   3.108 +		valid = 1;
   3.109 +	} else
   3.110 +		valid = 0;
   3.111 +
   3.112 +	if (valid) {
   3.113 +		pool = pi->set->string_pool.data;
   3.114 +		*package = p;
   3.115 +		*name = &pool[p->name];
   3.116 +		*version = &pool[p->version];
   3.117 +		*arch = &pool[p->arch];
   3.118 +	} else {
   3.119 +		*package = NULL;
   3.120 +	}
   3.121 +
   3.122 +	return valid;
   3.123 +}
   3.124 +
   3.125 +void
   3.126 +razor_package_iterator_destroy(struct razor_package_iterator *pi)
   3.127 +{
   3.128 +	if (pi->free_index)
   3.129 +		free(pi->index);
   3.130 +
   3.131 +	free(pi);
   3.132 +}
   3.133 +
   3.134 +struct razor_property_iterator *
   3.135 +razor_property_iterator_create(struct razor_set *set,
   3.136 +			       struct razor_package *package)
   3.137 +{
   3.138 +	struct razor_property_iterator *pi;
   3.139 +
   3.140 +	pi = zalloc(sizeof *pi);
   3.141 +	pi->set = set;
   3.142 +
   3.143 +	if (package) {
   3.144 +		pi->index = list_first(&package->properties,
   3.145 +				       &set->property_pool);
   3.146 +	} else {
   3.147 +		pi->property = set->properties.data;
   3.148 +		pi->end = set->properties.data + set->properties.size;
   3.149 +	}
   3.150 +
   3.151 +	return pi;
   3.152 +}
   3.153 +
   3.154 +int
   3.155 +razor_property_iterator_next(struct razor_property_iterator *pi,
   3.156 +			     struct razor_property **property,
   3.157 +			     const char **name,
   3.158 +			     uint32_t *flags,
   3.159 +			     const char **version)
   3.160 +{
   3.161 +	char *pool;
   3.162 +	int valid;
   3.163 +	struct razor_property *p, *properties;
   3.164 +
   3.165 +	if (pi->property) {
   3.166 +		p = pi->property++;
   3.167 +		valid = p < pi->end;
   3.168 +	} else if (pi->index) {
   3.169 +		properties = pi->set->properties.data;
   3.170 +		p = &properties[pi->index->data];
   3.171 +		pi->index = list_next(pi->index);
   3.172 +		valid = 1;
   3.173 +	} else
   3.174 +		valid = 0;
   3.175 +
   3.176 +	if (valid) {
   3.177 +		pool = pi->set->string_pool.data;
   3.178 +		*property = p;
   3.179 +		*name = &pool[p->name];
   3.180 +		*flags = p->flags;
   3.181 +		*version = &pool[p->version];
   3.182 +	} else {
   3.183 +		*property = NULL;
   3.184 +	}
   3.185 +
   3.186 +	return valid;
   3.187 +}
   3.188 +
   3.189 +void
   3.190 +razor_property_iterator_destroy(struct razor_property_iterator *pi)
   3.191 +{
   3.192 +	free(pi);
   3.193 +}
   3.194 +
   3.195 +struct razor_package_query {
   3.196 +	struct razor_set *set;
   3.197 +	char *vector;
   3.198 +	int count;
   3.199 +};
   3.200 +
   3.201 +struct razor_package_query *
   3.202 +razor_package_query_create(struct razor_set *set)
   3.203 +{
   3.204 +	struct razor_package_query *pq;
   3.205 +	int count;
   3.206 +
   3.207 +	pq = zalloc(sizeof *pq);
   3.208 +	pq->set = set;
   3.209 +	count = set->packages.size / sizeof(struct razor_package);
   3.210 +	pq->vector = zalloc(count * sizeof(char));
   3.211 +
   3.212 +	return pq;
   3.213 +}
   3.214 +
   3.215 +void
   3.216 +razor_package_query_add_package(struct razor_package_query *pq,
   3.217 +				struct razor_package *p)
   3.218 +{
   3.219 +	struct razor_package *packages;
   3.220 +
   3.221 +	packages = pq->set->packages.data;
   3.222 +	pq->count += pq->vector[p - packages] ^ 1;
   3.223 +	pq->vector[p - packages] = 1;
   3.224 +}
   3.225 +
   3.226 +void
   3.227 +razor_package_query_add_iterator(struct razor_package_query *pq,
   3.228 +				 struct razor_package_iterator *pi)
   3.229 +{
   3.230 +	struct razor_package *packages, *p;
   3.231 +	const char *name, *version, *arch;
   3.232 +
   3.233 +	packages = pq->set->packages.data;
   3.234 +	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
   3.235 +		pq->count += pq->vector[p - packages] ^ 1;
   3.236 +		pq->vector[p - packages] = 1;
   3.237 +	}
   3.238 +}
   3.239 +
   3.240 +struct razor_package_iterator *
   3.241 +razor_package_query_finish(struct razor_package_query *pq)
   3.242 +{
   3.243 +	struct razor_package_iterator *pi;
   3.244 +	struct razor_set *set;
   3.245 +	struct list *index;
   3.246 +	int i, j, count;
   3.247 +
   3.248 +	set = pq->set;
   3.249 +	count = set->packages.size / sizeof(struct razor_package);
   3.250 +	index = zalloc(pq->count * sizeof *index);
   3.251 +
   3.252 +	for (i = 0, j = 0; i < count; i++) {
   3.253 +		if (!pq->vector[i])
   3.254 +			continue;
   3.255 +
   3.256 +		index[j].data = i;
   3.257 +		if (j == pq->count - 1)
   3.258 +			index[j].flags = 0x80;
   3.259 +		j++;
   3.260 +	}
   3.261 +
   3.262 +	free(pq);
   3.263 +
   3.264 +	pi = razor_package_iterator_create_with_index(set, index);
   3.265 +	pi->free_index = 1;
   3.266 +
   3.267 +	return pi;
   3.268 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/librazor/merger.c	Fri Jun 20 15:10:34 2008 -0400
     4.3 @@ -0,0 +1,525 @@
     4.4 +/*
     4.5 + * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
     4.6 + * Copyright (C) 2008  Red Hat, Inc
     4.7 + *
     4.8 + * This program is free software; you can redistribute it and/or modify
     4.9 + * it under the terms of the GNU General Public License as published by
    4.10 + * the Free Software Foundation; either version 2 of the License, or
    4.11 + * (at your option) any later version.
    4.12 + *
    4.13 + * This program is distributed in the hope that it will be useful,
    4.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.16 + * GNU General Public License for more details.
    4.17 + *
    4.18 + * You should have received a copy of the GNU General Public License along
    4.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
    4.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    4.21 + */
    4.22 +
    4.23 +#include <string.h>
    4.24 +#include "razor-internal.h"
    4.25 +#include "razor.h"
    4.26 +
    4.27 +#define UPSTREAM_SOURCE 0x80
    4.28 +
    4.29 +struct source {
    4.30 +	struct razor_set *set;
    4.31 +	uint32_t *property_map;
    4.32 +	uint32_t *file_map;
    4.33 +};
    4.34 +
    4.35 +struct razor_merger {
    4.36 +	struct razor_set *set;
    4.37 +	struct hashtable table;
    4.38 +	struct source source1;
    4.39 +	struct source source2;
    4.40 +};
    4.41 +
    4.42 +struct razor_merger *
    4.43 +razor_merger_create(struct razor_set *set1, struct razor_set *set2)
    4.44 +{
    4.45 +	struct razor_merger *merger;
    4.46 +	int count;
    4.47 +	size_t size;
    4.48 +
    4.49 +	merger = zalloc(sizeof *merger);
    4.50 +	merger->set = razor_set_create();
    4.51 +	hashtable_init(&merger->table, &merger->set->string_pool);
    4.52 +
    4.53 +	merger->source1.set = set1;
    4.54 +	count = set1->properties.size / sizeof (struct razor_property);
    4.55 +	size = count * sizeof merger->source1.property_map[0];
    4.56 +	merger->source1.property_map = zalloc(size);
    4.57 +	count = set1->files.size / sizeof (struct razor_entry);
    4.58 +	size = count * sizeof merger->source1.file_map[0];
    4.59 +	merger->source1.file_map = zalloc(size);
    4.60 +
    4.61 +	merger->source2.set = set2;
    4.62 +	count = set2->properties.size / sizeof (struct razor_property);
    4.63 +	size = count * sizeof merger->source2.property_map[0];
    4.64 +	merger->source2.property_map = zalloc(size);
    4.65 +	count = set2->files.size / sizeof (struct razor_entry);
    4.66 +	size = count * sizeof merger->source2.file_map[0];
    4.67 +	merger->source2.file_map = zalloc(size);
    4.68 +
    4.69 +	return merger;
    4.70 +}
    4.71 +
    4.72 +void
    4.73 +razor_merger_add_package(struct razor_merger *merger,
    4.74 +			 struct razor_package *package)
    4.75 +{
    4.76 +	char *pool;
    4.77 +	struct list *r;
    4.78 +	struct razor_package *p;
    4.79 +	struct razor_set *set1;
    4.80 +	struct source *source;
    4.81 +	uint32_t flags;
    4.82 +
    4.83 +	set1 = merger->source1.set;
    4.84 +	if (set1->packages.data <= (void *) package &&
    4.85 +	    (void *) package < set1->packages.data + set1->packages.size) {
    4.86 +		source = &merger->source1;
    4.87 +		flags = 0;
    4.88 +	} else {
    4.89 +		source = &merger->source2;
    4.90 +		flags = UPSTREAM_SOURCE;
    4.91 +	}
    4.92 +
    4.93 +	pool = source->set->string_pool.data;
    4.94 +	p = array_add(&merger->set->packages, sizeof *p);
    4.95 +	p->name = hashtable_tokenize(&merger->table, &pool[package->name]);
    4.96 +	p->flags = flags;
    4.97 +	p->version = hashtable_tokenize(&merger->table,
    4.98 +					&pool[package->version]);
    4.99 +	p->arch = hashtable_tokenize(&merger->table,
   4.100 +				     &pool[package->arch]);
   4.101 +
   4.102 +	p->properties = package->properties;
   4.103 +	r = list_first(&package->properties, &source->set->property_pool);
   4.104 +	while (r) {
   4.105 +		source->property_map[r->data] = 1;
   4.106 +		r = list_next(r);
   4.107 +	}
   4.108 +
   4.109 +	p->files = package->files;
   4.110 +	r = list_first(&package->files, &source->set->file_pool);
   4.111 +	while (r) {
   4.112 +		source->file_map[r->data] = 1;
   4.113 +		r = list_next(r);
   4.114 +	}
   4.115 +}
   4.116 +
   4.117 +static uint32_t
   4.118 +add_property(struct razor_merger *merger,
   4.119 +	     const char *name, uint32_t flags, const char *version)
   4.120 +{
   4.121 +	struct razor_property *p;
   4.122 +
   4.123 +	p = array_add(&merger->set->properties, sizeof *p);
   4.124 +	p->name = hashtable_tokenize(&merger->table, name);
   4.125 +	p->flags = flags;
   4.126 +	p->version = hashtable_tokenize(&merger->table, version);
   4.127 +
   4.128 +	return p - (struct razor_property *) merger->set->properties.data;
   4.129 +}
   4.130 +
   4.131 +static void
   4.132 +merge_properties(struct razor_merger *merger)
   4.133 +{
   4.134 +	struct razor_property *p1, *p2;
   4.135 +	struct razor_set *set1, *set2;
   4.136 +	uint32_t *map1, *map2;
   4.137 +	int i, j, cmp, count1, count2;
   4.138 +	char *pool1, *pool2;
   4.139 +
   4.140 +	set1 = merger->source1.set;
   4.141 +	set2 = merger->source2.set;
   4.142 +	map1 = merger->source1.property_map;
   4.143 +	map2 = merger->source2.property_map;
   4.144 +
   4.145 +	i = 0;
   4.146 +	j = 0;
   4.147 +	pool1 = set1->string_pool.data;
   4.148 +	pool2 = set2->string_pool.data;
   4.149 +
   4.150 +	count1 = set1->properties.size / sizeof *p1;
   4.151 +	count2 = set2->properties.size / sizeof *p2;
   4.152 +	while (i < count1 || j < count2) {
   4.153 +		if (i < count1 && map1[i] == 0) {
   4.154 +			i++;
   4.155 +			continue;
   4.156 +		}
   4.157 +		if (j < count2 && map2[j] == 0) {
   4.158 +			j++;
   4.159 +			continue;
   4.160 +		}
   4.161 +		p1 = (struct razor_property *) set1->properties.data + i;
   4.162 +		p2 = (struct razor_property *) set2->properties.data + j;
   4.163 +		if (i < count1 && j < count2)
   4.164 +			cmp = strcmp(&pool1[p1->name], &pool2[p2->name]);
   4.165 +		else if (i < count1)
   4.166 +			cmp = -1;
   4.167 +		else
   4.168 +			cmp = 1;
   4.169 +		if (cmp == 0)
   4.170 +			cmp = p1->flags - p2->flags;
   4.171 +		if (cmp == 0)
   4.172 +			cmp = razor_versioncmp(&pool1[p1->version],
   4.173 +					       &pool2[p2->version]);
   4.174 +		if (cmp < 0) {
   4.175 +			map1[i++] = add_property(merger,
   4.176 +						 &pool1[p1->name],
   4.177 +						 p1->flags,
   4.178 +						 &pool1[p1->version]);
   4.179 +		} else if (cmp > 0) {
   4.180 +			map2[j++] = add_property(merger,
   4.181 +						 &pool2[p2->name],
   4.182 +						 p2->flags,
   4.183 +						 &pool2[p2->version]);
   4.184 +		} else  {
   4.185 +			map1[i++] = map2[j++] =
   4.186 +				add_property(merger,
   4.187 +					     &pool1[p1->name],
   4.188 +					     p1->flags,
   4.189 +					     &pool1[p1->version]);
   4.190 +		}
   4.191 +	}
   4.192 +}
   4.193 +
   4.194 +static void
   4.195 +emit_properties(struct list_head *properties, struct array *source_pool,
   4.196 +		uint32_t *map, struct array *pool)
   4.197 +{
   4.198 +	uint32_t r;
   4.199 +	struct list *p, *q;
   4.200 +
   4.201 +	r = pool->size / sizeof *q;
   4.202 +	p = list_first(properties, source_pool);
   4.203 +	while (p) {
   4.204 +		q = array_add(pool, sizeof *q);
   4.205 +		q->data = map[p->data];
   4.206 +		q->flags = p->flags;
   4.207 +		p = list_next(p);
   4.208 +	}
   4.209 +
   4.210 +	list_set_ptr(properties, r);
   4.211 +}
   4.212 +
   4.213 +static uint32_t
   4.214 +add_file(struct razor_merger *merger, const char *name)
   4.215 +{
   4.216 +	struct razor_entry *e;
   4.217 +
   4.218 +	e = array_add(&merger->set->files, sizeof *e);
   4.219 +	e->name = hashtable_tokenize(&merger->table, name);
   4.220 +	e->flags = 0;
   4.221 +	e->start = 0;
   4.222 +
   4.223 +	return e - (struct razor_entry *)merger->set->files.data;
   4.224 +}
   4.225 +
   4.226 +/* FIXME. Blah */
   4.227 +static int
   4.228 +fix_file_map(uint32_t *map,
   4.229 +	     struct razor_entry *files,
   4.230 +	     struct razor_entry *top)
   4.231 +{
   4.232 +	uint32_t e;
   4.233 +	int found_file = 0;
   4.234 +
   4.235 +	e = top->start;
   4.236 +	do {
   4.237 +		if (files[e].start)
   4.238 +			fix_file_map(map, files, &files[e]);
   4.239 +		if (map[e])
   4.240 +			found_file = 1;
   4.241 +	} while (!(files[e++].flags & RAZOR_ENTRY_LAST));
   4.242 +
   4.243 +	if (found_file)
   4.244 +		map[top - files] = 1;
   4.245 +	return found_file;
   4.246 +}
   4.247 +
   4.248 +struct merge_directory {
   4.249 +	uint32_t merged, dir1, dir2;
   4.250 +};
   4.251 +
   4.252 +static void
   4.253 +merge_one_directory(struct razor_merger *merger, struct merge_directory *md)
   4.254 +{
   4.255 +	struct razor_entry *root1, *root2, *mroot, *e1, *e2;
   4.256 +	struct razor_set *set1, *set2;
   4.257 +	struct array merge_stack;
   4.258 +	struct merge_directory *child_md, *end_md;
   4.259 +	uint32_t *map1, *map2, start, last;
   4.260 +	int cmp;
   4.261 +	char *pool1, *pool2;
   4.262 +
   4.263 +	set1 = merger->source1.set;
   4.264 +	set2 = merger->source2.set;
   4.265 +	map1 = merger->source1.file_map;
   4.266 +	map2 = merger->source2.file_map;
   4.267 +	pool1 = set1->string_pool.data;
   4.268 +	pool2 = set2->string_pool.data;
   4.269 +	root1 = (struct razor_entry *) set1->files.data;
   4.270 +	root2 = (struct razor_entry *) set2->files.data;
   4.271 +
   4.272 +	array_init(&merge_stack);
   4.273 +
   4.274 +	start = merger->set->files.size / sizeof (struct razor_entry);
   4.275 +	last = 0;
   4.276 +	e1 = md->dir1 ? root1 + md->dir1 : NULL;
   4.277 +	e2 = md->dir2 ? root2 + md->dir2 : NULL;
   4.278 +	while (e1 || e2) {
   4.279 +		if (!e2 && !map1[e1 - root1]) {
   4.280 +			if ((e1++)->flags & RAZOR_ENTRY_LAST)
   4.281 +				e1 = NULL;
   4.282 +			continue;
   4.283 +		}
   4.284 +		if (!e1 && !map2[e2 - root2]) {
   4.285 +			if ((e2++)->flags & RAZOR_ENTRY_LAST)
   4.286 +				e2 = NULL;
   4.287 +			continue;
   4.288 +		}
   4.289 +		if (e1 && !map1[e1 - root1] &&
   4.290 +		    e2 && !map1[e2 - root2]) {
   4.291 +			if ((e1++)->flags & RAZOR_ENTRY_LAST)
   4.292 +				e1 = NULL;
   4.293 +			if ((e2++)->flags & RAZOR_ENTRY_LAST)
   4.294 +				e2 = NULL;
   4.295 +			continue;
   4.296 +		}
   4.297 +
   4.298 +		if (!e1)
   4.299 +			cmp = 1;
   4.300 +		else if (!e2)
   4.301 +			cmp = -1;
   4.302 +		else {
   4.303 +			cmp = strcmp (&pool1[e1->name],
   4.304 +				      &pool2[e2->name]);
   4.305 +		}
   4.306 +
   4.307 +		if (cmp < 0) {
   4.308 +			if (map1[e1 - root1]) {
   4.309 +				map1[e1 - root1] = last =
   4.310 +					add_file(merger, &pool1[e1->name]);
   4.311 +				if (e1->start) {
   4.312 +					child_md = array_add(&merge_stack, sizeof (struct merge_directory));
   4.313 +					child_md->merged = last;
   4.314 +					child_md->dir1 = e1->start;
   4.315 +					child_md->dir2 = 0;
   4.316 +				}
   4.317 +			}
   4.318 +			if ((e1++)->flags & RAZOR_ENTRY_LAST)
   4.319 +				e1 = NULL;
   4.320 +		} else if (cmp > 0) {
   4.321 +			if (map2[e2 - root2]) {
   4.322 +				map2[e2 - root2] = last =
   4.323 +					add_file(merger, &pool2[e2->name]);
   4.324 +				if (e2->start) {
   4.325 +					child_md = array_add(&merge_stack, sizeof (struct merge_directory));
   4.326 +					child_md->merged = last;
   4.327 +					child_md->dir1 = 0;
   4.328 +					child_md->dir2 = e2->start;
   4.329 +				}
   4.330 +			}
   4.331 +			if ((e2++)->flags & RAZOR_ENTRY_LAST)
   4.332 +				e2 = NULL;
   4.333 +		} else {
   4.334 +			map1[e1 - root1] = map2[e2- root2] = last =
   4.335 +				add_file(merger, &pool1[e1->name]);
   4.336 +			if (e1->start || e2->start) {
   4.337 +				child_md = array_add(&merge_stack, sizeof (struct merge_directory));
   4.338 +				child_md->merged = last;
   4.339 +				child_md->dir1 = e1->start;
   4.340 +				child_md->dir2 = e2->start;
   4.341 +			}
   4.342 +			if ((e1++)->flags & RAZOR_ENTRY_LAST)
   4.343 +				e1 = NULL;
   4.344 +			if ((e2++)->flags & RAZOR_ENTRY_LAST)
   4.345 +				e2 = NULL;
   4.346 +		}
   4.347 +	}
   4.348 +
   4.349 +	mroot = (struct razor_entry *)merger->set->files.data;
   4.350 +	if (last) {
   4.351 +		mroot[last].flags = RAZOR_ENTRY_LAST;
   4.352 +		mroot[md->merged].start = start;
   4.353 +	} else
   4.354 +		mroot[md->merged].start = 0;
   4.355 +
   4.356 +	end_md = merge_stack.data + merge_stack.size;
   4.357 +	for (child_md = merge_stack.data; child_md < end_md; child_md++)
   4.358 +		merge_one_directory(merger, child_md);
   4.359 +	array_release(&merge_stack);
   4.360 +}
   4.361 +
   4.362 +static void
   4.363 +merge_files(struct razor_merger *merger)
   4.364 +{
   4.365 +	struct razor_entry *root;
   4.366 +	struct merge_directory md;
   4.367 +	uint32_t *map1, *map2;
   4.368 +
   4.369 +	map1 = merger->source1.file_map;
   4.370 +	map2 = merger->source2.file_map;
   4.371 +
   4.372 +	md.merged = 0;
   4.373 +
   4.374 +	if (merger->source1.set->files.size) {
   4.375 +		root = (struct razor_entry *) merger->source1.set->files.data;
   4.376 +		if (root->start)
   4.377 +			fix_file_map(map1, root, root);
   4.378 +		md.dir1 = root->start;
   4.379 +	} else
   4.380 +		md.dir1 = 0;
   4.381 +
   4.382 +	if (merger->source2.set->files.size) {
   4.383 +		root = (struct razor_entry *) merger->source2.set->files.data;
   4.384 +		if (root->start)
   4.385 +			fix_file_map(map2, root, root);
   4.386 +		md.dir2 = root->start;
   4.387 +	} else
   4.388 +		md.dir2 = 0;
   4.389 +
   4.390 +	merge_one_directory(merger, &md);
   4.391 +}
   4.392 +
   4.393 +static void
   4.394 +emit_files(struct list_head *files, struct array *source_pool,
   4.395 +	   uint32_t *map, struct array *pool)
   4.396 +{
   4.397 +	uint32_t r;
   4.398 +	struct list *p, *q;
   4.399 +
   4.400 +	r = pool->size / sizeof *q;
   4.401 +	p = list_first(files, source_pool);
   4.402 +	while (p) {
   4.403 +		q = array_add(pool, sizeof *q);
   4.404 +		q->data = map[p->data];
   4.405 +		q->flags = p->flags;
   4.406 +		p = list_next(p);
   4.407 +	}
   4.408 +
   4.409 +	list_set_ptr(files, r);
   4.410 +}
   4.411 +
   4.412 +/* Rebuild property->packages maps.  We can't just remap these, as a
   4.413 + * property may have lost or gained a number of packages.  Allocate an
   4.414 + * array per property and loop through the packages and add them to
   4.415 + * the arrays for their properties. */
   4.416 +static void
   4.417 +rebuild_property_package_lists(struct razor_set *set)
   4.418 +{
   4.419 +	struct array *pkgs, *a;
   4.420 +	struct razor_package *pkg, *pkg_end;
   4.421 +	struct razor_property *prop, *prop_end;
   4.422 +	struct list *r;
   4.423 +	uint32_t *q;
   4.424 +	int count;
   4.425 +
   4.426 +	count = set->properties.size / sizeof (struct razor_property);
   4.427 +	pkgs = zalloc(count * sizeof *pkgs);
   4.428 +	pkg_end = set->packages.data + set->packages.size;
   4.429 +
   4.430 +	for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
   4.431 +		r = list_first(&pkg->properties, &set->property_pool);
   4.432 +		while (r) {
   4.433 +			q = array_add(&pkgs[r->data], sizeof *q);
   4.434 +			*q = pkg - (struct razor_package *) set->packages.data;
   4.435 +			r = list_next(r);
   4.436 +		}
   4.437 +	}
   4.438 +
   4.439 +	prop_end = set->properties.data + set->properties.size;
   4.440 +	a = pkgs;
   4.441 +	for (prop = set->properties.data; prop < prop_end; prop++, a++) {
   4.442 +		list_set_array(&prop->packages, &set->package_pool, a, 0);
   4.443 +		array_release(a);
   4.444 +	}
   4.445 +	free(pkgs);
   4.446 +}
   4.447 +
   4.448 +static void
   4.449 +rebuild_file_package_lists(struct razor_set *set)
   4.450 +{
   4.451 +	struct array *pkgs, *a;
   4.452 +	struct razor_package *pkg, *pkg_end;
   4.453 +	struct razor_entry *entry, *entry_end;
   4.454 +	struct list *r;
   4.455 +	uint32_t *q;
   4.456 +	int count;
   4.457 +
   4.458 +	count = set->files.size / sizeof (struct razor_entry);
   4.459 +	pkgs = zalloc(count * sizeof *pkgs);
   4.460 +	pkg_end = set->packages.data + set->packages.size;
   4.461 +
   4.462 +	for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
   4.463 +		r = list_first(&pkg->files, &set->file_pool);
   4.464 +		while (r) {
   4.465 +			q = array_add(&pkgs[r->data], sizeof *q);
   4.466 +			*q = pkg - (struct razor_package *) set->packages.data;
   4.467 +			r = list_next(r);
   4.468 +		}
   4.469 +	}
   4.470 +
   4.471 +	entry_end = set->files.data + set->files.size;
   4.472 +	a = pkgs;
   4.473 +	for (entry = set->files.data; entry < entry_end; entry++, a++) {
   4.474 +		list_set_array(&entry->packages, &set->package_pool, a, 0);
   4.475 +		array_release(a);
   4.476 +	}
   4.477 +	free(pkgs);
   4.478 +}
   4.479 +
   4.480 +struct razor_set *
   4.481 +razor_merger_finish(struct razor_merger *merger)
   4.482 +{
   4.483 +	struct razor_set *result;
   4.484 +	struct razor_package *p, *pend;
   4.485 +
   4.486 +	/* As we built the package list, we filled out a bitvector of
   4.487 +	 * the properties that are referenced by the packages in the
   4.488 +	 * new set.  Now we do a parallel loop through the properties
   4.489 +	 * and emit those marked in the bit vector to the new set.  In
   4.490 +	 * the process, we update the bit vector to actually map from
   4.491 +	 * indices in the old property list to indices in the new
   4.492 +	 * property list for both sets. */
   4.493 +
   4.494 +	merge_properties(merger);
   4.495 +	merge_files(merger);
   4.496 +
   4.497 +	/* Now we loop through the packages again and emit the
   4.498 +	 * property lists, remapped to point to the new properties. */
   4.499 +
   4.500 +	pend = merger->set->packages.data + merger->set->packages.size;
   4.501 +	for (p = merger->set->packages.data; p < pend; p++) {
   4.502 +		struct source *src;
   4.503 +
   4.504 +		if (p->flags & UPSTREAM_SOURCE)
   4.505 +			src = &merger->source2;
   4.506 +		else
   4.507 +			src = &merger->source1;
   4.508 +
   4.509 +		emit_properties(&p->properties,
   4.510 +				&src->set->property_pool,
   4.511 +				src->property_map,
   4.512 +				&merger->set->property_pool);
   4.513 +		emit_files(&p->files,
   4.514 +			   &src->set->file_pool,
   4.515 +			   src->file_map,
   4.516 +			   &merger->set->file_pool);
   4.517 +		p->flags &= ~UPSTREAM_SOURCE;
   4.518 +	}
   4.519 +
   4.520 +	rebuild_property_package_lists(merger->set);
   4.521 +	rebuild_file_package_lists(merger->set);
   4.522 +
   4.523 +	result = merger->set;
   4.524 +	hashtable_release(&merger->table);
   4.525 +	free(merger);
   4.526 +
   4.527 +	return result;
   4.528 +}
     5.1 --- a/librazor/razor-internal.h	Fri Jun 20 14:18:52 2008 -0400
     5.2 +++ b/librazor/razor-internal.h	Fri Jun 20 15:10:34 2008 -0400
     5.3 @@ -1,8 +1,166 @@
     5.4  #ifndef _RAZOR_INTERNAL_H_
     5.5  #define _RAZOR_INTERNAL_H_
     5.6  
     5.7 +#include <stdlib.h>
     5.8 +#include <stdint.h>
     5.9 +
    5.10 +void *zalloc(size_t size);
    5.11 +
    5.12 +struct array {
    5.13 +	void *data;
    5.14 +	int size, alloc;
    5.15 +};
    5.16 +
    5.17 +void array_init(struct array *array);
    5.18 +void array_release(struct array *array);
    5.19 +void *array_add(struct array *array, int size);
    5.20 +
    5.21 +
    5.22 +struct list_head {
    5.23 +	uint32_t list_ptr : 24;
    5.24 +	uint32_t flags    : 8;
    5.25 +};
    5.26 +
    5.27 +struct list {
    5.28 +	uint32_t data  : 24;
    5.29 +	uint32_t flags : 8;
    5.30 +};
    5.31 +
    5.32 +void list_set_empty(struct list_head *head);
    5.33 +void list_set_ptr(struct list_head *head, uint32_t ptr);
    5.34 +void list_set_array(struct list_head *head, struct array *pool, struct array *items, int force_indirect);
    5.35 +
    5.36 +struct list *list_first(struct list_head *head, struct array *pool);
    5.37 +struct list *list_next(struct list *list);
    5.38 +
    5.39 +void list_remap_pool(struct array *pool, uint32_t *map);
    5.40 +void list_remap_head(struct list_head *list, uint32_t *map);
    5.41 +
    5.42 +
    5.43 +struct hashtable {
    5.44 +	struct array buckets;
    5.45 +	struct array *pool;
    5.46 +};
    5.47 +
    5.48 +void hashtable_init(struct hashtable *table, struct array *pool);
    5.49 +void hashtable_release(struct hashtable *table);
    5.50 +uint32_t hashtable_insert(struct hashtable *table, const char *key);
    5.51 +uint32_t hashtable_lookup(struct hashtable *table, const char *key);
    5.52 +uint32_t hashtable_tokenize(struct hashtable *table, const char *string);
    5.53 +
    5.54 +
    5.55 +struct razor_set_section {
    5.56 +	uint32_t type;
    5.57 +	uint32_t offset;
    5.58 +	uint32_t size;
    5.59 +};
    5.60 +
    5.61 +struct razor_set_header {
    5.62 +	uint32_t magic;
    5.63 +	uint32_t version;
    5.64 +	struct razor_set_section sections[0];
    5.65 +};
    5.66 +
    5.67 +#define RAZOR_MAGIC 0x7a7a7a7a
    5.68 +#define RAZOR_VERSION 1
    5.69 +
    5.70 +#define RAZOR_STRING_POOL	0
    5.71 +#define RAZOR_PACKAGES		1
    5.72 +#define RAZOR_PROPERTIES	2
    5.73 +#define RAZOR_FILES		3
    5.74 +#define RAZOR_PACKAGE_POOL	4
    5.75 +#define RAZOR_PROPERTY_POOL	5
    5.76 +#define RAZOR_FILE_POOL		6
    5.77 +
    5.78 +struct razor_package {
    5.79 +	uint32_t name  : 24;
    5.80 +	uint32_t flags : 8;
    5.81 +	uint32_t version;
    5.82 +	uint32_t arch;
    5.83 +	struct list_head properties;
    5.84 +	struct list_head files;
    5.85 +};
    5.86 +
    5.87 +struct razor_property {
    5.88 +	uint32_t name;
    5.89 +	uint32_t flags;
    5.90 +	uint32_t version;
    5.91 +	struct list_head packages;
    5.92 +};
    5.93 +
    5.94 +struct razor_entry {
    5.95 +	uint32_t name  : 24;
    5.96 +	uint32_t flags : 8;
    5.97 +	uint32_t start;
    5.98 +	struct list_head packages;
    5.99 +};
   5.100 +
   5.101 +#define RAZOR_ENTRY_LAST	0x80
   5.102 +
   5.103 +struct razor_set {
   5.104 +	struct array string_pool;
   5.105 + 	struct array packages;
   5.106 + 	struct array properties;
   5.107 + 	struct array files;
   5.108 +	struct array package_pool;
   5.109 + 	struct array property_pool;
   5.110 + 	struct array file_pool;
   5.111 +	struct razor_set_header *header;
   5.112 +};
   5.113 +
   5.114 +struct import_entry {
   5.115 +	uint32_t package;
   5.116 +	char *name;
   5.117 +};
   5.118 +
   5.119 +struct import_directory {
   5.120 +	uint32_t name, count;
   5.121 +	struct array files;
   5.122 +	struct array packages;
   5.123 +	struct import_directory *last;
   5.124 +};
   5.125 +
   5.126 +struct razor_importer {
   5.127 +	struct razor_set *set;
   5.128 +	struct hashtable table;
   5.129 +	struct razor_package *package;
   5.130 +	struct array properties;
   5.131 +	struct array files;
   5.132 +	struct array file_requires;
   5.133 +};
   5.134 +
   5.135 +struct razor_package_iterator {
   5.136 +	struct razor_set *set;
   5.137 +	struct razor_package *package, *end;
   5.138 +	struct list *index;
   5.139 +	int free_index;
   5.140 +};
   5.141 +
   5.142 +void
   5.143 +razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
   5.144 +					 struct razor_set *set,
   5.145 +					 struct razor_property *property);
   5.146 +
   5.147 +struct razor_property_iterator {
   5.148 +	struct razor_set *set;
   5.149 +	struct razor_property *property, *end;
   5.150 +	struct list *index;
   5.151 +};
   5.152 +
   5.153  #define ALIGN(value, base) (((value) + (base - 1)) & ~((base) - 1))
   5.154  
   5.155 +struct razor_entry *
   5.156 +razor_set_find_entry(struct razor_set *set,
   5.157 +		     struct razor_entry *dir, const char *pattern);
   5.158 +
   5.159 +struct razor_merger *
   5.160 +razor_merger_create(struct razor_set *set1, struct razor_set *set2);
   5.161 +void
   5.162 +razor_merger_add_package(struct razor_merger *merger,
   5.163 +			 struct razor_package *package);
   5.164 +struct razor_set *
   5.165 +razor_merger_finish(struct razor_merger *merger);
   5.166 +
   5.167  /* Utility functions */
   5.168  
   5.169  int razor_create_dir(const char *root, const char *path);
     6.1 --- a/librazor/razor-root.c	Fri Jun 20 14:18:52 2008 -0400
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,168 +0,0 @@
     6.4 -#include <stdlib.h>
     6.5 -#include <stdint.h>
     6.6 -#include <stdio.h>
     6.7 -#include <sys/stat.h>
     6.8 -#include <dirent.h>
     6.9 -#include <unistd.h>
    6.10 -#include <fcntl.h>
    6.11 -#include "razor.h"
    6.12 -#include "razor-internal.h"
    6.13 -
    6.14 -static const char system_repo_filename[] = "system.repo";
    6.15 -static const char next_repo_filename[] = "system-next.repo";
    6.16 -static const char razor_root_path[] = "/var/lib/razor";
    6.17 -
    6.18 -struct razor_root {
    6.19 -	struct razor_set *system;
    6.20 -	struct razor_set *next;
    6.21 -	int fd;
    6.22 -	char path[PATH_MAX];
    6.23 -	char new_path[PATH_MAX];
    6.24 -};
    6.25 -
    6.26 -int
    6.27 -razor_root_create(const char *root)
    6.28 -{
    6.29 -	struct stat buf;
    6.30 -	struct razor_set *set;
    6.31 -	char path[PATH_MAX];
    6.32 -
    6.33 -	if (stat(root, &buf) < 0) {
    6.34 -		if (mkdir(root, 0777) < 0) {
    6.35 -			fprintf(stderr,
    6.36 -				"could not create install root \"%s\"\n",
    6.37 -				root);
    6.38 -			return -1;
    6.39 -		}
    6.40 -		fprintf(stderr, "created install root \"%s\"\n", root);
    6.41 -	} else if (!S_ISDIR(buf.st_mode)) {
    6.42 -		fprintf(stderr,
    6.43 -			"install root \"%s\" exists, but is not a directory\n",
    6.44 -			root);
    6.45 -		return -1;
    6.46 -	}
    6.47 -
    6.48 -	snprintf(path, sizeof path, "%s/%s",
    6.49 -		 razor_root_path, system_repo_filename);
    6.50 -	if (razor_create_dir(root, path) < 0) {
    6.51 -		fprintf(stderr, "could not create %s%s\n",
    6.52 -			root, razor_root_path);
    6.53 -		return -1;
    6.54 -	}
    6.55 -
    6.56 -	set = razor_set_create();
    6.57 -	snprintf(path, sizeof path, "%s%s/%s",
    6.58 -		 root, razor_root_path, system_repo_filename);
    6.59 -	if (stat(path, &buf) == 0) {
    6.60 -		fprintf(stderr,
    6.61 -			"a razor install root is already initialized\n");
    6.62 -		return -1;
    6.63 -	}
    6.64 -	if (razor_set_write(set, path) < 0) {
    6.65 -		fprintf(stderr, "could not write initial package set\n");
    6.66 -		return -1;
    6.67 -	}
    6.68 -	razor_set_destroy(set);
    6.69 -
    6.70 -	return 0;
    6.71 -}
    6.72 -
    6.73 -struct razor_root *
    6.74 -razor_root_open(const char *root, int flags)
    6.75 -{
    6.76 -	struct razor_root *image;
    6.77 -
    6.78 -	image = malloc(sizeof *image);
    6.79 -	if (image == NULL)
    6.80 -		return NULL;
    6.81 -
    6.82 -	/* Create the new next repo file up front to ensure exclusive
    6.83 -	 * access. */
    6.84 -	snprintf(image->new_path, sizeof image->new_path,
    6.85 -		 "%s%s/%s", root, razor_root_path, next_repo_filename);
    6.86 -	image->fd = open(image->new_path,
    6.87 -			 O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666);
    6.88 -	if (image->fd < 0) {
    6.89 -		fprintf(stderr, "failed to get lock file, "
    6.90 -			"maybe previous operation crashed?\n");
    6.91 -
    6.92 -		/* FIXME: Use fcntl advisory locking on the system
    6.93 -		 * package set file to figure out whether previous
    6.94 -		 * operation crashed or is still in progress. */
    6.95 -
    6.96 -		free(image);
    6.97 -		return NULL;
    6.98 -	}
    6.99 -
   6.100 -	snprintf(image->path, sizeof image->path,
   6.101 -		 "%s%s/%s", root, razor_root_path, system_repo_filename);
   6.102 -	image->system = razor_set_open(image->path);
   6.103 -	if (image->system == NULL) {
   6.104 -		unlink(image->new_path);
   6.105 -		close(image->fd);
   6.106 -		free(image);
   6.107 -		return NULL;
   6.108 -	}
   6.109 -
   6.110 -	return image;
   6.111 -}
   6.112 -
   6.113 -struct razor_set *
   6.114 -razor_root_open_read_only(const char *root)
   6.115 -{
   6.116 -	char path[PATH_MAX];
   6.117 -
   6.118 -	snprintf(path, sizeof path, "%s%s/%s",
   6.119 -		 root, razor_root_path, system_repo_filename);
   6.120 -
   6.121 -	return razor_set_open(path);
   6.122 -}
   6.123 -
   6.124 -struct razor_transaction *
   6.125 -razor_root_create_transaction(struct razor_root *image,
   6.126 -			      struct razor_set *upstream)
   6.127 -{
   6.128 -	/* FIXME: This should take a number of upstream repos. */
   6.129 -	return razor_transaction_create(image->system, upstream);
   6.130 -}
   6.131 -
   6.132 -int
   6.133 -razor_root_close(struct razor_root *image)
   6.134 -{
   6.135 -	unlink(image->new_path);
   6.136 -	close(image->fd);
   6.137 -	free(image);
   6.138 -
   6.139 -	return 0;
   6.140 -}
   6.141 -
   6.142 -void
   6.143 -razor_root_update(struct razor_root *root, struct razor_set *next)
   6.144 -{
   6.145 -	razor_set_write_to_fd(next, root->fd);
   6.146 -	root->next = next;
   6.147 -
   6.148 -	/* Sync the new repo file so the new package set is on disk
   6.149 -	 * before we start upgrading. */
   6.150 -	fsync(root->fd);
   6.151 -	printf("wrote %s\n", root->new_path);
   6.152 -}
   6.153 -
   6.154 -int
   6.155 -razor_root_commit(struct razor_root *image)
   6.156 -{
   6.157 -	/* Make it so. */
   6.158 -	rename(image->new_path, image->path);
   6.159 -	printf("renamed %s to %s\n", image->new_path, image->path);
   6.160 -	close(image->fd);
   6.161 -	free(image);
   6.162 -
   6.163 -	return 0;
   6.164 -}
   6.165 -
   6.166 -void
   6.167 -razor_root_diff(struct razor_root *root,
   6.168 -		razor_package_callback_t callback, void *data)
   6.169 -{
   6.170 -	return razor_set_diff(root->system, root->next, callback, data);
   6.171 -}
     7.1 --- a/librazor/razor.c	Fri Jun 20 14:18:52 2008 -0400
     7.2 +++ b/librazor/razor.c	Fri Jun 20 15:10:34 2008 -0400
     7.3 @@ -35,89 +35,8 @@
     7.4  
     7.5  #include "razor.h"
     7.6  #include "razor-internal.h"
     7.7 -#include "types.h"
     7.8  
     7.9 -struct razor_set_section {
    7.10 -	uint32_t type;
    7.11 -	uint32_t offset;
    7.12 -	uint32_t size;
    7.13 -};
    7.14 -
    7.15 -struct razor_set_header {
    7.16 -	uint32_t magic;
    7.17 -	uint32_t version;
    7.18 -	struct razor_set_section sections[0];
    7.19 -};
    7.20 -
    7.21 -#define RAZOR_MAGIC 0x7a7a7a7a
    7.22 -#define RAZOR_VERSION 1
    7.23 -
    7.24 -#define RAZOR_STRING_POOL	0
    7.25 -#define RAZOR_PACKAGES		1
    7.26 -#define RAZOR_PROPERTIES	2
    7.27 -#define RAZOR_FILES		3
    7.28 -#define RAZOR_PACKAGE_POOL	4
    7.29 -#define RAZOR_PROPERTY_POOL	5
    7.30 -#define RAZOR_FILE_POOL		6
    7.31 -
    7.32 -struct razor_package {
    7.33 -	uint name  : 24;
    7.34 -	uint flags : 8;
    7.35 -	uint32_t version;
    7.36 -	uint32_t arch;
    7.37 -	struct list_head properties;
    7.38 -	struct list_head files;
    7.39 -};
    7.40 -
    7.41 -struct razor_property {
    7.42 -	uint32_t name;
    7.43 -	uint32_t flags;
    7.44 -	uint32_t version;
    7.45 -	struct list_head packages;
    7.46 -};
    7.47 -
    7.48 -struct razor_entry {
    7.49 -	uint name  : 24;
    7.50 -	uint flags : 8;
    7.51 -	uint32_t start;
    7.52 -	struct list_head packages;
    7.53 -};
    7.54 -
    7.55 -#define RAZOR_ENTRY_LAST	0x80
    7.56 -
    7.57 -struct razor_set {
    7.58 -	struct array string_pool;
    7.59 - 	struct array packages;
    7.60 - 	struct array properties;
    7.61 - 	struct array files;
    7.62 -	struct array package_pool;
    7.63 - 	struct array property_pool;
    7.64 - 	struct array file_pool;
    7.65 -	struct razor_set_header *header;
    7.66 -};
    7.67 -
    7.68 -struct import_entry {
    7.69 -	uint32_t package;
    7.70 -	char *name;
    7.71 -};
    7.72 -
    7.73 -struct import_directory {
    7.74 -	uint32_t name, count;
    7.75 -	struct array files;
    7.76 -	struct array packages;
    7.77 -	struct import_directory *last;
    7.78 -};
    7.79 -
    7.80 -struct razor_importer {
    7.81 -	struct razor_set *set;
    7.82 -	struct hashtable table;
    7.83 -	struct razor_package *package;
    7.84 -	struct array properties;
    7.85 -	struct array files;
    7.86 -	struct array file_requires;
    7.87 -};
    7.88 -
    7.89 -static void *
    7.90 +void *
    7.91  zalloc(size_t size)
    7.92  {
    7.93  	void *p;
    7.94 @@ -296,95 +215,8 @@
    7.95  		snprintf(evr_buf, size, "-%s", release);
    7.96  }
    7.97  
    7.98 -void
    7.99 -razor_importer_begin_package(struct razor_importer *importer,
   7.100 -			     const char *name,
   7.101 -			     const char *version,
   7.102 -			     const char *arch)
   7.103 -{
   7.104 -	struct razor_package *p;
   7.105 -
   7.106 -	p = array_add(&importer->set->packages, sizeof *p);
   7.107 -	p->name = hashtable_tokenize(&importer->table, name);
   7.108 -	p->flags = 0;
   7.109 -	p->version = hashtable_tokenize(&importer->table, version);
   7.110 -	p->arch = hashtable_tokenize(&importer->table, arch);
   7.111 -
   7.112 -	importer->package = p;
   7.113 -	array_init(&importer->properties);
   7.114 -}
   7.115 -
   7.116 -
   7.117 -void
   7.118 -razor_importer_finish_package(struct razor_importer *importer)
   7.119 -{
   7.120 -	list_set_array(&importer->package->properties,
   7.121 -		       &importer->set->property_pool,
   7.122 -		       &importer->properties,
   7.123 -		       1);
   7.124 -
   7.125 -	array_release(&importer->properties);
   7.126 -}
   7.127 -
   7.128 -void
   7.129 -razor_importer_add_property(struct razor_importer *importer,
   7.130 -			    const char *name,
   7.131 -			    uint32_t flags,
   7.132 -			    const char *version)
   7.133 -{
   7.134 -	struct razor_property *p;
   7.135 -	uint32_t *r;
   7.136 -
   7.137 -	p = array_add(&importer->set->properties, sizeof *p);
   7.138 -	p->name = hashtable_tokenize(&importer->table, name);
   7.139 -	p->flags = flags;
   7.140 -	p->version = hashtable_tokenize(&importer->table, version);
   7.141 -	list_set_ptr(&p->packages, importer->package -
   7.142 -		     (struct razor_package *) importer->set->packages.data);
   7.143 -
   7.144 -	r = array_add(&importer->properties, sizeof *r);
   7.145 -	*r = p - (struct razor_property *) importer->set->properties.data;
   7.146 -
   7.147 -	if (((flags & RAZOR_PROPERTY_TYPE_MASK) == RAZOR_PROPERTY_REQUIRES) &&
   7.148 -	    *name == '/') {
   7.149 -		r = array_add(&importer->file_requires, sizeof *r);
   7.150 -		*r = p->name;
   7.151 -	}
   7.152 -}
   7.153 -
   7.154 -void
   7.155 -razor_importer_add_file(struct razor_importer *importer, const char *name)
   7.156 -{
   7.157 -	struct import_entry *e;
   7.158 -
   7.159 -	e = array_add(&importer->files, sizeof *e);
   7.160 -
   7.161 -	e->package = importer->package -
   7.162 -		(struct razor_package *) importer->set->packages.data;
   7.163 -	e->name = strdup(name);
   7.164 -}
   7.165 -
   7.166 -struct razor_importer *
   7.167 -razor_importer_new(void)
   7.168 -{
   7.169 -	struct razor_importer *importer;
   7.170 -
   7.171 -	importer = zalloc(sizeof *importer);
   7.172 -	importer->set = razor_set_create();
   7.173 -	hashtable_init(&importer->table, &importer->set->string_pool);
   7.174 -
   7.175 -	return importer;
   7.176 -}
   7.177 -
   7.178 -/* Destroy an importer without creating the set. */
   7.179 -void
   7.180 -razor_importer_destroy(struct razor_importer *importer)
   7.181 -{
   7.182 -	/* FIXME: write this */
   7.183 -}
   7.184 -
   7.185 -static int
   7.186 -versioncmp(const char *s1, const char *s2)
   7.187 +int
   7.188 +razor_versioncmp(const char *s1, const char *s2)
   7.189  {
   7.190  	const char *p1, *p2;
   7.191  	long n1, n2;
   7.192 @@ -414,489 +246,12 @@
   7.193  		p1++;
   7.194  		p2++;
   7.195  		if (isdigit(*p1) && isdigit(*p2))
   7.196 -			return versioncmp(p1, p2);
   7.197 +			return razor_versioncmp(p1, p2);
   7.198  	}
   7.199  
   7.200  	return *p1 - *p2;
   7.201  }
   7.202  
   7.203 -static int
   7.204 -compare_packages(const void *p1, const void *p2, void *data)
   7.205 -{
   7.206 -	const struct razor_package *pkg1 = p1, *pkg2 = p2;
   7.207 -	struct razor_set *set = data;
   7.208 -	char *pool = set->string_pool.data;
   7.209 -
   7.210 -	/* FIXME: what if the flags are different? */
   7.211 -	if (pkg1->name == pkg2->name)
   7.212 -		return versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
   7.213 -	else
   7.214 -		return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
   7.215 -}
   7.216 -
   7.217 -static int
   7.218 -compare_properties(const void *p1, const void *p2, void *data)
   7.219 -{
   7.220 -	const struct razor_property *prop1 = p1, *prop2 = p2;
   7.221 -	struct razor_set *set = data;
   7.222 -	char *pool = set->string_pool.data;
   7.223 -
   7.224 -	if (prop1->name != prop2->name)
   7.225 -		return strcmp(&pool[prop1->name], &pool[prop2->name]);
   7.226 -	else if (prop1->flags != prop2->flags)
   7.227 -		return prop1->flags - prop2->flags;
   7.228 -	else
   7.229 -		return versioncmp(&pool[prop1->version], &pool[prop2->version]);
   7.230 -}
   7.231 -
   7.232 -static uint32_t *
   7.233 -uniqueify_properties(struct razor_set *set)
   7.234 -{
   7.235 -	struct razor_property *rp, *up, *rp_end;
   7.236 -	struct array *pkgs, *p;
   7.237 -	struct list_head *r;
   7.238 -	uint32_t *map, *rmap;
   7.239 -	int i, count, unique;
   7.240 -
   7.241 -	count = set->properties.size / sizeof(struct razor_property);
   7.242 -	map = razor_qsort_with_data(set->properties.data,
   7.243 -				    count,
   7.244 -				    sizeof(struct razor_property),
   7.245 -				    compare_properties,
   7.246 -				    set);
   7.247 -
   7.248 -	rp_end = set->properties.data + set->properties.size;
   7.249 -	rmap = malloc(count * sizeof *map);
   7.250 -	pkgs = zalloc(count * sizeof *pkgs);
   7.251 -	for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
   7.252 -		if (rp->name != up->name ||
   7.253 -		    rp->flags != up->flags ||
   7.254 -		    rp->version != up->version) {
   7.255 -			up++;
   7.256 -			up->name = rp->name;
   7.257 -			up->flags = rp->flags;
   7.258 -			up->version = rp->version;
   7.259 -		}
   7.260 -
   7.261 -		unique = up - (struct razor_property *) set->properties.data;
   7.262 -		rmap[map[i]] = unique;
   7.263 -		r = array_add(&pkgs[unique], sizeof *r);
   7.264 -		*r = rp->packages;
   7.265 -	}
   7.266 -	free(map);
   7.267 -
   7.268 -	if (up != rp)
   7.269 -		up++;
   7.270 -	set->properties.size = (void *) up - set->properties.data;
   7.271 -	rp_end = up;
   7.272 -	for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
   7.273 -		list_set_array(&rp->packages, &set->package_pool, p, 0);
   7.274 -		array_release(p);
   7.275 -	}
   7.276 -
   7.277 -	free(pkgs);
   7.278 -
   7.279 -	return rmap;
   7.280 -}
   7.281 -
   7.282 -static int
   7.283 -compare_filenames(const void *p1, const void *p2, void *data)
   7.284 -{
   7.285 -	const struct import_entry *e1 = p1;
   7.286 -	const struct import_entry *e2 = p2;
   7.287 -	const char *n1 = e1->name;
   7.288 -	const char *n2 = e2->name;
   7.289 -
   7.290 -	/* Need to make sure that the contents of a directory
   7.291 -	 * are sorted immediately after it. So "foo/bar" has to
   7.292 -	 * sort before "foo.conf"
   7.293 -	 *
   7.294 -	 * FIXME: this is about 60% slower than strcmp
   7.295 -	 */
   7.296 -	while (*n1 && *n2) {
   7.297 -		if (*n1 < *n2)
   7.298 -			return *n2 == '/' ? 1 : -1;
   7.299 -		else if (*n1 > *n2)
   7.300 -			return *n1 == '/' ? -1 : 1;
   7.301 -		n1++;
   7.302 -		n2++;
   7.303 -	}
   7.304 -	if (*n1)
   7.305 -		return 1;
   7.306 -	else if (*n2)
   7.307 -		return -1;
   7.308 -	else
   7.309 -		return 0;
   7.310 -}
   7.311 -
   7.312 -static void
   7.313 -count_entries(struct import_directory *d)
   7.314 -{
   7.315 -	struct import_directory *p, *end;
   7.316 -
   7.317 -	p = d->files.data;
   7.318 -	end = d->files.data + d->files.size;
   7.319 -	d->count = 0;
   7.320 -	while (p < end) {
   7.321 -		count_entries(p);
   7.322 -		d->count += p->count + 1;
   7.323 -		p++;
   7.324 -	}
   7.325 -}
   7.326 -
   7.327 -static void
   7.328 -serialize_files(struct razor_set *set,
   7.329 -		struct import_directory *d, struct array *array)
   7.330 -{
   7.331 -	struct import_directory *p, *end;
   7.332 -	struct razor_entry *e = NULL;
   7.333 -	uint32_t s;
   7.334 -
   7.335 -	p = d->files.data;
   7.336 -	end = d->files.data + d->files.size;
   7.337 -	s = array->size / sizeof *e + d->files.size / sizeof *p;
   7.338 -	while (p < end) {
   7.339 -		e = array_add(array, sizeof *e);
   7.340 -		e->name = p->name;
   7.341 -		e->flags = 0;
   7.342 -		e->start = p->count > 0 ? s : 0;
   7.343 -		s += p->count;
   7.344 -
   7.345 -		list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
   7.346 -		array_release(&p->packages);
   7.347 -		p++;
   7.348 -	}
   7.349 -	if (e != NULL)
   7.350 -		e->flags |= RAZOR_ENTRY_LAST;
   7.351 -
   7.352 -	p = d->files.data;
   7.353 -	end = d->files.data + d->files.size;
   7.354 -	while (p < end) {
   7.355 -		serialize_files(set, p, array);
   7.356 -		p++;
   7.357 -	}
   7.358 -}
   7.359 -
   7.360 -static void
   7.361 -remap_property_package_links(struct array *properties, uint32_t *rmap)
   7.362 -{
   7.363 -	struct razor_property *p, *end;
   7.364 -
   7.365 -	end = properties->data + properties->size;
   7.366 -	for (p = properties->data; p < end; p++)
   7.367 -		list_remap_head(&p->packages, rmap);
   7.368 -}
   7.369 -
   7.370 -static void
   7.371 -build_file_tree(struct razor_importer *importer)
   7.372 -{
   7.373 -	int count, i, length;
   7.374 -	struct import_entry *filenames;
   7.375 -	char *f, *end;
   7.376 -	uint32_t name, *r;
   7.377 -	char dirname[256];
   7.378 -	struct import_directory *d, root;
   7.379 -	struct razor_entry *e;
   7.380 -
   7.381 -	count = importer->files.size / sizeof (struct import_entry);
   7.382 -	razor_qsort_with_data(importer->files.data,
   7.383 -			      count,
   7.384 -			      sizeof (struct import_entry),
   7.385 -			      compare_filenames,
   7.386 -			      NULL);
   7.387 -
   7.388 -	root.name = hashtable_tokenize(&importer->table, "");
   7.389 -	array_init(&root.files);
   7.390 -	array_init(&root.packages);
   7.391 -	root.last = NULL;
   7.392 -
   7.393 -	filenames = importer->files.data;
   7.394 -	for (i = 0; i < count; i++) {
   7.395 -		f = filenames[i].name;
   7.396 -		if (*f != '/')
   7.397 -			continue;
   7.398 -		f++;
   7.399 -
   7.400 -		d = &root;
   7.401 -		while (*f) {
   7.402 -			end = strchr(f, '/');
   7.403 -			if (end == NULL)
   7.404 -				end = f + strlen(f);
   7.405 -			length = end - f;
   7.406 -			memcpy(dirname, f, length);
   7.407 -			dirname[length] ='\0';
   7.408 -			name = hashtable_tokenize(&importer->table, dirname);
   7.409 -			if (d->last == NULL || d->last->name != name) {
   7.410 -				d->last = array_add(&d->files, sizeof *d);
   7.411 -				d->last->name = name;
   7.412 -				d->last->last = NULL;
   7.413 -				array_init(&d->last->files);
   7.414 -				array_init(&d->last->packages);
   7.415 -			}
   7.416 -			d = d->last;
   7.417 -			f = end + 1;
   7.418 -			if (*end == '\0')
   7.419 -				break;
   7.420 -		}
   7.421 -
   7.422 -		r = array_add(&d->packages, sizeof *r);
   7.423 -		*r = filenames[i].package;
   7.424 -		free(filenames[i].name);
   7.425 -	}
   7.426 -
   7.427 -	count_entries(&root);
   7.428 -	e = importer->set->files.data;
   7.429 -	e->name = root.name;
   7.430 -	e->flags = RAZOR_ENTRY_LAST;
   7.431 -	e->start = importer->files.size ? 1 : 0;
   7.432 -	list_set_empty(&e->packages);
   7.433 -
   7.434 -	serialize_files(importer->set, &root, &importer->set->files);
   7.435 -
   7.436 -	array_release(&importer->files);
   7.437 -}
   7.438 -
   7.439 -static struct razor_entry *
   7.440 -find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern);
   7.441 -
   7.442 -static void
   7.443 -list_to_array(struct list *list, struct array *array)
   7.444 -{
   7.445 -	uint32_t *item;
   7.446 -
   7.447 -	while (list) {
   7.448 -		 item = array_add(array, sizeof *item);
   7.449 -		 *item = list->data;
   7.450 -		 list = list_next(list);
   7.451 -	}
   7.452 -}
   7.453 -
   7.454 -static int
   7.455 -compare_file_requires(const void *p1, const void *p2, void *data)
   7.456 -{
   7.457 -	uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
   7.458 -	const char *pool = data;
   7.459 -
   7.460 -	return strcmp(&pool[*f1], &pool[*f2]);
   7.461 -}
   7.462 -
   7.463 -static void
   7.464 -find_file_provides(struct razor_importer *importer)
   7.465 -{
   7.466 -	struct razor_property *prop;
   7.467 -	struct razor_entry *top, *entry;
   7.468 -	struct razor_package *packages;
   7.469 -	struct array pkgprops;
   7.470 -	struct list *pkg;
   7.471 -	uint32_t *req, *req_start, *req_end;
   7.472 -	uint32_t *map, *newprop;
   7.473 -	char *pool;
   7.474 -
   7.475 -	pool = importer->set->string_pool.data;
   7.476 -	packages = importer->set->packages.data;
   7.477 -	top = importer->set->files.data;
   7.478 -
   7.479 -	req = req_start = importer->file_requires.data;
   7.480 -	req_end = importer->file_requires.data + importer->file_requires.size;
   7.481 -	map = razor_qsort_with_data(req, req_end - req, sizeof *req,
   7.482 -				    compare_file_requires, pool);
   7.483 -	free(map);
   7.484 -
   7.485 -	for (req = req_start; req < req_end; req++) {
   7.486 -		if (req > req_start && req[0] == req[-1])
   7.487 -			continue;
   7.488 -		entry = find_entry(importer->set, top, &pool[*req]);
   7.489 -		if (!entry)
   7.490 -			continue;
   7.491 -
   7.492 -		for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
   7.493 -			prop = array_add(&importer->set->properties, sizeof *prop);
   7.494 -			prop->name = *req;
   7.495 -			prop->flags =
   7.496 -				RAZOR_PROPERTY_PROVIDES | RAZOR_PROPERTY_EQUAL;
   7.497 -			prop->version = hashtable_tokenize(&importer->table, "");
   7.498 -			list_set_ptr(&prop->packages, pkg->data);
   7.499 -
   7.500 -			/* Update property list of pkg */
   7.501 -			array_init(&pkgprops);
   7.502 -			list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
   7.503 -			newprop = array_add(&pkgprops, sizeof *newprop);
   7.504 -			*newprop = prop - (struct razor_property *)importer->set->properties.data;
   7.505 -			list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
   7.506 -			array_release(&pkgprops);
   7.507 -		}
   7.508 -	}
   7.509 -
   7.510 -	array_release(&importer->file_requires);
   7.511 -}
   7.512 -
   7.513 -static void
   7.514 -build_package_file_lists(struct razor_set *set, uint32_t *rmap)
   7.515 -{
   7.516 -	struct razor_package *p, *packages;
   7.517 -	struct array *pkgs;
   7.518 -	struct razor_entry *e, *end;
   7.519 -	struct list *r;
   7.520 -	uint32_t *q;
   7.521 -	int i, count;
   7.522 -
   7.523 -	count = set->packages.size / sizeof *p;
   7.524 -	pkgs = zalloc(count * sizeof *pkgs);
   7.525 -
   7.526 -	end = set->files.data + set->files.size;
   7.527 -	for (e = set->files.data; e < end; e++) {
   7.528 -		list_remap_head(&e->packages, rmap);
   7.529 -		r = list_first(&e->packages, &set->package_pool);
   7.530 -		while (r) {
   7.531 -			q = array_add(&pkgs[r->data], sizeof *q);
   7.532 -			*q = e - (struct razor_entry *) set->files.data;
   7.533 -			r = list_next(r);
   7.534 -		}
   7.535 -	}
   7.536 -
   7.537 -	packages = set->packages.data;
   7.538 -	for (i = 0; i < count; i++) {
   7.539 -		list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
   7.540 -		array_release(&pkgs[i]);
   7.541 -	}
   7.542 -	free(pkgs);
   7.543 -}
   7.544 -
   7.545 -struct razor_set *
   7.546 -razor_importer_finish(struct razor_importer *importer)
   7.547 -{
   7.548 -	struct razor_set *set;
   7.549 -	uint32_t *map, *rmap;
   7.550 -	int i, count;
   7.551 -
   7.552 -	build_file_tree(importer);
   7.553 -	find_file_provides(importer);
   7.554 -
   7.555 -	map = uniqueify_properties(importer->set);
   7.556 -	list_remap_pool(&importer->set->property_pool, map);
   7.557 -	free(map);
   7.558 -
   7.559 -	count = importer->set->packages.size / sizeof(struct razor_package);
   7.560 -	map = razor_qsort_with_data(importer->set->packages.data,
   7.561 -				    count,
   7.562 -				    sizeof(struct razor_package),
   7.563 -				    compare_packages,
   7.564 -				    importer->set);
   7.565 -
   7.566 -	rmap = malloc(count * sizeof *rmap);
   7.567 -	for (i = 0; i < count; i++)
   7.568 -		rmap[map[i]] = i;
   7.569 -	free(map);
   7.570 -
   7.571 -	list_remap_pool(&importer->set->package_pool, rmap);
   7.572 -	build_package_file_lists(importer->set, rmap);
   7.573 -	remap_property_package_links(&importer->set->properties, rmap);
   7.574 -	free(rmap);
   7.575 -
   7.576 -	set = importer->set;
   7.577 -	hashtable_release(&importer->table);
   7.578 -	free(importer);
   7.579 -
   7.580 -	return set;
   7.581 -}
   7.582 -
   7.583 -struct razor_package_iterator {
   7.584 -	struct razor_set *set;
   7.585 -	struct razor_package *package, *end;
   7.586 -	struct list *index;
   7.587 -	int free_index;
   7.588 -};
   7.589 -
   7.590 -static struct razor_package_iterator *
   7.591 -razor_package_iterator_create_with_index(struct razor_set *set,
   7.592 -					 struct list *index)
   7.593 -{
   7.594 -	struct razor_package_iterator *pi;
   7.595 -
   7.596 -	pi = zalloc(sizeof *pi);
   7.597 -	pi->set = set;
   7.598 -	pi->index = index;
   7.599 -
   7.600 -	return pi;
   7.601 -}
   7.602 -
   7.603 -struct razor_package_iterator *
   7.604 -razor_package_iterator_create(struct razor_set *set)
   7.605 -{
   7.606 -	struct razor_package_iterator *pi;
   7.607 -
   7.608 -	pi = zalloc(sizeof *pi);
   7.609 -	pi->set = set;
   7.610 -	pi->end = set->packages.data + set->packages.size;
   7.611 -	pi->package = set->packages.data;
   7.612 -
   7.613 -	return pi;
   7.614 -}
   7.615 -
   7.616 -static void
   7.617 -razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
   7.618 -					 struct razor_set *set,
   7.619 -					 struct razor_property *property)
   7.620 -{
   7.621 -	memset(pi, 0, sizeof *pi);
   7.622 -	pi->set = set;
   7.623 -	pi->index = list_first(&property->packages, &set->package_pool);
   7.624 -}
   7.625 -
   7.626 -struct razor_package_iterator *
   7.627 -razor_package_iterator_create_for_property(struct razor_set *set,
   7.628 -					   struct razor_property *property)
   7.629 -{
   7.630 -	struct list *index;
   7.631 -
   7.632 -	index = list_first(&property->packages, &set->package_pool);
   7.633 -	return razor_package_iterator_create_with_index(set, index);
   7.634 -}
   7.635 -
   7.636 -int
   7.637 -razor_package_iterator_next(struct razor_package_iterator *pi,
   7.638 -			    struct razor_package **package,
   7.639 -			    const char **name,
   7.640 -			    const char **version,
   7.641 -			    const char **arch)
   7.642 -{
   7.643 -	char *pool;
   7.644 -	int valid;
   7.645 -	struct razor_package *p, *packages;
   7.646 -
   7.647 -	if (pi->package) {
   7.648 -		p = pi->package++;
   7.649 -		valid = p < pi->end;
   7.650 -	} else if (pi->index) {
   7.651 -		packages = pi->set->packages.data;
   7.652 -		p = &packages[pi->index->data];
   7.653 -		pi->index = list_next(pi->index);
   7.654 -		valid = 1;
   7.655 -	} else
   7.656 -		valid = 0;
   7.657 -
   7.658 -	if (valid) {
   7.659 -		pool = pi->set->string_pool.data;
   7.660 -		*package = p;
   7.661 -		*name = &pool[p->name];
   7.662 -		*version = &pool[p->version];
   7.663 -		*arch = &pool[p->arch];
   7.664 -	} else {
   7.665 -		*package = NULL;
   7.666 -	}
   7.667 -
   7.668 -	return valid;
   7.669 -}
   7.670 -
   7.671 -void
   7.672 -razor_package_iterator_destroy(struct razor_package_iterator *pi)
   7.673 -{
   7.674 -	if (pi->free_index)
   7.675 -		free(pi->index);
   7.676 -
   7.677 -	free(pi);
   7.678 -}
   7.679 -
   7.680  struct razor_package *
   7.681  razor_set_get_package(struct razor_set *set, const char *package)
   7.682  {
   7.683 @@ -914,75 +269,9 @@
   7.684  	return p;
   7.685  }
   7.686  
   7.687 -struct razor_property_iterator {
   7.688 -	struct razor_set *set;
   7.689 -	struct razor_property *property, *end;
   7.690 -	struct list *index;
   7.691 -};
   7.692 -
   7.693 -struct razor_property_iterator *
   7.694 -razor_property_iterator_create(struct razor_set *set,
   7.695 -			       struct razor_package *package)
   7.696 -{
   7.697 -	struct razor_property_iterator *pi;
   7.698 -
   7.699 -	pi = zalloc(sizeof *pi);
   7.700 -	pi->set = set;
   7.701 -
   7.702 -	if (package) {
   7.703 -		pi->index = list_first(&package->properties,
   7.704 -				       &set->property_pool);
   7.705 -	} else {
   7.706 -		pi->property = set->properties.data;
   7.707 -		pi->end = set->properties.data + set->properties.size;
   7.708 -	}
   7.709 -
   7.710 -	return pi;
   7.711 -}
   7.712 -
   7.713 -int
   7.714 -razor_property_iterator_next(struct razor_property_iterator *pi,
   7.715 -			     struct razor_property **property,
   7.716 -			     const char **name,
   7.717 -			     uint32_t *flags,
   7.718 -			     const char **version)
   7.719 -{
   7.720 -	char *pool;
   7.721 -	int valid;
   7.722 -	struct razor_property *p, *properties;
   7.723 -
   7.724 -	if (pi->property) {
   7.725 -		p = pi->property++;
   7.726 -		valid = p < pi->end;
   7.727 -	} else if (pi->index) {
   7.728 -		properties = pi->set->properties.data;
   7.729 -		p = &properties[pi->index->data];
   7.730 -		pi->index = list_next(pi->index);
   7.731 -		valid = 1;
   7.732 -	} else
   7.733 -		valid = 0;
   7.734 -
   7.735 -	if (valid) {
   7.736 -		pool = pi->set->string_pool.data;
   7.737 -		*property = p;
   7.738 -		*name = &pool[p->name];
   7.739 -		*flags = p->flags;
   7.740 -		*version = &pool[p->version];
   7.741 -	} else {
   7.742 -		*property = NULL;
   7.743 -	}
   7.744 -
   7.745 -	return valid;
   7.746 -}
   7.747 -
   7.748 -void
   7.749 -razor_property_iterator_destroy(struct razor_property_iterator *pi)
   7.750 -{
   7.751 -	free(pi);
   7.752 -}
   7.753 -
   7.754 -static struct razor_entry *
   7.755 -find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern)
   7.756 +struct razor_entry *
   7.757 +razor_set_find_entry(struct razor_set *set,
   7.758 +		     struct razor_entry *dir, const char *pattern)
   7.759  {
   7.760  	struct razor_entry *e;
   7.761  	const char *n, *pool = set->string_pool.data;
   7.762 @@ -996,7 +285,7 @@
   7.763  		len = strlen(n);
   7.764  		if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
   7.765  		    pattern[len + 1] == '/') {
   7.766 -			return find_entry(set, e, pattern + len + 1);
   7.767 +			return razor_set_find_entry(set, e, pattern + len + 1);
   7.768  		}
   7.769  	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
   7.770  
   7.771 @@ -1039,7 +328,7 @@
   7.772  	}
   7.773  
   7.774  	strcpy(buffer, pattern);
   7.775 -	e = find_entry(set, set->files.data, buffer);
   7.776 +	e = razor_set_find_entry(set, set->files.data, buffer);
   7.777  	if (e && e->start > 0) {
   7.778  		base = NULL;
   7.779  	} else {
   7.780 @@ -1051,26 +340,11 @@
   7.781  			base = NULL;
   7.782  		}
   7.783  	}
   7.784 -	e = find_entry(set, set->files.data, buffer);
   7.785 +	e = razor_set_find_entry(set, set->files.data, buffer);
   7.786  	if (e->start != 0)
   7.787  		list_dir(set, e, buffer, base);
   7.788  }
   7.789  
   7.790 -struct razor_package_iterator *
   7.791 -razor_package_iterator_create_for_file(struct razor_set *set,
   7.792 -				       const char *filename)
   7.793 -{
   7.794 -	struct razor_entry *entry;
   7.795 -	struct list *index;
   7.796 -
   7.797 -	entry = find_entry(set, set->files.data, filename);
   7.798 -	if (entry == NULL)
   7.799 -		return NULL;
   7.800 -
   7.801 -	index = list_first(&entry->packages, &set->package_pool);
   7.802 -	return razor_package_iterator_create_with_index(set, index);
   7.803 -}
   7.804 -
   7.805  static struct list *
   7.806  list_package_files(struct razor_set *set, struct list *r,
   7.807  		   struct razor_entry *dir, uint32_t end,
   7.808 @@ -1142,509 +416,6 @@
   7.809  	list_package_files(set, r, set->files.data, end, buffer);
   7.810  }
   7.811  
   7.812 -#define UPSTREAM_SOURCE 0x80
   7.813 -
   7.814 -struct source {
   7.815 -	struct razor_set *set;
   7.816 -	uint32_t *property_map;
   7.817 -	uint32_t *file_map;
   7.818 -};
   7.819 -
   7.820 -struct razor_merger {
   7.821 -	struct razor_set *set;
   7.822 -	struct hashtable table;
   7.823 -	struct source source1;
   7.824 -	struct source source2;
   7.825 -};
   7.826 -
   7.827 -static struct razor_merger *
   7.828 -razor_merger_create(struct razor_set *set1, struct razor_set *set2)
   7.829 -{
   7.830 -	struct razor_merger *merger;
   7.831 -	int count;
   7.832 -	size_t size;
   7.833 -
   7.834 -	merger = zalloc(sizeof *merger);
   7.835 -	merger->set = razor_set_create();
   7.836 -	hashtable_init(&merger->table, &merger->set->string_pool);
   7.837 -
   7.838 -	merger->source1.set = set1;
   7.839 -	count = set1->properties.size / sizeof (struct razor_property);
   7.840 -	size = count * sizeof merger->source1.property_map[0];
   7.841 -	merger->source1.property_map = zalloc(size);
   7.842 -	count = set1->files.size / sizeof (struct razor_entry);
   7.843 -	size = count * sizeof merger->source1.file_map[0];
   7.844 -	merger->source1.file_map = zalloc(size);
   7.845 -
   7.846 -	merger->source2.set = set2;
   7.847 -	count = set2->properties.size / sizeof (struct razor_property);
   7.848 -	size = count * sizeof merger->source2.property_map[0];
   7.849 -	merger->source2.property_map = zalloc(size);
   7.850 -	count = set2->files.size / sizeof (struct razor_entry);
   7.851 -	size = count * sizeof merger->source2.file_map[0];
   7.852 -	merger->source2.file_map = zalloc(size);
   7.853 -
   7.854 -	return merger;
   7.855 -}
   7.856 -
   7.857 -static void
   7.858 -razor_merger_add_package(struct razor_merger *merger,
   7.859 -			 struct razor_package *package)
   7.860 -{
   7.861 -	char *pool;
   7.862 -	struct list *r;
   7.863 -	struct razor_package *p;
   7.864 -	struct razor_set *set1;
   7.865 -	struct source *source;
   7.866 -	uint32_t flags;
   7.867 -
   7.868 -	set1 = merger->source1.set;
   7.869 -	if (set1->packages.data <= (void *) package &&
   7.870 -	    (void *) package < set1->packages.data + set1->packages.size) {
   7.871 -		source = &merger->source1;
   7.872 -		flags = 0;
   7.873 -	} else {
   7.874 -		source = &merger->source2;
   7.875 -		flags = UPSTREAM_SOURCE;
   7.876 -	}
   7.877 -
   7.878 -	pool = source->set->string_pool.data;
   7.879 -	p = array_add(&merger->set->packages, sizeof *p);
   7.880 -	p->name = hashtable_tokenize(&merger->table, &pool[package->name]);
   7.881 -	p->flags = flags;
   7.882 -	p->version = hashtable_tokenize(&merger->table,
   7.883 -					&pool[package->version]);
   7.884 -	p->arch = hashtable_tokenize(&merger->table,
   7.885 -				     &pool[package->arch]);
   7.886 -
   7.887 -	p->properties = package->properties;
   7.888 -	r = list_first(&package->properties, &source->set->property_pool);
   7.889 -	while (r) {
   7.890 -		source->property_map[r->data] = 1;
   7.891 -		r = list_next(r);
   7.892 -	}
   7.893 -
   7.894 -	p->files = package->files;
   7.895 -	r = list_first(&package->files, &source->set->file_pool);
   7.896 -	while (r) {
   7.897 -		source->file_map[r->data] = 1;
   7.898 -		r = list_next(r);
   7.899 -	}
   7.900 -}
   7.901 -
   7.902 -static uint32_t
   7.903 -add_property(struct razor_merger *merger,
   7.904 -	     const char *name, uint32_t flags, const char *version)
   7.905 -{
   7.906 -	struct razor_property *p;
   7.907 -
   7.908 -	p = array_add(&merger->set->properties, sizeof *p);
   7.909 -	p->name = hashtable_tokenize(&merger->table, name);
   7.910 -	p->flags = flags;
   7.911 -	p->version = hashtable_tokenize(&merger->table, version);
   7.912 -
   7.913 -	return p - (struct razor_property *) merger->set->properties.data;
   7.914 -}
   7.915 -
   7.916 -static void
   7.917 -merge_properties(struct razor_merger *merger)
   7.918 -{
   7.919 -	struct razor_property *p1, *p2;
   7.920 -	struct razor_set *set1, *set2;
   7.921 -	uint32_t *map1, *map2;
   7.922 -	int i, j, cmp, count1, count2;
   7.923 -	char *pool1, *pool2;
   7.924 -
   7.925 -	set1 = merger->source1.set;
   7.926 -	set2 = merger->source2.set;
   7.927 -	map1 = merger->source1.property_map;
   7.928 -	map2 = merger->source2.property_map;
   7.929 -
   7.930 -	i = 0;
   7.931 -	j = 0;
   7.932 -	pool1 = set1->string_pool.data;
   7.933 -	pool2 = set2->string_pool.data;
   7.934 -
   7.935 -	count1 = set1->properties.size / sizeof *p1;
   7.936 -	count2 = set2->properties.size / sizeof *p2;
   7.937 -	while (i < count1 || j < count2) {
   7.938 -		if (i < count1 && map1[i] == 0) {
   7.939 -			i++;
   7.940 -			continue;
   7.941 -		}
   7.942 -		if (j < count2 && map2[j] == 0) {
   7.943 -			j++;
   7.944 -			continue;
   7.945 -		}
   7.946 -		p1 = (struct razor_property *) set1->properties.data + i;
   7.947 -		p2 = (struct razor_property *) set2->properties.data + j;
   7.948 -		if (i < count1 && j < count2)
   7.949 -			cmp = strcmp(&pool1[p1->name], &pool2[p2->name]);
   7.950 -		else if (i < count1)
   7.951 -			cmp = -1;
   7.952 -		else
   7.953 -			cmp = 1;
   7.954 -		if (cmp == 0)
   7.955 -			cmp = p1->flags - p2->flags;
   7.956 -		if (cmp == 0)
   7.957 -			cmp = versioncmp(&pool1[p1->version],
   7.958 -					 &pool2[p2->version]);
   7.959 -		if (cmp < 0) {
   7.960 -			map1[i++] = add_property(merger,
   7.961 -						 &pool1[p1->name],
   7.962 -						 p1->flags,
   7.963 -						 &pool1[p1->version]);
   7.964 -		} else if (cmp > 0) {
   7.965 -			map2[j++] = add_property(merger,
   7.966 -						 &pool2[p2->name],
   7.967 -						 p2->flags,
   7.968 -						 &pool2[p2->version]);
   7.969 -		} else  {
   7.970 -			map1[i++] = map2[j++] =
   7.971 -				add_property(merger,
   7.972 -					     &pool1[p1->name],
   7.973 -					     p1->flags,
   7.974 -					     &pool1[p1->version]);
   7.975 -		}
   7.976 -	}
   7.977 -}
   7.978 -
   7.979 -static void
   7.980 -emit_properties(struct list_head *properties, struct array *source_pool,
   7.981 -		uint32_t *map, struct array *pool)
   7.982 -{
   7.983 -	uint32_t r;
   7.984 -	struct list *p, *q;
   7.985 -
   7.986 -	r = pool->size / sizeof *q;
   7.987 -	p = list_first(properties, source_pool);
   7.988 -	while (p) {
   7.989 -		q = array_add(pool, sizeof *q);
   7.990 -		q->data = map[p->data];
   7.991 -		q->flags = p->flags;
   7.992 -		p = list_next(p);
   7.993 -	}
   7.994 -
   7.995 -	list_set_ptr(properties, r);
   7.996 -}
   7.997 -
   7.998 -static uint32_t
   7.999 -add_file(struct razor_merger *merger, const char *name)
  7.1000 -{
  7.1001 -	struct razor_entry *e;
  7.1002 -
  7.1003 -	e = array_add(&merger->set->files, sizeof *e);
  7.1004 -	e->name = hashtable_tokenize(&merger->table, name);
  7.1005 -	e->flags = 0;
  7.1006 -	e->start = 0;
  7.1007 -
  7.1008 -	return e - (struct razor_entry *)merger->set->files.data;
  7.1009 -}
  7.1010 -
  7.1011 -/* FIXME. Blah */
  7.1012 -static int
  7.1013 -fix_file_map(uint32_t *map,
  7.1014 -	     struct razor_entry *files,
  7.1015 -	     struct razor_entry *top)
  7.1016 -{
  7.1017 -	uint32_t e;
  7.1018 -	int found_file = 0;
  7.1019 -
  7.1020 -	e = top->start;
  7.1021 -	do {
  7.1022 -		if (files[e].start)
  7.1023 -			fix_file_map(map, files, &files[e]);
  7.1024 -		if (map[e])
  7.1025 -			found_file = 1;
  7.1026 -	} while (!(files[e++].flags & RAZOR_ENTRY_LAST));
  7.1027 -
  7.1028 -	if (found_file)
  7.1029 -		map[top - files] = 1;
  7.1030 -	return found_file;
  7.1031 -}
  7.1032 -
  7.1033 -struct merge_directory {
  7.1034 -	uint32_t merged, dir1, dir2;
  7.1035 -};
  7.1036 -
  7.1037 -static void
  7.1038 -merge_one_directory(struct razor_merger *merger, struct merge_directory *md)
  7.1039 -{
  7.1040 -	struct razor_entry *root1, *root2, *mroot, *e1, *e2;
  7.1041 -	struct razor_set *set1, *set2;
  7.1042 -	struct array merge_stack;
  7.1043 -	struct merge_directory *child_md, *end_md;
  7.1044 -	uint32_t *map1, *map2, start, last;
  7.1045 -	int cmp;
  7.1046 -	char *pool1, *pool2;
  7.1047 -
  7.1048 -	set1 = merger->source1.set;
  7.1049 -	set2 = merger->source2.set;
  7.1050 -	map1 = merger->source1.file_map;
  7.1051 -	map2 = merger->source2.file_map;
  7.1052 -	pool1 = set1->string_pool.data;
  7.1053 -	pool2 = set2->string_pool.data;
  7.1054 -	root1 = (struct razor_entry *) set1->files.data;
  7.1055 -	root2 = (struct razor_entry *) set2->files.data;
  7.1056 -
  7.1057 -	array_init(&merge_stack);
  7.1058 -
  7.1059 -	start = merger->set->files.size / sizeof (struct razor_entry);
  7.1060 -	last = 0;
  7.1061 -	e1 = md->dir1 ? root1 + md->dir1 : NULL;
  7.1062 -	e2 = md->dir2 ? root2 + md->dir2 : NULL;
  7.1063 -	while (e1 || e2) {
  7.1064 -		if (!e2 && !map1[e1 - root1]) {
  7.1065 -			if ((e1++)->flags & RAZOR_ENTRY_LAST)
  7.1066 -				e1 = NULL;
  7.1067 -			continue;
  7.1068 -		}
  7.1069 -		if (!e1 && !map2[e2 - root2]) {
  7.1070 -			if ((e2++)->flags & RAZOR_ENTRY_LAST)
  7.1071 -				e2 = NULL;
  7.1072 -			continue;
  7.1073 -		}
  7.1074 -		if (e1 && !map1[e1 - root1] &&
  7.1075 -		    e2 && !map1[e2 - root2]) {
  7.1076 -			if ((e1++)->flags & RAZOR_ENTRY_LAST)
  7.1077 -				e1 = NULL;
  7.1078 -			if ((e2++)->flags & RAZOR_ENTRY_LAST)
  7.1079 -				e2 = NULL;
  7.1080 -			continue;
  7.1081 -		}
  7.1082 -
  7.1083 -		if (!e1)
  7.1084 -			cmp = 1;
  7.1085 -		else if (!e2)
  7.1086 -			cmp = -1;
  7.1087 -		else {
  7.1088 -			cmp = strcmp (&pool1[e1->name],
  7.1089 -				      &pool2[e2->name]);
  7.1090 -		}
  7.1091 -
  7.1092 -		if (cmp < 0) {
  7.1093 -			if (map1[e1 - root1]) {
  7.1094 -				map1[e1 - root1] = last =
  7.1095 -					add_file(merger, &pool1[e1->name]);
  7.1096 -				if (e1->start) {
  7.1097 -					child_md = array_add(&merge_stack, sizeof (struct merge_directory));
  7.1098 -					child_md->merged = last;
  7.1099 -					child_md->dir1 = e1->start;
  7.1100 -					child_md->dir2 = 0;
  7.1101 -				}
  7.1102 -			}
  7.1103 -			if ((e1++)->flags & RAZOR_ENTRY_LAST)
  7.1104 -				e1 = NULL;
  7.1105 -		} else if (cmp > 0) {
  7.1106 -			if (map2[e2 - root2]) {
  7.1107 -				map2[e2 - root2] = last =
  7.1108 -					add_file(merger, &pool2[e2->name]);
  7.1109 -				if (e2->start) {
  7.1110 -					child_md = array_add(&merge_stack, sizeof (struct merge_directory));
  7.1111 -					child_md->merged = last;
  7.1112 -					child_md->dir1 = 0;
  7.1113 -					child_md->dir2 = e2->start;
  7.1114 -				}
  7.1115 -			}
  7.1116 -			if ((e2++)->flags & RAZOR_ENTRY_LAST)
  7.1117 -				e2 = NULL;
  7.1118 -		} else {
  7.1119 -			map1[e1 - root1] = map2[e2- root2] = last =
  7.1120 -				add_file(merger, &pool1[e1->name]);
  7.1121 -			if (e1->start || e2->start) {
  7.1122 -				child_md = array_add(&merge_stack, sizeof (struct merge_directory));
  7.1123 -				child_md->merged = last;
  7.1124 -				child_md->dir1 = e1->start;
  7.1125 -				child_md->dir2 = e2->start;
  7.1126 -			}
  7.1127 -			if ((e1++)->flags & RAZOR_ENTRY_LAST)
  7.1128 -				e1 = NULL;
  7.1129 -			if ((e2++)->flags & RAZOR_ENTRY_LAST)
  7.1130 -				e2 = NULL;
  7.1131 -		}
  7.1132 -	}
  7.1133 -
  7.1134 -	mroot = (struct razor_entry *)merger->set->files.data;
  7.1135 -	if (last) {
  7.1136 -		mroot[last].flags = RAZOR_ENTRY_LAST;
  7.1137 -		mroot[md->merged].start = start;
  7.1138 -	} else
  7.1139 -		mroot[md->merged].start = 0;
  7.1140 -
  7.1141 -	end_md = merge_stack.data + merge_stack.size;
  7.1142 -	for (child_md = merge_stack.data; child_md < end_md; child_md++)
  7.1143 -		merge_one_directory(merger, child_md);
  7.1144 -	array_release(&merge_stack);
  7.1145 -}
  7.1146 -
  7.1147 -static void
  7.1148 -merge_files(struct razor_merger *merger)
  7.1149 -{
  7.1150 -	struct razor_entry *root;
  7.1151 -	struct merge_directory md;
  7.1152 -	uint32_t *map1, *map2;
  7.1153 -
  7.1154 -	map1 = merger->source1.file_map;
  7.1155 -	map2 = merger->source2.file_map;
  7.1156 -
  7.1157 -	md.merged = 0;
  7.1158 -
  7.1159 -	if (merger->source1.set->files.size) {
  7.1160 -		root = (struct razor_entry *) merger->source1.set->files.data;
  7.1161 -		if (root->start)
  7.1162 -			fix_file_map(map1, root, root);
  7.1163 -		md.dir1 = root->start;
  7.1164 -	} else
  7.1165 -		md.dir1 = 0;
  7.1166 -
  7.1167 -	if (merger->source2.set->files.size) {
  7.1168 -		root = (struct razor_entry *) merger->source2.set->files.data;
  7.1169 -		if (root->start)
  7.1170 -			fix_file_map(map2, root, root);
  7.1171 -		md.dir2 = root->start;
  7.1172 -	} else
  7.1173 -		md.dir2 = 0;
  7.1174 -
  7.1175 -	merge_one_directory(merger, &md);
  7.1176 -}
  7.1177 -
  7.1178 -static void
  7.1179 -emit_files(struct list_head *files, struct array *source_pool,
  7.1180 -	   uint32_t *map, struct array *pool)
  7.1181 -{
  7.1182 -	uint32_t r;
  7.1183 -	struct list *p, *q;
  7.1184 -
  7.1185 -	r = pool->size / sizeof *q;
  7.1186 -	p = list_first(files, source_pool);
  7.1187 -	while (p) {
  7.1188 -		q = array_add(pool, sizeof *q);
  7.1189 -		q->data = map[p->data];
  7.1190 -		q->flags = p->flags;
  7.1191 -		p = list_next(p);
  7.1192 -	}
  7.1193 -
  7.1194 -	list_set_ptr(files, r);
  7.1195 -}
  7.1196 -
  7.1197 -/* Rebuild property->packages maps.  We can't just remap these, as a
  7.1198 - * property may have lost or gained a number of packages.  Allocate an
  7.1199 - * array per property and loop through the packages and add them to
  7.1200 - * the arrays for their properties. */
  7.1201 -static void
  7.1202 -rebuild_property_package_lists(struct razor_set *set)
  7.1203 -{
  7.1204 -	struct array *pkgs, *a;
  7.1205 -	struct razor_package *pkg, *pkg_end;
  7.1206 -	struct razor_property *prop, *prop_end;
  7.1207 -	struct list *r;
  7.1208 -	uint32_t *q;
  7.1209 -	int count;
  7.1210 -
  7.1211 -	count = set->properties.size / sizeof (struct razor_property);
  7.1212 -	pkgs = zalloc(count * sizeof *pkgs);
  7.1213 -	pkg_end = set->packages.data + set->packages.size;
  7.1214 -
  7.1215 -	for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
  7.1216 -		r = list_first(&pkg->properties, &set->property_pool);
  7.1217 -		while (r) {
  7.1218 -			q = array_add(&pkgs[r->data], sizeof *q);
  7.1219 -			*q = pkg - (struct razor_package *) set->packages.data;
  7.1220 -			r = list_next(r);
  7.1221 -		}
  7.1222 -	}
  7.1223 -
  7.1224 -	prop_end = set->properties.data + set->properties.size;
  7.1225 -	a = pkgs;
  7.1226 -	for (prop = set->properties.data; prop < prop_end; prop++, a++) {
  7.1227 -		list_set_array(&prop->packages, &set->package_pool, a, 0);
  7.1228 -		array_release(a);
  7.1229 -	}
  7.1230 -	free(pkgs);
  7.1231 -}
  7.1232 -
  7.1233 -static void
  7.1234 -rebuild_file_package_lists(struct razor_set *set)
  7.1235 -{
  7.1236 -	struct array *pkgs, *a;
  7.1237 -	struct razor_package *pkg, *pkg_end;
  7.1238 -	struct razor_entry *entry, *entry_end;
  7.1239 -	struct list *r;
  7.1240 -	uint32_t *q;
  7.1241 -	int count;
  7.1242 -
  7.1243 -	count = set->files.size / sizeof (struct razor_entry);
  7.1244 -	pkgs = zalloc(count * sizeof *pkgs);
  7.1245 -	pkg_end = set->packages.data + set->packages.size;
  7.1246 -
  7.1247 -	for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
  7.1248 -		r = list_first(&pkg->files, &set->file_pool);
  7.1249 -		while (r) {
  7.1250 -			q = array_add(&pkgs[r->data], sizeof *q);
  7.1251 -			*q = pkg - (struct razor_package *) set->packages.data;
  7.1252 -			r = list_next(r);
  7.1253 -		}
  7.1254 -	}
  7.1255 -
  7.1256 -	entry_end = set->files.data + set->files.size;
  7.1257 -	a = pkgs;
  7.1258 -	for (entry = set->files.data; entry < entry_end; entry++, a++) {
  7.1259 -		list_set_array(&entry->packages, &set->package_pool, a, 0);
  7.1260 -		array_release(a);
  7.1261 -	}
  7.1262 -	free(pkgs);
  7.1263 -}
  7.1264 -
  7.1265 -static struct razor_set *
  7.1266 -razor_merger_finish(struct razor_merger *merger)
  7.1267 -{
  7.1268 -	struct razor_set *result;
  7.1269 -	struct razor_package *p, *pend;
  7.1270 -
  7.1271 -	/* As we built the package list, we filled out a bitvector of
  7.1272 -	 * the properties that are referenced by the packages in the
  7.1273 -	 * new set.  Now we do a parallel loop through the properties
  7.1274 -	 * and emit those marked in the bit vector to the new set.  In
  7.1275 -	 * the process, we update the bit vector to actually map from
  7.1276 -	 * indices in the old property list to indices in the new
  7.1277 -	 * property list for both sets. */
  7.1278 -
  7.1279 -	merge_properties(merger);
  7.1280 -	merge_files(merger);
  7.1281 -
  7.1282 -	/* Now we loop through the packages again and emit the
  7.1283 -	 * property lists, remapped to point to the new properties. */
  7.1284 -
  7.1285 -	pend = merger->set->packages.data + merger->set->packages.size;
  7.1286 -	for (p = merger->set->packages.data; p < pend; p++) {
  7.1287 -		struct source *src;
  7.1288 -
  7.1289 -		if (p->flags & UPSTREAM_SOURCE)
  7.1290 -			src = &merger->source2;
  7.1291 -		else
  7.1292 -			src = &merger->source1;
  7.1293 -
  7.1294 -		emit_properties(&p->properties,
  7.1295 -				&src->set->property_pool,
  7.1296 -				src->property_map,
  7.1297 -				&merger->set->property_pool);
  7.1298 -		emit_files(&p->files,
  7.1299 -			   &src->set->file_pool,
  7.1300 -			   src->file_map,
  7.1301 -			   &merger->set->file_pool);
  7.1302 -		p->flags &= ~UPSTREAM_SOURCE;
  7.1303 -	}
  7.1304 -
  7.1305 -	rebuild_property_package_lists(merger->set);
  7.1306 -	rebuild_file_package_lists(merger->set);
  7.1307 -
  7.1308 -	result = merger->set;
  7.1309 -	hashtable_release(&merger->table);
  7.1310 -	free(merger);
  7.1311 -
  7.1312 -	return result;
  7.1313 -}
  7.1314 -
  7.1315  /* The diff order matters.  We should sort the packages so that a
  7.1316   * REMOVE of a package comes before the INSTALL, and so that all
  7.1317   * requires for a package have been installed before the package.
  7.1318 @@ -1669,7 +440,7 @@
  7.1319  		if (p1 && p2) {
  7.1320  			res = strcmp(name1, name2);
  7.1321  			if (res == 0)
  7.1322 -				res = versioncmp(version1, version2);
  7.1323 +				res = razor_versioncmp(version1, version2);
  7.1324  		} else {
  7.1325  			res = 0;
  7.1326  		}
  7.1327 @@ -1690,953 +461,3 @@
  7.1328  	razor_package_iterator_destroy(pi1);
  7.1329  	razor_package_iterator_destroy(pi2);
  7.1330  }
  7.1331 -
  7.1332 -static int
  7.1333 -provider_satisfies_requirement(struct razor_property *provider,
  7.1334 -			       const char *provider_strings,
  7.1335 -			       uint32_t flags,
  7.1336 -			       const char *required)
  7.1337 -{
  7.1338 -	int cmp, len;
  7.1339 -	const char *provided = &provider_strings[provider->version];
  7.1340 -
  7.1341 -	if (!*required)
  7.1342 -		return 1;
  7.1343 -	if (!*provided) {
  7.1344 -		if (flags & RAZOR_PROPERTY_LESS)
  7.1345 -			return 0;
  7.1346 -		else
  7.1347 -			return 1;
  7.1348 -	}
  7.1349 -
  7.1350 -	cmp = versioncmp(provided, required);
  7.1351 -
  7.1352 -	switch (flags & RAZOR_PROPERTY_RELATION_MASK) {
  7.1353 -	case RAZOR_PROPERTY_LESS:
  7.1354 -		return cmp < 0;
  7.1355 -
  7.1356 -	case RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL:
  7.1357 -		if (cmp <= 0)
  7.1358 -			return 1;
  7.1359 -		/* fall through: FIXME, make sure this is correct */
  7.1360 -
  7.1361 -	case RAZOR_PROPERTY_EQUAL:
  7.1362 -		if (cmp == 0)
  7.1363 -			return 1;
  7.1364 -
  7.1365 -		/* "foo == 1.1" is satisfied by "foo 1.1-2" */
  7.1366 -		len = strlen(required);
  7.1367 -		if (!strncmp(required, provided, len) && provided[len] == '-')
  7.1368 -			return 1;
  7.1369 -		return 0;
  7.1370 -
  7.1371 -	case RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL:
  7.1372 -		return cmp >= 0;
  7.1373 -
  7.1374 -	case RAZOR_PROPERTY_GREATER:
  7.1375 -		return cmp > 0;
  7.1376 -	}
  7.1377 -
  7.1378 -	/* shouldn't happen */
  7.1379 -	return 0;
  7.1380 -}
  7.1381 -
  7.1382 -#define TRANS_PACKAGE_PRESENT		1
  7.1383 -#define TRANS_PACKAGE_UPDATE		2
  7.1384 -#define TRANS_PROPERTY_SATISFIED	0x80000000
  7.1385 -
  7.1386 -struct transaction_set {
  7.1387 -	struct razor_set *set;
  7.1388 -	uint32_t *packages;
  7.1389 -	uint32_t *properties;
  7.1390 -};
  7.1391 -
  7.1392 -struct razor_transaction {
  7.1393 -	int package_count, errors;
  7.1394 -	struct transaction_set system, upstream;
  7.1395 -	int changes;
  7.1396 -};
  7.1397 -
  7.1398 -static void
  7.1399 -transaction_set_init(struct transaction_set *ts, struct razor_set *set)
  7.1400 -{
  7.1401 -	int count;
  7.1402 -
  7.1403 -	ts->set = set;
  7.1404 -	count = set->packages.size / sizeof (struct razor_package);
  7.1405 -	ts->packages = zalloc(count * sizeof *ts->packages);
  7.1406 -	count = set->properties.size / sizeof (struct razor_property);
  7.1407 -	ts->properties = zalloc(count * sizeof *ts->properties);
  7.1408 -}
  7.1409 -
  7.1410 -static void
  7.1411 -transaction_set_release(struct transaction_set *ts)
  7.1412 -{
  7.1413 -	free(ts->packages);
  7.1414 -	free(ts->properties);
  7.1415 -}
  7.1416 -
  7.1417 -static void
  7.1418 -transaction_set_install_package(struct transaction_set *ts,
  7.1419 -				struct razor_package *package)
  7.1420 -{
  7.1421 -	struct razor_package *pkgs;
  7.1422 -	struct list *prop;
  7.1423 -	int i;
  7.1424 -
  7.1425 -	pkgs = ts->set->packages.data;
  7.1426 -	i = package - pkgs;
  7.1427 -	if (ts->packages[i] == TRANS_PACKAGE_PRESENT)
  7.1428 -		return;
  7.1429 -
  7.1430 -	ts->packages[i] = TRANS_PACKAGE_PRESENT;
  7.1431 -
  7.1432 -	prop = list_first(&package->properties, &ts->set->property_pool);
  7.1433 -	while (prop) {
  7.1434 -		ts->properties[prop->data]++;
  7.1435 -		prop = list_next(prop);
  7.1436 -	}
  7.1437 -}
  7.1438 -
  7.1439 -static void
  7.1440 -transaction_set_remove_package(struct transaction_set *ts,
  7.1441 -			       struct razor_package *package)
  7.1442 -{
  7.1443 -	struct razor_package *pkgs;
  7.1444 -	struct list *prop;
  7.1445 -	int i;
  7.1446 -
  7.1447 -	pkgs = ts->set->packages.data;
  7.1448 -	i = package - pkgs;
  7.1449 -	if (ts->packages[i] == 0)
  7.1450 -		return;
  7.1451 -
  7.1452 -	ts->packages[i] = 0;
  7.1453 -
  7.1454 -	prop = list_first(&package->properties, &ts->set->property_pool);
  7.1455 -	while (prop) {
  7.1456 -		ts->properties[prop->data]--;
  7.1457 -		prop = list_next(prop);
  7.1458 -	}
  7.1459 -}
  7.1460 -
  7.1461 -struct razor_transaction *
  7.1462 -razor_transaction_create(struct razor_set *system, struct razor_set *upstream)
  7.1463 -{
  7.1464 -	struct razor_transaction *trans;
  7.1465 -	struct razor_package *p, *spkgs, *pend;
  7.1466 -
  7.1467 -	trans = zalloc(sizeof *trans);
  7.1468 -	transaction_set_init(&trans->system, system);
  7.1469 -	transaction_set_init(&trans->upstream, upstream);
  7.1470 -
  7.1471 -	spkgs = trans->system.set->packages.data;
  7.1472 -	pend = trans->system.set->packages.data +
  7.1473 -		trans->system.set->packages.size;
  7.1474 -	for (p = spkgs; p < pend; p++)
  7.1475 -		transaction_set_install_package(&trans->system, p);
  7.1476 -
  7.1477 -	return trans;
  7.1478 -}
  7.1479 -
  7.1480 -void
  7.1481 -razor_transaction_install_package(struct razor_transaction *trans,
  7.1482 -				  struct razor_package *package)
  7.1483 -{
  7.1484 -	transaction_set_install_package(&trans->upstream, package);
  7.1485 -	trans->changes++;
  7.1486 -}
  7.1487 -
  7.1488 -void
  7.1489 -razor_transaction_remove_package(struct razor_transaction *trans,
  7.1490 -				 struct razor_package *package)
  7.1491 -{
  7.1492 -	transaction_set_remove_package(&trans->system, package);
  7.1493 -	trans->changes++;
  7.1494 -}
  7.1495 -
  7.1496 -void
  7.1497 -razor_transaction_update_package(struct razor_transaction *trans,
  7.1498 -				  struct razor_package *package)
  7.1499 -{
  7.1500 -	struct razor_package *spkgs, *upkgs, *end;
  7.1501 -
  7.1502 -	spkgs = trans->system.set->packages.data;
  7.1503 -	upkgs = trans->upstream.set->packages.data;
  7.1504 -	end = trans->system.set->packages.data +
  7.1505 -		trans->system.set->packages.size;
  7.1506 -	if (spkgs <= package && package < end)
  7.1507 -		trans->system.packages[package - spkgs] |= TRANS_PACKAGE_UPDATE;
  7.1508 -	else
  7.1509 -		trans->upstream.packages[package - upkgs] |= TRANS_PACKAGE_UPDATE;
  7.1510 -}
  7.1511 -
  7.1512 -struct prop_iter {
  7.1513 -	struct razor_property *p, *start, *end;
  7.1514 -	const char *pool;
  7.1515 -	uint32_t *present;
  7.1516 -};
  7.1517 -
  7.1518 -static void
  7.1519 -prop_iter_init(struct prop_iter *pi, struct transaction_set *ts)
  7.1520 -{
  7.1521 -	pi->p = ts->set->properties.data;
  7.1522 -	pi->start = ts->set->properties.data;
  7.1523 -	pi->end = ts->set->properties.data + ts->set->properties.size;
  7.1524 -	pi->pool = ts->set->string_pool.data;
  7.1525 -	pi->present = ts->properties;
  7.1526 -}
  7.1527 -
  7.1528 -static int
  7.1529 -prop_iter_next(struct prop_iter *pi, uint32_t flags, struct razor_property **p)
  7.1530 -{
  7.1531 -	while (pi->p < pi->end) {
  7.1532 -		if ((pi->present[pi->p - pi->start] & ~TRANS_PROPERTY_SATISFIED) &&
  7.1533 -		    (pi->p->flags & RAZOR_PROPERTY_TYPE_MASK) == flags) {
  7.1534 -			*p = pi->p++;
  7.1535 -			return 1;
  7.1536 -		}
  7.1537 -		pi->p++;
  7.1538 -	}
  7.1539 -
  7.1540 -	return 0;
  7.1541 -}
  7.1542 -
  7.1543 -static struct razor_property *
  7.1544 -prop_iter_seek_to(struct prop_iter *pi,
  7.1545 -		  uint32_t flags, const char *match)
  7.1546 -{
  7.1547 -	uint32_t name;
  7.1548 -
  7.1549 -	while (pi->p < pi->end && strcmp(&pi->pool[pi->p->name], match) < 0)
  7.1550 -		pi->p++;
  7.1551 -
  7.1552 -	if (pi->p == pi->end || strcmp(&pi->pool[pi->p->name], match) > 0)
  7.1553 -		return NULL;
  7.1554 -
  7.1555 -	name = pi->p->name;
  7.1556 -	while (pi->p < pi->end &&
  7.1557 -	       pi->p->name == name &&
  7.1558 -	       (pi->p->flags & RAZOR_PROPERTY_TYPE_MASK) != flags)
  7.1559 -		pi->p++;
  7.1560 -
  7.1561 -	if (pi->p == pi->end || pi->p->name != name)
  7.1562 -		return NULL;
  7.1563 -
  7.1564 -	return pi->p;
  7.1565 -}
  7.1566 -
  7.1567 -/* Remove packages from set that provide any of the matching (same
  7.1568 - * name and type) providers from ppi onwards that match the
  7.1569 - * requirement that rpi points to. */
  7.1570 -static void
  7.1571 -remove_matching_providers(struct razor_transaction *trans,
  7.1572 -			  struct prop_iter *ppi,
  7.1573 -			  uint32_t flags,
  7.1574 -			  const char *version)
  7.1575 -{
  7.1576 -	struct razor_property *p;
  7.1577 -	struct razor_package *pkg, *pkgs;
  7.1578 -	struct razor_package_iterator pkg_iter;
  7.1579 -	struct razor_set *set;
  7.1580 -	const char *n, *v, *a;
  7.1581 -	uint32_t type;
  7.1582 -
  7.1583 -	if (ppi->present == trans->system.properties)
  7.1584 -		set = trans->system.set;
  7.1585 -	else
  7.1586 -		set = trans->upstream.set;
  7.1587 -
  7.1588 -	pkgs = (struct razor_package *) set->packages.data;
  7.1589 -	type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
  7.1590 -	for (p = ppi->p;
  7.1591 -	     p < ppi->end &&
  7.1592 -	     p->name == ppi->p->name &&
  7.1593 -	     (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
  7.1594 -	     p++) {
  7.1595 -		if (!ppi->present[p - ppi->start])
  7.1596 -			continue;
  7.1597 -		if (!provider_satisfies_requirement(p, ppi->pool,
  7.1598 -						    flags, version))
  7.1599 -			continue;
  7.1600 -
  7.1601 -		razor_package_iterator_init_for_property(&pkg_iter, set, p);
  7.1602 -		while (razor_package_iterator_next(&pkg_iter,
  7.1603 -						   &pkg, &n, &v, &a)) {
  7.1604 -			fprintf(stderr, "removing %s-%s\n", n, v);
  7.1605 -			razor_transaction_remove_package(trans, pkg);
  7.1606 -		}
  7.1607 -	}
  7.1608 -}
  7.1609 -
  7.1610 -static void
  7.1611 -flag_matching_providers(struct razor_transaction *trans,
  7.1612 -			struct prop_iter *ppi,
  7.1613 -			struct razor_property *r,
  7.1614 -			struct prop_iter *rpi,
  7.1615 -			unsigned int flag)
  7.1616 -{
  7.1617 -	struct razor_property *p;
  7.1618 -	struct razor_package *pkg, *pkgs;
  7.1619 -	struct razor_package_iterator pkg_iter;
  7.1620 -	struct razor_set *set;
  7.1621 -	const char *name, *version, *arch;
  7.1622 -	uint32_t *flags, type;
  7.1623 -
  7.1624 -	if (ppi->present == trans->system.properties) {
  7.1625 -		set = trans->system.set;
  7.1626 -		flags = trans->system.packages;
  7.1627 -	} else {
  7.1628 -		set = trans->upstream.set;
  7.1629 -		flags = trans->upstream.packages;
  7.1630 -	}
  7.1631 -
  7.1632 -	pkgs = (struct razor_package *) set->packages.data;
  7.1633 -	type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
  7.1634 -	for (p = ppi->p;
  7.1635 -	     p < ppi->end &&
  7.1636 -		     p->name == ppi->p->name &&
  7.1637 -		     (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
  7.1638 -	     p++) {
  7.1639 -		if (!ppi->present[p - ppi->start])
  7.1640 -			continue;
  7.1641 -		if (!provider_satisfies_requirement(p, ppi->pool,
  7.1642 -						    r->flags,
  7.1643 -						    &rpi->pool[r->version]))
  7.1644 -			continue;
  7.1645 -
  7.1646 -		razor_package_iterator_init_for_property(&pkg_iter, set, p);
  7.1647 -		while (razor_package_iterator_next(&pkg_iter, &pkg,
  7.1648 -						   &name, &version, &arch)) {
  7.1649 -
  7.1650 -			fprintf(stderr, "flagging %s-%s for providing %s matching %s %s\n",
  7.1651 -				name, version,
  7.1652 -				ppi->pool + p->name,
  7.1653 -				rpi->pool + r->name,
  7.1654 -				rpi->pool + r->version);
  7.1655 -			flags[pkg - pkgs] |= flag;
  7.1656 -		}
  7.1657 -	}
  7.1658 -}
  7.1659 -
  7.1660 -static struct razor_package *
  7.1661 -pick_matching_provider(struct razor_set *set,
  7.1662 -		       struct prop_iter *ppi,
  7.1663 -		       uint32_t flags,
  7.1664 -		       const char *version)
  7.1665 -{
  7.1666 -	struct razor_property *p;
  7.1667 -	struct razor_package *pkgs;
  7.1668 -	struct list *i;
  7.1669 -	uint32_t type;
  7.1670 -
  7.1671 -	/* This is where we decide which pkgs to pull in to satisfy a
  7.1672 -	 * requirement.  There may be several different providers
  7.1673 -	 * (different versions) and each version of a provider may
  7.1674 -	 * come from a number of packages.  We pick the first package
  7.1675 -	 * from the first provider that matches. */
  7.1676 -
  7.1677 -	pkgs = set->packages.data;
  7.1678 -	type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
  7.1679 -	for (p = ppi->p;
  7.1680 -	     p < ppi->end &&
  7.1681 -		     p->name == ppi->p->name &&
  7.1682 -		     (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type &&
  7.1683 -		     ppi->present[p - ppi->start] == 0;
  7.1684 -	     p++) {
  7.1685 -		if (!provider_satisfies_requirement(p, ppi->pool,
  7.1686 -						    flags, version))
  7.1687 -			continue;
  7.1688 -
  7.1689 -		i = list_first(&p->packages, &set->package_pool);
  7.1690 -
  7.1691 -		return &pkgs[i->data];
  7.1692 -	}
  7.1693 -
  7.1694 -	return NULL;
  7.1695 -}
  7.1696 -
  7.1697 -static void
  7.1698 -remove_obsoleted_packages(struct razor_transaction *trans)
  7.1699 -{
  7.1700 -	struct razor_property *up;
  7.1701 -	struct razor_package *spkgs;
  7.1702 -	struct prop_iter spi, upi;
  7.1703 -
  7.1704 -	spkgs = trans->system.set->packages.data;
  7.1705 -	prop_iter_init(&spi, &trans->system);
  7.1706 -	prop_iter_init(&upi, &trans->upstream);
  7.1707 -
  7.1708 -	while (prop_iter_next(&upi, RAZOR_PROPERTY_OBSOLETES, &up)) {
  7.1709 -		if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
  7.1710 -				       &upi.pool[up->name]))
  7.1711 -			continue;
  7.1712 -		remove_matching_providers(trans, &spi, up->flags,
  7.1713 -					  &upi.pool[up->version]);
  7.1714 -	}
  7.1715 -}
  7.1716 -
  7.1717 -static int
  7.1718 -any_provider_satisfies_requirement(struct prop_iter *ppi,
  7.1719 -				   uint32_t flags,
  7.1720 -				   const char *version)
  7.1721 -{
  7.1722 -	struct razor_property *p;
  7.1723 -	uint32_t type;
  7.1724 -
  7.1725 -	type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
  7.1726 -	for (p = ppi->p;
  7.1727 -	     p < ppi->end &&
  7.1728 -		     p->name == ppi->p->name &&
  7.1729 -		     (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
  7.1730 -	     p++) {
  7.1731 -		if (ppi->present[p - ppi->start] > 0 &&
  7.1732 -		    provider_satisfies_requirement(p, ppi->pool,
  7.1733 -						   flags, version))
  7.1734 -			return 1;
  7.1735 -	}
  7.1736 -
  7.1737 -	return 0;
  7.1738 -}
  7.1739 -
  7.1740 -static void
  7.1741 -clear_requires_flags(struct transaction_set *ts)
  7.1742 -{
  7.1743 -	struct razor_property *p;
  7.1744 -	const char *pool;
  7.1745 -	int i, count;
  7.1746 -
  7.1747 -	count = ts->set->properties.size / sizeof *p;
  7.1748 -	p = ts->set->properties.data;
  7.1749 -	pool = ts->set->string_pool.data;
  7.1750 -	for (i = 0; i < count; i++) {
  7.1751 -		ts->properties[i] &= ~TRANS_PROPERTY_SATISFIED;
  7.1752 -		if (strncmp(&pool[p[i].name], "rpmlib(", 7) == 0)
  7.1753 -			ts->properties[i] |= TRANS_PROPERTY_SATISFIED;
  7.1754 -	}
  7.1755 -}
  7.1756 -
  7.1757 -const char *
  7.1758 -razor_property_relation_to_string(struct razor_property *p)
  7.1759 -{
  7.1760 -	switch (p->flags & RAZOR_PROPERTY_RELATION_MASK) {
  7.1761 -	case RAZOR_PROPERTY_LESS:
  7.1762 -		return "<";
  7.1763 -
  7.1764 -	case RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL:
  7.1765 -		return "<=";
  7.1766 -
  7.1767 -	case RAZOR_PROPERTY_EQUAL:
  7.1768 -		return "=";
  7.1769 -
  7.1770 -	case RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL:
  7.1771 -		return ">=";
  7.1772 -
  7.1773 -	case RAZOR_PROPERTY_GREATER:
  7.1774 -		return ">";
  7.1775 -
  7.1776 -	default:
  7.1777 -		return "?";
  7.1778 -	}
  7.1779 -}
  7.1780 -
  7.1781 -const char *
  7.1782 -razor_property_type_to_string(struct razor_property *p)
  7.1783 -{
  7.1784 -	switch (p->flags & RAZOR_PROPERTY_TYPE_MASK) {
  7.1785 -	case RAZOR_PROPERTY_REQUIRES:
  7.1786 -		return "requires";
  7.1787 -	case RAZOR_PROPERTY_PROVIDES:
  7.1788 -		return "provides";
  7.1789 -	case RAZOR_PROPERTY_CONFLICTS:
  7.1790 -		return "conflicts";
  7.1791 -	case RAZOR_PROPERTY_OBSOLETES:
  7.1792 -		return "obsoletes";
  7.1793 -	default:
  7.1794 -		return NULL;
  7.1795 -	}
  7.1796 -}
  7.1797 -
  7.1798 -static void
  7.1799 -mark_satisfied_requires(struct razor_transaction *trans,
  7.1800 -			struct transaction_set *rts,
  7.1801 -			struct transaction_set *pts)
  7.1802 -{
  7.1803 -	struct prop_iter rpi, ppi;
  7.1804 -	struct razor_property *rp;
  7.1805 -
  7.1806 -	prop_iter_init(&rpi, rts);
  7.1807 -	prop_iter_init(&ppi, pts);
  7.1808 -
  7.1809 -	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  7.1810 -		if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES,
  7.1811 -				       &rpi.pool[rp->name]))
  7.1812 -			continue;
  7.1813 -
  7.1814 -		if (any_provider_satisfies_requirement(&ppi, rp->flags,
  7.1815 -						       &rpi.pool[rp->version]))
  7.1816 -			rpi.present[rp - rpi.start] |= TRANS_PROPERTY_SATISFIED;
  7.1817 -	}
  7.1818 -}
  7.1819 -
  7.1820 -static void
  7.1821 -mark_all_satisfied_requires(struct razor_transaction *trans)
  7.1822 -{
  7.1823 -	clear_requires_flags(&trans->system);
  7.1824 -	clear_requires_flags(&trans->upstream);
  7.1825 -	mark_satisfied_requires(trans, &trans->system, &trans->system);
  7.1826 -	mark_satisfied_requires(trans, &trans->system, &trans->upstream);
  7.1827 -	mark_satisfied_requires(trans, &trans->upstream, &trans->system);
  7.1828 -	mark_satisfied_requires(trans, &trans->upstream, &trans->upstream);
  7.1829 -}
  7.1830 -
  7.1831 -static void
  7.1832 -update_unsatisfied_packages(struct razor_transaction *trans)
  7.1833 -{
  7.1834 -	struct razor_package *spkgs, *pkg;
  7.1835 -	struct razor_property *sp;
  7.1836 -	struct prop_iter spi;
  7.1837 -	struct razor_package_iterator pkg_iter;
  7.1838 -	const char *name, *version, *arch;
  7.1839 -
  7.1840 -	spkgs = trans->system.set->packages.data;
  7.1841 -	prop_iter_init(&spi, &trans->system);
  7.1842 -
  7.1843 -	while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
  7.1844 -		if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
  7.1845 -			continue;
  7.1846 -
  7.1847 -		razor_package_iterator_init_for_property(&pkg_iter,
  7.1848 -							 trans->system.set,
  7.1849 -							 sp);
  7.1850 -		while (razor_package_iterator_next(&pkg_iter, &pkg,
  7.1851 -						   &name, &version, &arch)) {
  7.1852 -			fprintf(stderr, "updating %s because %s %s %s "
  7.1853 -				"isn't satisfied\n",
  7.1854 -				name, spi.pool + sp->name,
  7.1855 -				razor_property_relation_to_string(sp),
  7.1856 -				spi.pool + sp->version);
  7.1857 -			trans->system.packages[pkg - spkgs] |=
  7.1858 -				TRANS_PACKAGE_UPDATE;
  7.1859 -		}
  7.1860 -	}
  7.1861 -}
  7.1862 -
  7.1863 -void
  7.1864 -razor_transaction_update_all(struct razor_transaction *trans)
  7.1865 -{
  7.1866 -	struct razor_package *p;
  7.1867 -	int i, count;
  7.1868 -
  7.1869 -	count = trans->system.set->packages.size / sizeof *p;
  7.1870 -	for (i = 0; i < count; i++)
  7.1871 -		trans->system.packages[i] |= TRANS_PACKAGE_UPDATE;
  7.1872 -}
  7.1873 -
  7.1874 -static void
  7.1875 -update_conflicted_packages(struct razor_transaction *trans)
  7.1876 -{
  7.1877 -	struct razor_package *pkg, *spkgs;
  7.1878 -	struct razor_property *up, *sp;
  7.1879 -	struct prop_iter spi, upi;
  7.1880 -	struct razor_package_iterator pkg_iter;
  7.1881 -	const char *name, *version, *arch;
  7.1882 -
  7.1883 -	spkgs = trans->system.set->packages.data;
  7.1884 -	prop_iter_init(&spi, &trans->system);
  7.1885 -	prop_iter_init(&upi, &trans->upstream);
  7.1886 -
  7.1887 -	while (prop_iter_next(&spi, RAZOR_PROPERTY_CONFLICTS, &sp)) {
  7.1888 -		if (!prop_iter_seek_to(&upi, RAZOR_PROPERTY_PROVIDES,
  7.1889 -				       &spi.pool[sp->name]))
  7.1890 -			continue;
  7.1891 -
  7.1892 -		if (!any_provider_satisfies_requirement(&upi, sp->flags,
  7.1893 -							&spi.pool[sp->version]))
  7.1894 -			continue;
  7.1895 -
  7.1896 -		razor_package_iterator_init_for_property(&pkg_iter,
  7.1897 -							 trans->system.set,
  7.1898 -							 sp);
  7.1899 -		while (razor_package_iterator_next(&pkg_iter, &pkg,
  7.1900 -						   &name, &version, &arch)) {
  7.1901 -			fprintf(stderr, "updating %s %s because it conflicts with %s",
  7.1902 -				name, version, spi.pool + sp->name);
  7.1903 -			trans->system.packages[pkg - spkgs] |=
  7.1904 -				TRANS_PACKAGE_UPDATE;
  7.1905 -		}
  7.1906 -	}
  7.1907 -
  7.1908 -	prop_iter_init(&spi, &trans->system);
  7.1909 -	prop_iter_init(&upi, &trans->upstream);
  7.1910 -
  7.1911 -	while (prop_iter_next(&upi, RAZOR_PROPERTY_CONFLICTS, &up)) {
  7.1912 -		sp = prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
  7.1913 -				       &upi.pool[upi.p->name]);
  7.1914 -
  7.1915 -		if (sp)
  7.1916 -			flag_matching_providers(trans, &spi, up, &upi,
  7.1917 -						TRANS_PACKAGE_UPDATE);
  7.1918 -	}
  7.1919 -}
  7.1920 -
  7.1921 -static void
  7.1922 -pull_in_requirements(struct razor_transaction *trans,
  7.1923 -		     struct prop_iter *rpi, struct prop_iter *ppi)
  7.1924 -{
  7.1925 -	struct razor_property *rp, *pp;
  7.1926 -	struct razor_package *pkg, *upkgs;
  7.1927 -
  7.1928 -	upkgs = trans->upstream.set->packages.data;
  7.1929 -	while (prop_iter_next(rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  7.1930 -		if (rpi->present[rp - rpi->start] & TRANS_PROPERTY_SATISFIED)
  7.1931 -			continue;
  7.1932 -
  7.1933 -		pp = prop_iter_seek_to(ppi, RAZOR_PROPERTY_PROVIDES,
  7.1934 -				       &rpi->pool[rp->name]);
  7.1935 -		if (pp == NULL)
  7.1936 -			continue;
  7.1937 -		pkg = pick_matching_provider(trans->upstream.set,
  7.1938 -					     ppi, rp->flags,
  7.1939 -					     &rpi->pool[rp->version]);
  7.1940 -		if (pkg == NULL)
  7.1941 -			continue;
  7.1942 -
  7.1943 -		rpi->present[rp - rpi->start] |= TRANS_PROPERTY_SATISFIED;
  7.1944 -
  7.1945 -		fprintf(stderr, "pulling in %s which provides %s %s %s "
  7.1946 -			"to satisfy %s %s %s\n",
  7.1947 -			ppi->pool + pkg->name,
  7.1948 -			ppi->pool + pp->name,
  7.1949 -			razor_property_relation_to_string(pp),
  7.1950 -			ppi->pool + pp->version,
  7.1951 -			&rpi->pool[rp->name],
  7.1952 -			razor_property_relation_to_string(rp),
  7.1953 -			&rpi->pool[rp->version]);
  7.1954 -
  7.1955 -		trans->upstream.packages[pkg - upkgs] |= TRANS_PACKAGE_UPDATE;
  7.1956 -	}
  7.1957 -}
  7.1958 -
  7.1959 -static void
  7.1960 -pull_in_all_requirements(struct razor_transaction *trans)
  7.1961 -{
  7.1962 -	struct prop_iter rpi, ppi;
  7.1963 -
  7.1964 -	prop_iter_init(&rpi, &trans->system);
  7.1965 -	prop_iter_init(&ppi, &trans->upstream);
  7.1966 -	pull_in_requirements(trans, &rpi, &ppi);
  7.1967 -
  7.1968 -	prop_iter_init(&rpi, &trans->upstream);
  7.1969 -	prop_iter_init(&ppi, &trans->upstream);
  7.1970 -	pull_in_requirements(trans, &rpi, &ppi);
  7.1971 -}
  7.1972 -
  7.1973 -static void
  7.1974 -flush_scheduled_system_updates(struct razor_transaction *trans)
  7.1975 -{
  7.1976 - 	struct razor_package_iterator *pi;
  7.1977 - 	struct razor_package *p, *pkg, *spkgs;
  7.1978 -	struct prop_iter ppi;
  7.1979 -	const char *name, *version, *arch;
  7.1980 -
  7.1981 -	spkgs = trans->system.set->packages.data;
  7.1982 -	pi = razor_package_iterator_create(trans->system.set);
  7.1983 -	prop_iter_init(&ppi, &trans->upstream);
  7.1984 -
  7.1985 -	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  7.1986 -		if (!(trans->system.packages[p - spkgs] & TRANS_PACKAGE_UPDATE))
  7.1987 -			continue;
  7.1988 -
  7.1989 -		if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES, name))
  7.1990 -			continue;
  7.1991 -
  7.1992 -		pkg = pick_matching_provider(trans->upstream.set, &ppi,
  7.1993 -					     RAZOR_PROPERTY_GREATER, version);
  7.1994 -		if (pkg == NULL)
  7.1995 -			continue;
  7.1996 -
  7.1997 -		fprintf(stderr, "updating %s-%s to %s-%s\n",
  7.1998 -			name, version,
  7.1999 -			&ppi.pool[pkg->name], &ppi.pool[pkg->version]);
  7.2000 -
  7.2001 -		razor_transaction_remove_package(trans, p);
  7.2002 -		razor_transaction_install_package(trans, pkg);
  7.2003 -	}
  7.2004 -
  7.2005 -	razor_package_iterator_destroy(pi);
  7.2006 -}
  7.2007 -
  7.2008 -static void
  7.2009 -flush_scheduled_upstream_updates(struct razor_transaction *trans)
  7.2010 -{
  7.2011 - 	struct razor_package_iterator *pi;
  7.2012 - 	struct razor_package *p, *upkgs;
  7.2013 -	struct prop_iter spi;
  7.2014 -	const char *name, *version, *arch;
  7.2015 -
  7.2016 -	upkgs = trans->upstream.set->packages.data;
  7.2017 -	pi = razor_package_iterator_create(trans->upstream.set);
  7.2018 -	prop_iter_init(&spi, &trans->system);
  7.2019 -
  7.2020 -	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  7.2021 -		if (!(trans->upstream.packages[p - upkgs] & TRANS_PACKAGE_UPDATE))
  7.2022 -			continue;
  7.2023 -
  7.2024 -		if (prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES, name))
  7.2025 -			remove_matching_providers(trans,
  7.2026 -						  &spi,
  7.2027 -						  RAZOR_PROPERTY_LESS,
  7.2028 -						  version);
  7.2029 -		razor_transaction_install_package(trans, p);
  7.2030 -		fprintf(stderr, "installing %s-%s\n", name, version);
  7.2031 -	}
  7.2032 -}
  7.2033 -
  7.2034 -int
  7.2035 -razor_transaction_resolve(struct razor_transaction *trans)
  7.2036 -{
  7.2037 -	int last = 0;
  7.2038 -
  7.2039 -	flush_scheduled_system_updates(trans);
  7.2040 -	flush_scheduled_upstream_updates(trans);
  7.2041 -
  7.2042 -	while (last < trans->changes) {
  7.2043 -		last = trans->changes;
  7.2044 -		remove_obsoleted_packages(trans);
  7.2045 -		mark_all_satisfied_requires(trans);
  7.2046 -		update_unsatisfied_packages(trans);
  7.2047 -		update_conflicted_packages(trans);
  7.2048 -		pull_in_all_requirements(trans);
  7.2049 -		flush_scheduled_system_updates(trans);
  7.2050 -		flush_scheduled_upstream_updates(trans);
  7.2051 -	}
  7.2052 -
  7.2053 -	return trans->changes;
  7.2054 -}
  7.2055 -
  7.2056 -static void
  7.2057 -describe_unsatisfied(struct razor_set *set, struct razor_property *rp)
  7.2058 -{
  7.2059 -	struct razor_package_iterator pi;
  7.2060 -	struct razor_package *pkg;
  7.2061 -	const char *name, *version, *arch, *pool;
  7.2062 -
  7.2063 -	pool = set->string_pool.data;
  7.2064 -	if (pool[rp->version] == '\0') {
  7.2065 -		razor_package_iterator_init_for_property(&pi, set, rp);
  7.2066 -		while (razor_package_iterator_next(&pi, &pkg,
  7.2067 -						   &name, &version, &arch))
  7.2068 -			fprintf(stderr, "%s is needed by %s-%s.%s\n",
  7.2069 -				&pool[rp->name],
  7.2070 -				name, version, arch);
  7.2071 -	} else {
  7.2072 -		razor_package_iterator_init_for_property(&pi, set, rp);
  7.2073 -		while (razor_package_iterator_next(&pi, &pkg,
  7.2074 -						   &name, &version, &arch))
  7.2075 -			fprintf(stderr, "%s %s %s is needed by %s-%s.%s\n",
  7.2076 -				&pool[rp->name],
  7.2077 -				razor_property_relation_to_string(rp),
  7.2078 -				&pool[rp->version],
  7.2079 -				name, version, arch);
  7.2080 -	}
  7.2081 -}
  7.2082 -
  7.2083 -int
  7.2084 -razor_transaction_describe(struct razor_transaction *trans)
  7.2085 -{
  7.2086 -	struct prop_iter rpi;
  7.2087 -	struct razor_property *rp;
  7.2088 -	int unsatisfied;
  7.2089 -
  7.2090 -	flush_scheduled_system_updates(trans);
  7.2091 -	flush_scheduled_upstream_updates(trans);
  7.2092 -	mark_all_satisfied_requires(trans);
  7.2093 -
  7.2094 -	unsatisfied = 0;
  7.2095 -	prop_iter_init(&rpi, &trans->system);
  7.2096 -	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  7.2097 -		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
  7.2098 -			describe_unsatisfied(trans->system.set, rp);
  7.2099 -		        unsatisfied++;
  7.2100 -		}
  7.2101 -	}
  7.2102 -
  7.2103 -	prop_iter_init(&rpi, &trans->upstream);
  7.2104 -	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  7.2105 -		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
  7.2106 -			describe_unsatisfied(trans->upstream.set, rp);
  7.2107 -			unsatisfied++;
  7.2108 -		}
  7.2109 -	}
  7.2110 -
  7.2111 -	return unsatisfied;
  7.2112 -}
  7.2113 -
  7.2114 -int
  7.2115 -razor_transaction_unsatisfied_property(struct razor_transaction *trans,
  7.2116 -				       const char *name,
  7.2117 -				       uint32_t flags,
  7.2118 -				       const char *version)
  7.2119 -{
  7.2120 -	struct prop_iter pi;
  7.2121 -	struct razor_property *p;
  7.2122 -
  7.2123 -	prop_iter_init(&pi, &trans->system);
  7.2124 -	while (prop_iter_next(&pi, flags, &p)) {
  7.2125 -		if (!(trans->system.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
  7.2126 -		    p->flags == flags &&
  7.2127 -		    strcmp(&pi.pool[p->name], name) == 0 &&
  7.2128 -		    strcmp(&pi.pool[p->version], version) == 0)
  7.2129 -
  7.2130 -			return 1;
  7.2131 -	}
  7.2132 -
  7.2133 -	prop_iter_init(&pi, &trans->upstream);
  7.2134 -	while (prop_iter_next(&pi, flags, &p)) {
  7.2135 -		if (!(trans->upstream.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
  7.2136 -		    p->flags == flags &&
  7.2137 -		    strcmp(&pi.pool[p->name], name) == 0 &&
  7.2138 -		    strcmp(&pi.pool[p->version], version) == 0)
  7.2139 -
  7.2140 -			return 1;
  7.2141 -	}
  7.2142 -
  7.2143 -	return 0;
  7.2144 -}
  7.2145 -
  7.2146 -struct razor_set *
  7.2147 -razor_transaction_finish(struct razor_transaction *trans)
  7.2148 -{
  7.2149 -	struct razor_merger *merger;
  7.2150 -	struct razor_package *u, *uend, *upkgs, *s, *send, *spkgs;
  7.2151 -	char *upool, *spool;
  7.2152 -	int cmp;
  7.2153 -
  7.2154 -	s = trans->system.set->packages.data;
  7.2155 -	spkgs = trans->system.set->packages.data;
  7.2156 -	send = trans->system.set->packages.data +
  7.2157 -		trans->system.set->packages.size;
  7.2158 -	spool = trans->system.set->string_pool.data;
  7.2159 -
  7.2160 -	u = trans->upstream.set->packages.data;
  7.2161 -	upkgs = trans->upstream.set->packages.data;
  7.2162 -	uend = trans->upstream.set->packages.data +
  7.2163 -		trans->upstream.set->packages.size;
  7.2164 -	upool = trans->upstream.set->string_pool.data;
  7.2165 -
  7.2166 -	merger = razor_merger_create(trans->system.set, trans->upstream.set);
  7.2167 -	while (s < send || u < uend) {
  7.2168 -		if (s < send && u < uend)
  7.2169 -			cmp = strcmp(&spool[s->name], &upool[u->name]);
  7.2170 -		else if (s < send)
  7.2171 -			cmp = -1;
  7.2172 -		else
  7.2173 -			cmp = 1;
  7.2174 -
  7.2175 -		if (cmp < 0) {
  7.2176 -			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
  7.2177 -				razor_merger_add_package(merger, s);
  7.2178 -			s++;
  7.2179 -		} else if (cmp == 0) {
  7.2180 -			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
  7.2181 -				razor_merger_add_package(merger, s);
  7.2182 -			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
  7.2183 -				razor_merger_add_package(merger, u);
  7.2184 -
  7.2185 -			s++;
  7.2186 -			u++;
  7.2187 -		} else {
  7.2188 -			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
  7.2189 -				razor_merger_add_package(merger, u);
  7.2190 -			u++;
  7.2191 -		}
  7.2192 -	}
  7.2193 -
  7.2194 -	razor_transaction_destroy(trans);
  7.2195 -
  7.2196 -	return razor_merger_finish(merger);
  7.2197 -}
  7.2198 -
  7.2199 -void
  7.2200 -razor_transaction_destroy(struct razor_transaction *trans)
  7.2201 -{
  7.2202 -	transaction_set_release(&trans->system);
  7.2203 -	transaction_set_release(&trans->upstream);
  7.2204 -	free(trans);
  7.2205 -}
  7.2206 -
  7.2207 -struct razor_package_query {
  7.2208 -	struct razor_set *set;
  7.2209 -	char *vector;
  7.2210 -	int count;
  7.2211 -};
  7.2212 -
  7.2213 -struct razor_package_query *
  7.2214 -razor_package_query_create(struct razor_set *set)
  7.2215 -{
  7.2216 -	struct razor_package_query *pq;
  7.2217 -	int count;
  7.2218 -
  7.2219 -	pq = zalloc(sizeof *pq);
  7.2220 -	pq->set = set;
  7.2221 -	count = set->packages.size / sizeof(struct razor_package);
  7.2222 -	pq->vector = zalloc(count * sizeof(char));
  7.2223 -
  7.2224 -	return pq;
  7.2225 -}
  7.2226 -
  7.2227 -void
  7.2228 -razor_package_query_add_package(struct razor_package_query *pq,
  7.2229 -				struct razor_package *p)
  7.2230 -{
  7.2231 -	struct razor_package *packages;
  7.2232 -
  7.2233 -	packages = pq->set->packages.data;
  7.2234 -	pq->count += pq->vector[p - packages] ^ 1;
  7.2235 -	pq->vector[p - packages] = 1;
  7.2236 -}
  7.2237 -
  7.2238 -void
  7.2239 -razor_package_query_add_iterator(struct razor_package_query *pq,
  7.2240 -				 struct razor_package_iterator *pi)
  7.2241 -{
  7.2242 -	struct razor_package *packages, *p;
  7.2243 -	const char *name, *version, *arch;
  7.2244 -
  7.2245 -	packages = pq->set->packages.data;
  7.2246 -	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  7.2247 -		pq->count += pq->vector[p - packages] ^ 1;
  7.2248 -		pq->vector[p - packages] = 1;
  7.2249 -	}
  7.2250 -}
  7.2251 -
  7.2252 -struct razor_package_iterator *
  7.2253 -razor_package_query_finish(struct razor_package_query *pq)
  7.2254 -{
  7.2255 -	struct razor_package_iterator *pi;
  7.2256 -	struct razor_set *set;
  7.2257 -	struct list *index;
  7.2258 -	int i, j, count;
  7.2259 -
  7.2260 -	set = pq->set;
  7.2261 -	count = set->packages.size / sizeof(struct razor_package);
  7.2262 -	index = zalloc(pq->count * sizeof *index);
  7.2263 -
  7.2264 -	for (i = 0, j = 0; i < count; i++) {
  7.2265 -		if (!pq->vector[i])
  7.2266 -			continue;
  7.2267 -
  7.2268 -		index[j].data = i;
  7.2269 -		if (j == pq->count - 1)
  7.2270 -			index[j].flags = 0x80;
  7.2271 -		j++;
  7.2272 -	}
  7.2273 -
  7.2274 -	free(pq);
  7.2275 -
  7.2276 -	pi = razor_package_iterator_create_with_index(set, index);
  7.2277 -	pi->free_index = 1;
  7.2278 -
  7.2279 -	return pi;
  7.2280 -}
     8.1 --- a/librazor/razor.h	Fri Jun 20 14:18:52 2008 -0400
     8.2 +++ b/librazor/razor.h	Fri Jun 20 15:10:34 2008 -0400
     8.3 @@ -164,6 +164,7 @@
     8.4  
     8.5  void razor_build_evr(char *evr_buf, int size, const char *epoch,
     8.6  		     const char *version, const char *release);
     8.7 +int razor_versioncmp(const char *s1, const char *s2);
     8.8  
     8.9  struct razor_set *razor_set_create_from_yum(void);
    8.10  struct razor_set *razor_set_create_from_rpmdb(void);
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/librazor/root.c	Fri Jun 20 15:10:34 2008 -0400
     9.3 @@ -0,0 +1,168 @@
     9.4 +#include <stdlib.h>
     9.5 +#include <stdint.h>
     9.6 +#include <stdio.h>
     9.7 +#include <sys/stat.h>
     9.8 +#include <dirent.h>
     9.9 +#include <unistd.h>
    9.10 +#include <fcntl.h>
    9.11 +#include "razor.h"
    9.12 +#include "razor-internal.h"
    9.13 +
    9.14 +static const char system_repo_filename[] = "system.repo";
    9.15 +static const char next_repo_filename[] = "system-next.repo";
    9.16 +static const char razor_root_path[] = "/var/lib/razor";
    9.17 +
    9.18 +struct razor_root {
    9.19 +	struct razor_set *system;
    9.20 +	struct razor_set *next;
    9.21 +	int fd;
    9.22 +	char path[PATH_MAX];
    9.23 +	char new_path[PATH_MAX];
    9.24 +};
    9.25 +
    9.26 +int
    9.27 +razor_root_create(const char *root)
    9.28 +{
    9.29 +	struct stat buf;
    9.30 +	struct razor_set *set;
    9.31 +	char path[PATH_MAX];
    9.32 +
    9.33 +	if (stat(root, &buf) < 0) {
    9.34 +		if (mkdir(root, 0777) < 0) {
    9.35 +			fprintf(stderr,
    9.36 +				"could not create install root \"%s\"\n",
    9.37 +				root);
    9.38 +			return -1;
    9.39 +		}
    9.40 +		fprintf(stderr, "created install root \"%s\"\n", root);
    9.41 +	} else if (!S_ISDIR(buf.st_mode)) {
    9.42 +		fprintf(stderr,
    9.43 +			"install root \"%s\" exists, but is not a directory\n",
    9.44 +			root);
    9.45 +		return -1;
    9.46 +	}
    9.47 +
    9.48 +	snprintf(path, sizeof path, "%s/%s",
    9.49 +		 razor_root_path, system_repo_filename);
    9.50 +	if (razor_create_dir(root, path) < 0) {
    9.51 +		fprintf(stderr, "could not create %s%s\n",
    9.52 +			root, razor_root_path);
    9.53 +		return -1;
    9.54 +	}
    9.55 +
    9.56 +	set = razor_set_create();
    9.57 +	snprintf(path, sizeof path, "%s%s/%s",
    9.58 +		 root, razor_root_path, system_repo_filename);
    9.59 +	if (stat(path, &buf) == 0) {
    9.60 +		fprintf(stderr,
    9.61 +			"a razor install root is already initialized\n");
    9.62 +		return -1;
    9.63 +	}
    9.64 +	if (razor_set_write(set, path) < 0) {
    9.65 +		fprintf(stderr, "could not write initial package set\n");
    9.66 +		return -1;
    9.67 +	}
    9.68 +	razor_set_destroy(set);
    9.69 +
    9.70 +	return 0;
    9.71 +}
    9.72 +
    9.73 +struct razor_root *
    9.74 +razor_root_open(const char *root, int flags)
    9.75 +{
    9.76 +	struct razor_root *image;
    9.77 +
    9.78 +	image = malloc(sizeof *image);
    9.79 +	if (image == NULL)
    9.80 +		return NULL;
    9.81 +
    9.82 +	/* Create the new next repo file up front to ensure exclusive
    9.83 +	 * access. */
    9.84 +	snprintf(image->new_path, sizeof image->new_path,
    9.85 +		 "%s%s/%s", root, razor_root_path, next_repo_filename);
    9.86 +	image->fd = open(image->new_path,
    9.87 +			 O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666);
    9.88 +	if (image->fd < 0) {
    9.89 +		fprintf(stderr, "failed to get lock file, "
    9.90 +			"maybe previous operation crashed?\n");
    9.91 +
    9.92 +		/* FIXME: Use fcntl advisory locking on the system
    9.93 +		 * package set file to figure out whether previous
    9.94 +		 * operation crashed or is still in progress. */
    9.95 +
    9.96 +		free(image);
    9.97 +		return NULL;
    9.98 +	}
    9.99 +
   9.100 +	snprintf(image->path, sizeof image->path,
   9.101 +		 "%s%s/%s", root, razor_root_path, system_repo_filename);
   9.102 +	image->system = razor_set_open(image->path);
   9.103 +	if (image->system == NULL) {
   9.104 +		unlink(image->new_path);
   9.105 +		close(image->fd);
   9.106 +		free(image);
   9.107 +		return NULL;
   9.108 +	}
   9.109 +
   9.110 +	return image;
   9.111 +}
   9.112 +
   9.113 +struct razor_set *
   9.114 +razor_root_open_read_only(const char *root)
   9.115 +{
   9.116 +	char path[PATH_MAX];
   9.117 +
   9.118 +	snprintf(path, sizeof path, "%s%s/%s",
   9.119 +		 root, razor_root_path, system_repo_filename);
   9.120 +
   9.121 +	return razor_set_open(path);
   9.122 +}
   9.123 +
   9.124 +struct razor_transaction *
   9.125 +razor_root_create_transaction(struct razor_root *image,
   9.126 +			      struct razor_set *upstream)
   9.127 +{
   9.128 +	/* FIXME: This should take a number of upstream repos. */
   9.129 +	return razor_transaction_create(image->system, upstream);
   9.130 +}
   9.131 +
   9.132 +int
   9.133 +razor_root_close(struct razor_root *image)
   9.134 +{
   9.135 +	unlink(image->new_path);
   9.136 +	close(image->fd);
   9.137 +	free(image);
   9.138 +
   9.139 +	return 0;
   9.140 +}
   9.141 +
   9.142 +void
   9.143 +razor_root_update(struct razor_root *root, struct razor_set *next)
   9.144 +{
   9.145 +	razor_set_write_to_fd(next, root->fd);
   9.146 +	root->next = next;
   9.147 +
   9.148 +	/* Sync the new repo file so the new package set is on disk
   9.149 +	 * before we start upgrading. */
   9.150 +	fsync(root->fd);
   9.151 +	printf("wrote %s\n", root->new_path);
   9.152 +}
   9.153 +
   9.154 +int
   9.155 +razor_root_commit(struct razor_root *image)
   9.156 +{
   9.157 +	/* Make it so. */
   9.158 +	rename(image->new_path, image->path);
   9.159 +	printf("renamed %s to %s\n", image->new_path, image->path);
   9.160 +	close(image->fd);
   9.161 +	free(image);
   9.162 +
   9.163 +	return 0;
   9.164 +}
   9.165 +
   9.166 +void
   9.167 +razor_root_diff(struct razor_root *root,
   9.168 +		razor_package_callback_t callback, void *data)
   9.169 +{
   9.170 +	return razor_set_diff(root->system, root->next, callback, data);
   9.171 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/librazor/transaction.c	Fri Jun 20 15:10:34 2008 -0400
    10.3 @@ -0,0 +1,912 @@
    10.4 +/*
    10.5 + * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    10.6 + * Copyright (C) 2008  Red Hat, Inc
    10.7 + *
    10.8 + * This program is free software; you can redistribute it and/or modify
    10.9 + * it under the terms of the GNU General Public License as published by
   10.10 + * the Free Software Foundation; either version 2 of the License, or
   10.11 + * (at your option) any later version.
   10.12 + *
   10.13 + * This program is distributed in the hope that it will be useful,
   10.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.16 + * GNU General Public License for more details.
   10.17 + *
   10.18 + * You should have received a copy of the GNU General Public License along
   10.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
   10.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   10.21 + */
   10.22 +
   10.23 +#define _GNU_SOURCE
   10.24 +
   10.25 +#include <stdlib.h>
   10.26 +#include <stddef.h>
   10.27 +#include <stdint.h>
   10.28 +#include <stdio.h>
   10.29 +#include <string.h>
   10.30 +#include <sys/types.h>
   10.31 +#include <sys/stat.h>
   10.32 +#include <sys/mman.h>
   10.33 +#include <unistd.h>
   10.34 +#include <fcntl.h>
   10.35 +#include <errno.h>
   10.36 +#include <ctype.h>
   10.37 +#include <fnmatch.h>
   10.38 +
   10.39 +#include "razor-internal.h"
   10.40 +#include "razor.h"
   10.41 +
   10.42 +static int
   10.43 +provider_satisfies_requirement(struct razor_property *provider,
   10.44 +			       const char *provider_strings,
   10.45 +			       uint32_t flags,
   10.46 +			       const char *required)
   10.47 +{
   10.48 +	int cmp, len;
   10.49 +	const char *provided = &provider_strings[provider->version];
   10.50 +
   10.51 +	if (!*required)
   10.52 +		return 1;
   10.53 +	if (!*provided) {
   10.54 +		if (flags & RAZOR_PROPERTY_LESS)
   10.55 +			return 0;
   10.56 +		else
   10.57 +			return 1;
   10.58 +	}
   10.59 +
   10.60 +	cmp = razor_versioncmp(provided, required);
   10.61 +
   10.62 +	switch (flags & RAZOR_PROPERTY_RELATION_MASK) {
   10.63 +	case RAZOR_PROPERTY_LESS:
   10.64 +		return cmp < 0;
   10.65 +
   10.66 +	case RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL:
   10.67 +		if (cmp <= 0)
   10.68 +			return 1;
   10.69 +		/* fall through: FIXME, make sure this is correct */
   10.70 +
   10.71 +	case RAZOR_PROPERTY_EQUAL:
   10.72 +		if (cmp == 0)
   10.73 +			return 1;
   10.74 +
   10.75 +		/* "foo == 1.1" is satisfied by "foo 1.1-2" */
   10.76 +		len = strlen(required);
   10.77 +		if (!strncmp(required, provided, len) && provided[len] == '-')
   10.78 +			return 1;
   10.79 +		return 0;
   10.80 +
   10.81 +	case RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL:
   10.82 +		return cmp >= 0;
   10.83 +
   10.84 +	case RAZOR_PROPERTY_GREATER:
   10.85 +		return cmp > 0;
   10.86 +	}
   10.87 +
   10.88 +	/* shouldn't happen */
   10.89 +	return 0;
   10.90 +}
   10.91 +
   10.92 +#define TRANS_PACKAGE_PRESENT		1
   10.93 +#define TRANS_PACKAGE_UPDATE		2
   10.94 +#define TRANS_PROPERTY_SATISFIED	0x80000000
   10.95 +
   10.96 +struct transaction_set {
   10.97 +	struct razor_set *set;
   10.98 +	uint32_t *packages;
   10.99 +	uint32_t *properties;
  10.100 +};
  10.101 +
  10.102 +struct razor_transaction {
  10.103 +	int package_count, errors;
  10.104 +	struct transaction_set system, upstream;
  10.105 +	int changes;
  10.106 +};
  10.107 +
  10.108 +static void
  10.109 +transaction_set_init(struct transaction_set *ts, struct razor_set *set)
  10.110 +{
  10.111 +	int count;
  10.112 +
  10.113 +	ts->set = set;
  10.114 +	count = set->packages.size / sizeof (struct razor_package);
  10.115 +	ts->packages = zalloc(count * sizeof *ts->packages);
  10.116 +	count = set->properties.size / sizeof (struct razor_property);
  10.117 +	ts->properties = zalloc(count * sizeof *ts->properties);
  10.118 +}
  10.119 +
  10.120 +static void
  10.121 +transaction_set_release(struct transaction_set *ts)
  10.122 +{
  10.123 +	free(ts->packages);
  10.124 +	free(ts->properties);
  10.125 +}
  10.126 +
  10.127 +static void
  10.128 +transaction_set_install_package(struct transaction_set *ts,
  10.129 +				struct razor_package *package)
  10.130 +{
  10.131 +	struct razor_package *pkgs;
  10.132 +	struct list *prop;
  10.133 +	int i;
  10.134 +
  10.135 +	pkgs = ts->set->packages.data;
  10.136 +	i = package - pkgs;
  10.137 +	if (ts->packages[i] == TRANS_PACKAGE_PRESENT)
  10.138 +		return;
  10.139 +
  10.140 +	ts->packages[i] = TRANS_PACKAGE_PRESENT;
  10.141 +
  10.142 +	prop = list_first(&package->properties, &ts->set->property_pool);
  10.143 +	while (prop) {
  10.144 +		ts->properties[prop->data]++;
  10.145 +		prop = list_next(prop);
  10.146 +	}
  10.147 +}
  10.148 +
  10.149 +static void
  10.150 +transaction_set_remove_package(struct transaction_set *ts,
  10.151 +			       struct razor_package *package)
  10.152 +{
  10.153 +	struct razor_package *pkgs;
  10.154 +	struct list *prop;
  10.155 +	int i;
  10.156 +
  10.157 +	pkgs = ts->set->packages.data;
  10.158 +	i = package - pkgs;
  10.159 +	if (ts->packages[i] == 0)
  10.160 +		return;
  10.161 +
  10.162 +	ts->packages[i] = 0;
  10.163 +
  10.164 +	prop = list_first(&package->properties, &ts->set->property_pool);
  10.165 +	while (prop) {
  10.166 +		ts->properties[prop->data]--;
  10.167 +		prop = list_next(prop);
  10.168 +	}
  10.169 +}
  10.170 +
  10.171 +struct razor_transaction *
  10.172 +razor_transaction_create(struct razor_set *system, struct razor_set *upstream)
  10.173 +{
  10.174 +	struct razor_transaction *trans;
  10.175 +	struct razor_package *p, *spkgs, *pend;
  10.176 +
  10.177 +	trans = zalloc(sizeof *trans);
  10.178 +	transaction_set_init(&trans->system, system);
  10.179 +	transaction_set_init(&trans->upstream, upstream);
  10.180 +
  10.181 +	spkgs = trans->system.set->packages.data;
  10.182 +	pend = trans->system.set->packages.data +
  10.183 +		trans->system.set->packages.size;
  10.184 +	for (p = spkgs; p < pend; p++)
  10.185 +		transaction_set_install_package(&trans->system, p);
  10.186 +
  10.187 +	return trans;
  10.188 +}
  10.189 +
  10.190 +void
  10.191 +razor_transaction_install_package(struct razor_transaction *trans,
  10.192 +				  struct razor_package *package)
  10.193 +{
  10.194 +	transaction_set_install_package(&trans->upstream, package);
  10.195 +	trans->changes++;
  10.196 +}
  10.197 +
  10.198 +void
  10.199 +razor_transaction_remove_package(struct razor_transaction *trans,
  10.200 +				 struct razor_package *package)
  10.201 +{
  10.202 +	transaction_set_remove_package(&trans->system, package);
  10.203 +	trans->changes++;
  10.204 +}
  10.205 +
  10.206 +void
  10.207 +razor_transaction_update_package(struct razor_transaction *trans,
  10.208 +				  struct razor_package *package)
  10.209 +{
  10.210 +	struct razor_package *spkgs, *upkgs, *end;
  10.211 +
  10.212 +	spkgs = trans->system.set->packages.data;
  10.213 +	upkgs = trans->upstream.set->packages.data;
  10.214 +	end = trans->system.set->packages.data +
  10.215 +		trans->system.set->packages.size;
  10.216 +	if (spkgs <= package && package < end)
  10.217 +		trans->system.packages[package - spkgs] |= TRANS_PACKAGE_UPDATE;
  10.218 +	else
  10.219 +		trans->upstream.packages[package - upkgs] |= TRANS_PACKAGE_UPDATE;
  10.220 +}
  10.221 +
  10.222 +struct prop_iter {
  10.223 +	struct razor_property *p, *start, *end;
  10.224 +	const char *pool;
  10.225 +	uint32_t *present;
  10.226 +};
  10.227 +
  10.228 +static void
  10.229 +prop_iter_init(struct prop_iter *pi, struct transaction_set *ts)
  10.230 +{
  10.231 +	pi->p = ts->set->properties.data;
  10.232 +	pi->start = ts->set->properties.data;
  10.233 +	pi->end = ts->set->properties.data + ts->set->properties.size;
  10.234 +	pi->pool = ts->set->string_pool.data;
  10.235 +	pi->present = ts->properties;
  10.236 +}
  10.237 +
  10.238 +static int
  10.239 +prop_iter_next(struct prop_iter *pi, uint32_t flags, struct razor_property **p)
  10.240 +{
  10.241 +	while (pi->p < pi->end) {
  10.242 +		if ((pi->present[pi->p - pi->start] & ~TRANS_PROPERTY_SATISFIED) &&
  10.243 +		    (pi->p->flags & RAZOR_PROPERTY_TYPE_MASK) == flags) {
  10.244 +			*p = pi->p++;
  10.245 +			return 1;
  10.246 +		}
  10.247 +		pi->p++;
  10.248 +	}
  10.249 +
  10.250 +	return 0;
  10.251 +}
  10.252 +
  10.253 +static struct razor_property *
  10.254 +prop_iter_seek_to(struct prop_iter *pi,
  10.255 +		  uint32_t flags, const char *match)
  10.256 +{
  10.257 +	uint32_t name;
  10.258 +
  10.259 +	while (pi->p < pi->end && strcmp(&pi->pool[pi->p->name], match) < 0)
  10.260 +		pi->p++;
  10.261 +
  10.262 +	if (pi->p == pi->end || strcmp(&pi->pool[pi->p->name], match) > 0)
  10.263 +		return NULL;
  10.264 +
  10.265 +	name = pi->p->name;
  10.266 +	while (pi->p < pi->end &&
  10.267 +	       pi->p->name == name &&
  10.268 +	       (pi->p->flags & RAZOR_PROPERTY_TYPE_MASK) != flags)
  10.269 +		pi->p++;
  10.270 +
  10.271 +	if (pi->p == pi->end || pi->p->name != name)
  10.272 +		return NULL;
  10.273 +
  10.274 +	return pi->p;
  10.275 +}
  10.276 +
  10.277 +/* Remove packages from set that provide any of the matching (same
  10.278 + * name and type) providers from ppi onwards that match the
  10.279 + * requirement that rpi points to. */
  10.280 +static void
  10.281 +remove_matching_providers(struct razor_transaction *trans,
  10.282 +			  struct prop_iter *ppi,
  10.283 +			  uint32_t flags,
  10.284 +			  const char *version)
  10.285 +{
  10.286 +	struct razor_property *p;
  10.287 +	struct razor_package *pkg, *pkgs;
  10.288 +	struct razor_package_iterator pkg_iter;
  10.289 +	struct razor_set *set;
  10.290 +	const char *n, *v, *a;
  10.291 +	uint32_t type;
  10.292 +
  10.293 +	if (ppi->present == trans->system.properties)
  10.294 +		set = trans->system.set;
  10.295 +	else
  10.296 +		set = trans->upstream.set;
  10.297 +
  10.298 +	pkgs = (struct razor_package *) set->packages.data;
  10.299 +	type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
  10.300 +	for (p = ppi->p;
  10.301 +	     p < ppi->end &&
  10.302 +	     p->name == ppi->p->name &&
  10.303 +	     (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
  10.304 +	     p++) {
  10.305 +		if (!ppi->present[p - ppi->start])
  10.306 +			continue;
  10.307 +		if (!provider_satisfies_requirement(p, ppi->pool,
  10.308 +						    flags, version))
  10.309 +			continue;
  10.310 +
  10.311 +		razor_package_iterator_init_for_property(&pkg_iter, set, p);
  10.312 +		while (razor_package_iterator_next(&pkg_iter,
  10.313 +						   &pkg, &n, &v, &a)) {
  10.314 +			fprintf(stderr, "removing %s-%s\n", n, v);
  10.315 +			razor_transaction_remove_package(trans, pkg);
  10.316 +		}
  10.317 +	}
  10.318 +}
  10.319 +
  10.320 +static void
  10.321 +flag_matching_providers(struct razor_transaction *trans,
  10.322 +			struct prop_iter *ppi,
  10.323 +			struct razor_property *r,
  10.324 +			struct prop_iter *rpi,
  10.325 +			unsigned int flag)
  10.326 +{
  10.327 +	struct razor_property *p;
  10.328 +	struct razor_package *pkg, *pkgs;
  10.329 +	struct razor_package_iterator pkg_iter;
  10.330 +	struct razor_set *set;
  10.331 +	const char *name, *version, *arch;
  10.332 +	uint32_t *flags, type;
  10.333 +
  10.334 +	if (ppi->present == trans->system.properties) {
  10.335 +		set = trans->system.set;
  10.336 +		flags = trans->system.packages;
  10.337 +	} else {
  10.338 +		set = trans->upstream.set;
  10.339 +		flags = trans->upstream.packages;
  10.340 +	}
  10.341 +
  10.342 +	pkgs = (struct razor_package *) set->packages.data;
  10.343 +	type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
  10.344 +	for (p = ppi->p;
  10.345 +	     p < ppi->end &&
  10.346 +		     p->name == ppi->p->name &&
  10.347 +		     (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
  10.348 +	     p++) {
  10.349 +		if (!ppi->present[p - ppi->start])
  10.350 +			continue;
  10.351 +		if (!provider_satisfies_requirement(p, ppi->pool,
  10.352 +						    r->flags,
  10.353 +						    &rpi->pool[r->version]))
  10.354 +			continue;
  10.355 +
  10.356 +		razor_package_iterator_init_for_property(&pkg_iter, set, p);
  10.357 +		while (razor_package_iterator_next(&pkg_iter, &pkg,
  10.358 +						   &name, &version, &arch)) {
  10.359 +
  10.360 +			fprintf(stderr, "flagging %s-%s for providing %s matching %s %s\n",
  10.361 +				name, version,
  10.362 +				ppi->pool + p->name,
  10.363 +				rpi->pool + r->name,
  10.364 +				rpi->pool + r->version);
  10.365 +			flags[pkg - pkgs] |= flag;
  10.366 +		}
  10.367 +	}
  10.368 +}
  10.369 +
  10.370 +static struct razor_package *
  10.371 +pick_matching_provider(struct razor_set *set,
  10.372 +		       struct prop_iter *ppi,
  10.373 +		       uint32_t flags,
  10.374 +		       const char *version)
  10.375 +{
  10.376 +	struct razor_property *p;
  10.377 +	struct razor_package *pkgs;
  10.378 +	struct list *i;
  10.379 +	uint32_t type;
  10.380 +
  10.381 +	/* This is where we decide which pkgs to pull in to satisfy a
  10.382 +	 * requirement.  There may be several different providers
  10.383 +	 * (different versions) and each version of a provider may
  10.384 +	 * come from a number of packages.  We pick the first package
  10.385 +	 * from the first provider that matches. */
  10.386 +
  10.387 +	pkgs = set->packages.data;
  10.388 +	type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
  10.389 +	for (p = ppi->p;
  10.390 +	     p < ppi->end &&
  10.391 +		     p->name == ppi->p->name &&
  10.392 +		     (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type &&
  10.393 +		     ppi->present[p - ppi->start] == 0;
  10.394 +	     p++) {
  10.395 +		if (!provider_satisfies_requirement(p, ppi->pool,
  10.396 +						    flags, version))
  10.397 +			continue;
  10.398 +
  10.399 +		i = list_first(&p->packages, &set->package_pool);
  10.400 +
  10.401 +		return &pkgs[i->data];
  10.402 +	}
  10.403 +
  10.404 +	return NULL;
  10.405 +}
  10.406 +
  10.407 +static void
  10.408 +remove_obsoleted_packages(struct razor_transaction *trans)
  10.409 +{
  10.410 +	struct razor_property *up;
  10.411 +	struct razor_package *spkgs;
  10.412 +	struct prop_iter spi, upi;
  10.413 +
  10.414 +	spkgs = trans->system.set->packages.data;
  10.415 +	prop_iter_init(&spi, &trans->system);
  10.416 +	prop_iter_init(&upi, &trans->upstream);
  10.417 +
  10.418 +	while (prop_iter_next(&upi, RAZOR_PROPERTY_OBSOLETES, &up)) {
  10.419 +		if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
  10.420 +				       &upi.pool[up->name]))
  10.421 +			continue;
  10.422 +		remove_matching_providers(trans, &spi, up->flags,
  10.423 +					  &upi.pool[up->version]);
  10.424 +	}
  10.425 +}
  10.426 +
  10.427 +static int
  10.428 +any_provider_satisfies_requirement(struct prop_iter *ppi,
  10.429 +				   uint32_t flags,
  10.430 +				   const char *version)
  10.431 +{
  10.432 +	struct razor_property *p;
  10.433 +	uint32_t type;
  10.434 +
  10.435 +	type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
  10.436 +	for (p = ppi->p;
  10.437 +	     p < ppi->end &&
  10.438 +		     p->name == ppi->p->name &&
  10.439 +		     (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
  10.440 +	     p++) {
  10.441 +		if (ppi->present[p - ppi->start] > 0 &&
  10.442 +		    provider_satisfies_requirement(p, ppi->pool,
  10.443 +						   flags, version))
  10.444 +			return 1;
  10.445 +	}
  10.446 +
  10.447 +	return 0;
  10.448 +}
  10.449 +
  10.450 +static void
  10.451 +clear_requires_flags(struct transaction_set *ts)
  10.452 +{
  10.453 +	struct razor_property *p;
  10.454 +	const char *pool;
  10.455 +	int i, count;
  10.456 +
  10.457 +	count = ts->set->properties.size / sizeof *p;
  10.458 +	p = ts->set->properties.data;
  10.459 +	pool = ts->set->string_pool.data;
  10.460 +	for (i = 0; i < count; i++) {
  10.461 +		ts->properties[i] &= ~TRANS_PROPERTY_SATISFIED;
  10.462 +		if (strncmp(&pool[p[i].name], "rpmlib(", 7) == 0)
  10.463 +			ts->properties[i] |= TRANS_PROPERTY_SATISFIED;
  10.464 +	}
  10.465 +}
  10.466 +
  10.467 +const char *
  10.468 +razor_property_relation_to_string(struct razor_property *p)
  10.469 +{
  10.470 +	switch (p->flags & RAZOR_PROPERTY_RELATION_MASK) {
  10.471 +	case RAZOR_PROPERTY_LESS:
  10.472 +		return "<";
  10.473 +
  10.474 +	case RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL:
  10.475 +		return "<=";
  10.476 +
  10.477 +	case RAZOR_PROPERTY_EQUAL:
  10.478 +		return "=";
  10.479 +
  10.480 +	case RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL:
  10.481 +		return ">=";
  10.482 +
  10.483 +	case RAZOR_PROPERTY_GREATER:
  10.484 +		return ">";
  10.485 +
  10.486 +	default:
  10.487 +		return "?";
  10.488 +	}
  10.489 +}
  10.490 +
  10.491 +const char *
  10.492 +razor_property_type_to_string(struct razor_property *p)
  10.493 +{
  10.494 +	switch (p->flags & RAZOR_PROPERTY_TYPE_MASK) {
  10.495 +	case RAZOR_PROPERTY_REQUIRES:
  10.496 +		return "requires";
  10.497 +	case RAZOR_PROPERTY_PROVIDES:
  10.498 +		return "provides";
  10.499 +	case RAZOR_PROPERTY_CONFLICTS:
  10.500 +		return "conflicts";
  10.501 +	case RAZOR_PROPERTY_OBSOLETES:
  10.502 +		return "obsoletes";
  10.503 +	default:
  10.504 +		return NULL;
  10.505 +	}
  10.506 +}
  10.507 +
  10.508 +static void
  10.509 +mark_satisfied_requires(struct razor_transaction *trans,
  10.510 +			struct transaction_set *rts,
  10.511 +			struct transaction_set *pts)
  10.512 +{
  10.513 +	struct prop_iter rpi, ppi;
  10.514 +	struct razor_property *rp;
  10.515 +
  10.516 +	prop_iter_init(&rpi, rts);
  10.517 +	prop_iter_init(&ppi, pts);
  10.518 +
  10.519 +	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  10.520 +		if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES,
  10.521 +				       &rpi.pool[rp->name]))
  10.522 +			continue;
  10.523 +
  10.524 +		if (any_provider_satisfies_requirement(&ppi, rp->flags,
  10.525 +						       &rpi.pool[rp->version]))
  10.526 +			rpi.present[rp - rpi.start] |= TRANS_PROPERTY_SATISFIED;
  10.527 +	}
  10.528 +}
  10.529 +
  10.530 +static void
  10.531 +mark_all_satisfied_requires(struct razor_transaction *trans)
  10.532 +{
  10.533 +	clear_requires_flags(&trans->system);
  10.534 +	clear_requires_flags(&trans->upstream);
  10.535 +	mark_satisfied_requires(trans, &trans->system, &trans->system);
  10.536 +	mark_satisfied_requires(trans, &trans->system, &trans->upstream);
  10.537 +	mark_satisfied_requires(trans, &trans->upstream, &trans->system);
  10.538 +	mark_satisfied_requires(trans, &trans->upstream, &trans->upstream);
  10.539 +}
  10.540 +
  10.541 +static void
  10.542 +update_unsatisfied_packages(struct razor_transaction *trans)
  10.543 +{
  10.544 +	struct razor_package *spkgs, *pkg;
  10.545 +	struct razor_property *sp;
  10.546 +	struct prop_iter spi;
  10.547 +	struct razor_package_iterator pkg_iter;
  10.548 +	const char *name, *version, *arch;
  10.549 +
  10.550 +	spkgs = trans->system.set->packages.data;
  10.551 +	prop_iter_init(&spi, &trans->system);
  10.552 +
  10.553 +	while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
  10.554 +		if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
  10.555 +			continue;
  10.556 +
  10.557 +		razor_package_iterator_init_for_property(&pkg_iter,
  10.558 +							 trans->system.set,
  10.559 +							 sp);
  10.560 +		while (razor_package_iterator_next(&pkg_iter, &pkg,
  10.561 +						   &name, &version, &arch)) {
  10.562 +			fprintf(stderr, "updating %s because %s %s %s "
  10.563 +				"isn't satisfied\n",
  10.564 +				name, spi.pool + sp->name,
  10.565 +				razor_property_relation_to_string(sp),
  10.566 +				spi.pool + sp->version);
  10.567 +			trans->system.packages[pkg - spkgs] |=
  10.568 +				TRANS_PACKAGE_UPDATE;
  10.569 +		}
  10.570 +	}
  10.571 +}
  10.572 +
  10.573 +void
  10.574 +razor_transaction_update_all(struct razor_transaction *trans)
  10.575 +{
  10.576 +	struct razor_package *p;
  10.577 +	int i, count;
  10.578 +
  10.579 +	count = trans->system.set->packages.size / sizeof *p;
  10.580 +	for (i = 0; i < count; i++)
  10.581 +		trans->system.packages[i] |= TRANS_PACKAGE_UPDATE;
  10.582 +}
  10.583 +
  10.584 +static void
  10.585 +update_conflicted_packages(struct razor_transaction *trans)
  10.586 +{
  10.587 +	struct razor_package *pkg, *spkgs;
  10.588 +	struct razor_property *up, *sp;
  10.589 +	struct prop_iter spi, upi;
  10.590 +	struct razor_package_iterator pkg_iter;
  10.591 +	const char *name, *version, *arch;
  10.592 +
  10.593 +	spkgs = trans->system.set->packages.data;
  10.594 +	prop_iter_init(&spi, &trans->system);
  10.595 +	prop_iter_init(&upi, &trans->upstream);
  10.596 +
  10.597 +	while (prop_iter_next(&spi, RAZOR_PROPERTY_CONFLICTS, &sp)) {
  10.598 +		if (!prop_iter_seek_to(&upi, RAZOR_PROPERTY_PROVIDES,
  10.599 +				       &spi.pool[sp->name]))
  10.600 +			continue;
  10.601 +
  10.602 +		if (!any_provider_satisfies_requirement(&upi, sp->flags,
  10.603 +							&spi.pool[sp->version]))
  10.604 +			continue;
  10.605 +
  10.606 +		razor_package_iterator_init_for_property(&pkg_iter,
  10.607 +							 trans->system.set,
  10.608 +							 sp);
  10.609 +		while (razor_package_iterator_next(&pkg_iter, &pkg,
  10.610 +						   &name, &version, &arch)) {
  10.611 +			fprintf(stderr, "updating %s %s because it conflicts with %s",
  10.612 +				name, version, spi.pool + sp->name);
  10.613 +			trans->system.packages[pkg - spkgs] |=
  10.614 +				TRANS_PACKAGE_UPDATE;
  10.615 +		}
  10.616 +	}
  10.617 +
  10.618 +	prop_iter_init(&spi, &trans->system);
  10.619 +	prop_iter_init(&upi, &trans->upstream);
  10.620 +
  10.621 +	while (prop_iter_next(&upi, RAZOR_PROPERTY_CONFLICTS, &up)) {
  10.622 +		sp = prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
  10.623 +				       &upi.pool[upi.p->name]);
  10.624 +
  10.625 +		if (sp)
  10.626 +			flag_matching_providers(trans, &spi, up, &upi,
  10.627 +						TRANS_PACKAGE_UPDATE);
  10.628 +	}
  10.629 +}
  10.630 +
  10.631 +static void
  10.632 +pull_in_requirements(struct razor_transaction *trans,
  10.633 +		     struct prop_iter *rpi, struct prop_iter *ppi)
  10.634 +{
  10.635 +	struct razor_property *rp, *pp;
  10.636 +	struct razor_package *pkg, *upkgs;
  10.637 +
  10.638 +	upkgs = trans->upstream.set->packages.data;
  10.639 +	while (prop_iter_next(rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  10.640 +		if (rpi->present[rp - rpi->start] & TRANS_PROPERTY_SATISFIED)
  10.641 +			continue;
  10.642 +
  10.643 +		pp = prop_iter_seek_to(ppi, RAZOR_PROPERTY_PROVIDES,
  10.644 +				       &rpi->pool[rp->name]);
  10.645 +		if (pp == NULL)
  10.646 +			continue;
  10.647 +		pkg = pick_matching_provider(trans->upstream.set,
  10.648 +					     ppi, rp->flags,
  10.649 +					     &rpi->pool[rp->version]);
  10.650 +		if (pkg == NULL)
  10.651 +			continue;
  10.652 +
  10.653 +		rpi->present[rp - rpi->start] |= TRANS_PROPERTY_SATISFIED;
  10.654 +
  10.655 +		fprintf(stderr, "pulling in %s which provides %s %s %s "
  10.656 +			"to satisfy %s %s %s\n",
  10.657 +			ppi->pool + pkg->name,
  10.658 +			ppi->pool + pp->name,
  10.659 +			razor_property_relation_to_string(pp),
  10.660 +			ppi->pool + pp->version,
  10.661 +			&rpi->pool[rp->name],
  10.662 +			razor_property_relation_to_string(rp),
  10.663 +			&rpi->pool[rp->version]);
  10.664 +
  10.665 +		trans->upstream.packages[pkg - upkgs] |= TRANS_PACKAGE_UPDATE;
  10.666 +	}
  10.667 +}
  10.668 +
  10.669 +static void
  10.670 +pull_in_all_requirements(struct razor_transaction *trans)
  10.671 +{
  10.672 +	struct prop_iter rpi, ppi;
  10.673 +
  10.674 +	prop_iter_init(&rpi, &trans->system);
  10.675 +	prop_iter_init(&ppi, &trans->upstream);
  10.676 +	pull_in_requirements(trans, &rpi, &ppi);
  10.677 +
  10.678 +	prop_iter_init(&rpi, &trans->upstream);
  10.679 +	prop_iter_init(&ppi, &trans->upstream);
  10.680 +	pull_in_requirements(trans, &rpi, &ppi);
  10.681 +}
  10.682 +
  10.683 +static void
  10.684 +flush_scheduled_system_updates(struct razor_transaction *trans)
  10.685 +{
  10.686 + 	struct razor_package_iterator *pi;
  10.687 + 	struct razor_package *p, *pkg, *spkgs;
  10.688 +	struct prop_iter ppi;
  10.689 +	const char *name, *version, *arch;
  10.690 +
  10.691 +	spkgs = trans->system.set->packages.data;
  10.692 +	pi = razor_package_iterator_create(trans->system.set);
  10.693 +	prop_iter_init(&ppi, &trans->upstream);
  10.694 +
  10.695 +	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  10.696 +		if (!(trans->system.packages[p - spkgs] & TRANS_PACKAGE_UPDATE))
  10.697 +			continue;
  10.698 +
  10.699 +		if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES, name))
  10.700 +			continue;
  10.701 +
  10.702 +		pkg = pick_matching_provider(trans->upstream.set, &ppi,
  10.703 +					     RAZOR_PROPERTY_GREATER, version);
  10.704 +		if (pkg == NULL)
  10.705 +			continue;
  10.706 +
  10.707 +		fprintf(stderr, "updating %s-%s to %s-%s\n",
  10.708 +			name, version,
  10.709 +			&ppi.pool[pkg->name], &ppi.pool[pkg->version]);
  10.710 +
  10.711 +		razor_transaction_remove_package(trans, p);
  10.712 +		razor_transaction_install_package(trans, pkg);
  10.713 +	}
  10.714 +
  10.715 +	razor_package_iterator_destroy(pi);
  10.716 +}
  10.717 +
  10.718 +static void
  10.719 +flush_scheduled_upstream_updates(struct razor_transaction *trans)
  10.720 +{
  10.721 + 	struct razor_package_iterator *pi;
  10.722 + 	struct razor_package *p, *upkgs;
  10.723 +	struct prop_iter spi;
  10.724 +	const char *name, *version, *arch;
  10.725 +
  10.726 +	upkgs = trans->upstream.set->packages.data;
  10.727 +	pi = razor_package_iterator_create(trans->upstream.set);
  10.728 +	prop_iter_init(&spi, &trans->system);
  10.729 +
  10.730 +	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  10.731 +		if (!(trans->upstream.packages[p - upkgs] & TRANS_PACKAGE_UPDATE))
  10.732 +			continue;
  10.733 +
  10.734 +		if (prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES, name))
  10.735 +			remove_matching_providers(trans,
  10.736 +						  &spi,
  10.737 +						  RAZOR_PROPERTY_LESS,
  10.738 +						  version);
  10.739 +		razor_transaction_install_package(trans, p);
  10.740 +		fprintf(stderr, "installing %s-%s\n", name, version);
  10.741 +	}
  10.742 +}
  10.743 +
  10.744 +int
  10.745 +razor_transaction_resolve(struct razor_transaction *trans)
  10.746 +{
  10.747 +	int last = 0;
  10.748 +
  10.749 +	flush_scheduled_system_updates(trans);
  10.750 +	flush_scheduled_upstream_updates(trans);
  10.751 +
  10.752 +	while (last < trans->changes) {
  10.753 +		last = trans->changes;
  10.754 +		remove_obsoleted_packages(trans);
  10.755 +		mark_all_satisfied_requires(trans);
  10.756 +		update_unsatisfied_packages(trans);
  10.757 +		update_conflicted_packages(trans);
  10.758 +		pull_in_all_requirements(trans);
  10.759 +		flush_scheduled_system_updates(trans);
  10.760 +		flush_scheduled_upstream_updates(trans);
  10.761 +	}
  10.762 +
  10.763 +	return trans->changes;
  10.764 +}
  10.765 +
  10.766 +static void
  10.767 +describe_unsatisfied(struct razor_set *set, struct razor_property *rp)
  10.768 +{
  10.769 +	struct razor_package_iterator pi;
  10.770 +	struct razor_package *pkg;
  10.771 +	const char *name, *version, *arch, *pool;
  10.772 +
  10.773 +	pool = set->string_pool.data;
  10.774 +	if (pool[rp->version] == '\0') {
  10.775 +		razor_package_iterator_init_for_property(&pi, set, rp);
  10.776 +		while (razor_package_iterator_next(&pi, &pkg,
  10.777 +						   &name, &version, &arch))
  10.778 +			fprintf(stderr, "%s is needed by %s-%s.%s\n",
  10.779 +				&pool[rp->name],
  10.780 +				name, version, arch);
  10.781 +	} else {
  10.782 +		razor_package_iterator_init_for_property(&pi, set, rp);
  10.783 +		while (razor_package_iterator_next(&pi, &pkg,
  10.784 +						   &name, &version, &arch))
  10.785 +			fprintf(stderr, "%s %s %s is needed by %s-%s.%s\n",
  10.786 +				&pool[rp->name],
  10.787 +				razor_property_relation_to_string(rp),
  10.788 +				&pool[rp->version],
  10.789 +				name, version, arch);
  10.790 +	}
  10.791 +}
  10.792 +
  10.793 +int
  10.794 +razor_transaction_describe(struct razor_transaction *trans)
  10.795 +{
  10.796 +	struct prop_iter rpi;
  10.797 +	struct razor_property *rp;
  10.798 +	int unsatisfied;
  10.799 +
  10.800 +	flush_scheduled_system_updates(trans);
  10.801 +	flush_scheduled_upstream_updates(trans);
  10.802 +	mark_all_satisfied_requires(trans);
  10.803 +
  10.804 +	unsatisfied = 0;
  10.805 +	prop_iter_init(&rpi, &trans->system);
  10.806 +	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  10.807 +		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
  10.808 +			describe_unsatisfied(trans->system.set, rp);
  10.809 +		        unsatisfied++;
  10.810 +		}
  10.811 +	}
  10.812 +
  10.813 +	prop_iter_init(&rpi, &trans->upstream);
  10.814 +	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  10.815 +		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
  10.816 +			describe_unsatisfied(trans->upstream.set, rp);
  10.817 +			unsatisfied++;
  10.818 +		}
  10.819 +	}
  10.820 +
  10.821 +	return unsatisfied;
  10.822 +}
  10.823 +
  10.824 +int
  10.825 +razor_transaction_unsatisfied_property(struct razor_transaction *trans,
  10.826 +				       const char *name,
  10.827 +				       uint32_t flags,
  10.828 +				       const char *version)
  10.829 +{
  10.830 +	struct prop_iter pi;
  10.831 +	struct razor_property *p;
  10.832 +
  10.833 +	prop_iter_init(&pi, &trans->system);
  10.834 +	while (prop_iter_next(&pi, flags, &p)) {
  10.835 +		if (!(trans->system.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
  10.836 +		    p->flags == flags &&
  10.837 +		    strcmp(&pi.pool[p->name], name) == 0 &&
  10.838 +		    strcmp(&pi.pool[p->version], version) == 0)
  10.839 +
  10.840 +			return 1;
  10.841 +	}
  10.842 +
  10.843 +	prop_iter_init(&pi, &trans->upstream);
  10.844 +	while (prop_iter_next(&pi, flags, &p)) {
  10.845 +		if (!(trans->upstream.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
  10.846 +		    p->flags == flags &&
  10.847 +		    strcmp(&pi.pool[p->name], name) == 0 &&
  10.848 +		    strcmp(&pi.pool[p->version], version) == 0)
  10.849 +
  10.850 +			return 1;
  10.851 +	}
  10.852 +
  10.853 +	return 0;
  10.854 +}
  10.855 +
  10.856 +struct razor_set *
  10.857 +razor_transaction_finish(struct razor_transaction *trans)
  10.858 +{
  10.859 +	struct razor_merger *merger;
  10.860 +	struct razor_package *u, *uend, *upkgs, *s, *send, *spkgs;
  10.861 +	char *upool, *spool;
  10.862 +	int cmp;
  10.863 +
  10.864 +	s = trans->system.set->packages.data;
  10.865 +	spkgs = trans->system.set->packages.data;
  10.866 +	send = trans->system.set->packages.data +
  10.867 +		trans->system.set->packages.size;
  10.868 +	spool = trans->system.set->string_pool.data;
  10.869 +
  10.870 +	u = trans->upstream.set->packages.data;
  10.871 +	upkgs = trans->upstream.set->packages.data;
  10.872 +	uend = trans->upstream.set->packages.data +
  10.873 +		trans->upstream.set->packages.size;
  10.874 +	upool = trans->upstream.set->string_pool.data;
  10.875 +
  10.876 +	merger = razor_merger_create(trans->system.set, trans->upstream.set);
  10.877 +	while (s < send || u < uend) {
  10.878 +		if (s < send && u < uend)
  10.879 +			cmp = strcmp(&spool[s->name], &upool[u->name]);
  10.880 +		else if (s < send)
  10.881 +			cmp = -1;
  10.882 +		else
  10.883 +			cmp = 1;
  10.884 +
  10.885 +		if (cmp < 0) {
  10.886 +			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
  10.887 +				razor_merger_add_package(merger, s);
  10.888 +			s++;
  10.889 +		} else if (cmp == 0) {
  10.890 +			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
  10.891 +				razor_merger_add_package(merger, s);
  10.892 +			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
  10.893 +				razor_merger_add_package(merger, u);
  10.894 +
  10.895 +			s++;
  10.896 +			u++;
  10.897 +		} else {
  10.898 +			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
  10.899 +				razor_merger_add_package(merger, u);
  10.900 +			u++;
  10.901 +		}
  10.902 +	}
  10.903 +
  10.904 +	razor_transaction_destroy(trans);
  10.905 +
  10.906 +	return razor_merger_finish(merger);
  10.907 +}
  10.908 +
  10.909 +void
  10.910 +razor_transaction_destroy(struct razor_transaction *trans)
  10.911 +{
  10.912 +	transaction_set_release(&trans->system);
  10.913 +	transaction_set_release(&trans->upstream);
  10.914 +	free(trans);
  10.915 +}
    11.1 --- a/librazor/types.c	Fri Jun 20 14:18:52 2008 -0400
    11.2 +++ b/librazor/types.c	Fri Jun 20 15:10:34 2008 -0400
    11.3 @@ -1,7 +1,7 @@
    11.4  #include <stdlib.h>
    11.5  #include <string.h>
    11.6  
    11.7 -#include "types.h"
    11.8 +#include "razor-internal.h"
    11.9  
   11.10  void
   11.11  array_init(struct array *array)
    12.1 --- a/librazor/types.h	Fri Jun 20 14:18:52 2008 -0400
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,59 +0,0 @@
    12.4 -#ifndef _RAZOR_TYPES_H_
    12.5 -#define _RAZOR_TYPES_H_
    12.6 -
    12.7 -#include <stdint.h>
    12.8 -
    12.9 -struct array {
   12.10 -	void *data;
   12.11 -	int size, alloc;
   12.12 -};
   12.13 -
   12.14 -void array_init(struct array *array);
   12.15 -void array_release(struct array *array);
   12.16 -void *array_add(struct array *array, int size);
   12.17 -
   12.18 -
   12.19 -struct list_head {
   12.20 -	uint list_ptr : 24;
   12.21 -	uint flags    : 8;
   12.22 -};
   12.23 -
   12.24 -struct list {
   12.25 -	uint data  : 24;
   12.26 -	uint flags : 8;
   12.27 -};
   12.28 -
   12.29 -void list_set_empty(struct list_head *head);
   12.30 -void list_set_ptr(struct list_head *head, uint32_t ptr);
   12.31 -void list_set_array(struct list_head *head, struct array *pool, struct array *items, int force_indirect);
   12.32 -
   12.33 -struct list *list_first(struct list_head *head, struct array *pool);
   12.34 -struct list *list_next(struct list *list);
   12.35 -
   12.36 -void list_remap_pool(struct array *pool, uint32_t *map);
   12.37 -void list_remap_head(struct list_head *list, uint32_t *map);
   12.38 -
   12.39 -
   12.40 -struct hashtable {
   12.41 -	struct array buckets;
   12.42 -	struct array *pool;
   12.43 -};
   12.44 -
   12.45 -void hashtable_init(struct hashtable *table, struct array *pool);
   12.46 -void hashtable_release(struct hashtable *table);
   12.47 -uint32_t hashtable_insert(struct hashtable *table, const char *key);
   12.48 -uint32_t hashtable_lookup(struct hashtable *table, const char *key);
   12.49 -uint32_t hashtable_tokenize(struct hashtable *table, const char *string);
   12.50 -
   12.51 -
   12.52 -struct bitarray {
   12.53 -	uint32_t *bits;
   12.54 -};
   12.55 -
   12.56 -void bitarray_init(struct bitarray *bitarray, int size, int intial_value);
   12.57 -void bitarray_release(struct bitarray *bitarray);
   12.58 -void bitarray_set(struct bitarray *bitarray, int bit, int value);
   12.59 -int bitarray_get(struct bitarray *bitarray, int bit);
   12.60 -
   12.61 -
   12.62 -#endif /* _RAZOR_TYPES_H_ */
    13.1 --- a/src/.gitignore	Fri Jun 20 14:18:52 2008 -0400
    13.2 +++ b/src/.gitignore	Fri Jun 20 15:10:34 2008 -0400
    13.3 @@ -1,5 +1,8 @@
    13.4  .deps
    13.5  .libs
    13.6  razor
    13.7 -rpm-razor
    13.8 -
    13.9 +rpm
   13.10 +*.repo
   13.11 +*.xml.gz
   13.12 +install
   13.13 +rpms