razor.c
changeset 129 d221757574c1
parent 128 18350b26395b
child 130 10e6914910dd
child 131 1b5338bcb7d1
     1.1 --- a/razor.c	Wed Feb 20 16:54:03 2008 -0500
     1.2 +++ b/razor.c	Thu Feb 21 12:09:13 2008 -0500
     1.3 @@ -676,7 +676,7 @@
     1.4  	e = array_add(&importer->set->files, sizeof *e);
     1.5  	e->name = root.name;
     1.6  	e->flags = RAZOR_ENTRY_LAST;
     1.7 -	e->start = 1;
     1.8 +	e->start = importer->files.size ? 1 : 0;
     1.9  	list_set_empty(&e->packages);
    1.10  
    1.11  	serialize_files(importer->set, &root, &importer->set->files);
    1.12 @@ -1093,12 +1093,10 @@
    1.13  		if (r->type != RAZOR_PROPERTY_REQUIRES)
    1.14  			continue;
    1.15  
    1.16 -		if (r->name != p->name) {
    1.17 -			p = r;
    1.18 -			while (p < end && p->name == r->name &&
    1.19 -			       p->type == r->type)
    1.20 -				p++;
    1.21 -		}
    1.22 +		p = r;
    1.23 +		while (p < end && p->name == r->name &&
    1.24 +		       p->type == r->type)
    1.25 +			p++;
    1.26  
    1.27  		/* If there is more than one version of a provides,
    1.28  		 * seek to the end for the highest version. */
    1.29 @@ -1396,6 +1394,7 @@
    1.30  	return e - (struct razor_entry *)merger->set->files.data;
    1.31  }
    1.32  
    1.33 +/* FIXME. Blah */
    1.34  static int
    1.35  fix_file_map(uint32_t *map,
    1.36  	     struct razor_entry *files,
    1.37 @@ -1534,22 +1533,31 @@
    1.38  static void
    1.39  merge_files(struct razor_merger *merger)
    1.40  {
    1.41 -	struct razor_entry *root1, *root2;
    1.42 +	struct razor_entry *root;
    1.43  	struct merge_directory md;
    1.44  	uint32_t *map1, *map2;
    1.45  
    1.46  	map1 = merger->source1.file_map;
    1.47  	map2 = merger->source2.file_map;
    1.48 -	root1 = (struct razor_entry *) merger->source1.set->files.data;
    1.49 -	root2 = (struct razor_entry *) merger->source2.set->files.data;
    1.50 -
    1.51 -	/* FIXME. Blah */
    1.52 -	fix_file_map(map1, root1, root1);
    1.53 -	fix_file_map(map2, root2, root2);
    1.54  
    1.55  	md.merged = add_file(merger, "");
    1.56 -	md.dir1 = root1->start;
    1.57 -	md.dir2 = root2->start;
    1.58 +
    1.59 +	if (merger->source1.set->files.size) {
    1.60 +		root = (struct razor_entry *) merger->source1.set->files.data;
    1.61 +		if (root->start)
    1.62 +			fix_file_map(map1, root, root);
    1.63 +		md.dir1 = root->start;
    1.64 +	} else
    1.65 +		md.dir1 = 0;
    1.66 +
    1.67 +	if (merger->source2.set->files.size) {
    1.68 +		root = (struct razor_entry *) merger->source2.set->files.data;
    1.69 +		if (root->start)
    1.70 +			fix_file_map(map2, root, root);
    1.71 +		md.dir2 = root->start;
    1.72 +	} else
    1.73 +		md.dir2 = 0;
    1.74 +
    1.75  	merge_one_directory(merger, &md);
    1.76  }
    1.77  
    1.78 @@ -1644,35 +1652,8 @@
    1.79  razor_merger_finish(struct razor_merger *merger)
    1.80  {
    1.81  	struct razor_set *result;
    1.82 -
    1.83 -	result = merger->set;
    1.84 -	hashtable_release(&merger->table);
    1.85 -	free(merger);
    1.86 -
    1.87 -	return result;
    1.88 -}
    1.89 -
    1.90 -/* Add packages from 'upstream' to 'set'.  The packages to add are
    1.91 - * specified by the 'packages' array, which is a sorted list of
    1.92 - * package indexes.  Returns a newly allocated package set.  Does not
    1.93 - * enforce validity of the resulting package set.
    1.94 - *
    1.95 - * This looks more complicated than it is.  An easy way to merge two
    1.96 - * package sets would be to just use a razor_importer, but that
    1.97 - * requires resorting, and is thus O(n log n).  We can do this in a
    1.98 - * linear sweep, but it gets a little more complicated.
    1.99 - */
   1.100 -struct razor_set *
   1.101 -razor_set_add(struct razor_set *set, struct razor_set *upstream,
   1.102 -	      struct array *packages)
   1.103 -{
   1.104 -	struct razor_merger *merger;
   1.105  	struct razor_package *p, *pend;
   1.106  
   1.107 -	merger = razor_merger_create(set, upstream);
   1.108 -
   1.109 -	merge_packages(merger, packages);
   1.110 -
   1.111  	/* As we built the package list, we filled out a bitvector of
   1.112  	 * the properties that are referenced by the packages in the
   1.113  	 * new set.  Now we do a parallel loop through the properties
   1.114 @@ -1710,6 +1691,33 @@
   1.115  	rebuild_property_package_lists(merger->set);
   1.116  	rebuild_file_package_lists(merger->set);
   1.117  
   1.118 +	result = merger->set;
   1.119 +	hashtable_release(&merger->table);
   1.120 +	free(merger);
   1.121 +
   1.122 +	return result;
   1.123 +}
   1.124 +
   1.125 +/* Add packages from 'upstream' to 'set'.  The packages to add are
   1.126 + * specified by the 'packages' array, which is a sorted list of
   1.127 + * package indexes.  Returns a newly allocated package set.  Does not
   1.128 + * enforce validity of the resulting package set.
   1.129 + *
   1.130 + * This looks more complicated than it is.  An easy way to merge two
   1.131 + * package sets would be to just use a razor_importer, but that
   1.132 + * requires resorting, and is thus O(n log n).  We can do this in a
   1.133 + * linear sweep, but it gets a little more complicated.
   1.134 + */
   1.135 +struct razor_set *
   1.136 +razor_set_add(struct razor_set *set, struct razor_set *upstream,
   1.137 +	      struct array *packages)
   1.138 +{
   1.139 +	struct razor_merger *merger;
   1.140 +
   1.141 +	merger = razor_merger_create(set, upstream);
   1.142 +
   1.143 +	merge_packages(merger, packages);
   1.144 +
   1.145  	return razor_merger_finish(merger);
   1.146  }
   1.147  
   1.148 @@ -1839,6 +1847,108 @@
   1.149  	return set;
   1.150  }
   1.151  
   1.152 +static struct razor_set *
   1.153 +razor_set_remove_internal(struct razor_set *set, struct array *list,
   1.154 +			  struct array *unsatisfied)
   1.155 +{
   1.156 +	struct razor_set *empty, *new;
   1.157 +	struct razor_merger *merger;
   1.158 +	struct razor_package *pkgs;
   1.159 +	int pkg_count, remove_count, p, r;
   1.160 +	struct array unsatisfied_before;
   1.161 +	uint32_t *u, *uend, *ub, *ubend;
   1.162 +	struct razor_property *props, *propsb;
   1.163 +	char *pool, *poolb;
   1.164 +
   1.165 +	array_init(&unsatisfied_before);
   1.166 +	razor_set_validate(set, &unsatisfied_before);
   1.167 +
   1.168 +	empty = razor_set_create();
   1.169 +	merger = razor_merger_create(set, empty);
   1.170 +
   1.171 +	remove_count = list->size / sizeof (uint32_t);
   1.172 +	pkg_count = set->packages.size / sizeof (struct razor_package);
   1.173 +	pkgs = set->packages.data;
   1.174 +
   1.175 +	for (p = 0; p < pkg_count; p++) {
   1.176 +		for (r = 0; r < remove_count; r++) {
   1.177 +			if (p == ((uint32_t *)list->data)[r])
   1.178 +				goto skip;
   1.179 +		}
   1.180 +
   1.181 +		add_package(merger, &pkgs[p], &merger->source1, 0);
   1.182 +	skip:
   1.183 +		;
   1.184 +	}
   1.185 +
   1.186 +	new = razor_merger_finish(merger);
   1.187 +
   1.188 +	razor_set_validate(new, unsatisfied);
   1.189 +
   1.190 +	ubend = unsatisfied_before.data + unsatisfied_before.size;
   1.191 +	uend = unsatisfied->data + unsatisfied->size;
   1.192 +	props = new->properties.data;
   1.193 +	propsb = set->properties.data;
   1.194 +	pool = new->string_pool.data;
   1.195 +	poolb = set->string_pool.data;
   1.196 +
   1.197 +	for (u = unsatisfied->data; u < uend; u++) {
   1.198 +		for (ub = unsatisfied_before.data; ub < ubend; ub++) {
   1.199 +			if (!strcmp (&pool[props[*u].name],
   1.200 +				     &poolb[propsb[*ub].name]) &&
   1.201 +			    props[*u].relation == propsb[*ub].relation &&
   1.202 +			    !strcmp (&pool[props[*u].version],
   1.203 +				     &poolb[propsb[*ub].version])) {
   1.204 +				*(u--) = *(--uend);
   1.205 +				break;
   1.206 +			}
   1.207 +		}
   1.208 +	}
   1.209 +
   1.210 +	unsatisfied->size = (void *)uend - unsatisfied->data;
   1.211 +	return new;
   1.212 +}
   1.213 +
   1.214 +struct razor_set *
   1.215 +razor_set_remove(struct razor_set *set, int count, const char **packages)
   1.216 +{
   1.217 +	struct razor_set *new;
   1.218 +	struct array list, unsatisfied;
   1.219 +	struct razor_property *props;
   1.220 +	uint32_t *u, *uend, *p;
   1.221 +	struct list *r;
   1.222 +
   1.223 +	array_init(&list);
   1.224 +	find_packages(set, count, packages, &list);
   1.225 +
   1.226 +	while (list.size > 0) {
   1.227 +		array_init(&unsatisfied);
   1.228 +		new = razor_set_remove_internal(set, &list, &unsatisfied);
   1.229 +		array_release(&list);
   1.230 +		razor_set_destroy(set);
   1.231 +		set = new;
   1.232 +
   1.233 +		props = set->properties.data;
   1.234 +		array_init(&list);
   1.235 +		uend = unsatisfied.data + unsatisfied.size;
   1.236 +		for (u = unsatisfied.data; u < uend; u++) {
   1.237 +			if (props[*u].type == RAZOR_PROPERTY_REQUIRES) {
   1.238 +				r = list_first(&props[*u].packages, &set->package_pool);
   1.239 +				while (r) {
   1.240 +					p = array_add(&list, sizeof *p);
   1.241 +					*p = r->data;
   1.242 +					r = list_next(r);
   1.243 +				}
   1.244 +			}
   1.245 +		}
   1.246 +
   1.247 +		array_release(&unsatisfied);
   1.248 +	}
   1.249 +
   1.250 +	array_release(&list);
   1.251 +	return set;
   1.252 +}
   1.253 +
   1.254  /* The diff order matters.  We should sort the packages so that a
   1.255   * REMOVE of a package comes before the INSTALL, and so that all
   1.256   * requires for a package have been installed before the package.