razor.c
changeset 231 fef9808171ff
parent 220 1fcb5c23034a
child 237 715b18dc94f3
     1.1 --- a/razor.c	Wed Jun 04 20:53:17 2008 -0400
     1.2 +++ b/razor.c	Mon Jun 09 14:38:58 2008 -0400
     1.3 @@ -839,6 +839,16 @@
     1.4  	return pi;
     1.5  }
     1.6  
     1.7 +static void
     1.8 +razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
     1.9 +					 struct razor_set *set,
    1.10 +					 struct razor_property *property)
    1.11 +{
    1.12 +	memset(pi, 0, sizeof *pi);
    1.13 +	pi->set = set;
    1.14 +	pi->index = list_first(&property->packages, &set->package_pool);
    1.15 +}
    1.16 +
    1.17  struct razor_package_iterator *
    1.18  razor_package_iterator_create_for_property(struct razor_set *set,
    1.19  					   struct razor_property *property)
    1.20 @@ -1140,82 +1150,6 @@
    1.21  	list_package_files(set, r, set->files.data, end, buffer);
    1.22  }
    1.23  
    1.24 -static void
    1.25 -razor_set_validate(struct razor_set *set, struct array *unsatisfied)
    1.26 -{
    1.27 -	struct razor_property *r, *p, *end;
    1.28 -	uint32_t *u;
    1.29 -	char *pool;
    1.30 -
    1.31 -	end = set->properties.data + set->properties.size;
    1.32 -	pool = set->string_pool.data;
    1.33 -	
    1.34 -	for (r = set->properties.data, p = r; r < end; r++) {
    1.35 -		if (r->type != RAZOR_PROPERTY_REQUIRES)
    1.36 -			continue;
    1.37 -
    1.38 -		p = r;
    1.39 -		while (p < end && p->name == r->name &&
    1.40 -		       p->type == r->type)
    1.41 -			p++;
    1.42 -
    1.43 -		/* If there is more than one version of a provides,
    1.44 -		 * seek to the end for the highest version. */
    1.45 -		/* FIXME: This doesn't work if we have a series of
    1.46 -		 * requires a = 1, provides a = 1, requires a = 2,
    1.47 -		 * provides a = 2, as the kernel and kernel-devel
    1.48 -		 * does.*/
    1.49 -		while (p + 1 < end && p->name == (p + 1)->name &&
    1.50 -		       p->type == (p + 1)->type)
    1.51 -			p++;
    1.52 -
    1.53 -		/* FIXME: We need to track property flags (<, <=, =
    1.54 -		 * etc) to properly determine if a requires is
    1.55 -		 * satisfied.  The current code doesn't track that the
    1.56 -		 * requires a = 1 isn't satisfied by a = 2 provides. */
    1.57 -
    1.58 -		if (p == end ||
    1.59 -		    p->type != RAZOR_PROPERTY_PROVIDES ||
    1.60 -		    r->name != p->name ||
    1.61 -		    versioncmp(&pool[r->version], &pool[p->version]) > 0) {
    1.62 -			/* FIXME: We ignore file requires for now. */
    1.63 -			if (pool[r->name] == '/')
    1.64 -				continue;
    1.65 -			u = array_add(unsatisfied, sizeof *u);
    1.66 -			*u = r - (struct razor_property *) set->properties.data;
    1.67 -		}
    1.68 -	}
    1.69 -}
    1.70 -
    1.71 -void
    1.72 -razor_set_list_unsatisfied(struct razor_set *set)
    1.73 -{
    1.74 -	struct array unsatisfied;
    1.75 -	struct razor_property *properties, *r;
    1.76 -	uint32_t *u, *end;
    1.77 -	char *pool;
    1.78 -
    1.79 -	array_init(&unsatisfied);
    1.80 -	razor_set_validate(set, &unsatisfied);
    1.81 -
    1.82 -	end = unsatisfied.data + unsatisfied.size;
    1.83 -	properties = set->properties.data;
    1.84 -	pool = set->string_pool.data;
    1.85 -
    1.86 -	for (u = unsatisfied.data; u < end; u++) {
    1.87 -		r = properties + *u;
    1.88 -		if (pool[r->version] == '\0')
    1.89 -			printf("%s not satisfied\n",
    1.90 -			       &pool[r->name]);
    1.91 -		else
    1.92 -			printf("%s-%s not satisfied\n",
    1.93 -			       &pool[r->name],
    1.94 -			       &pool[r->version]);
    1.95 -	}
    1.96 -
    1.97 -	array_release(&unsatisfied);
    1.98 -}
    1.99 -
   1.100  #define UPSTREAM_SOURCE 0x80
   1.101  
   1.102  struct source {
   1.103 @@ -1262,13 +1196,25 @@
   1.104  }
   1.105  
   1.106  static void
   1.107 -add_package(struct razor_merger *merger,
   1.108 -	    struct razor_package *package, struct source *source,
   1.109 -	    uint32_t flags)
   1.110 +razor_merger_add_package(struct razor_merger *merger,
   1.111 +			 struct razor_package *package)
   1.112  {
   1.113  	char *pool;
   1.114  	struct list *r;
   1.115  	struct razor_package *p;
   1.116 +	struct razor_set *set1;
   1.117 +	struct source *source;
   1.118 +	uint32_t flags;
   1.119 +
   1.120 +	set1 = merger->source1.set;
   1.121 +	if (set1->packages.data <= (void *) package &&
   1.122 +	    (void *) package < set1->packages.data + set1->packages.size) {
   1.123 +		source = &merger->source1;
   1.124 +		flags = 0;
   1.125 +	} else {
   1.126 +		source = &merger->source2;
   1.127 +		flags = UPSTREAM_SOURCE;
   1.128 +	}
   1.129  
   1.130  	pool = source->set->string_pool.data;
   1.131  	p = array_add(&merger->set->packages, sizeof *p);
   1.132 @@ -1723,8 +1669,8 @@
   1.133  razor_set_diff(struct razor_set *set, struct razor_set *upstream,
   1.134  	       razor_package_callback_t callback, void *data)
   1.135  {
   1.136 -	struct razor_package_iterator *pi1, *pi2;
   1.137 -	struct razor_package *p1, *p2;
   1.138 + 	struct razor_package_iterator *pi1, *pi2;
   1.139 + 	struct razor_package *p1, *p2;
   1.140  	const char *name1, *name2, *version1, *version2, *arch1, *arch2;
   1.141  	int res;
   1.142  
   1.143 @@ -1760,232 +1706,19 @@
   1.144  	razor_package_iterator_destroy(pi2);
   1.145  }
   1.146  
   1.147 -struct razor_transaction;
   1.148 -struct razor_transaction_package;
   1.149 -struct razor_transaction_resolver;
   1.150 -
   1.151 -struct razor_transaction {
   1.152 -	int package_count, errors;
   1.153 -	struct razor_set *system, *upstream;
   1.154 -
   1.155 -	struct bitarray syspkgs, uppkgs;
   1.156 -	struct array packages;
   1.157 -};
   1.158 -
   1.159 -struct razor_transaction_package {
   1.160 -	const char *name, *old_version, *new_version;
   1.161 -	struct razor_package *old_package, *new_package;
   1.162 -	enum razor_transaction_package_state state;
   1.163 -
   1.164 -	/* dep_package is the name of the package that resulted in
   1.165 -	 * this entry being created (or NULL if the user requested the
   1.166 -	 * install/remove), with the other dep_ fields providing
   1.167 -	 * additional information.
   1.168 -	 *
   1.169 -	 * For INSTALL, if dep_type is REQUIRES, then dep_package
   1.170 -	 * required something that this package provides. If dep_type
   1.171 -	 * is CONFLICTS, then dep_package is a package that conflicted
   1.172 -	 * with an older version of this package, forcing an upgrade.
   1.173 -	 *
   1.174 -	 * For REMOVE, if dep_type is REQUIRES, then dep_package is a
   1.175 -	 * package that is being removed. If dep_type is OBSOLETES,
   1.176 -	 * then dep_package is a package that obsoletes this one.
   1.177 -	 *
   1.178 -	 * For OLD_CONFLICT or NEW_CONFLICT, dep_package is an
   1.179 -	 * existing package that conflicts with this one. The
   1.180 -	 * conflicting property comes from the already-installed
   1.181 -	 * package for OLD_CONFLICT, or the to-be-installed package
   1.182 -	 * for NEW_CONFLICT.
   1.183 -	 *
   1.184 -	 * For UNSATISFIABLE, the dep_ fields are as for an INSTALL,
   1.185 -	 * but the name field will be NULL.
   1.186 -	 */
   1.187 -	const char *dep_package;
   1.188 -	enum razor_property_type dep_type;
   1.189 -	const char *dep_property;
   1.190 -	enum razor_version_relation dep_relation;
   1.191 -	const char *dep_version;
   1.192 -};
   1.193 -
   1.194 -static int
   1.195 -package_in_set(void *package, struct razor_set *set)
   1.196 -{
   1.197 -	return package >= set->packages.data &&
   1.198 -		package < set->packages.data + set->packages.size;
   1.199 -}
   1.200 -
   1.201 -static int
   1.202 -property_in_set(void *property, struct razor_set *set)
   1.203 -{
   1.204 -	return property >= set->properties.data &&
   1.205 -		property < set->properties.data + set->properties.size;
   1.206 -}
   1.207 -
   1.208 -static struct razor_package *
   1.209 -property_provider_package(struct razor_transaction *trans,
   1.210 -			  struct razor_property *prop,
   1.211 -			  int installed)
   1.212 -{
   1.213 -	struct razor_set *set;
   1.214 -	struct bitarray *pkgbits;
   1.215 -	struct razor_package *pkgs;
   1.216 -	struct list *p;
   1.217 -
   1.218 -	if (installed && prop->type != RAZOR_PROPERTY_PROVIDES)
   1.219 -		return NULL;
   1.220 -	else if (!installed &&
   1.221 -		 prop->type != RAZOR_PROPERTY_PROVIDES &&
   1.222 -		 prop->type != RAZOR_PROPERTY_OBSOLETES)
   1.223 -		return NULL;
   1.224 -
   1.225 -	if (property_in_set(prop, trans->system)) {
   1.226 -		set = trans->system;
   1.227 -		pkgbits = &trans->syspkgs;
   1.228 -	} else {
   1.229 -		set = trans->upstream;
   1.230 -		pkgbits = &trans->uppkgs;
   1.231 -	}
   1.232 -	pkgs = set->packages.data;
   1.233 -
   1.234 -	for (p = list_first(&prop->packages, &set->package_pool); p; p = list_next(p)) {
   1.235 -		if (bitarray_get(pkgbits, p->data) != installed)
   1.236 -			continue;
   1.237 -		if (prop->type == RAZOR_PROPERTY_OBSOLETES ||
   1.238 -		    pkgs[p->data].name == prop->name)
   1.239 -			return &pkgs[p->data];
   1.240 -	}
   1.241 -	return NULL;
   1.242 -}
   1.243 -
   1.244 -static int
   1.245 -compare_transaction_packages(const void *one, const void *two)
   1.246 -{
   1.247 -	struct razor_transaction_package **tp1 = (void *)one;
   1.248 -	struct razor_transaction_package **tp2 = (void *)two;
   1.249 -
   1.250 -	if (!(*tp1)->name)
   1.251 -		return 1;
   1.252 -	else if (!(*tp2)->name)
   1.253 -		return -1;
   1.254 -	else
   1.255 -		return strcmp((*tp1)->name, (*tp2)->name);
   1.256 -}
   1.257 -
   1.258 -/* FIXME: merge this into the other property loop in razor_transaction_satisfy */
   1.259 -static void
   1.260 -resolve_new_packages(struct razor_transaction *trans,
   1.261 -		     int start, int end)
   1.262 -{
   1.263 -	struct razor_property *sp, *up, *sp_end, *up_end;
   1.264 -	struct razor_package *spkg, *spkgs, *upkg, *upkgs;
   1.265 -	struct razor_transaction_package **packages;
   1.266 -	const char *spool, *upool;
   1.267 -	int i;
   1.268 -
   1.269 -	sp_end = trans->system->properties.data + trans->system->properties.size;
   1.270 -	spool = trans->system->string_pool.data;
   1.271 -	spkgs = trans->system->packages.data;
   1.272 -	up_end = trans->upstream->properties.data + trans->upstream->properties.size;
   1.273 -	upool = trans->upstream->string_pool.data;
   1.274 -	upkgs = trans->upstream->packages.data;
   1.275 -
   1.276 -	/* FIXME, check if sorting the packages directly (rather than
   1.277 -	 * sorting pointers-to-packages) still results in confusing
   1.278 -	 * descriptions.
   1.279 -	 */
   1.280 -	packages = calloc(end - start, sizeof *packages);
   1.281 -	for (i = start; i < end; i++)
   1.282 -		packages[i - start] = ((struct razor_transaction_package *)trans->packages.data) + i;
   1.283 -	qsort(packages, end - start, sizeof *packages,
   1.284 -	      compare_transaction_packages);
   1.285 -
   1.286 -	sp = trans->system->properties.data;
   1.287 -	up = trans->upstream->properties.data;
   1.288 -	for (i = 0; i < end - start; i++) {
   1.289 -		if (!packages[i]->name ||
   1.290 -		    packages[i]->state >= RAZOR_PACKAGE_FIRST_ERROR_STATE)
   1.291 -			continue;
   1.292 -
   1.293 -		spkg = NULL;
   1.294 -		while (sp < sp_end &&
   1.295 -		       strcmp(&spool[sp->name], packages[i]->name) < 0)
   1.296 -			sp++;
   1.297 -		while (sp < sp_end &&
   1.298 -		       strcmp(&spool[sp->name], packages[i]->name) == 0 &&
   1.299 -		       !(spkg = property_provider_package(trans, sp, 1)))
   1.300 -			sp++;
   1.301 -
   1.302 -		upkg = NULL;
   1.303 -		while (up < up_end &&
   1.304 -		       strcmp(&upool[up->name], packages[i]->name) < 0)
   1.305 -			up++;
   1.306 -		while (up < up_end &&
   1.307 -		       strcmp(&upool[up->name], packages[i]->name) == 0 &&
   1.308 -		       !(upkg = property_provider_package(trans, up, 0)))
   1.309 -			up++;
   1.310 -
   1.311 -		if (packages[i]->state == RAZOR_PACKAGE_REMOVE ||
   1.312 -		    packages[i]->state == RAZOR_PACKAGE_OBSOLETED) {
   1.313 -			if (spkg) {
   1.314 -				packages[i]->old_package = spkg;
   1.315 -				packages[i]->name = &spool[spkg->name];
   1.316 -				packages[i]->old_version = &spool[spkg->version];
   1.317 -				bitarray_set(&trans->syspkgs, spkg - spkgs, 0);
   1.318 -			}
   1.319 -			if (!packages[i]->old_package) {
   1.320 -				packages[i]->name = strdup(packages[i]->name);
   1.321 -				packages[i]->state |= RAZOR_PACKAGE_UNAVAILABLE_FLAG;
   1.322 -				trans->errors++;
   1.323 -			}
   1.324 -		} else {
   1.325 -			if (upkg) {
   1.326 -				packages[i]->new_package = upkg;
   1.327 -				packages[i]->name = &upool[upkg->name];
   1.328 -				packages[i]->new_version = &upool[upkg->version];
   1.329 -
   1.330 -				if (up->name != upkg->name) {
   1.331 -					packages[i]->dep_package = &upool[upkg->name];
   1.332 -					packages[i]->dep_type = up->type;
   1.333 -					packages[i]->dep_property = &upool[up->name];
   1.334 -					packages[i]->dep_relation = up->relation;
   1.335 -					packages[i]->dep_version = &upool[up->version];
   1.336 -				}
   1.337 -
   1.338 -				if (spkg) {
   1.339 -					packages[i]->old_package = spkg;
   1.340 -					packages[i]->old_version = &spool[spkg->version];
   1.341 -					if (versioncmp(&spool[spkg->version], &upool[up->version]) >= 0) {
   1.342 -						packages[i]->state = RAZOR_PACKAGE_UP_TO_DATE;
   1.343 -						trans->errors++;
   1.344 -						continue;
   1.345 -					}
   1.346 -					bitarray_set(&trans->syspkgs, spkg - spkgs, 0);
   1.347 -				}
   1.348 -				bitarray_set(&trans->uppkgs, upkg - upkgs, 1);
   1.349 -			}
   1.350 -			if (!packages[i]->new_package) {
   1.351 -				packages[i]->name = strdup(packages[i]->name);
   1.352 -				packages[i]->state |= RAZOR_PACKAGE_UNAVAILABLE_FLAG;
   1.353 -				trans->errors++;
   1.354 -			}
   1.355 -		}
   1.356 -	}
   1.357 -}
   1.358 -
   1.359  static int
   1.360  provider_satisfies_requirement(struct razor_property *provider,
   1.361  			       const char *provider_strings,
   1.362 -			       struct razor_property *requirement,
   1.363 -			       const char *requirement_strings)
   1.364 +			       enum razor_version_relation relation,
   1.365 +			       const char *required)
   1.366  {
   1.367  	int cmp, len;
   1.368  	const char *provided = &provider_strings[provider->version];
   1.369 -	const char *required = &requirement_strings[requirement->version];
   1.370  
   1.371  	if (!*required)
   1.372  		return 1;
   1.373  	if (!*provided) {
   1.374 -		if (requirement->relation >= RAZOR_VERSION_EQUAL)
   1.375 +		if (relation >= RAZOR_VERSION_EQUAL)
   1.376  			return 1;
   1.377  		else
   1.378  			return 0;
   1.379 @@ -1993,7 +1726,7 @@
   1.380  
   1.381  	cmp = versioncmp(provided, required);
   1.382  
   1.383 -	switch (requirement->relation) {
   1.384 +	switch (relation) {
   1.385  	case RAZOR_VERSION_LESS:
   1.386  		return cmp < 0;
   1.387  
   1.388 @@ -2023,614 +1756,82 @@
   1.389  	return 0;
   1.390  }
   1.391  
   1.392 -static struct razor_package *
   1.393 -find_package_for_file(struct razor_set *set, struct bitarray *pkgbits,
   1.394 -		      const char *filename, int installed)
   1.395 +#define TRANS_PACKAGE_PRESENT		1
   1.396 +#define TRANS_PACKAGE_UPDATE		2
   1.397 +#define TRANS_PROPERTY_SATISFIED	0x80000000
   1.398 +
   1.399 +struct transaction_set {
   1.400 +	struct razor_set *set;
   1.401 +	uint32_t *packages;
   1.402 +	uint32_t *properties;
   1.403 +};
   1.404 +
   1.405 +struct razor_transaction {
   1.406 +	int package_count, errors;
   1.407 +	struct transaction_set system, upstream;
   1.408 +	int changes;
   1.409 +};
   1.410 +
   1.411 +static void
   1.412 +transaction_set_init(struct transaction_set *ts, struct razor_set *set)
   1.413  {
   1.414 -	struct razor_package *pkgs = set->packages.data;
   1.415 -	struct razor_entry *entry;
   1.416 -	struct list *p;
   1.417 +	int count;
   1.418  
   1.419 -	if (filename[0] != '/')
   1.420 -		return 0;
   1.421 -
   1.422 -	entry = find_entry(set, set->files.data, filename);
   1.423 -	if (!entry)
   1.424 -		return 0;
   1.425 -
   1.426 -	for (p = list_first(&entry->packages, &set->package_pool); p; p = list_next(p)) {
   1.427 -		if (bitarray_get(pkgbits, p->data) == installed)
   1.428 -			return &pkgs[p->data];
   1.429 -	}
   1.430 -	return NULL;
   1.431 -}
   1.432 -
   1.433 -static struct razor_package *
   1.434 -find_installed_package_for_file(struct razor_transaction *trans,
   1.435 -				const char *filename)
   1.436 -{
   1.437 -	struct razor_package *pkg;
   1.438 -
   1.439 -	pkg = find_package_for_file(trans->system, &trans->syspkgs,
   1.440 -				    filename, 1);
   1.441 -	if (!pkg)
   1.442 -		pkg = find_package_for_file(trans->upstream, &trans->uppkgs,
   1.443 -					    filename, 1);
   1.444 -	return pkg;
   1.445 -}
   1.446 -
   1.447 -static struct razor_package *
   1.448 -find_uninstalled_package_for_file(struct razor_transaction *trans,
   1.449 -				  const char *filename)
   1.450 -{
   1.451 -	struct razor_package *pkg;
   1.452 -
   1.453 -	pkg = find_package_for_file(trans->upstream, &trans->uppkgs,
   1.454 -				    filename, 0);
   1.455 -	if (!pkg)
   1.456 -		pkg = find_package_for_file(trans->system, &trans->syspkgs,
   1.457 -					    filename, 0);
   1.458 -	return pkg;
   1.459 -}
   1.460 -
   1.461 -static struct razor_property *
   1.462 -skip_to_matching_property(struct razor_transaction *trans,
   1.463 -			  struct razor_property *match,
   1.464 -			  struct razor_property *prop)
   1.465 -{
   1.466 -	struct razor_set *mset, *pset;
   1.467 -	const char *ppool, *mpool;
   1.468 -	struct razor_property *prop_end;
   1.469 -
   1.470 -	if (property_in_set(match, trans->system))
   1.471 -		mset = trans->system;
   1.472 -	else
   1.473 -		mset = trans->upstream;
   1.474 -
   1.475 -	if (property_in_set(prop, trans->system))
   1.476 -		pset = trans->system;
   1.477 -	else if (property_in_set(prop, trans->upstream))
   1.478 -		pset = trans->upstream;
   1.479 -	else
   1.480 -		return prop;
   1.481 -
   1.482 -	prop_end = pset->properties.data + pset->properties.size;
   1.483 -	ppool = pset->string_pool.data;
   1.484 -	mpool = mset->string_pool.data;
   1.485 -
   1.486 -	while (prop < prop_end &&
   1.487 -	       strcmp(&ppool[prop->name], &mpool[match->name]) < 0)
   1.488 -		prop++;
   1.489 -	return prop;
   1.490 -}
   1.491 -
   1.492 -static struct razor_package *
   1.493 -find_package_matching(struct razor_transaction *trans, int installed,
   1.494 -		      struct razor_property *prop,
   1.495 -		      struct razor_property *req,
   1.496 -		      struct razor_set *req_set)
   1.497 -{
   1.498 -	struct razor_set *set;
   1.499 -	struct bitarray *pkgbits;
   1.500 -	struct razor_package *pkgs;
   1.501 -	struct razor_property *props, *prop_end;
   1.502 -	enum razor_property_type match_type;
   1.503 -	const char *pool;
   1.504 -	const char *rpool;
   1.505 -	int match_name = (req->type == RAZOR_PROPERTY_OBSOLETES);
   1.506 -	int match;
   1.507 -
   1.508 -	if (property_in_set(prop, trans->system)) {
   1.509 -		set = trans->system;
   1.510 -		pkgbits = &trans->syspkgs;
   1.511 -	} else if (property_in_set(prop, trans->upstream)) {
   1.512 -		set = trans->upstream;
   1.513 -		pkgbits = &trans->uppkgs;
   1.514 -	} else
   1.515 -		return NULL;
   1.516 -
   1.517 -	if (!req_set) {
   1.518 -		if (property_in_set(req, trans->system))
   1.519 -			req_set = trans->system;
   1.520 -		else
   1.521 -			req_set = trans->upstream;
   1.522 -	}
   1.523 -	rpool = req_set->string_pool.data;
   1.524 -
   1.525 -	if (req->type == RAZOR_PROPERTY_PROVIDES)
   1.526 -		match_type = RAZOR_PROPERTY_CONFLICTS;
   1.527 -	else
   1.528 -		match_type = RAZOR_PROPERTY_PROVIDES;
   1.529 -
   1.530 -	pkgs = set->packages.data;
   1.531 -	props = set->properties.data;
   1.532 -	prop_end = set->properties.data + set->properties.size;
   1.533 -	pool = set->string_pool.data;
   1.534 -
   1.535 -	/* Find first matching property */
   1.536 -	while (prop < prop_end &&
   1.537 -	       strcmp(&pool[prop->name], &rpool[req->name]) < 0)
   1.538 -		prop++;
   1.539 -	if (prop == prop_end ||
   1.540 -	    strcmp(&pool[prop->name], &rpool[req->name]) > 0)
   1.541 -		return NULL;
   1.542 -
   1.543 -	if (prop->type < match_type) {
   1.544 -		while (prop < prop_end && prop->type != match_type)
   1.545 -			prop++;
   1.546 -	} else {
   1.547 -		while (prop >= props && prop->type != match_type)
   1.548 -			prop--;
   1.549 -		while (prop > props + 1 && (prop - 1)->name == prop->name &&
   1.550 -		       (prop - 1)->type == match_type)
   1.551 -			prop--;
   1.552 -	}
   1.553 -
   1.554 -	/* Scan matching properties */
   1.555 -	while (prop < prop_end && prop->type == match_type &&
   1.556 -	       strcmp(&pool[prop->name], &rpool[req->name]) == 0) {
   1.557 -		if (match_type == RAZOR_PROPERTY_PROVIDES)
   1.558 -			match = provider_satisfies_requirement(prop, pool, req, rpool);
   1.559 -		else
   1.560 -			match = provider_satisfies_requirement(req, rpool, prop, pool);
   1.561 -		if (match) {
   1.562 -			struct list *pkg;
   1.563 -
   1.564 -			for (pkg = list_first(&prop->packages, &set->package_pool); pkg; pkg = list_next(pkg)) {
   1.565 -				if (bitarray_get(pkgbits, pkg->data) != installed)
   1.566 -					continue;
   1.567 -				if (!match_name ||
   1.568 -				    strcmp(&pool[pkgs[pkg->data].name],
   1.569 -					   &rpool[req->name]) == 0)
   1.570 -					return &pkgs[pkg->data];
   1.571 -			}
   1.572 -		}
   1.573 -		prop++;
   1.574 -	}
   1.575 -
   1.576 -	return NULL;
   1.577 -}
   1.578 -
   1.579 -static struct razor_package *
   1.580 -find_installed_package_for_property(struct razor_transaction *trans,
   1.581 -				    struct razor_property *sys_start,
   1.582 -				    struct razor_property *up_start,
   1.583 -				    struct razor_property *req)
   1.584 -{
   1.585 -	struct razor_package *pkg;
   1.586 -
   1.587 -	pkg = find_package_matching(trans, 1, sys_start, req, NULL);
   1.588 -	if (!pkg)
   1.589 -		pkg = find_package_matching(trans, 1, up_start, req, NULL);
   1.590 -	return pkg;
   1.591 -}
   1.592 -
   1.593 -static struct razor_package *
   1.594 -find_uninstalled_package_for_property(struct razor_transaction *trans,
   1.595 -				      struct razor_property *sys_start,
   1.596 -				      struct razor_property *up_start,
   1.597 -				      struct razor_property *req)
   1.598 -{
   1.599 -	struct razor_package *pkg;
   1.600 -
   1.601 -	pkg = find_package_matching(trans, 0, up_start, req, NULL);
   1.602 -	if (!pkg)
   1.603 -		pkg = find_package_matching(trans, 0, sys_start, req, NULL);
   1.604 -	return pkg;
   1.605 -}
   1.606 -
   1.607 -static struct razor_transaction_package *
   1.608 -find_transaction_package(struct razor_transaction *trans, const char *name)
   1.609 -{
   1.610 -	struct razor_transaction_package *packages;
   1.611 -	int count, i;
   1.612 -
   1.613 -	packages = trans->packages.data;
   1.614 -	count = trans->packages.size / sizeof *packages;
   1.615 -	for (i = 0; i < count; i++) {
   1.616 -		if (packages[i].name && !strcmp(packages[i].name, name))
   1.617 -			return &packages[i];
   1.618 -	}
   1.619 -	return NULL;
   1.620 -}
   1.621 -
   1.622 -/* FIXME? */
   1.623 -static int
   1.624 -prop_is_being_installed(struct razor_transaction *trans,
   1.625 -			struct razor_property *prop)
   1.626 -{
   1.627 -	struct list *pkg;
   1.628 -
   1.629 -	for (pkg = list_first(&prop->packages, &trans->upstream->package_pool); pkg; pkg = list_next(pkg)) {
   1.630 -		if (bitarray_get(&trans->uppkgs, pkg->data))
   1.631 -			return 1;
   1.632 -	}
   1.633 -	return 0;
   1.634 -}
   1.635 -
   1.636 -static int
   1.637 -prop_is_being_removed(struct razor_transaction *trans,
   1.638 -		      struct razor_property *prop)
   1.639 -{
   1.640 -	struct list *pkg;
   1.641 -
   1.642 -	for (pkg = list_first(&prop->packages, &trans->system->package_pool); pkg; pkg = list_next(pkg)) {
   1.643 -		if (bitarray_get(&trans->syspkgs, pkg->data))
   1.644 -			return 0;
   1.645 -	}
   1.646 -	return 1;
   1.647 -}
   1.648 -
   1.649 -static int
   1.650 -prop_is_being_updated(struct razor_transaction *trans,
   1.651 -		      struct razor_property *prop)
   1.652 -{
   1.653 -	struct razor_package *packages = trans->system->packages.data;
   1.654 -	const char *pool = trans->system->string_pool.data;
   1.655 -	struct razor_transaction_package *tp;
   1.656 -	struct list *pkg;
   1.657 -
   1.658 -	/* Assumes prop_is_being_removed returns true */
   1.659 -
   1.660 -	for (pkg = list_first(&prop->packages, &trans->system->package_pool); pkg; pkg = list_next(pkg)) {
   1.661 -		tp = find_transaction_package(trans, &pool[packages[pkg->data].name]);
   1.662 -		if (tp && tp->state == RAZOR_PACKAGE_REMOVE)
   1.663 -			return 0;
   1.664 -	}
   1.665 -	return 1;
   1.666 +	ts->set = set;
   1.667 +	count = set->packages.size / sizeof (struct razor_package);
   1.668 +	ts->packages = zalloc(count * sizeof *ts->packages);
   1.669 +	count = set->properties.size / sizeof (struct razor_property);
   1.670 +	ts->properties = zalloc(count * sizeof *ts->properties);
   1.671  }
   1.672  
   1.673  static void
   1.674 -add_transaction_package(struct razor_transaction *trans,
   1.675 -			struct razor_package *new_package,
   1.676 -			struct razor_package *old_package,
   1.677 -			enum razor_transaction_package_state state,
   1.678 -			const char *req_package,
   1.679 -			struct razor_property *req_prop)
   1.680 +transaction_set_release(struct transaction_set *ts)
   1.681  {
   1.682 -	struct razor_set *new_package_set, *old_package_set, *req_set;
   1.683 -	struct bitarray *reqpkgbits;
   1.684 -	struct razor_transaction_package *tp, *already;
   1.685 -	const char *pool;
   1.686 -	struct razor_package *pkgs;
   1.687 -	struct list *pkg;
   1.688 -	int contradiction = 0;
   1.689 -
   1.690 -	if (package_in_set(new_package, trans->system))
   1.691 -		new_package_set = trans->system;
   1.692 -	else
   1.693 -		new_package_set = trans->upstream;
   1.694 -	if (package_in_set(old_package, trans->system))
   1.695 -		old_package_set = trans->system;
   1.696 -	else
   1.697 -		old_package_set = trans->upstream;
   1.698 -	if (property_in_set(req_prop, trans->system)) {
   1.699 -		req_set = trans->system;
   1.700 -		reqpkgbits = &trans->syspkgs;
   1.701 -	} else {
   1.702 -		req_set = trans->upstream;
   1.703 -		reqpkgbits = &trans->uppkgs;
   1.704 -	}
   1.705 -
   1.706 -	if (new_package) {
   1.707 -		pool = new_package_set->string_pool.data;
   1.708 -		already = find_transaction_package(trans, &pool[new_package->name]);
   1.709 -		if (already) {
   1.710 -			if (already->new_package == new_package) {
   1.711 -				/* Already taken care of */
   1.712 -				return;
   1.713 -			} else if (new_package_set == trans->upstream &&
   1.714 -				   already->state == RAZOR_PACKAGE_FORCED_UPDATE) {
   1.715 -				already->new_package = new_package;
   1.716 -				return;
   1.717 -			} else if (new_package_set == trans->upstream) {
   1.718 -				return;
   1.719 -			}
   1.720 -
   1.721 -			/* Oops. We lose */
   1.722 -			if (state != RAZOR_PACKAGE_CONTRADICTION)
   1.723 -				contradiction = 1;
   1.724 -		}
   1.725 -	} else if (old_package) {
   1.726 -		pool = old_package_set->string_pool.data;
   1.727 -		already = find_transaction_package(trans, &pool[old_package->name]);
   1.728 -		if (already) {
   1.729 -			if (already->old_package == old_package) {
   1.730 -				/* Already taken care of */
   1.731 -				return;
   1.732 -			} else if (old_package_set == trans->system) {
   1.733 -				already->old_package = old_package;
   1.734 -				return;
   1.735 -			}
   1.736 -
   1.737 -			/* Oops. We lose */
   1.738 -			if (state != RAZOR_PACKAGE_CONTRADICTION)
   1.739 -				contradiction = 1;
   1.740 -		}
   1.741 -	} else
   1.742 -		state = RAZOR_PACKAGE_UNSATISFIABLE;
   1.743 -
   1.744 -	tp = array_add(&trans->packages, sizeof *tp);
   1.745 -	memset(tp, 0, sizeof *tp);
   1.746 -
   1.747 -	if (new_package) {
   1.748 -		pool = new_package_set->string_pool.data;
   1.749 -		tp->new_package = new_package;
   1.750 -		tp->name = &pool[new_package->name];
   1.751 -		tp->new_version = &pool[new_package->version];
   1.752 -
   1.753 -		pkgs = new_package_set->packages.data;
   1.754 -	}
   1.755 -	if (old_package) {
   1.756 -		pool = old_package_set->string_pool.data;
   1.757 -		tp->old_package = old_package;
   1.758 -		tp->name = &pool[old_package->name];
   1.759 -		tp->old_version = &pool[old_package->version];
   1.760 -
   1.761 -		pkgs = old_package_set->packages.data;
   1.762 -	}
   1.763 -
   1.764 -	tp->state = state;
   1.765 -	if (state != RAZOR_PACKAGE_INSTALL &&
   1.766 -	    state != RAZOR_PACKAGE_FORCED_UPDATE &&
   1.767 -	    state != RAZOR_PACKAGE_REMOVE &&
   1.768 -	    state != RAZOR_PACKAGE_OBSOLETED)
   1.769 -		trans->errors++;
   1.770 -
   1.771 -	if (contradiction) {
   1.772 -		/* Do this now, after adding tp, so that it ends up
   1.773 -		 * after both the INSTALL and the REMOVE in the array.
   1.774 -		 */
   1.775 -		add_transaction_package(trans, new_package, old_package,
   1.776 -					RAZOR_PACKAGE_CONTRADICTION,
   1.777 -					NULL, NULL);
   1.778 -	}
   1.779 -
   1.780 -	if (req_package)
   1.781 -		tp->dep_package = req_package;
   1.782 -	if (!req_prop)
   1.783 -		return;
   1.784 -
   1.785 -	pool = req_set->string_pool.data;
   1.786 -	pkgs = req_set->packages.data;
   1.787 -	if (!req_package) {
   1.788 -		for (pkg = list_first(&req_prop->packages, &req_set->package_pool); pkg; pkg = list_next(pkg)) {
   1.789 -			if (bitarray_get(reqpkgbits, pkg->data))
   1.790 -				break;
   1.791 -		}
   1.792 -		if (pkg)
   1.793 -			tp->dep_package = &pool[pkgs[pkg->data].name];
   1.794 -	}
   1.795 -
   1.796 -	tp->dep_type = req_prop->type;
   1.797 -	tp->dep_property = &pool[req_prop->name];
   1.798 -	tp->dep_relation = req_prop->relation;
   1.799 -	tp->dep_version = &pool[req_prop->version];
   1.800 +	free(ts->packages);
   1.801 +	free(ts->properties);
   1.802  }
   1.803  
   1.804  static void
   1.805 -razor_transaction_satisfy(struct razor_transaction *trans)
   1.806 +transaction_set_install_package(struct transaction_set *ts,
   1.807 +				struct razor_package *package)
   1.808  {
   1.809 -	struct razor_package *spkgs, *upkgs, *pkg;
   1.810 -	struct razor_property *sp, *sprops, *sprop_end;
   1.811 -	struct razor_property *up, *uprops, *uprop_end;
   1.812 -	struct razor_property *sr, *ur, *first_up;
   1.813 -	const char *spool, *upool, *removed_package;
   1.814 -	struct list *reqpkg;
   1.815 +	struct razor_package *pkgs;
   1.816 +	struct list *prop;
   1.817 +	int i;
   1.818  
   1.819 -	spkgs = trans->system->packages.data;
   1.820 -	sprops = trans->system->properties.data;
   1.821 -	sprop_end = trans->system->properties.data + trans->system->properties.size;
   1.822 -	spool = trans->system->string_pool.data;
   1.823 -	upkgs = trans->upstream->packages.data;
   1.824 -	uprops = trans->upstream->properties.data;
   1.825 -	uprop_end = trans->upstream->properties.data + trans->upstream->properties.size;
   1.826 -	upool = trans->upstream->string_pool.data;
   1.827 +	pkgs = ts->set->packages.data;
   1.828 +	i = package - pkgs;
   1.829 +	if (ts->packages[i] == TRANS_PACKAGE_PRESENT)
   1.830 +		return;
   1.831  
   1.832 -	sp = sprops;
   1.833 -	for (up = uprops; up < uprop_end; up++) {
   1.834 -		/* Skip 'up' ahead to a property of a package which is
   1.835 -		 * to-be-installed.
   1.836 -		 */
   1.837 -		while (up < uprop_end &&
   1.838 -		       !prop_is_being_installed(trans, up))
   1.839 -			up++;
   1.840 -		if (up == uprop_end)
   1.841 -			break;
   1.842 -		sp = skip_to_matching_property(trans, up, sp);
   1.843 +	ts->packages[i] = TRANS_PACKAGE_PRESENT;
   1.844  
   1.845 -		switch (up->type) {
   1.846 -		case RAZOR_PROPERTY_REQUIRES:
   1.847 -			if (!strncmp(&upool[up->name], "rpmlib(", 7))
   1.848 -				break;
   1.849 -
   1.850 -			if (find_installed_package_for_property(trans, sp, up, up) ||
   1.851 -			    find_installed_package_for_file(trans, &upool[up->name])) {
   1.852 -				/* Requires something that is either installed
   1.853 -				 * or to-be-installed.
   1.854 -				 */
   1.855 -				break;
   1.856 -			}
   1.857 -
   1.858 -			/* See if we can install a new upstream provider */
   1.859 -			pkg = find_uninstalled_package_for_property(trans, sp, up, up);
   1.860 -			if (!pkg)
   1.861 -				pkg = find_uninstalled_package_for_file(trans, &upool[up->name]);
   1.862 -			add_transaction_package(trans, pkg, NULL,
   1.863 -						RAZOR_PACKAGE_INSTALL,
   1.864 -						NULL, up);
   1.865 -			break;
   1.866 -
   1.867 -		case RAZOR_PROPERTY_PROVIDES:
   1.868 -			/* find_installed_package_for_property works backwards
   1.869 -			 * here, finding a *conflicting* installed package.
   1.870 -			 */
   1.871 -			pkg = find_installed_package_for_property(trans, sp, up, up);
   1.872 -			if (!pkg)
   1.873 -				break;
   1.874 -
   1.875 -			if (package_in_set(pkg, trans->system)) {
   1.876 -				/* pkg CONFLICTS with what 'up' PROVIDES. Try
   1.877 -				 * finding an upgrade
   1.878 -				 */
   1.879 -				add_transaction_package(trans, NULL, pkg,
   1.880 -							RAZOR_PACKAGE_FORCED_UPDATE,
   1.881 -							&upool[up->name], sp);
   1.882 -			} else {
   1.883 -				add_transaction_package(trans, NULL, pkg,
   1.884 -							RAZOR_PACKAGE_CONTRADICTION,
   1.885 -							NULL, up);
   1.886 -			}
   1.887 -			break;
   1.888 -
   1.889 -		case RAZOR_PROPERTY_CONFLICTS:
   1.890 -			pkg = find_installed_package_for_property(trans, sp, up, up);
   1.891 -			if (!pkg)
   1.892 -				break;
   1.893 -
   1.894 -			if (package_in_set(pkg, trans->system)) {
   1.895 -				/* Conflicts with something already installed.
   1.896 -				 * Try to upgrade out.
   1.897 -				 */
   1.898 -				add_transaction_package(trans, NULL, pkg,
   1.899 -							RAZOR_PACKAGE_FORCED_UPDATE,
   1.900 -							NULL, up);
   1.901 -			} else {
   1.902 -				add_transaction_package(trans, pkg, NULL,
   1.903 -							RAZOR_PACKAGE_CONTRADICTION,
   1.904 -							NULL, up);
   1.905 -			}
   1.906 -			break;
   1.907 -
   1.908 -		case RAZOR_PROPERTY_OBSOLETES:
   1.909 -			pkg = find_installed_package_for_property(trans, sp, up, up);
   1.910 -			if (pkg) {
   1.911 -				/* If pkg is to-be-installed, this
   1.912 -				 * will add a CONTRADICTION error as well.
   1.913 -				 */
   1.914 -				add_transaction_package(trans, NULL, pkg,
   1.915 -							RAZOR_PACKAGE_OBSOLETED,
   1.916 -							NULL, up);
   1.917 -			}
   1.918 -			break;
   1.919 -
   1.920 -		default:
   1.921 -			/* can't happen */
   1.922 -			break;
   1.923 -		}
   1.924 -	}
   1.925 -
   1.926 -	up = uprops;
   1.927 -	for (sp = sprops; sp < sprop_end; sp++) {
   1.928 -		/* Skip 'sp' ahead to a PROVIDES of a package which is
   1.929 -		 * to-be-removed.
   1.930 -		 */
   1.931 -		while (sp < sprop_end &&
   1.932 -		       (sp->type != RAZOR_PROPERTY_PROVIDES ||
   1.933 -			!prop_is_being_removed(trans, sp)))
   1.934 -			sp++;
   1.935 -		if (sp == sprop_end)
   1.936 -			break;
   1.937 -
   1.938 -		removed_package = &spool[spkgs[list_first(&sp->packages, &trans->system->package_pool)->data].name];
   1.939 -
   1.940 -		/* Skip 'up' to match */
   1.941 -		up = skip_to_matching_property(trans, sp, up);
   1.942 -		ur = first_up = up;
   1.943 -
   1.944 -		/* If the package is just being upgraded, we may
   1.945 -		 * already be installing an identical PROVIDES, so
   1.946 -		 * check for that.
   1.947 -		 */
   1.948 -		while (up < uprop_end &&
   1.949 -		       strcmp(&spool[sp->name], &upool[up->name]) == 0 &&
   1.950 -		       (up->type != RAZOR_PROPERTY_PROVIDES || 
   1.951 -			sp->relation != up->relation ||
   1.952 -			strcmp(&spool[sp->name], &upool[up->name]) != 0))
   1.953 -			up++;
   1.954 -		if (up < uprop_end &&
   1.955 -		    up->type == RAZOR_PROPERTY_PROVIDES &&
   1.956 -		    strcmp(&spool[sp->name], &upool[up->name]) == 0 &&
   1.957 -		    sp->relation == up->relation &&
   1.958 -		    strcmp(&spool[sp->version], &upool[up->version]) == 0 &&
   1.959 -		    prop_is_being_installed(trans, up)) {
   1.960 -			up = first_up;
   1.961 -			continue;
   1.962 -		}
   1.963 -		up = first_up;
   1.964 -
   1.965 -		/* For all still-installed packages that require
   1.966 -		 * sp->name, see if they are satisfied by any other
   1.967 -		 * still-installed or to-be-installed property. If
   1.968 -		 * not, either remove or attempt to update the
   1.969 -		 * package, depending on why the required property has
   1.970 -		 * disappeared
   1.971 -		 */
   1.972 -		sr = sp;
   1.973 -		while (sr > sprops + 1 && (sr - 1)->name == sr->name)
   1.974 -			sr--;
   1.975 -		for (; sr->type == RAZOR_PROPERTY_REQUIRES; sr++) {
   1.976 -			if (prop_is_being_removed(trans, sr))
   1.977 -				continue;
   1.978 -			if (find_installed_package_for_property(trans, sp, up, sr))
   1.979 -				continue;
   1.980 -
   1.981 -			for (reqpkg = list_first(&sr->packages, &trans->system->package_pool); reqpkg; reqpkg = list_next(reqpkg)) {
   1.982 -				if (!bitarray_get(&trans->syspkgs, reqpkg->data))
   1.983 -					continue;
   1.984 -				pkg = &spkgs[reqpkg->data];
   1.985 -				if (prop_is_being_updated(trans, sp)) {
   1.986 -					add_transaction_package(trans, NULL, pkg,
   1.987 -								RAZOR_PACKAGE_FORCED_UPDATE,
   1.988 -								removed_package, NULL);
   1.989 -				} else {
   1.990 -					add_transaction_package(trans, NULL, pkg,
   1.991 -								RAZOR_PACKAGE_REMOVE,
   1.992 -								removed_package, sr);
   1.993 -				}
   1.994 -			}
   1.995 -		}
   1.996 +	prop = list_first(&package->properties, &ts->set->property_pool);
   1.997 +	while (prop) {
   1.998 +		ts->properties[prop->data]++;
   1.999 +		prop = list_next(prop);
  1.1000  	}
  1.1001  }
  1.1002  
  1.1003 -void
  1.1004 -razor_transaction_install_package(struct razor_transaction *transaction,
  1.1005 -				  struct razor_package *package)
  1.1006 +static void
  1.1007 +transaction_set_remove_package(struct transaction_set *ts,
  1.1008 +			       struct razor_package *package)
  1.1009  {
  1.1010 -	add_transaction_package(transaction, package, NULL,
  1.1011 -				RAZOR_PACKAGE_INSTALL, NULL, NULL);
  1.1012 -}
  1.1013 +	struct razor_package *pkgs;
  1.1014 +	struct list *prop;
  1.1015 +	int i;
  1.1016  
  1.1017 -void
  1.1018 -razor_transaction_remove_package(struct razor_transaction *transaction,
  1.1019 -				 struct razor_package *package)
  1.1020 -{
  1.1021 -	add_transaction_package(transaction, NULL, package,
  1.1022 -				RAZOR_PACKAGE_REMOVE, NULL, NULL);
  1.1023 -}
  1.1024 +	pkgs = ts->set->packages.data;
  1.1025 +	i = package - pkgs;
  1.1026 +	if (ts->packages[i] == 0)
  1.1027 +		return;
  1.1028  
  1.1029 -void
  1.1030 -razor_transaction_update_all(struct razor_transaction *trans)
  1.1031 -{
  1.1032 -	struct razor_package *sp, *spkgs, *send, *up, *upkgs, *uend;
  1.1033 -	const char *spool, *upool;
  1.1034 +	ts->packages[i] = 0;
  1.1035  
  1.1036 -	spkgs = trans->system->packages.data;
  1.1037 -	send = trans->system->packages.data + trans->system->packages.size;
  1.1038 -	spool = trans->system->string_pool.data;
  1.1039 -	up = upkgs = trans->upstream->packages.data;
  1.1040 -	uend = trans->upstream->packages.data + trans->upstream->packages.size;
  1.1041 -	upool = trans->upstream->string_pool.data;
  1.1042 -
  1.1043 -	for (sp = spkgs; sp < send; sp++) {
  1.1044 -		while (up < uend && strcmp(&spool[sp->name], &upool[up->name]) > 0)
  1.1045 -			up++;
  1.1046 -		if (strcmp(&spool[sp->name], &upool[up->name]) == 0 &&
  1.1047 -		    versioncmp(&spool[sp->version], &upool[up->version]) < 0) {
  1.1048 -			add_transaction_package(trans, up, sp,
  1.1049 -						RAZOR_PACKAGE_INSTALL,
  1.1050 -						NULL, NULL);
  1.1051 -		}
  1.1052 +	prop = list_first(&package->properties, &ts->set->property_pool);
  1.1053 +	while (prop) {
  1.1054 +		ts->properties[prop->data]--;
  1.1055 +		prop = list_next(prop);
  1.1056  	}
  1.1057  }
  1.1058  
  1.1059 @@ -2638,242 +1839,618 @@
  1.1060  razor_transaction_create(struct razor_set *system, struct razor_set *upstream)
  1.1061  {
  1.1062  	struct razor_transaction *trans;
  1.1063 -	int count;
  1.1064 +	struct razor_package *p, *spkgs, *pend;
  1.1065  
  1.1066  	trans = zalloc(sizeof *trans);
  1.1067 +	transaction_set_init(&trans->system, system);
  1.1068 +	transaction_set_init(&trans->upstream, upstream);
  1.1069  
  1.1070 -	trans->system = system;
  1.1071 -	trans->upstream = upstream ? upstream : razor_set_create();
  1.1072 -	array_init(&trans->packages);
  1.1073 -	count = trans->system->packages.size / sizeof (struct razor_package);
  1.1074 -	bitarray_init(&trans->syspkgs, count, 1);
  1.1075 -	count = trans->upstream->packages.size / sizeof (struct razor_package);
  1.1076 -	bitarray_init(&trans->uppkgs, count, 0);
  1.1077 +	spkgs = trans->system.set->packages.data;
  1.1078 +	pend = trans->system.set->packages.data +
  1.1079 +		trans->system.set->packages.size;
  1.1080 +	for (p = spkgs; p < pend; p++)
  1.1081 +		transaction_set_install_package(&trans->system, p);
  1.1082  
  1.1083  	return trans;
  1.1084  }
  1.1085  
  1.1086 -static void
  1.1087 -resolve_transaction(struct razor_transaction *trans)
  1.1088 +void
  1.1089 +razor_transaction_install_package(struct razor_transaction *trans,
  1.1090 +				  struct razor_package *package)
  1.1091  {
  1.1092 -	int start, end;
  1.1093 -
  1.1094 -	if (trans->package_count > 0)
  1.1095 -		/* Already did this, return. */
  1.1096 -		return;
  1.1097 -
  1.1098 -	start = 0;
  1.1099 -	end = trans->packages.size / sizeof (struct razor_transaction_package);
  1.1100 -
  1.1101 -	while (start != end) {
  1.1102 -		resolve_new_packages(trans, start, end);
  1.1103 -		if (trans->errors)
  1.1104 -			break;
  1.1105 -
  1.1106 -		razor_transaction_satisfy(trans);
  1.1107 -
  1.1108 -		start = end;
  1.1109 -		end = trans->packages.size / sizeof (struct razor_transaction_package);
  1.1110 -	}
  1.1111 -
  1.1112 -	trans->package_count = end;
  1.1113 +	transaction_set_install_package(&trans->upstream, package);
  1.1114 +	trans->changes++;
  1.1115  }
  1.1116  
  1.1117 -const char * const razor_version_relations[] = {
  1.1118 -	/* same order as enum razor_version_relation */
  1.1119 -	"<", "<=", "=", ">=", ">"
  1.1120 -};
  1.1121 +void
  1.1122 +razor_transaction_remove_package(struct razor_transaction *trans,
  1.1123 +				 struct razor_package *package)
  1.1124 +{
  1.1125 +	transaction_set_remove_package(&trans->system, package);
  1.1126 +	trans->changes++;
  1.1127 +}
  1.1128  
  1.1129 -const char * const razor_property_types[] = {
  1.1130 -	/* same order as enum razor_property_type */
  1.1131 -	"requires", "provides", "conflicts with", "obsoletes"
  1.1132 +void
  1.1133 +razor_transaction_update_package(struct razor_transaction *trans,
  1.1134 +				  struct razor_package *package)
  1.1135 +{
  1.1136 +	struct razor_package *spkgs;
  1.1137 +
  1.1138 +	spkgs = trans->system.set->packages.data;
  1.1139 +	trans->system.packages[package - spkgs] |= TRANS_PACKAGE_UPDATE;
  1.1140 +}
  1.1141 +
  1.1142 +struct prop_iter {
  1.1143 +	struct razor_property *p, *start, *end;
  1.1144 +	const char *pool;
  1.1145 +	uint32_t *present;
  1.1146  };
  1.1147  
  1.1148  static void
  1.1149 -print_requirement(struct razor_transaction_package *p)
  1.1150 +prop_iter_init(struct prop_iter *pi, struct transaction_set *ts)
  1.1151  {
  1.1152 -	if (p->dep_type == RAZOR_PROPERTY_CONFLICTS &&
  1.1153 -	    !strcmp(p->dep_package, p->name)) {
  1.1154 -		printf(" because %s %s conflicts with %s",
  1.1155 -		       p->name, p->old_version, p->dep_property);
  1.1156 -		if (*p->dep_version) {
  1.1157 -			printf(" %s %s",
  1.1158 -			       razor_version_relations[p->dep_relation],
  1.1159 -			       p->dep_version);
  1.1160 +	pi->p = ts->set->properties.data;
  1.1161 +	pi->start = ts->set->properties.data;
  1.1162 +	pi->end = ts->set->properties.data + ts->set->properties.size;
  1.1163 +	pi->pool = ts->set->string_pool.data;
  1.1164 +	pi->present = ts->properties;
  1.1165 +}
  1.1166 +
  1.1167 +static int
  1.1168 +prop_iter_next(struct prop_iter *pi,
  1.1169 +	       enum razor_property_type type, struct razor_property **p)
  1.1170 +{
  1.1171 +	while (pi->p < pi->end) {
  1.1172 +		if ((pi->present[pi->p - pi->start] & ~TRANS_PROPERTY_SATISFIED) &&
  1.1173 +		    pi->p->type == type) {
  1.1174 +			*p = pi->p++;
  1.1175 +			return 1;
  1.1176  		}
  1.1177 +		pi->p++;
  1.1178 +	}
  1.1179 +
  1.1180 +	return 0;
  1.1181 +}
  1.1182 +
  1.1183 +static struct razor_property *
  1.1184 +prop_iter_seek_to(struct prop_iter *pi,
  1.1185 +		  enum razor_property_type type, const char *match)
  1.1186 +{
  1.1187 +	uint32_t name;
  1.1188 +
  1.1189 +	while (pi->p < pi->end && strcmp(&pi->pool[pi->p->name], match) < 0)
  1.1190 +		pi->p++;
  1.1191 +
  1.1192 +	if (pi->p == pi->end || strcmp(&pi->pool[pi->p->name], match) > 0)
  1.1193 +		return NULL;
  1.1194 +
  1.1195 +	name = pi->p->name;
  1.1196 +	while (pi->p < pi->end &&
  1.1197 +	       pi->p->name == name &&
  1.1198 +	       pi->p->type != type)
  1.1199 +		pi->p++;
  1.1200 +
  1.1201 +	if (pi->p == pi->end || pi->p->name != name)
  1.1202 +		return NULL;
  1.1203 +
  1.1204 +	return pi->p;
  1.1205 +}
  1.1206 +
  1.1207 +/* Remove packages from set that provide any of the matching (same
  1.1208 + * name and type) providers from ppi onwards that match the
  1.1209 + * requirement that rpi points to. */
  1.1210 +static void
  1.1211 +remove_matching_providers(struct razor_transaction *trans,
  1.1212 +			  struct prop_iter *ppi,
  1.1213 +			  enum razor_version_relation relation,
  1.1214 +			  const char *version)
  1.1215 +{
  1.1216 +	struct razor_property *p;
  1.1217 +	struct razor_package *pkg, *pkgs;
  1.1218 +	struct razor_package_iterator pkg_iter;
  1.1219 +	struct razor_set *set;
  1.1220 +	const char *n, *v, *a;
  1.1221 +
  1.1222 +	if (ppi->present == trans->system.properties)
  1.1223 +		set = trans->system.set;
  1.1224 +	else
  1.1225 +		set = trans->upstream.set;
  1.1226 +   
  1.1227 +	pkgs = (struct razor_package *) set->packages.data;
  1.1228 +	for (p = ppi->p; 
  1.1229 +	     p < ppi->end && 
  1.1230 +	     p->name == ppi->p->name &&
  1.1231 +	     p->type == ppi->p->type;
  1.1232 +	     p++) {
  1.1233 +		if (!ppi->present[p - ppi->start])
  1.1234 +			continue;
  1.1235 +		if (!provider_satisfies_requirement(p, ppi->pool,
  1.1236 +						    relation, version))
  1.1237 +			continue;
  1.1238 +		    
  1.1239 +		razor_package_iterator_init_for_property(&pkg_iter, set, p);
  1.1240 +		while (razor_package_iterator_next(&pkg_iter,
  1.1241 +						   &pkg, &n, &v, &a)) {
  1.1242 +			fprintf(stderr, "removing %s-%s\n", n, v);
  1.1243 +			razor_transaction_remove_package(trans, pkg);
  1.1244 +		}
  1.1245 +	}
  1.1246 +}
  1.1247 +
  1.1248 +static void
  1.1249 +flag_matching_providers(struct razor_transaction *trans,
  1.1250 +			struct prop_iter *ppi,
  1.1251 +			struct razor_property *r,
  1.1252 +			struct prop_iter *rpi,
  1.1253 +			unsigned int flag)
  1.1254 +{
  1.1255 +	struct razor_property *p;
  1.1256 +	struct razor_package *pkg, *pkgs;
  1.1257 +	struct razor_package_iterator pkg_iter;
  1.1258 +	struct razor_set *set;
  1.1259 +	const char *name, *version, *arch;
  1.1260 +	uint32_t *flags;
  1.1261 +
  1.1262 +	if (ppi->present == trans->system.properties) {
  1.1263 +		set = trans->system.set;
  1.1264 +		flags = trans->system.packages;
  1.1265  	} else {
  1.1266 -		if (strcmp(p->name, p->dep_package) != 0)
  1.1267 -			printf(" for %s", p->dep_package);
  1.1268 -		if (*p->dep_version) {
  1.1269 -			printf(", which %s %s %s %s",
  1.1270 -			       razor_property_types[p->dep_type],
  1.1271 -			       p->dep_property,
  1.1272 -			       razor_version_relations[p->dep_relation],
  1.1273 -			       p->dep_version);
  1.1274 -		} else if (strcmp(p->dep_property, p->name) != 0) {
  1.1275 -			printf(", which %s %s",
  1.1276 -			       razor_property_types[p->dep_type],
  1.1277 -			       p->dep_property);
  1.1278 +		set = trans->upstream.set;
  1.1279 +		flags = trans->upstream.packages;
  1.1280 +	}
  1.1281 +   
  1.1282 +	pkgs = (struct razor_package *) set->packages.data;
  1.1283 +	for (p = ppi->p; 
  1.1284 +	     p < ppi->end && 
  1.1285 +		     p->name == ppi->p->name &&
  1.1286 +		     p->type == ppi->p->type;
  1.1287 +	     p++) {
  1.1288 +		if (!ppi->present[p - ppi->start])
  1.1289 +			continue;
  1.1290 +		if (!provider_satisfies_requirement(p, ppi->pool,
  1.1291 +						    r->relation,
  1.1292 +						    &rpi->pool[r->version]))
  1.1293 +			continue;
  1.1294 +		    
  1.1295 +		razor_package_iterator_init_for_property(&pkg_iter, set, p);
  1.1296 +		while (razor_package_iterator_next(&pkg_iter, &pkg,
  1.1297 +						   &name, &version, &arch)) {
  1.1298 +
  1.1299 +			fprintf(stderr, "flagging %s-%s for providing %s matching %s %s\n",
  1.1300 +				name, version,
  1.1301 +				ppi->pool + p->name,
  1.1302 +				rpi->pool + r->name,
  1.1303 +				rpi->pool + r->version);
  1.1304 +			flags[pkg - pkgs] |= flag;
  1.1305  		}
  1.1306  	}
  1.1307  }
  1.1308  
  1.1309 +static struct razor_package *
  1.1310 +pick_matching_provider(struct razor_set *set,
  1.1311 +		       struct prop_iter *ppi,
  1.1312 +		       enum razor_version_relation relation,
  1.1313 +		       const char *version)
  1.1314 +{
  1.1315 +	struct razor_property *p;
  1.1316 +	struct razor_package *pkgs;
  1.1317 +	struct list *i;
  1.1318 +
  1.1319 +	/* This is where we decide which pkgs to pull in to satisfy a
  1.1320 +	 * requirement.  There may be several different providers
  1.1321 +	 * (different versions) and each version of a provider may
  1.1322 +	 * come from a number of packages.  We pick the first package
  1.1323 +	 * from the first provider that matches. */
  1.1324 +
  1.1325 +	pkgs = set->packages.data;
  1.1326 +	for (p = ppi->p;
  1.1327 +	     p < ppi->end &&
  1.1328 +		     p->name == ppi->p->name &&
  1.1329 +		     p->type == ppi->p->type &&
  1.1330 +		     ppi->present[p - ppi->start] == 0;
  1.1331 +	     p++) {
  1.1332 +		if (!provider_satisfies_requirement(p, ppi->pool,
  1.1333 +						    relation, version))
  1.1334 +			continue;
  1.1335 +
  1.1336 +		i = list_first(&p->packages, &set->package_pool);
  1.1337 +
  1.1338 +		return &pkgs[i->data];
  1.1339 +	}
  1.1340 +
  1.1341 +	return NULL;
  1.1342 +}
  1.1343 +
  1.1344 +static void
  1.1345 +remove_obsoleted_packages(struct razor_transaction *trans)
  1.1346 +{
  1.1347 +	struct razor_property *up;
  1.1348 +	struct razor_package *spkgs;
  1.1349 +	struct prop_iter spi, upi;
  1.1350 +
  1.1351 +	spkgs = trans->system.set->packages.data;
  1.1352 +	prop_iter_init(&spi, &trans->system);
  1.1353 +	prop_iter_init(&upi, &trans->upstream);
  1.1354 +	
  1.1355 +	while (prop_iter_next(&upi, RAZOR_PROPERTY_OBSOLETES, &up)) {
  1.1356 +		if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
  1.1357 +				       &upi.pool[up->name]))
  1.1358 +			continue;
  1.1359 +		remove_matching_providers(trans, &spi, up->relation,
  1.1360 +					  &upi.pool[up->version]);
  1.1361 +	}
  1.1362 +}
  1.1363 +
  1.1364 +static int
  1.1365 +any_provider_satisfies_requirement(struct prop_iter *ppi,
  1.1366 +				   enum razor_version_relation relation,
  1.1367 +				   const char *version)
  1.1368 +{
  1.1369 +	struct razor_property *p;
  1.1370 +
  1.1371 +	for (p = ppi->p;
  1.1372 +	     p < ppi->end &&
  1.1373 +		     p->name == ppi->p->name &&
  1.1374 +		     p->type == ppi->p->type;
  1.1375 +	     p++) {
  1.1376 +		if (ppi->present[p - ppi->start] > 0 &&
  1.1377 +		    provider_satisfies_requirement(p, ppi->pool,
  1.1378 +						   relation, version))
  1.1379 +			return 1;
  1.1380 +	}
  1.1381 +
  1.1382 +	return 0;
  1.1383 +}
  1.1384 +
  1.1385 +static void
  1.1386 +clear_requires_flags(struct transaction_set *ts)
  1.1387 +{
  1.1388 +	struct razor_property *p;
  1.1389 +	const char *pool;
  1.1390 +	int i, count;
  1.1391 +
  1.1392 +	count = ts->set->properties.size / sizeof *p;
  1.1393 +	p = ts->set->properties.data;
  1.1394 +	pool = ts->set->string_pool.data;
  1.1395 +	for (i = 0; i < count; i++) {
  1.1396 +		ts->properties[i] &= ~TRANS_PROPERTY_SATISFIED;
  1.1397 +		if (strncmp(&pool[p[i].name], "rpmlib(", 7) == 0)
  1.1398 +			ts->properties[i] |= TRANS_PROPERTY_SATISFIED;
  1.1399 +	}
  1.1400 +}
  1.1401 +
  1.1402 +static void
  1.1403 +mark_satisfied_requires(struct razor_transaction *trans,
  1.1404 +			struct transaction_set *rts,
  1.1405 +			struct transaction_set *pts)
  1.1406 +{
  1.1407 +	struct prop_iter rpi, ppi;
  1.1408 +	struct razor_property *rp;
  1.1409 +
  1.1410 +	prop_iter_init(&rpi, rts);
  1.1411 +	prop_iter_init(&ppi, pts);
  1.1412 +
  1.1413 +	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  1.1414 +		if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES,
  1.1415 +				       &rpi.pool[rp->name]))
  1.1416 +			continue;
  1.1417 +
  1.1418 +		if (any_provider_satisfies_requirement(&ppi, rp->relation,
  1.1419 +						       &rpi.pool[rp->version]))
  1.1420 +			rpi.present[rp - rpi.start] |= TRANS_PROPERTY_SATISFIED;
  1.1421 +	}
  1.1422 +}
  1.1423 +
  1.1424 +static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
  1.1425 +
  1.1426 +static void
  1.1427 +mark_all_satisfied_requires(struct razor_transaction *trans)
  1.1428 +{
  1.1429 +	struct razor_property *sp;
  1.1430 +	struct prop_iter spi;
  1.1431 +
  1.1432 +	clear_requires_flags(&trans->system);
  1.1433 +	clear_requires_flags(&trans->upstream);
  1.1434 +	mark_satisfied_requires(trans, &trans->system, &trans->system);
  1.1435 +	mark_satisfied_requires(trans, &trans->system, &trans->upstream);
  1.1436 +	mark_satisfied_requires(trans, &trans->upstream, &trans->system);
  1.1437 +	mark_satisfied_requires(trans, &trans->upstream, &trans->upstream);
  1.1438 +
  1.1439 +	prop_iter_init(&spi, &trans->system);
  1.1440 +	while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
  1.1441 +		if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
  1.1442 +			continue;
  1.1443 +		fprintf(stderr, "unsatisfied system requires: %s %s %s\n",
  1.1444 +			spi.pool + sp->name,
  1.1445 +			relation_string[sp->relation],
  1.1446 +			spi.pool + sp->version);
  1.1447 +	}
  1.1448 +
  1.1449 +	prop_iter_init(&spi, &trans->upstream);
  1.1450 +	while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
  1.1451 +		if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
  1.1452 +			continue;
  1.1453 +		fprintf(stderr, "unsatisfied upstream requires: %s %s %s\n",
  1.1454 +			spi.pool + sp->name,
  1.1455 +			relation_string[sp->relation],
  1.1456 +			spi.pool + sp->version);
  1.1457 +	}
  1.1458 +}
  1.1459 +
  1.1460 +static void
  1.1461 +update_unsatisfied_packages(struct razor_transaction *trans)
  1.1462 +{
  1.1463 +	struct razor_package *spkgs, *pkg;
  1.1464 +	struct razor_property *sp;
  1.1465 +	struct prop_iter spi;
  1.1466 +	struct razor_package_iterator pkg_iter;
  1.1467 +	const char *name, *version, *arch;
  1.1468 +
  1.1469 +	spkgs = trans->system.set->packages.data;
  1.1470 +	prop_iter_init(&spi, &trans->system);
  1.1471 +	
  1.1472 +	while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
  1.1473 +		if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
  1.1474 +			continue;
  1.1475 +		
  1.1476 +		razor_package_iterator_init_for_property(&pkg_iter,
  1.1477 +							 trans->system.set,
  1.1478 +							 sp);
  1.1479 +		while (razor_package_iterator_next(&pkg_iter, &pkg,
  1.1480 +						   &name, &version, &arch)) {
  1.1481 +			fprintf(stderr, "updating %s because %s %s %s "
  1.1482 +				"isn't satisfied\n",
  1.1483 +				name, spi.pool + sp->name,
  1.1484 +				relation_string[sp->relation],
  1.1485 +				spi.pool + sp->version);
  1.1486 +			trans->system.packages[pkg - spkgs] |=
  1.1487 +				TRANS_PACKAGE_UPDATE;
  1.1488 +		}
  1.1489 +	}
  1.1490 +}
  1.1491 +
  1.1492 +void
  1.1493 +razor_transaction_update_all(struct razor_transaction *trans)
  1.1494 +{
  1.1495 +	struct razor_package *p;
  1.1496 +	int i, count;
  1.1497 +
  1.1498 +	count = trans->system.set->packages.size / sizeof *p;
  1.1499 +	for (i = 0; i < count; i++)
  1.1500 +		trans->system.packages[i] |= TRANS_PACKAGE_UPDATE;
  1.1501 +}
  1.1502 +
  1.1503 +static void
  1.1504 +update_conflicted_packages(struct razor_transaction *trans)
  1.1505 +{
  1.1506 +	struct razor_package *pkg, *spkgs;
  1.1507 +	struct razor_property *up, *sp;
  1.1508 +	struct prop_iter spi, upi;
  1.1509 +	struct razor_package_iterator pkg_iter;
  1.1510 +	const char *name, *version, *arch;
  1.1511 +
  1.1512 +	spkgs = trans->system.set->packages.data;
  1.1513 +	prop_iter_init(&spi, &trans->system);
  1.1514 +	prop_iter_init(&upi, &trans->upstream);
  1.1515 +
  1.1516 +	while (prop_iter_next(&spi, RAZOR_PROPERTY_CONFLICTS, &sp)) {
  1.1517 +		if (!prop_iter_seek_to(&upi, RAZOR_PROPERTY_PROVIDES,
  1.1518 +				       &spi.pool[sp->name]))
  1.1519 +			continue;
  1.1520 +
  1.1521 +		if (!any_provider_satisfies_requirement(&upi, sp->relation,
  1.1522 +							&spi.pool[sp->version]))
  1.1523 +			continue;
  1.1524 +
  1.1525 +		razor_package_iterator_init_for_property(&pkg_iter,
  1.1526 +							 trans->system.set,
  1.1527 +							 sp);
  1.1528 +		while (razor_package_iterator_next(&pkg_iter, &pkg,
  1.1529 +						   &name, &version, &arch)) {
  1.1530 +			fprintf(stderr, "updating %s %s because it conflicts with %s",
  1.1531 +				name, version, spi.pool + sp->name);
  1.1532 +			trans->system.packages[pkg - spkgs] |=
  1.1533 +				TRANS_PACKAGE_UPDATE;
  1.1534 +		}
  1.1535 +	}
  1.1536 +
  1.1537 +	prop_iter_init(&spi, &trans->system);
  1.1538 +	prop_iter_init(&upi, &trans->upstream);
  1.1539 +
  1.1540 +	while (prop_iter_next(&upi, RAZOR_PROPERTY_CONFLICTS, &up)) {
  1.1541 +		sp = prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
  1.1542 +				       &upi.pool[upi.p->name]);
  1.1543 +
  1.1544 +		if (sp)
  1.1545 +			flag_matching_providers(trans, &spi, up, &upi,
  1.1546 +						TRANS_PACKAGE_UPDATE);
  1.1547 +	}
  1.1548 +}
  1.1549 +
  1.1550 +static void
  1.1551 +pull_in_requirements(struct razor_transaction *trans,
  1.1552 +		     struct prop_iter *rpi, struct prop_iter *ppi)
  1.1553 +{
  1.1554 +	struct razor_property *rp, *pp;
  1.1555 +	struct razor_package *pkg, *upkgs;
  1.1556 +
  1.1557 +	upkgs = trans->upstream.set->packages.data;
  1.1558 +	while (prop_iter_next(rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  1.1559 +		if (rpi->present[rp - rpi->start] & TRANS_PROPERTY_SATISFIED)
  1.1560 +			continue;
  1.1561 +
  1.1562 +		pp = prop_iter_seek_to(ppi, RAZOR_PROPERTY_PROVIDES,
  1.1563 +				       &rpi->pool[rp->name]);
  1.1564 +		if (pp == NULL)
  1.1565 +			continue;
  1.1566 +		pkg = pick_matching_provider(trans->upstream.set,
  1.1567 +					     ppi, rp->relation,
  1.1568 +					     &rpi->pool[rp->version]);
  1.1569 +		if (pkg == NULL)
  1.1570 +			continue;
  1.1571 +
  1.1572 +		rpi->present[rp - rpi->start] |= TRANS_PROPERTY_SATISFIED;
  1.1573 +
  1.1574 +		fprintf(stderr, "pulling in %s which provides %s %s %s "
  1.1575 +			"to satisfy %s %s %s\n",
  1.1576 +			ppi->pool + pkg->name,
  1.1577 +			ppi->pool + pp->name, 
  1.1578 +			relation_string[pp->relation],
  1.1579 +			ppi->pool + pp->version, 
  1.1580 +			&rpi->pool[rp->name],
  1.1581 +			relation_string[rp->relation],
  1.1582 +			&rpi->pool[rp->version]);
  1.1583 +
  1.1584 +		trans->upstream.packages[pkg - upkgs] |= TRANS_PACKAGE_UPDATE;
  1.1585 +	}
  1.1586 +}
  1.1587 +
  1.1588 +static void
  1.1589 +pull_in_all_requirements(struct razor_transaction *trans)
  1.1590 +{
  1.1591 +	struct prop_iter rpi, ppi;
  1.1592 +	struct razor_property *rp;
  1.1593 +
  1.1594 +	prop_iter_init(&rpi, &trans->system);
  1.1595 +	prop_iter_init(&ppi, &trans->upstream);
  1.1596 +	pull_in_requirements(trans, &rpi, &ppi);
  1.1597 +	
  1.1598 +	prop_iter_init(&rpi, &trans->upstream);
  1.1599 +	prop_iter_init(&ppi, &trans->upstream);
  1.1600 +	pull_in_requirements(trans, &rpi, &ppi);
  1.1601 +
  1.1602 +	prop_iter_init(&rpi, &trans->system);
  1.1603 +	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  1.1604 +		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED))
  1.1605 +			fprintf(stderr, "could not satisfy req %s %s %s\n",
  1.1606 +				&rpi.pool[rp->name],
  1.1607 +				relation_string[rp->relation],
  1.1608 +				&rpi.pool[rp->version]);
  1.1609 +	}
  1.1610 +
  1.1611 +	prop_iter_init(&rpi, &trans->upstream);
  1.1612 +	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  1.1613 +		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED))
  1.1614 +			fprintf(stderr, "could not satisfy req %s %s %s\n",
  1.1615 +				&rpi.pool[rp->name],
  1.1616 +				relation_string[rp->relation],
  1.1617 +				&rpi.pool[rp->version]);
  1.1618 +	}
  1.1619 +}
  1.1620 +
  1.1621 +static void
  1.1622 +flush_scheduled_system_updates(struct razor_transaction *trans)
  1.1623 +{
  1.1624 + 	struct razor_package_iterator *pi;
  1.1625 + 	struct razor_package *p, *pkg, *spkgs;
  1.1626 +	struct prop_iter ppi;
  1.1627 +	const char *name, *version, *arch;
  1.1628 +
  1.1629 +	spkgs = trans->system.set->packages.data;
  1.1630 +	pi = razor_package_iterator_create(trans->system.set);
  1.1631 +	prop_iter_init(&ppi, &trans->upstream);
  1.1632 +
  1.1633 +	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  1.1634 +		if (!(trans->system.packages[p - spkgs] & TRANS_PACKAGE_UPDATE))
  1.1635 +			continue;
  1.1636 +
  1.1637 +		if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES, name)) {
  1.1638 +			fprintf(stderr, "nothing provides %s\n", name);
  1.1639 +			continue;
  1.1640 +		}
  1.1641 +
  1.1642 +		pkg = pick_matching_provider(trans->upstream.set, &ppi,
  1.1643 +					     RAZOR_VERSION_GREATER, version);
  1.1644 +		if (pkg == NULL) {
  1.1645 +			fprintf(stderr,
  1.1646 +				"no newer version of %s available\n", name);
  1.1647 +			continue;
  1.1648 +		}
  1.1649 +		
  1.1650 +		fprintf(stderr, "updating %s from %s to %s\n",
  1.1651 +			name, version, &ppi.pool[pkg->version]);
  1.1652 +
  1.1653 +		razor_transaction_remove_package(trans, p);
  1.1654 +		razor_transaction_install_package(trans, pkg);
  1.1655 +	}
  1.1656 +
  1.1657 +	razor_package_iterator_destroy(pi);
  1.1658 +}
  1.1659 +
  1.1660 +static void
  1.1661 +flush_scheduled_upstream_updates(struct razor_transaction *trans)
  1.1662 +{
  1.1663 + 	struct razor_package_iterator *pi;
  1.1664 + 	struct razor_package *p, *upkgs;
  1.1665 +	struct prop_iter spi;
  1.1666 +	const char *name, *version, *arch;
  1.1667 +
  1.1668 +	upkgs = trans->upstream.set->packages.data;
  1.1669 +	pi = razor_package_iterator_create(trans->upstream.set);
  1.1670 +	prop_iter_init(&spi, &trans->system);
  1.1671 +
  1.1672 +	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  1.1673 +		if (!(trans->upstream.packages[p - upkgs] & TRANS_PACKAGE_UPDATE))
  1.1674 +			continue;
  1.1675 +
  1.1676 +		if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES, name))
  1.1677 +			continue;
  1.1678 +		remove_matching_providers(trans, &spi,
  1.1679 +					  RAZOR_VERSION_LESS, version);
  1.1680 +		razor_transaction_install_package(trans, p);
  1.1681 +		fprintf(stderr, "installing %s-%s\n", name, version);
  1.1682 +	}
  1.1683 +}
  1.1684 +
  1.1685  int
  1.1686  razor_transaction_resolve(struct razor_transaction *trans)
  1.1687  {
  1.1688 -	struct razor_transaction_package *p, *pend, *tps;
  1.1689 -	int errors_only = 0;
  1.1690 +	int last = 0;
  1.1691  
  1.1692 -	resolve_transaction(trans);
  1.1693 +	flush_scheduled_system_updates(trans);
  1.1694  
  1.1695 -	tps = trans->packages.data;
  1.1696 -	pend = trans->packages.data + trans->packages.size;
  1.1697 -	for (p = trans->packages.data; p < pend; p++) {
  1.1698 -		switch (p->state) {
  1.1699 -		case RAZOR_PACKAGE_INSTALL:
  1.1700 -			if (errors_only)
  1.1701 -				break;
  1.1702 -
  1.1703 -			printf("Installing %s %s", p->name, p->new_version);
  1.1704 -			if (p->dep_package)
  1.1705 -				print_requirement(p);
  1.1706 -			printf("\n");
  1.1707 -			break;
  1.1708 -
  1.1709 -		case RAZOR_PACKAGE_FORCED_UPDATE:
  1.1710 -			if (errors_only)
  1.1711 -				break;
  1.1712 -
  1.1713 -			printf("Updating %s to %s due to update of %s\n",
  1.1714 -			       p->name, p->new_version, p->dep_package);
  1.1715 -			break;
  1.1716 -
  1.1717 -		case RAZOR_PACKAGE_REMOVE:
  1.1718 -			if (errors_only)
  1.1719 -				break;
  1.1720 -			printf("Removing %s %s", p->name, p->old_version);
  1.1721 -			if (p->dep_package) {
  1.1722 -				printf(" which required %s",
  1.1723 -				       p->dep_package);
  1.1724 -				if (strcmp(p->dep_property, p->dep_package) != 0)
  1.1725 -					printf(" for %s", p->dep_property);
  1.1726 -			}
  1.1727 -			printf("\n");
  1.1728 -			break;
  1.1729 -
  1.1730 -		case RAZOR_PACKAGE_OBSOLETED:
  1.1731 -			if (errors_only)
  1.1732 -				break;
  1.1733 -			printf("Removing %s %s", p->name, p->old_version);
  1.1734 -			if (p->dep_package) {
  1.1735 -				printf(" which is obsoleted by %s",
  1.1736 -				       p->dep_package);
  1.1737 -			}
  1.1738 -			printf("\n");
  1.1739 -			break;
  1.1740 -
  1.1741 -		case RAZOR_PACKAGE_INSTALL_UNAVAILABLE:
  1.1742 -			printf("Error: can't find %s", p->name);
  1.1743 -			if (p->dep_package) {
  1.1744 -				printf(" (which is required");
  1.1745 -				print_requirement(p);
  1.1746 -				printf(")");
  1.1747 -			}
  1.1748 -			printf("\n");
  1.1749 -			errors_only = 1;
  1.1750 -			break;
  1.1751 -
  1.1752 -		case RAZOR_PACKAGE_UPDATE_UNAVAILABLE:
  1.1753 -			printf("Error: can't find an updated version of %s (which must be updated due to update of %s)\n",
  1.1754 -			       p->name, p->dep_package);
  1.1755 -			errors_only = 1;
  1.1756 -			break;
  1.1757 -
  1.1758 -		case RAZOR_PACKAGE_REMOVE_NOT_INSTALLED:
  1.1759 -			printf("Error: can't remove %s: not installed\n", p->name);
  1.1760 -			errors_only = 1;
  1.1761 -			break;
  1.1762 -
  1.1763 -		case RAZOR_PACKAGE_UP_TO_DATE:
  1.1764 -			printf("Error: can't update %s", p->name);
  1.1765 -			if (p->dep_package)
  1.1766 -				printf(" (which must be updated due to update of %s)", p->dep_package);
  1.1767 -			printf(": %s is most recent version\n", p->old_version);
  1.1768 -			errors_only = 1;
  1.1769 -			break;
  1.1770 -
  1.1771 -		case RAZOR_PACKAGE_CONTRADICTION:
  1.1772 -			printf("Error: package %s is marked for both installation and removal\n", p->name);
  1.1773 -			errors_only = 1;
  1.1774 -			break;
  1.1775 -
  1.1776 -		case RAZOR_PACKAGE_OLD_CONFLICT:
  1.1777 -			printf("Error: can't install %s, because installed package %s conflicts with ",
  1.1778 -			       p->name, p->dep_package);
  1.1779 -			if (*p->dep_version) {
  1.1780 -				printf("%s %s %s",
  1.1781 -				       p->dep_property,
  1.1782 -				       razor_version_relations[p->dep_relation],
  1.1783 -				       p->dep_version);
  1.1784 -			} else
  1.1785 -				printf("it");
  1.1786 -			printf("\n");
  1.1787 -
  1.1788 -			errors_only = 1;
  1.1789 -			break;
  1.1790 -
  1.1791 -		case RAZOR_PACKAGE_NEW_CONFLICT:
  1.1792 -			printf("Error: can't install %s, because it conflicts with %s",
  1.1793 -			       p->name, p->dep_package);
  1.1794 -			if (*p->dep_version) {
  1.1795 -				printf(" %s %s",
  1.1796 -				       razor_version_relations[p->dep_relation],
  1.1797 -				       p->dep_version);
  1.1798 -			}
  1.1799 -			printf("\n");
  1.1800 -
  1.1801 -			errors_only = 1;
  1.1802 -			break;
  1.1803 -
  1.1804 -		case RAZOR_PACKAGE_UNSATISFIABLE:
  1.1805 -			printf("Error: can't find package for %s", p->dep_property);
  1.1806 -			if (*p->dep_version) {
  1.1807 -				printf(" %s %s",
  1.1808 -					razor_version_relations[p->dep_relation],
  1.1809 -					p->dep_version);
  1.1810 -			}
  1.1811 -			printf(" which is required by %s\n",
  1.1812 -				p->dep_package);
  1.1813 -			errors_only = 1;
  1.1814 -			break;
  1.1815 -
  1.1816 -		default:
  1.1817 -			/* Shouldn't actually happen */
  1.1818 -			break;
  1.1819 -		}
  1.1820 +	while (last < trans->changes) {
  1.1821 +		last = trans->changes;
  1.1822 +		remove_obsoleted_packages(trans);
  1.1823 +		mark_all_satisfied_requires(trans);
  1.1824 +		update_unsatisfied_packages(trans);
  1.1825 +		update_conflicted_packages(trans);
  1.1826 +		pull_in_all_requirements(trans);
  1.1827 +		flush_scheduled_system_updates(trans);
  1.1828 +		flush_scheduled_upstream_updates(trans);
  1.1829  	}
  1.1830  
  1.1831 -	return trans->errors;
  1.1832 +	return trans->changes;
  1.1833  }
  1.1834  
  1.1835  int
  1.1836  razor_transaction_unsatisfied_property(struct razor_transaction *trans,
  1.1837  				       const char *name,
  1.1838  				       enum razor_version_relation rel,
  1.1839 -				       const char *version)
  1.1840 +				       const char *version,
  1.1841 +				       enum razor_property_type type)
  1.1842  {
  1.1843 -	struct razor_transaction_package *p, *end;
  1.1844 +	struct prop_iter pi;
  1.1845 +	struct razor_property *p;
  1.1846  
  1.1847 -	end = trans->packages.data + trans->packages.size;
  1.1848 -	for (p = trans->packages.data; p < end; p++) {
  1.1849 -		if (p->state != RAZOR_PACKAGE_UNSATISFIABLE)
  1.1850 -			continue;
  1.1851 -		if (strcmp(name, p->dep_property) != 0 ||
  1.1852 -		    rel != p->dep_relation ||
  1.1853 -		    strcmp(version, p->dep_version) != 0)
  1.1854 -			continue;
  1.1855 +	prop_iter_init(&pi, &trans->system);
  1.1856 +	while (prop_iter_next(&pi, type, &p)) {
  1.1857 +		if (!(trans->system.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
  1.1858 +		    p->relation == rel &&
  1.1859 +		    strcmp(&pi.pool[p->name], name) == 0 &&
  1.1860 +		    strcmp(&pi.pool[p->version], version) == 0)
  1.1861 +		    
  1.1862 +			return 1;
  1.1863 +	}
  1.1864  
  1.1865 -		return 1;
  1.1866 +	prop_iter_init(&pi, &trans->upstream);
  1.1867 +	while (prop_iter_next(&pi, type, &p)) {
  1.1868 +		if (!(trans->upstream.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
  1.1869 +		    p->relation == rel &&
  1.1870 +		    strcmp(&pi.pool[p->name], name) == 0 &&
  1.1871 +		    strcmp(&pi.pool[p->version], version) == 0)
  1.1872 +		    
  1.1873 +			return 1;
  1.1874  	}
  1.1875  
  1.1876  	return 0;
  1.1877 @@ -2882,117 +2459,61 @@
  1.1878  struct razor_set *
  1.1879  razor_transaction_finish(struct razor_transaction *trans)
  1.1880  {
  1.1881 -	struct array install_packages, remove_packages;
  1.1882  	struct razor_merger *merger;
  1.1883 -	struct razor_package *pkg, *i, *iend, *r, *rend, *s, *send;
  1.1884 -	struct razor_set *set;
  1.1885 -	struct source *source1, *source2;
  1.1886 -	char *spool, *ipool, *rpool;
  1.1887 -	uint32_t *map;
  1.1888 -	struct razor_transaction_package *p, *end;
  1.1889 +	struct razor_package *u, *uend, *upkgs, *s, *send, *spkgs;
  1.1890 +	char *upool, *spool;
  1.1891  	int cmp;
  1.1892  
  1.1893 -	/* FIXME */
  1.1894 -	if (trans->errors)
  1.1895 -		return NULL;
  1.1896 +	s = trans->system.set->packages.data;
  1.1897 +	spkgs = trans->system.set->packages.data;
  1.1898 +	send = trans->system.set->packages.data +
  1.1899 +		trans->system.set->packages.size;
  1.1900 +	spool = trans->system.set->string_pool.data;
  1.1901  
  1.1902 -	/* Sort the transaction packages into two arrays */
  1.1903 -	array_init(&install_packages);
  1.1904 -	array_init(&remove_packages);
  1.1905 +	u = trans->upstream.set->packages.data;
  1.1906 +	upkgs = trans->upstream.set->packages.data;
  1.1907 +	uend = trans->upstream.set->packages.data +
  1.1908 +		trans->upstream.set->packages.size;
  1.1909 +	upool = trans->upstream.set->string_pool.data;
  1.1910  
  1.1911 -	end = trans->packages.data + trans->packages.size;
  1.1912 -	for (p = trans->packages.data; p < end; p++) {
  1.1913 -		if (p->new_package) {
  1.1914 -			pkg = array_add(&install_packages, sizeof *pkg);
  1.1915 -			*pkg = *p->new_package;
  1.1916 -		} else {
  1.1917 -			pkg = array_add(&remove_packages, sizeof *pkg);
  1.1918 -			*pkg = *p->old_package;
  1.1919 -		}
  1.1920 -	}
  1.1921 -	map = razor_qsort_with_data(install_packages.data,
  1.1922 -				    install_packages.size / sizeof *pkg,
  1.1923 -				    sizeof *pkg,
  1.1924 -				    compare_packages,
  1.1925 -				    trans->upstream);
  1.1926 -	free(map);
  1.1927 -	map = razor_qsort_with_data(remove_packages.data,
  1.1928 -				    remove_packages.size / sizeof *pkg,
  1.1929 -				    sizeof *pkg,
  1.1930 -				    compare_packages,
  1.1931 -				    trans->system);
  1.1932 -	free(map);
  1.1933 -
  1.1934 -	merger = razor_merger_create(trans->system, trans->upstream);
  1.1935 -
  1.1936 -	source1 = &merger->source1;
  1.1937 -	source2 = &merger->source2;
  1.1938 -
  1.1939 -	i = install_packages.data;
  1.1940 -	iend = install_packages.data + install_packages.size;
  1.1941 -	ipool = trans->upstream->string_pool.data;
  1.1942 -
  1.1943 -	r = remove_packages.data;
  1.1944 -	rend = remove_packages.data + remove_packages.size;
  1.1945 -	rpool = trans->system->string_pool.data;
  1.1946 -
  1.1947 -	s = trans->system->packages.data;
  1.1948 -	send = trans->system->packages.data + trans->system->packages.size;
  1.1949 -	spool = trans->system->string_pool.data;
  1.1950 -
  1.1951 -	while (s < send || i < iend) {
  1.1952 -		/* Check if s is being removed */
  1.1953 -		if (s < send && r < rend &&
  1.1954 -		    s->name == r->name && s->version && r->version) {
  1.1955 -			s++;
  1.1956 -			r++;
  1.1957 -			continue;
  1.1958 -		}
  1.1959 -
  1.1960 -		if (s < send && i < iend)
  1.1961 -			cmp = strcmp(&spool[s->name], &ipool[i->name]);
  1.1962 +	merger = razor_merger_create(trans->system.set, trans->upstream.set);
  1.1963 +	while (s < send || u < uend) {
  1.1964 +		if (s < send && u < uend)
  1.1965 +			cmp = strcmp(&spool[s->name], &upool[u->name]);
  1.1966  		else if (s < send)
  1.1967  			cmp = -1;
  1.1968  		else
  1.1969  			cmp = 1;
  1.1970 +
  1.1971  		if (cmp < 0) {
  1.1972 -			add_package(merger, s, source1, 0);
  1.1973 +			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
  1.1974 +				razor_merger_add_package(merger, s);
  1.1975  			s++;
  1.1976  		} else if (cmp == 0) {
  1.1977 -			add_package(merger, i, source2, UPSTREAM_SOURCE);
  1.1978 +			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
  1.1979 +				razor_merger_add_package(merger, s);
  1.1980 +			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
  1.1981 +				razor_merger_add_package(merger, u);
  1.1982 +
  1.1983  			s++;
  1.1984 -			i++;
  1.1985 +			u++;
  1.1986  		} else {
  1.1987 -			add_package(merger, i, source2, UPSTREAM_SOURCE);
  1.1988 -			i++;
  1.1989 +			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
  1.1990 +				razor_merger_add_package(merger, u);
  1.1991 +			u++;
  1.1992  		}
  1.1993  	}
  1.1994  
  1.1995 -	array_release(&install_packages);
  1.1996 -	array_release(&remove_packages);
  1.1997 -
  1.1998 -	set = razor_merger_finish(merger);
  1.1999  	razor_transaction_destroy(trans);
  1.2000  
  1.2001 -	return set;
  1.2002 +	return razor_merger_finish(merger);
  1.2003  }
  1.2004  
  1.2005  void
  1.2006  razor_transaction_destroy(struct razor_transaction *trans)
  1.2007  {
  1.2008 -	struct razor_transaction_package *p, *end;
  1.2009 -
  1.2010 -	end = trans->packages.data + trans->packages.size;
  1.2011 -	for (p = trans->packages.data; p < end; p++) {
  1.2012 -		if (!p->dep_package &&
  1.2013 -		    (p->state == RAZOR_PACKAGE_INSTALL_UNAVAILABLE ||
  1.2014 -		     p->state == RAZOR_PACKAGE_REMOVE_NOT_INSTALLED))
  1.2015 -			free((char *)p->name);
  1.2016 -	}
  1.2017 -
  1.2018 -	array_release(&trans->packages);
  1.2019 -	bitarray_release(&trans->syspkgs);
  1.2020 -	bitarray_release(&trans->uppkgs);
  1.2021 +	transaction_set_release(&trans->system);
  1.2022 +	transaction_set_release(&trans->upstream);
  1.2023  	free(trans);
  1.2024  
  1.2025  	/* FIXME: free upstream if it was created as an empty set */