razor.c
changeset 139 a416240614e3
parent 138 49deac048d07
child 140 017f92f7039a
     1.1 --- a/razor.c	Fri Feb 29 12:45:08 2008 -0500
     1.2 +++ b/razor.c	Fri Feb 29 15:09:44 2008 -0500
     1.3 @@ -1978,19 +1978,70 @@
     1.4  }
     1.5  
     1.6  static void
     1.7 -lose_requirement(struct razor_transaction *trans, struct array *package_array,
     1.8 -		 const char *req_package, struct razor_property *req,
     1.9 -		 struct razor_property *lost_provider,
    1.10 -		 struct razor_property *first_provider)
    1.11 +gather_lost_files(struct razor_set *set, struct razor_package *pkg,
    1.12 +		  struct array *lost_files)
    1.13  {
    1.14 -	struct razor_property *provider, *prop_end;
    1.15 -	struct razor_package *pkgs;
    1.16 +	struct razor_entry *entries = set->files.data, *entry, **lost;
    1.17 +	struct list *e, *providers;
    1.18 +
    1.19 +	for (e = list_first(&pkg->files, &set->file_pool); e; e = list_next(e)) {
    1.20 +		entry = &entries[e->data];
    1.21 +		providers = list_first(&entry->packages, &set->package_pool);
    1.22 +		if (providers && !list_next(providers)) {
    1.23 +			lost = array_add(lost_files, sizeof *lost);
    1.24 +			*lost = entry;
    1.25 +		}
    1.26 +	}
    1.27 +}
    1.28 +
    1.29 +static void
    1.30 +lose_required_package(struct razor_transaction *trans,
    1.31 +		      struct array *package_array,
    1.32 +		      struct razor_property *req,
    1.33 +		      struct list_head *lost_package_list)
    1.34 +{
    1.35 +	struct razor_package *pkgs, *lost_package;
    1.36  	char *pool = trans->system->string_pool.data;
    1.37  	struct list *p;
    1.38  	struct razor_transaction_package *tp, *packages;;
    1.39  	int already;
    1.40  
    1.41  	pkgs = trans->system->packages.data;
    1.42 +	lost_package = &pkgs[list_first(lost_package_list, &trans->system->package_pool)->data];
    1.43 +
    1.44 +	for (p = list_first(&req->packages, &trans->system->package_pool); p; p = list_next(p)) {
    1.45 +		packages = package_array->data;
    1.46 +		already = find_transaction_package(package_array, &pkgs[p->data]);
    1.47 +		if (already != -1 &&
    1.48 +		    (packages[already].state & RAZOR_PACKAGE_REMOVE))
    1.49 +			continue;
    1.50 +
    1.51 +		tp = array_add(package_array, sizeof *tp);
    1.52 +		memset(tp, 0, sizeof *tp);
    1.53 +		tp->package = &pkgs[p->data];
    1.54 +		tp->name = &pool[tp->package->name];
    1.55 +		tp->version = &pool[tp->package->version];
    1.56 +		tp->req_package = &pool[lost_package->name];
    1.57 +		tp->req_property = &pool[req->name];
    1.58 +		tp->req_relation = req->relation;
    1.59 +		tp->req_version = &pool[req->version];
    1.60 +		if (already != -1) {
    1.61 +			tp->state = RAZOR_PACKAGE_REMOVE_BLOCKED;
    1.62 +			trans->errors++;
    1.63 +		} else
    1.64 +			tp->state = RAZOR_PACKAGE_REMOVE;
    1.65 +	}
    1.66 +}
    1.67 +
    1.68 +static void
    1.69 +lose_requirement(struct razor_transaction *trans, struct array *package_array,
    1.70 +		 struct razor_property *req,
    1.71 +		 struct razor_property *lost_provider,
    1.72 +		 struct razor_property *first_provider)
    1.73 +{
    1.74 +	struct razor_property *provider, *prop_end;
    1.75 +	char *pool = trans->system->string_pool.data;
    1.76 +
    1.77  	prop_end = trans->system->properties.data + trans->system->properties.size;
    1.78  
    1.79  	/* See if any other provider satisfies req */
    1.80 @@ -2004,29 +2055,8 @@
    1.81  			return;
    1.82  	}
    1.83  
    1.84 -	/* Remove each of the packages requiring req */
    1.85 -	for (p = list_first(&req->packages, &trans->system->package_pool); p; p = list_next(p)) {
    1.86 -		packages = package_array->data;
    1.87 -		already = find_transaction_package(package_array, &pkgs[p->data]);
    1.88 -		if (already != -1 &&
    1.89 -		    (packages[already].state & RAZOR_PACKAGE_REMOVE))
    1.90 -			continue;
    1.91 -
    1.92 -		tp = array_add(package_array, sizeof *tp);
    1.93 -		memset(tp, 0, sizeof *tp);
    1.94 -		tp->package = &pkgs[p->data];
    1.95 -		tp->name = &pool[tp->package->name];
    1.96 -		tp->version = &pool[tp->package->version];
    1.97 -		tp->req_package = req_package;
    1.98 -		tp->req_property = &pool[req->name];
    1.99 -		tp->req_relation = req->relation;
   1.100 -		tp->req_version = &pool[req->version];
   1.101 -		if (already != -1) {
   1.102 -			tp->state = RAZOR_PACKAGE_REMOVE_BLOCKED;
   1.103 -			trans->errors++;
   1.104 -		} else
   1.105 -			tp->state = RAZOR_PACKAGE_REMOVE;
   1.106 -	}
   1.107 +	lose_required_package(trans, package_array, req,
   1.108 +			      &lost_provider->packages);
   1.109  }
   1.110  
   1.111  static void
   1.112 @@ -2038,41 +2068,74 @@
   1.113  	struct razor_package *pkgs;
   1.114  	int pkg_count, r;
   1.115  	uint32_t *lost, *lost_end;
   1.116 +	struct razor_entry *entry, **lostf, **lostf_end;
   1.117  	struct razor_property *props, *prop_end, *req, *first_provider;
   1.118 -	struct array lost_provides;
   1.119 -	const char *req_package;
   1.120 +	struct array lost_provides, lost_files;
   1.121 +	char *pool;
   1.122  
   1.123  	pkgs = trans->system->packages.data;
   1.124  	pkg_count = trans->system->packages.size / sizeof (struct razor_package);
   1.125  	props = trans->system->properties.data;
   1.126  	prop_end = trans->system->properties.data + trans->system->properties.size;
   1.127 +	pool = trans->system->string_pool.data;
   1.128  
   1.129 +	array_init(&lost_files);
   1.130 +	array_init(&lost_provides);
   1.131  	for (r = start; r < end; r++) {
   1.132  		packages = package_array->data;
   1.133  		if (packages[r].state != RAZOR_PACKAGE_REMOVE)
   1.134  			continue;
   1.135  
   1.136 -		array_init(&lost_provides);
   1.137 -		req_package = packages[r].name;
   1.138  		gather_lost_provides(trans->system, packages[r].package,
   1.139  				     &lost_provides);
   1.140 +		gather_lost_files(trans->system, packages[r].package,
   1.141 +				  &lost_files);
   1.142 +	}
   1.143  
   1.144 -		lost_end = lost_provides.data + lost_provides.size;
   1.145 -		for (lost = lost_provides.data; lost < lost_end; lost++) {
   1.146 -			/* Requires FOO will appear before Provides FOO */
   1.147 -			for (req = &props[*lost]; req > props && req->name == props[*lost].name && req->type != RAZOR_PROPERTY_REQUIRES; req--)
   1.148 -				;
   1.149 -			first_provider = req + 1;
   1.150 +	/* Handle lost_provides */
   1.151 +	lost_end = lost_provides.data + lost_provides.size;
   1.152 +	for (lost = lost_provides.data; lost < lost_end; lost++) {
   1.153 +		/* Requires FOO will appear before Provides FOO */
   1.154 +		for (req = &props[*lost]; req > props && req->name == props[*lost].name && req->type != RAZOR_PROPERTY_REQUIRES; req--)
   1.155 +			;
   1.156 +		first_provider = req + 1;
   1.157  
   1.158 -			while (req > props && req->name == props[*lost].name) {
   1.159 -				lose_requirement(trans, package_array,
   1.160 -						 req_package, req,
   1.161 -						 &props[*lost], first_provider);
   1.162 -				req--;
   1.163 -			}
   1.164 +		while (req > props && req->name == props[*lost].name) {
   1.165 +			lose_requirement(trans, package_array, req,
   1.166 +					 &props[*lost], first_provider);
   1.167 +			req--;
   1.168  		}
   1.169 -		array_release(&lost_provides);
   1.170  	}
   1.171 +	array_release(&lost_provides);
   1.172 +
   1.173 +	/* And now lost_files. FIXME, inefficient */
   1.174 +	lostf_end = lost_files.data + lost_files.size;
   1.175 +
   1.176 +	req = props;
   1.177 +	/* Due to the sorting of props, this loop is likely a no-op */
   1.178 +	while (pool[req->name] != '/')
   1.179 +		req++;
   1.180 +
   1.181 +	for (; req < prop_end && pool[req->name] == '/'; req++) {
   1.182 +		if (req->type != RAZOR_PROPERTY_REQUIRES)
   1.183 +			continue;
   1.184 +
   1.185 +		entry = find_entry(trans->system, trans->system->files.data,
   1.186 +				   &pool[req->name]);
   1.187 +		if (!entry)
   1.188 +			continue;
   1.189 +
   1.190 +		for (lostf = lost_files.data; lostf < lostf_end; lostf++) {
   1.191 +			if (*lostf == entry)
   1.192 +				break;
   1.193 +		}
   1.194 +		if (lostf == lostf_end)
   1.195 +			continue;
   1.196 +
   1.197 +		lose_required_package(trans, package_array, req,
   1.198 +				      &(entry)->packages);
   1.199 +	}
   1.200 +	array_release(&lost_files);
   1.201  }
   1.202  
   1.203  /* The diff order matters.  We should sort the packages so that a