checkpoint, misc rewritage
authorDan Winship <danw@gnome.org>
Tue Mar 04 19:07:14 2008 -0500 (2008-03-04)
changeset 14456c487a56fa2
parent 143 59a9513fac54
child 145 097f7b60b97a
checkpoint, misc rewritage
razor.c
     1.1 --- a/razor.c	Tue Mar 04 10:55:01 2008 -0500
     1.2 +++ b/razor.c	Tue Mar 04 19:07:14 2008 -0500
     1.3 @@ -1682,105 +1682,135 @@
     1.4  	int errors;
     1.5  };
     1.6  
     1.7 +static int
     1.8 +package_in_set(void *package, struct razor_set *set)
     1.9 +{
    1.10 +	return package >= set->packages.data &&
    1.11 +		package < set->packages.data + set->packages.size;
    1.12 +}
    1.13 +
    1.14 +static int
    1.15 +property_in_set(void *property, struct razor_set *set)
    1.16 +{
    1.17 +	return property >= set->properties.data &&
    1.18 +		property < set->properties.data + set->properties.size;
    1.19 +}
    1.20 +
    1.21 +static int
    1.22 +compare_transaction_packages(const void *one, const void *two)
    1.23 +{
    1.24 +	const struct razor_transaction_package *tp1 = one;
    1.25 +	const struct razor_transaction_package *tp2 = two;
    1.26 +
    1.27 +	return strcmp(tp1->name, tp2->name);
    1.28 +}
    1.29 +
    1.30  static void
    1.31  find_packages(struct razor_transaction_resolver *trans,
    1.32 -	      int count, const char **package_names,
    1.33 -	      enum razor_transaction_package_state state)
    1.34 +	      int update_count, const char **update_packages,
    1.35 +	      int remove_count, const char **remove_packages)
    1.36  {
    1.37 -	struct razor_set *set;
    1.38 -	struct bitarray *pkgbits;
    1.39 -	struct razor_package_iterator *pi;
    1.40 -	struct razor_package *p, *packages;
    1.41 -	const char *name, *version;
    1.42 -	struct razor_transaction_package *tp;
    1.43 -	int i, *found;
    1.44 -
    1.45 -	if (state == RAZOR_PACKAGE_INSTALL) {
    1.46 -		set = trans->upstream;
    1.47 -		pkgbits = &trans->uppkgs;
    1.48 -	} else {
    1.49 -		set = trans->system;
    1.50 -		pkgbits = &trans->syspkgs;
    1.51 +	struct razor_package *sp, *spkgs, *up, *upkgs, *send, *uend;
    1.52 +	struct razor_transaction_package *packages, *tp;
    1.53 +	const char *spool, *upool;
    1.54 +	int i;
    1.55 +
    1.56 +	spkgs = trans->system->packages.data;
    1.57 +	send = trans->system->packages.data + trans->system->packages.size;
    1.58 +	spool = trans->system->string_pool.data;
    1.59 +	upkgs = trans->upstream->packages.data;
    1.60 +	uend = trans->upstream->packages.data + trans->upstream->packages.size;
    1.61 +	upool = trans->upstream->string_pool.data;
    1.62 +
    1.63 +	for (i = 0; i < update_count; i++) {
    1.64 +		tp = array_add(&trans->packages, sizeof *tp);
    1.65 +		memset(tp, 0, sizeof *tp);
    1.66 +		tp->name = update_packages[i];
    1.67 +		tp->state = RAZOR_PACKAGE_INSTALL;
    1.68  	}
    1.69 -
    1.70 -	packages = (struct razor_package *) set->packages.data;
    1.71 -	pi = razor_package_iterator_create(set);
    1.72 -	found = zalloc(count * sizeof (int));
    1.73 -
    1.74 -	while (razor_package_iterator_next(pi, &p, &name, &version)) {
    1.75 -		for (i = 0; i < count; i++) {
    1.76 -			if (strcmp(name, package_names[i]) == 0) {
    1.77 -				found[i] = 1;
    1.78 -				tp = array_add(&trans->packages, sizeof *tp);
    1.79 -				memset(tp, 0, sizeof *tp);
    1.80 -				tp->package = p;
    1.81 -				tp->name = name;
    1.82 -				tp->version = version;
    1.83 -				tp->state = state;
    1.84 -				bitarray_set(pkgbits, p - packages,
    1.85 -					     state == RAZOR_PACKAGE_INSTALL);
    1.86 -				break;
    1.87 +	for (i = 0; i < remove_count; i++) {
    1.88 +		tp = array_add(&trans->packages, sizeof *tp);
    1.89 +		memset(tp, 0, sizeof *tp);
    1.90 +		tp->name = remove_packages[i];
    1.91 +		tp->state = RAZOR_PACKAGE_REMOVE;
    1.92 +	}
    1.93 +	qsort(trans->packages.data, update_count + remove_count,
    1.94 +	      sizeof *tp, compare_transaction_packages);
    1.95 +	packages = trans->packages.data;
    1.96 +
    1.97 +	sp = spkgs;
    1.98 +	up = upkgs;
    1.99 +	for (i = 0; i < update_count + remove_count; i++) {
   1.100 +		while (sp < send && strcmp(&spool[sp->name], packages[i].name) < 0)
   1.101 +			sp++;
   1.102 +		while (up < uend && strcmp(&upool[up->name], packages[i].name) < 0)
   1.103 +			up++;
   1.104 +
   1.105 +		if (packages[i].state == RAZOR_PACKAGE_REMOVE) {
   1.106 +			if (sp < send && strcmp(packages[i].name, &spool[sp->name]) == 0) {
   1.107 +				packages[i].package = sp;
   1.108 +				packages[i].name = &spool[sp->name];
   1.109 +				packages[i].version = &spool[sp->version];
   1.110 +				bitarray_set(&trans->syspkgs, sp - spkgs, 0);
   1.111 +			} else {
   1.112 +				packages[i].name = strdup(packages[i].name);
   1.113 +				packages[i].state |= RAZOR_PACKAGE_UNAVAILABLE;
   1.114 +				trans->errors++;
   1.115 +			}
   1.116 +		} else {
   1.117 +			if (up < uend && strcmp(packages[i].name, &upool[up->name]) == 0) {
   1.118 +				if (sp < send && strcmp(packages[i].name, &spool[sp->name]) == 0) {
   1.119 +					if (versioncmp(&spool[sp->version], &upool[up->version]) >= 0) {
   1.120 +						/* FIXME: need a distinct error */
   1.121 +						packages[i].name = strdup(packages[i].name);
   1.122 +						packages[i].state |= RAZOR_PACKAGE_UNAVAILABLE;
   1.123 +						trans->errors++;
   1.124 +						continue;
   1.125 +					}
   1.126 +					bitarray_set(&trans->syspkgs, sp - spkgs, 0);
   1.127 +				}
   1.128 +				packages[i].package = up;
   1.129 +				packages[i].name = &upool[up->name];
   1.130 +				packages[i].version = &upool[up->version];
   1.131 +				bitarray_set(&trans->uppkgs, up - upkgs, 1);
   1.132 +			} else {
   1.133 +				packages[i].name = strdup(packages[i].name);
   1.134 +				packages[i].state |= RAZOR_PACKAGE_UNAVAILABLE;
   1.135 +				trans->errors++;
   1.136  			}
   1.137  		}
   1.138  	}
   1.139 -
   1.140 -	for (i = 0; i < count; i++) {
   1.141 -		if (!found[i]) {
   1.142 -			tp = array_add(&trans->packages, sizeof *tp);
   1.143 -			memset(tp, 0, sizeof *tp);
   1.144 -			tp->name = strdup(package_names[i]);
   1.145 -			tp->state = state | RAZOR_PACKAGE_UNAVAILABLE;
   1.146 -			trans->errors++;
   1.147 -		}
   1.148 -	}
   1.149 -
   1.150 -	razor_package_iterator_destroy(pi);
   1.151 -	free(found);
   1.152  }
   1.153  
   1.154  static void
   1.155  find_all_packages(struct razor_transaction_resolver *trans)
   1.156  {
   1.157  	struct razor_transaction_package *tp;
   1.158 -	struct razor_package *p, *packages, *u, *pend, *uend;
   1.159 -	char *pool, *upool;
   1.160 -
   1.161 -	packages = trans->system->packages.data;
   1.162 -	pend = trans->system->packages.data + trans->system->packages.size;
   1.163 -	pool = trans->system->string_pool.data;
   1.164 -	u = trans->upstream->packages.data;
   1.165 +	struct razor_package *sp, *spkgs, *send, *up, *upkgs, *uend;
   1.166 +	const char *spool, *upool;
   1.167 +
   1.168 +	spkgs = trans->system->packages.data;
   1.169 +	send = trans->system->packages.data + trans->system->packages.size;
   1.170 +	spool = trans->system->string_pool.data;
   1.171 +	up = upkgs = trans->upstream->packages.data;
   1.172  	uend = trans->upstream->packages.data + trans->upstream->packages.size;
   1.173  	upool = trans->upstream->string_pool.data;
   1.174  
   1.175 -	for (p = packages; p < pend; p++) {
   1.176 -		while (u < uend && strcmp(&pool[p->name], &upool[u->name]) > 0)
   1.177 -			u++;
   1.178 -		if (strcmp(&pool[p->name], &upool[u->name]) == 0) {
   1.179 +	for (sp = spkgs; sp < send; sp++) {
   1.180 +		while (up < uend && strcmp(&spool[sp->name], &upool[up->name]) > 0)
   1.181 +			up++;
   1.182 +		if (strcmp(&spool[sp->name], &upool[up->name]) == 0) {
   1.183  			tp = array_add(&trans->packages, sizeof *tp);
   1.184  			memset(tp, 0, sizeof *tp);
   1.185 -			tp->name = &upool[u->name];
   1.186 -			tp->version = &upool[u->version];
   1.187 +			tp->name = &upool[up->name];
   1.188 +			tp->version = &upool[up->version];
   1.189  			tp->state = RAZOR_PACKAGE_INSTALL;
   1.190 -			bitarray_set(&trans->uppkgs, p - packages, 1);
   1.191 +			bitarray_set(&trans->uppkgs, up - upkgs, 1);
   1.192 +			bitarray_set(&trans->syspkgs, sp - spkgs, 0);
   1.193  		}
   1.194  	}
   1.195  }
   1.196  
   1.197 -/* FIXME: wrong, need to compare names, not razor_package* */
   1.198 -static int
   1.199 -find_transaction_package(struct array *package_array,
   1.200 -			 struct razor_package *package)
   1.201 -{
   1.202 -	struct razor_transaction_package *tps = package_array->data;
   1.203 -	int i, tpcount = package_array->size / sizeof *tps;
   1.204 -
   1.205 -	for (i = 0; i < tpcount; i++) {
   1.206 -		if (tps[i].package == package)
   1.207 -			return i;
   1.208 -	}
   1.209 -	return -1;
   1.210 -}
   1.211 -
   1.212  static int
   1.213  provider_satisfies_requirement(struct razor_property *provider,
   1.214  			       const char *provider_strings,
   1.215 @@ -1827,8 +1857,8 @@
   1.216  }
   1.217  
   1.218  static struct razor_package *
   1.219 -find_file(struct razor_set *set, struct bitarray *pkgbits,
   1.220 -	  const char *filename, int installed)
   1.221 +find_package_for_file(struct razor_set *set, struct bitarray *pkgbits,
   1.222 +		      const char *filename, int installed)
   1.223  {
   1.224  	struct razor_package *pkgs = set->packages.data;
   1.225  	struct razor_entry *entry;
   1.226 @@ -1849,179 +1879,278 @@
   1.227  }
   1.228  
   1.229  static struct razor_package *
   1.230 -find_system_file(struct razor_transaction_resolver *trans,
   1.231 -		 const char *filename, int installed)
   1.232 +find_installed_package_for_file(struct razor_transaction_resolver *trans,
   1.233 +				const char *filename)
   1.234  {
   1.235 -	return find_file(trans->system, &trans->syspkgs, filename, installed);
   1.236 +	struct razor_package *pkg;
   1.237 +
   1.238 +	pkg = find_package_for_file(trans->system, &trans->syspkgs,
   1.239 +				    filename, 1);
   1.240 +	if (!pkg)
   1.241 +		pkg = find_package_for_file(trans->upstream, &trans->uppkgs,
   1.242 +					    filename, 1);
   1.243 +	return pkg;
   1.244  }
   1.245  
   1.246  static struct razor_package *
   1.247 -find_upstream_file(struct razor_transaction_resolver *trans,
   1.248 -		   const char *filename, int installed)
   1.249 +find_uninstalled_package_for_file(struct razor_transaction_resolver *trans,
   1.250 +				  const char *filename)
   1.251  {
   1.252 -	return find_file(trans->upstream, &trans->uppkgs, filename, installed);
   1.253 +	struct razor_package *pkg;
   1.254 +
   1.255 +	pkg = find_package_for_file(trans->upstream, &trans->uppkgs,
   1.256 +				    filename, 0);
   1.257 +	if (!pkg)
   1.258 +		pkg = find_package_for_file(trans->system, &trans->syspkgs,
   1.259 +					    filename, 0);
   1.260 +	return pkg;
   1.261  }
   1.262  
   1.263  static struct razor_package *
   1.264 -find_system_provider(struct razor_transaction_resolver *trans,
   1.265 -		     int installed, int match_name,
   1.266 -		     struct razor_property *req, int *sp)
   1.267 +find_package_matching(struct razor_transaction_resolver *trans, int installed,
   1.268 +		      struct razor_property **start_prop,
   1.269 +		      struct razor_property *req,
   1.270 +		      struct razor_set *req_set)
   1.271  {
   1.272 -	struct razor_package *spkgs = trans->system->packages.data;
   1.273 -	struct razor_property *sprops = trans->system->properties.data;
   1.274 -	const char *spool = trans->system->string_pool.data;
   1.275 -	const char *upool = trans->upstream->string_pool.data;
   1.276 -	int scount = trans->system->properties.size / sizeof *sprops;
   1.277 -
   1.278 -	/* Skip ahead to first matching PROVIDES */
   1.279 -	while (*sp < scount &&
   1.280 -	       strcmp(&spool[sprops[*sp].name], &upool[req->name]) < 0)
   1.281 -		(*sp)++;
   1.282 -	while (*sp < scount &&
   1.283 -	       sprops[*sp].type != RAZOR_PROPERTY_PROVIDES &&
   1.284 -	       strcmp(&spool[sprops[*sp].name], &upool[req->name]) == 0)
   1.285 -		(*sp)++;	       
   1.286 -
   1.287 -	/* Scan matching PROVIDES */
   1.288 -	while (*sp < scount &&
   1.289 -	       sprops[*sp].type == RAZOR_PROPERTY_PROVIDES &&
   1.290 -	       strcmp(&spool[sprops[*sp].name],
   1.291 -		      &upool[req->name]) == 0) {
   1.292 -		if (provider_satisfies_requirement(&sprops[*sp], spool,
   1.293 -						   req, upool)) {
   1.294 +	struct razor_set *set;
   1.295 +	struct bitarray *pkgbits;
   1.296 +	struct razor_package *pkgs;
   1.297 +	struct razor_property *prop, *props, *prop_end;
   1.298 +	enum razor_property_type match_type;
   1.299 +	const char *pool;
   1.300 +	const char *rpool = req_set->string_pool.data;
   1.301 +	int match_name = (req->type == RAZOR_PROPERTY_OBSOLETES ||
   1.302 +			  req->type == RAZOR_PROPERTY_CONFLICTS);
   1.303 +	int match;
   1.304 +
   1.305 +	prop = *start_prop;
   1.306 +	if (property_in_set(prop, trans->system)) {
   1.307 +		set = trans->system;
   1.308 +		pkgbits = &trans->syspkgs;
   1.309 +	} else if (property_in_set(prop, trans->upstream)) {
   1.310 +		set = trans->upstream;
   1.311 +		pkgbits = &trans->uppkgs;
   1.312 +	} else
   1.313 +		return NULL;
   1.314 +
   1.315 +	if (req->type == RAZOR_PROPERTY_PROVIDES)
   1.316 +		match_type = RAZOR_PROPERTY_CONFLICTS;
   1.317 +	else
   1.318 +		match_type = RAZOR_PROPERTY_PROVIDES;
   1.319 +
   1.320 +	pkgs = set->packages.data;
   1.321 +	props = set->properties.data;
   1.322 +	prop_end = set->properties.data + set->properties.size;
   1.323 +	pool = set->string_pool.data;
   1.324 +
   1.325 +	/* Find first matching property */
   1.326 +	while (prop < prop_end &&
   1.327 +	       strcmp(&pool[prop->name], &rpool[req->name]) < 0)
   1.328 +		prop++;
   1.329 +	*start_prop = prop;
   1.330 +	if (prop == prop_end ||
   1.331 +	    strcmp(&pool[prop->name], &rpool[req->name]) > 0)
   1.332 +		return NULL;
   1.333 +
   1.334 +	if (prop->type < match_type) {
   1.335 +		while (prop < prop_end && prop->type != match_type)
   1.336 +			prop++;
   1.337 +	} else {
   1.338 +		while (prop >= props && prop->type != match_type)
   1.339 +			prop--;
   1.340 +		while (prop > props + 1 && (prop - 1)->type == match_type)
   1.341 +			prop--;
   1.342 +	}
   1.343 +
   1.344 +	/* Scan matching proeprties */
   1.345 +	while (prop < prop_end && prop->type == match_type &&
   1.346 +	       strcmp(&pool[prop->name], &rpool[req->name]) == 0) {
   1.347 +		if (match_type == RAZOR_PROPERTY_PROVIDES)
   1.348 +			match = provider_satisfies_requirement(prop, pool, req, rpool);
   1.349 +		else
   1.350 +			match = provider_satisfies_requirement(req, rpool, prop, pool);
   1.351 +		if (match) {
   1.352  			struct list *pkg;
   1.353  
   1.354 -			for (pkg = list_first(&sprops[*sp].packages, &trans->system->package_pool); pkg; pkg = list_next(pkg)) {
   1.355 -				if (bitarray_get(&trans->syspkgs, pkg->data) != installed)
   1.356 +			for (pkg = list_first(&prop->packages, &set->package_pool); pkg; pkg = list_next(pkg)) {
   1.357 +				if (bitarray_get(pkgbits, pkg->data) != installed)
   1.358  					continue;
   1.359  				if (!match_name ||
   1.360 -				    strcmp(&spool[spkgs[pkg->data].name],
   1.361 -					   &upool[req->name]) == 0)
   1.362 -					return &spkgs[pkg->data];
   1.363 +				    strcmp(&pool[pkgs[pkg->data].name],
   1.364 +					   &rpool[req->name]) == 0)
   1.365 +					return &pkgs[pkg->data];
   1.366  			}
   1.367  		}
   1.368 -		(*sp)++;
   1.369 +		prop++;
   1.370  	}
   1.371  
   1.372  	return NULL;
   1.373  }
   1.374  
   1.375  static struct razor_package *
   1.376 -find_upstream_provider(struct razor_transaction_resolver *trans,
   1.377 -		       int installed, int match_name,
   1.378 -		       struct razor_property *req, int up)
   1.379 +find_installed_package_for_property(struct razor_transaction_resolver *trans,
   1.380 +				    struct razor_property **sys_sp,
   1.381 +				    struct razor_property *req)
   1.382  {
   1.383 -	struct razor_package *upkgs = trans->upstream->packages.data;
   1.384 -	struct razor_property *uprops = trans->upstream->properties.data;
   1.385 -	const char *upool = trans->upstream->string_pool.data;
   1.386 -	int ucount = trans->upstream->properties.size / sizeof *uprops;
   1.387 -
   1.388 -	/* Skip to first matching provide */
   1.389 -	if (req->type < RAZOR_PROPERTY_PROVIDES) {
   1.390 -		while (up < ucount &&
   1.391 -		       uprops[up].type != RAZOR_PROPERTY_PROVIDES)
   1.392 -			up++;
   1.393 -	} else {
   1.394 -		while (up >= 0 &&
   1.395 -		       uprops[up].type != RAZOR_PROPERTY_PROVIDES)
   1.396 -			up--;
   1.397 -		while (up > 0 &&
   1.398 -		       uprops[up - 1].type == RAZOR_PROPERTY_PROVIDES)
   1.399 -			up--;
   1.400 -		if (up < 0)
   1.401 -			return NULL;
   1.402 -	}
   1.403 -
   1.404 -	/* Scan matching PROVIDES */
   1.405 -	while (up < ucount &&
   1.406 -	       uprops[up].type == RAZOR_PROPERTY_PROVIDES &&
   1.407 -	       uprops[up].name == req->name) {
   1.408 -		if (provider_satisfies_requirement(&uprops[up], upool,
   1.409 -						   req, upool)) {
   1.410 -			struct list *pkg;
   1.411 -
   1.412 -			for (pkg = list_first(&uprops[up].packages, &trans->upstream->package_pool); pkg; pkg = list_next(pkg)) {
   1.413 -				if (bitarray_get(&trans->uppkgs, pkg->data) != installed)
   1.414 -					continue;
   1.415 -				if (!match_name ||
   1.416 -				    strcmp(&upool[upkgs[pkg->data].name],
   1.417 -					   &upool[req->name]) == 0)
   1.418 -					return &upkgs[pkg->data];
   1.419 -			}
   1.420 -		}
   1.421 -		up++;
   1.422 -	}
   1.423 -	return NULL;
   1.424 +	struct razor_package *pkg;
   1.425 +
   1.426 +	pkg = find_package_matching(trans, 1, sys_sp, req, trans->upstream);
   1.427 +	if (!pkg)
   1.428 +		pkg = find_package_matching(trans, 1, &req, req, trans->upstream);
   1.429 +	return pkg;
   1.430 +}
   1.431 +
   1.432 +static struct razor_package *
   1.433 +find_uninstalled_package_for_property(struct razor_transaction_resolver *trans,
   1.434 +				      struct razor_property **sys_sp,
   1.435 +				      struct razor_property *req)
   1.436 +{
   1.437 +	struct razor_package *pkg;
   1.438 +
   1.439 +	pkg = find_package_matching(trans, 0, sys_sp, req, trans->upstream);
   1.440 +	if (!pkg)
   1.441 +		pkg = find_package_matching(trans, 0, &req, req, trans->upstream);
   1.442 +	return pkg;
   1.443  }
   1.444  
   1.445  static struct razor_package *
   1.446  find_upgrade(struct razor_transaction_resolver *trans,
   1.447 -	     struct razor_property *obsolete, int up)
   1.448 +	     struct razor_property *sp, struct razor_property *up)
   1.449  {
   1.450 -	struct razor_property *uprops = trans->upstream->properties.data;
   1.451 -	const char *upool = trans->upstream->string_pool.data;
   1.452 -	struct razor_property req;
   1.453 -
   1.454 -	if (uprops[up].relation > RAZOR_VERSION_EQUAL ||
   1.455 -	    !upool[uprops[up].version])
   1.456 +	struct razor_property *conflict, req;
   1.457 +	struct razor_set *set;
   1.458 +	const char *pool;
   1.459 +
   1.460 +	if (sp->type == RAZOR_PROPERTY_CONFLICTS) {
   1.461 +		conflict = sp;
   1.462 +		set = trans->system;
   1.463 +	} else {
   1.464 +		conflict = up;
   1.465 +		set = trans->upstream;
   1.466 +	}
   1.467 +	pool = set->string_pool.data;
   1.468 +
   1.469 +	if (conflict->relation > RAZOR_VERSION_EQUAL ||
   1.470 +	    !pool[conflict->version])
   1.471  		return NULL;
   1.472  
   1.473 -	memcpy(&req, obsolete, sizeof req);
   1.474 +	memcpy(&req, conflict, sizeof req);
   1.475  	req.type = RAZOR_PROPERTY_REQUIRES;
   1.476 -	if (uprops[up].relation == RAZOR_VERSION_LESS)
   1.477 +	if (conflict->relation == RAZOR_VERSION_LESS)
   1.478  		req.relation = RAZOR_VERSION_GREATER_OR_EQUAL;
   1.479  	else
   1.480  		req.relation = RAZOR_VERSION_GREATER;
   1.481  
   1.482 -	/* We need to rewind up, since OBSOLETES > PROVIDES, so we've
   1.483 -	 * already gone past the possible upgrades.
   1.484 -	 */
   1.485 -	while (up >= 0 &&
   1.486 -	       uprops[up].type != RAZOR_PROPERTY_PROVIDES)
   1.487 -		up--;
   1.488 -	while (up > 0 &&
   1.489 -	       uprops[up - 1].type == RAZOR_PROPERTY_PROVIDES)
   1.490 -		up--;
   1.491 -	if (up < 0)
   1.492 +	return find_package_matching(trans, 0, &up, &req, set);
   1.493 +}
   1.494 +
   1.495 +/* FIXME */
   1.496 +static struct razor_package *
   1.497 +find_upgrade_for_installed_conflict(struct razor_transaction_resolver *trans,
   1.498 +				    struct razor_package *conflicting_pkg,
   1.499 +				    struct razor_property *provider)
   1.500 +{
   1.501 +	struct razor_package *upkgs, *up, *uend;
   1.502 +	struct razor_property *uprops;
   1.503 +	const char *spool, *upool;
   1.504 +	struct list *prop;
   1.505 +
   1.506 +	if (!package_in_set(conflicting_pkg, trans->system))
   1.507  		return NULL;
   1.508  
   1.509 -	return find_upstream_provider(trans, 0, 1, &req, up);
   1.510 +	up = upkgs = trans->upstream->packages.data;
   1.511 +	uend = trans->upstream->packages.data + trans->upstream->packages.size;
   1.512 +	upool = trans->upstream->string_pool.data;
   1.513 +	uprops = trans->upstream->properties.data;
   1.514 +	spool = trans->system->string_pool.data;
   1.515 +
   1.516 +	while (up < uend &&
   1.517 +	       strcmp(&upool[up->name], &spool[conflicting_pkg->name]) < 0)
   1.518 +		up++;
   1.519 +	if (up == uend || strcmp(&upool[up->name], &spool[conflicting_pkg->name]) != 0)
   1.520 +		return NULL;
   1.521 +
   1.522 +	for (prop = list_first(&up->properties, &trans->system->property_pool); prop; prop = list_next(prop)) {
   1.523 +		if (uprops[prop->data].type == RAZOR_PROPERTY_CONFLICTS &&
   1.524 +		    provider_satisfies_requirement(provider, upool, &uprops[prop->data], upool))
   1.525 +			return NULL;
   1.526 +	}
   1.527 +	return up;
   1.528 +}
   1.529 +
   1.530 +/* FIXME */
   1.531 +static int
   1.532 +prop_is_being_installed(struct razor_transaction_resolver *trans,
   1.533 +			struct razor_property *prop)
   1.534 +{
   1.535 +	struct list *pkg;
   1.536 +
   1.537 +	for (pkg = list_first(&prop->packages, &trans->upstream->package_pool); pkg; pkg = list_next(pkg)) {
   1.538 +		if (bitarray_get(&trans->uppkgs, pkg->data))
   1.539 +			return 1;
   1.540 +	}
   1.541 +	return 0;
   1.542  }
   1.543  
   1.544  static void
   1.545  add_transaction_package(struct razor_transaction_resolver *trans,
   1.546  			struct razor_package *package,
   1.547 -			struct razor_set *package_set,
   1.548  			enum razor_transaction_package_state state,
   1.549 -			struct razor_property *req_prop,
   1.550 -			struct razor_set *req_set)
   1.551 +			const char *req_package,
   1.552 +			struct razor_property *req_prop)
   1.553  {
   1.554 -	struct razor_transaction_package *tp;
   1.555 +	struct razor_set *package_set;
   1.556 +	struct razor_transaction_package *tp, *packages;
   1.557  	const char *pool;
   1.558  	struct razor_package *pkgs;
   1.559  	struct list *pkg;
   1.560  
   1.561 +	package_set = package_in_set(package, trans->system) ? trans->system : trans->upstream;
   1.562 +
   1.563  	tp = array_add(&trans->packages, sizeof *tp);
   1.564  	memset(tp, 0, sizeof *tp);
   1.565  
   1.566  	if (package) {
   1.567 +		int i, count;
   1.568 +
   1.569 +		/* Make sure we aren't already acting on this package */
   1.570 +		packages = trans->packages.data;
   1.571 +		count = trans->packages.size / sizeof *packages;
   1.572 +		pool = package_set->string_pool.data;
   1.573 +		for (i = 0; i < count; i++) {
   1.574 +			if (packages[i].name &&
   1.575 +			    !strcmp(packages[i].name, &pool[package->name])) {
   1.576 +				if (state == packages[i].state) {
   1.577 +					/* Already taken care of */
   1.578 +					return;
   1.579 +				}
   1.580 +				/* Oops. We lose */
   1.581 +				state |= RAZOR_PACKAGE_BLOCKED;
   1.582 +				break;
   1.583 +			}
   1.584 +		}
   1.585 +
   1.586  		tp->package = package;
   1.587 -		pool = package_set->string_pool.data;
   1.588  		tp->name = &pool[package->name];
   1.589  		tp->version = &pool[package->version];
   1.590  		tp->state = state;
   1.591  	} else
   1.592  		tp->state = state | RAZOR_PACKAGE_UNSATISFIABLE;
   1.593  
   1.594 -	for (pkg = list_first(&req_prop->packages, &req_set->package_pool); pkg; pkg = list_next(pkg)) {
   1.595 -		if (bitarray_get(&trans->uppkgs, pkg->data))
   1.596 -			break;
   1.597 +	if (req_package)
   1.598 +		tp->req_package = req_package;
   1.599 +	else {
   1.600 +		for (pkg = list_first(&req_prop->packages, &trans->upstream->package_pool); pkg; pkg = list_next(pkg)) {
   1.601 +			if (bitarray_get(&trans->uppkgs, pkg->data))
   1.602 +				break;
   1.603 +		}
   1.604 +		if (pkg) {
   1.605 +			pool = trans->upstream->string_pool.data;
   1.606 +			pkgs = trans->upstream->packages.data;
   1.607 +			tp->req_package = &pool[pkgs[pkg->data].name];
   1.608 +		}
   1.609  	}
   1.610 -	if (pkg) {
   1.611 -		pool = req_set->string_pool.data;
   1.612 -		pkgs = req_set->packages.data;
   1.613 -		tp->req_package = &pool[pkgs[pkg->data].name];
   1.614 -	}
   1.615 +
   1.616  	tp->req_type = req_prop->type;
   1.617  	tp->req_property = &pool[req_prop->name];
   1.618  	tp->req_relation = req_prop->relation;
   1.619 @@ -2036,57 +2165,61 @@
   1.620  		trans->errors++;
   1.621  }
   1.622  
   1.623 -/* FIXME */
   1.624 -static int
   1.625 -prop_is_being_installed(struct razor_transaction_resolver *trans,
   1.626 -			struct razor_property *prop)
   1.627 +/* FIXME: make this more efficient */
   1.628 +static void
   1.629 +maybe_mark_upgraded(struct razor_transaction_resolver *trans,
   1.630 +		    struct razor_package *pkg)
   1.631  {
   1.632 -	struct list *pkg;
   1.633 -
   1.634 -	for (pkg = list_first(&prop->packages, &trans->upstream->package_pool); pkg; pkg = list_next(pkg)) {
   1.635 -		if (bitarray_get(&trans->uppkgs, pkg->data))
   1.636 -			return 1;
   1.637 -	}
   1.638 -	return 0;
   1.639 +	struct razor_package *spkgs, *sp, *send;
   1.640 +	const char *spool, *upool;
   1.641 +
   1.642 +	sp = spkgs = trans->system->packages.data;
   1.643 +	send = trans->system->packages.data + trans->system->packages.size;
   1.644 +	spool = trans->system->string_pool.data;
   1.645 +	upool = trans->upstream->string_pool.data;
   1.646 +
   1.647 +	while (sp < send &&
   1.648 +	       strcmp(&spool[sp->name], &upool[pkg->name]) < 0)
   1.649 +		sp++;
   1.650 +	if (sp < send && strcmp(&spool[sp->name], &upool[pkg->name]) == 0)
   1.651 +		bitarray_set(&trans->syspkgs, sp - spkgs, 0);
   1.652  }
   1.653  
   1.654  static void
   1.655  razor_transaction_satisfy_installs(struct razor_transaction_resolver *trans)
   1.656  {
   1.657 -	struct razor_package *spkgs, *upkgs, *pkg;
   1.658 -	struct razor_property *prop, *sprops, *uprops;
   1.659 -	int sp, up, ucount;
   1.660 +	struct razor_package *spkgs, *upkgs, *pkg, *upgrade;
   1.661 +	struct razor_property *sp, *sprops, *sprop_end;
   1.662 +	struct razor_property *up, *uprops, *uprop_end;
   1.663  	const char *upool;
   1.664  
   1.665  	spkgs = trans->system->packages.data;
   1.666  	sprops = trans->system->properties.data;
   1.667 +	sprop_end = trans->system->properties.data + trans->system->properties.size;
   1.668  	upkgs = trans->upstream->packages.data;
   1.669  	uprops = trans->upstream->properties.data;
   1.670 -	ucount = trans->upstream->properties.size / sizeof *uprops;
   1.671 +	uprop_end = trans->upstream->properties.data + trans->upstream->properties.size;
   1.672  	upool = trans->upstream->string_pool.data;
   1.673  
   1.674 -	sp = up = 0;
   1.675 -	while (up < ucount) {
   1.676 +	sp = sprops;
   1.677 +	up = uprops;
   1.678 +	while (up < uprop_end) {
   1.679  		/* Skip 'up' ahead to a property of a package which is
   1.680  		 * to-be-installed.
   1.681  		 */
   1.682 -		while (up < ucount &&
   1.683 -		       (uprops[up].type == RAZOR_PROPERTY_PROVIDES ||
   1.684 -			!prop_is_being_installed(trans, &uprops[up])))
   1.685 +		while (up < uprop_end &&
   1.686 +		       !prop_is_being_installed(trans, up))
   1.687  			up++;
   1.688 -		if (up == ucount)
   1.689 +		if (up == uprop_end)
   1.690  			break;
   1.691  
   1.692 -		prop = &uprops[up];
   1.693 -		switch (prop->type) {
   1.694 +		switch (up->type) {
   1.695  		case RAZOR_PROPERTY_REQUIRES:
   1.696 -			if (!strncmp(&upool[prop->name], "rpmlib(", 7))
   1.697 +			if (!strncmp(&upool[up->name], "rpmlib(", 7))
   1.698  				break;
   1.699  
   1.700 -			if (find_system_provider(trans, 1, 0, prop, &sp) ||
   1.701 -			    find_upstream_provider(trans, 1, 0, prop, up) ||
   1.702 -			    find_system_file(trans, &upool[prop->name], 1) ||
   1.703 -			    find_upstream_file(trans, &upool[prop->name], 1)) {
   1.704 +			if (find_installed_package_for_property(trans, &sp, up) ||
   1.705 +			    find_installed_package_for_file(trans, &upool[up->name])) {
   1.706  				/* Requires something that is either installed
   1.707  				 * or to-be-installed.
   1.708  				 */
   1.709 @@ -2094,56 +2227,87 @@
   1.710  			}
   1.711  
   1.712  			/* See if we can install a new upstream provider */
   1.713 -			pkg = find_upstream_provider(trans, 0, 0, prop, up);
   1.714 +			pkg = find_uninstalled_package_for_property(trans, &sp, up);
   1.715 +			if (!pkg) {
   1.716 +				pkg = find_uninstalled_package_for_file(trans, &upool[up->name]);
   1.717 +				if (pkg) {
   1.718 +					/* FIXME: find a way to do this more efficiently */
   1.719 +					maybe_mark_upgraded(trans, pkg);
   1.720 +				}
   1.721 +			}
   1.722 +			add_transaction_package(trans, pkg,
   1.723 +						RAZOR_PACKAGE_INSTALL,
   1.724 +						NULL, up);
   1.725 +			break;
   1.726 +
   1.727 +		case RAZOR_PROPERTY_PROVIDES:
   1.728 +			/* find_installed_package_for_property works backwards
   1.729 +			 * here, finding a *conflicting* installed package.
   1.730 +			 */
   1.731 +			pkg = find_installed_package_for_property(trans, &sp, up);
   1.732  			if (!pkg)
   1.733 -				pkg = find_upstream_file(trans, &upool[prop->name], 0);
   1.734 -			add_transaction_package(trans, pkg, trans->upstream,
   1.735 -						RAZOR_PACKAGE_INSTALL,
   1.736 -						prop, trans->upstream);
   1.737 +				break;
   1.738 +
   1.739 +			/* pkg CONFLICTS with what 'up' PROVIDES. Try
   1.740 +			 * finding an upgrade
   1.741 +			 */
   1.742 +			upgrade = find_upgrade_for_installed_conflict(trans, pkg, up);
   1.743 +			if (upgrade) {
   1.744 +				bitarray_set(&trans->syspkgs, pkg - spkgs, 0);
   1.745 +				add_transaction_package(trans, upgrade,
   1.746 +							RAZOR_PACKAGE_INSTALL,
   1.747 +							NULL, up);
   1.748 +			} else {
   1.749 +				add_transaction_package(trans, pkg,
   1.750 +							/* FIXME? */
   1.751 +							RAZOR_PACKAGE_REMOVE_CONFLICT,
   1.752 +							NULL, up);
   1.753 +			}
   1.754  			break;
   1.755  
   1.756  		case RAZOR_PROPERTY_CONFLICTS:
   1.757 -			if ((pkg = find_system_provider(trans, 1, 1, prop, &sp))) {
   1.758 -				struct razor_package *upgrade;
   1.759 -
   1.760 +			pkg = find_installed_package_for_property(trans, &sp, up);
   1.761 +			if (!pkg)
   1.762 +				break;
   1.763 +
   1.764 +			if (package_in_set(pkg, trans->system)) {
   1.765  				/* Conflicts with something already installed.
   1.766  				 * Try to upgrade out.
   1.767  				 */
   1.768 -				upgrade = find_upgrade(trans, prop, up);
   1.769 +				upgrade = find_upgrade(trans, sp, up);
   1.770  				if (upgrade) {
   1.771  					bitarray_set(&trans->syspkgs, pkg - spkgs, 0);
   1.772  					add_transaction_package(trans, upgrade,
   1.773 -								trans->upstream,
   1.774  								RAZOR_PACKAGE_INSTALL,
   1.775 -								prop, trans->upstream);
   1.776 +								NULL, up);
   1.777  				} else {
   1.778  					add_transaction_package(trans, pkg,
   1.779 -								trans->system, 
   1.780  								RAZOR_PACKAGE_INSTALL_CONFLICT,
   1.781 -								prop, trans->upstream);
   1.782 +								NULL, up);
   1.783  				}
   1.784 -			} else if ((pkg = find_upstream_provider(trans, 1, 1, prop, up))) {
   1.785 +			} else {
   1.786  				/* Conflicts with something already to-be-installed */
   1.787  				add_transaction_package(trans, pkg,
   1.788 -							trans->upstream, 
   1.789  							RAZOR_PACKAGE_INSTALL_CONFLICT,
   1.790 -							prop, trans->upstream);
   1.791 +							NULL, up);
   1.792  			}
   1.793  			break;
   1.794  
   1.795  		case RAZOR_PROPERTY_OBSOLETES:
   1.796 -			if ((pkg = find_system_provider(trans, 1, 1, prop, &sp))) {
   1.797 +			pkg = find_installed_package_for_property(trans, &sp, up);
   1.798 +			if (!pkg)
   1.799 +				break;
   1.800 +
   1.801 +			if (package_in_set(pkg, trans->system)) {
   1.802  				/* Obsoletes something installed */
   1.803  				add_transaction_package(trans, pkg,
   1.804 -							trans->system, 
   1.805  							RAZOR_PACKAGE_REMOVE,
   1.806 -							prop, trans->upstream);
   1.807 -			} else if ((pkg = find_upstream_provider(trans, 1, 1, prop, up))) {
   1.808 +							NULL, up);
   1.809 +			} else {
   1.810  				/* Obsoletes something that was to-be-installed */
   1.811  				add_transaction_package(trans, pkg,
   1.812 -							trans->upstream, 
   1.813  							RAZOR_PACKAGE_REMOVE_CONFLICT,
   1.814 -							prop, trans->upstream);
   1.815 +							NULL, up);
   1.816  			}
   1.817  			break;
   1.818  
   1.819 @@ -2204,36 +2368,14 @@
   1.820  	struct razor_package *pkgs, *lost_package;
   1.821  	char *pool = trans->system->string_pool.data;
   1.822  	struct list *p;
   1.823 -	struct razor_transaction_package *tp, *packages;;
   1.824 -	int already;
   1.825  
   1.826  	pkgs = trans->system->packages.data;
   1.827  	lost_package = &pkgs[list_first(lost_package_list, &trans->system->package_pool)->data];
   1.828  
   1.829  	for (p = list_first(&req->packages, &trans->system->package_pool); p; p = list_next(p)) {
   1.830 -		packages = trans->packages.data;
   1.831 -		already = find_transaction_package(&trans->packages, &pkgs[p->data]);
   1.832 -		if (already != -1 &&
   1.833 -		    (packages[already].state & RAZOR_PACKAGE_REMOVE))
   1.834 -			continue;
   1.835 -
   1.836 -		tp = array_add(&trans->packages, sizeof *tp);
   1.837 -		memset(tp, 0, sizeof *tp);
   1.838 -		tp->package = &pkgs[p->data];
   1.839 -		tp->name = &pool[tp->package->name];
   1.840 -		tp->version = &pool[tp->package->version];
   1.841 -		tp->req_package = &pool[lost_package->name];
   1.842 -		tp->req_type = req->type;
   1.843 -		tp->req_property = &pool[req->name];
   1.844 -		tp->req_relation = req->relation;
   1.845 -		tp->req_version = &pool[req->version];
   1.846 -		if (already != -1) {
   1.847 -			tp->state = RAZOR_PACKAGE_REMOVE_BLOCKED;
   1.848 -			trans->errors++;
   1.849 -		} else {
   1.850 -			tp->state = RAZOR_PACKAGE_REMOVE;
   1.851 -			bitarray_set(&trans->syspkgs, p->data, 0);
   1.852 -		}
   1.853 +		add_transaction_package(trans, &pkgs[p->data],
   1.854 +					RAZOR_PACKAGE_REMOVE,
   1.855 +					&pool[lost_package->name], req);
   1.856  	}
   1.857  }
   1.858  
   1.859 @@ -2280,11 +2422,11 @@
   1.860  	props = trans->system->properties.data;
   1.861  	prop_end = trans->system->properties.data + trans->system->properties.size;
   1.862  	pool = trans->system->string_pool.data;
   1.863 +	packages = trans->packages.data;
   1.864  
   1.865  	array_init(&lost_files);
   1.866  	array_init(&lost_provides);
   1.867  	for (r = start; r < end; r++) {
   1.868 -		packages = trans->packages.data;
   1.869  		if (packages[r].state != RAZOR_PACKAGE_REMOVE)
   1.870  			continue;
   1.871  
   1.872 @@ -2401,19 +2543,13 @@
   1.873  	bitarray_init(&trans.uppkgs, trans.upstream->packages.size / sizeof (struct razor_package), 0);
   1.874  	trans.errors = 0;
   1.875  
   1.876 -	/* Find initial upstream packages to be installed */
   1.877 -	if (update_count > 0) {
   1.878 -		find_packages(&trans, update_count, update_packages,
   1.879 -			      RAZOR_PACKAGE_INSTALL);
   1.880 -	} else if (remove_count == 0)
   1.881 +	if (update_count > 0 || remove_count > 0) {
   1.882 +		find_packages(&trans,
   1.883 +			      update_count, update_packages,
   1.884 +			      remove_count, remove_packages);
   1.885 +	} else
   1.886  		find_all_packages(&trans);
   1.887  
   1.888 -	/* Find initial installed packages to remove. */
   1.889 -	if (remove_count > 0) {
   1.890 -		find_packages(&trans, remove_count, remove_packages,
   1.891 -			      RAZOR_PACKAGE_REMOVE);
   1.892 -	}
   1.893 -
   1.894  	start = 0;
   1.895  	end = trans.packages.size / sizeof (struct razor_transaction_package);
   1.896  
   1.897 @@ -2483,24 +2619,26 @@
   1.898  			break;
   1.899  
   1.900  		case RAZOR_PACKAGE_INSTALL_UNAVAILABLE:
   1.901 -			if (*p->req_version && strcmp(p->req_property, p->name) == 0) {
   1.902 -				printf ("Can't find %s %s %s, which is required by %s",
   1.903 -					p->name,
   1.904 -					razor_version_relations[p->req_relation],
   1.905 -					p->req_version,
   1.906 -					p->req_package);
   1.907 -			} else {
   1.908 -				printf ("Can't find %s", p->name);
   1.909 -				if (*p->version)
   1.910 -					printf (" %s", p->version);
   1.911 -				
   1.912 -				if (p->req_package) {
   1.913 -					printf ("  which is required by %s",
   1.914 +			printf ("Can't find %s", p->name);
   1.915 +			if (p->req_package) {
   1.916 +				if (*p->req_version && strcmp(p->req_property, p->name) == 0) {
   1.917 +					printf ("%s %s, which is required by %s",
   1.918 +						razor_version_relations[p->req_relation],
   1.919 +						p->req_version,
   1.920  						p->req_package);
   1.921 -					if (strcmp(p->req_property, p->name) != 0)
   1.922 -						printf (" for %s", p->req_property);
   1.923 +				} else {
   1.924 +					if (*p->version)
   1.925 +						printf (" %s", p->version);
   1.926 +
   1.927 +					if (p->req_package) {
   1.928 +						printf ("  which is required by %s",
   1.929 +							p->req_package);
   1.930 +						if (strcmp(p->req_property, p->name) != 0)
   1.931 +							printf (" for %s", p->req_property);
   1.932 +					}
   1.933  				}
   1.934 -			}
   1.935 +			} else if (p->version && *p->version)
   1.936 +				printf (" %s", p->version);
   1.937  			printf("\n");
   1.938  			errors_only = 1;
   1.939  			break;