Add support for removing packages
authorDan Winship <danw@gnome.org>
Thu Feb 21 12:09:13 2008 -0500 (2008-02-21)
changeset 129d221757574c1
parent 128 18350b26395b
child 130 10e6914910dd
child 131 1b5338bcb7d1
Add support for removing packages

Should be redone to avoid rebuilding the set multiple times

First two tests pass now
main.c
razor.c
razor.h
test-driver.c
     1.1 --- a/main.c	Wed Feb 20 16:54:03 2008 -0500
     1.2 +++ b/main.c	Thu Feb 21 12:09:13 2008 -0500
     1.3 @@ -339,6 +339,22 @@
     1.4  	return 0;
     1.5  }
     1.6  
     1.7 +static int
     1.8 +command_remove(int argc, const char *argv[])
     1.9 +{
    1.10 +	struct razor_set *set;
    1.11 +
    1.12 +	set = razor_set_open(repo_filename);
    1.13 +	if (set == NULL)
    1.14 +		return 1;
    1.15 +	set = razor_set_remove(set, argc, argv);
    1.16 +	razor_set_write(set, updated_repo_filename);
    1.17 +	razor_set_destroy(set);
    1.18 +	printf("wrote system-updated.repo\n");
    1.19 +
    1.20 +	return 0;
    1.21 +}
    1.22 +
    1.23  static void
    1.24  print_diff(const char *name,
    1.25  	   const char *old_version, const char *new_version, void *data)
    1.26 @@ -483,6 +499,7 @@
    1.27  	{ "import-rpms", "import rpms from the given directory", command_import_rpms },
    1.28  	{ "validate", "validate a package set", command_validate },
    1.29  	{ "update", "update all or specified packages", command_update },
    1.30 +	{ "remove", "remove specified packages", command_remove },
    1.31  	{ "diff", "show diff between two package sets", command_diff },
    1.32  	{ "install", "install rpm", command_install }
    1.33  };
     2.1 --- a/razor.c	Wed Feb 20 16:54:03 2008 -0500
     2.2 +++ b/razor.c	Thu Feb 21 12:09:13 2008 -0500
     2.3 @@ -676,7 +676,7 @@
     2.4  	e = array_add(&importer->set->files, sizeof *e);
     2.5  	e->name = root.name;
     2.6  	e->flags = RAZOR_ENTRY_LAST;
     2.7 -	e->start = 1;
     2.8 +	e->start = importer->files.size ? 1 : 0;
     2.9  	list_set_empty(&e->packages);
    2.10  
    2.11  	serialize_files(importer->set, &root, &importer->set->files);
    2.12 @@ -1093,12 +1093,10 @@
    2.13  		if (r->type != RAZOR_PROPERTY_REQUIRES)
    2.14  			continue;
    2.15  
    2.16 -		if (r->name != p->name) {
    2.17 -			p = r;
    2.18 -			while (p < end && p->name == r->name &&
    2.19 -			       p->type == r->type)
    2.20 -				p++;
    2.21 -		}
    2.22 +		p = r;
    2.23 +		while (p < end && p->name == r->name &&
    2.24 +		       p->type == r->type)
    2.25 +			p++;
    2.26  
    2.27  		/* If there is more than one version of a provides,
    2.28  		 * seek to the end for the highest version. */
    2.29 @@ -1396,6 +1394,7 @@
    2.30  	return e - (struct razor_entry *)merger->set->files.data;
    2.31  }
    2.32  
    2.33 +/* FIXME. Blah */
    2.34  static int
    2.35  fix_file_map(uint32_t *map,
    2.36  	     struct razor_entry *files,
    2.37 @@ -1534,22 +1533,31 @@
    2.38  static void
    2.39  merge_files(struct razor_merger *merger)
    2.40  {
    2.41 -	struct razor_entry *root1, *root2;
    2.42 +	struct razor_entry *root;
    2.43  	struct merge_directory md;
    2.44  	uint32_t *map1, *map2;
    2.45  
    2.46  	map1 = merger->source1.file_map;
    2.47  	map2 = merger->source2.file_map;
    2.48 -	root1 = (struct razor_entry *) merger->source1.set->files.data;
    2.49 -	root2 = (struct razor_entry *) merger->source2.set->files.data;
    2.50 -
    2.51 -	/* FIXME. Blah */
    2.52 -	fix_file_map(map1, root1, root1);
    2.53 -	fix_file_map(map2, root2, root2);
    2.54  
    2.55  	md.merged = add_file(merger, "");
    2.56 -	md.dir1 = root1->start;
    2.57 -	md.dir2 = root2->start;
    2.58 +
    2.59 +	if (merger->source1.set->files.size) {
    2.60 +		root = (struct razor_entry *) merger->source1.set->files.data;
    2.61 +		if (root->start)
    2.62 +			fix_file_map(map1, root, root);
    2.63 +		md.dir1 = root->start;
    2.64 +	} else
    2.65 +		md.dir1 = 0;
    2.66 +
    2.67 +	if (merger->source2.set->files.size) {
    2.68 +		root = (struct razor_entry *) merger->source2.set->files.data;
    2.69 +		if (root->start)
    2.70 +			fix_file_map(map2, root, root);
    2.71 +		md.dir2 = root->start;
    2.72 +	} else
    2.73 +		md.dir2 = 0;
    2.74 +
    2.75  	merge_one_directory(merger, &md);
    2.76  }
    2.77  
    2.78 @@ -1644,35 +1652,8 @@
    2.79  razor_merger_finish(struct razor_merger *merger)
    2.80  {
    2.81  	struct razor_set *result;
    2.82 -
    2.83 -	result = merger->set;
    2.84 -	hashtable_release(&merger->table);
    2.85 -	free(merger);
    2.86 -
    2.87 -	return result;
    2.88 -}
    2.89 -
    2.90 -/* Add packages from 'upstream' to 'set'.  The packages to add are
    2.91 - * specified by the 'packages' array, which is a sorted list of
    2.92 - * package indexes.  Returns a newly allocated package set.  Does not
    2.93 - * enforce validity of the resulting package set.
    2.94 - *
    2.95 - * This looks more complicated than it is.  An easy way to merge two
    2.96 - * package sets would be to just use a razor_importer, but that
    2.97 - * requires resorting, and is thus O(n log n).  We can do this in a
    2.98 - * linear sweep, but it gets a little more complicated.
    2.99 - */
   2.100 -struct razor_set *
   2.101 -razor_set_add(struct razor_set *set, struct razor_set *upstream,
   2.102 -	      struct array *packages)
   2.103 -{
   2.104 -	struct razor_merger *merger;
   2.105  	struct razor_package *p, *pend;
   2.106  
   2.107 -	merger = razor_merger_create(set, upstream);
   2.108 -
   2.109 -	merge_packages(merger, packages);
   2.110 -
   2.111  	/* As we built the package list, we filled out a bitvector of
   2.112  	 * the properties that are referenced by the packages in the
   2.113  	 * new set.  Now we do a parallel loop through the properties
   2.114 @@ -1710,6 +1691,33 @@
   2.115  	rebuild_property_package_lists(merger->set);
   2.116  	rebuild_file_package_lists(merger->set);
   2.117  
   2.118 +	result = merger->set;
   2.119 +	hashtable_release(&merger->table);
   2.120 +	free(merger);
   2.121 +
   2.122 +	return result;
   2.123 +}
   2.124 +
   2.125 +/* Add packages from 'upstream' to 'set'.  The packages to add are
   2.126 + * specified by the 'packages' array, which is a sorted list of
   2.127 + * package indexes.  Returns a newly allocated package set.  Does not
   2.128 + * enforce validity of the resulting package set.
   2.129 + *
   2.130 + * This looks more complicated than it is.  An easy way to merge two
   2.131 + * package sets would be to just use a razor_importer, but that
   2.132 + * requires resorting, and is thus O(n log n).  We can do this in a
   2.133 + * linear sweep, but it gets a little more complicated.
   2.134 + */
   2.135 +struct razor_set *
   2.136 +razor_set_add(struct razor_set *set, struct razor_set *upstream,
   2.137 +	      struct array *packages)
   2.138 +{
   2.139 +	struct razor_merger *merger;
   2.140 +
   2.141 +	merger = razor_merger_create(set, upstream);
   2.142 +
   2.143 +	merge_packages(merger, packages);
   2.144 +
   2.145  	return razor_merger_finish(merger);
   2.146  }
   2.147  
   2.148 @@ -1839,6 +1847,108 @@
   2.149  	return set;
   2.150  }
   2.151  
   2.152 +static struct razor_set *
   2.153 +razor_set_remove_internal(struct razor_set *set, struct array *list,
   2.154 +			  struct array *unsatisfied)
   2.155 +{
   2.156 +	struct razor_set *empty, *new;
   2.157 +	struct razor_merger *merger;
   2.158 +	struct razor_package *pkgs;
   2.159 +	int pkg_count, remove_count, p, r;
   2.160 +	struct array unsatisfied_before;
   2.161 +	uint32_t *u, *uend, *ub, *ubend;
   2.162 +	struct razor_property *props, *propsb;
   2.163 +	char *pool, *poolb;
   2.164 +
   2.165 +	array_init(&unsatisfied_before);
   2.166 +	razor_set_validate(set, &unsatisfied_before);
   2.167 +
   2.168 +	empty = razor_set_create();
   2.169 +	merger = razor_merger_create(set, empty);
   2.170 +
   2.171 +	remove_count = list->size / sizeof (uint32_t);
   2.172 +	pkg_count = set->packages.size / sizeof (struct razor_package);
   2.173 +	pkgs = set->packages.data;
   2.174 +
   2.175 +	for (p = 0; p < pkg_count; p++) {
   2.176 +		for (r = 0; r < remove_count; r++) {
   2.177 +			if (p == ((uint32_t *)list->data)[r])
   2.178 +				goto skip;
   2.179 +		}
   2.180 +
   2.181 +		add_package(merger, &pkgs[p], &merger->source1, 0);
   2.182 +	skip:
   2.183 +		;
   2.184 +	}
   2.185 +
   2.186 +	new = razor_merger_finish(merger);
   2.187 +
   2.188 +	razor_set_validate(new, unsatisfied);
   2.189 +
   2.190 +	ubend = unsatisfied_before.data + unsatisfied_before.size;
   2.191 +	uend = unsatisfied->data + unsatisfied->size;
   2.192 +	props = new->properties.data;
   2.193 +	propsb = set->properties.data;
   2.194 +	pool = new->string_pool.data;
   2.195 +	poolb = set->string_pool.data;
   2.196 +
   2.197 +	for (u = unsatisfied->data; u < uend; u++) {
   2.198 +		for (ub = unsatisfied_before.data; ub < ubend; ub++) {
   2.199 +			if (!strcmp (&pool[props[*u].name],
   2.200 +				     &poolb[propsb[*ub].name]) &&
   2.201 +			    props[*u].relation == propsb[*ub].relation &&
   2.202 +			    !strcmp (&pool[props[*u].version],
   2.203 +				     &poolb[propsb[*ub].version])) {
   2.204 +				*(u--) = *(--uend);
   2.205 +				break;
   2.206 +			}
   2.207 +		}
   2.208 +	}
   2.209 +
   2.210 +	unsatisfied->size = (void *)uend - unsatisfied->data;
   2.211 +	return new;
   2.212 +}
   2.213 +
   2.214 +struct razor_set *
   2.215 +razor_set_remove(struct razor_set *set, int count, const char **packages)
   2.216 +{
   2.217 +	struct razor_set *new;
   2.218 +	struct array list, unsatisfied;
   2.219 +	struct razor_property *props;
   2.220 +	uint32_t *u, *uend, *p;
   2.221 +	struct list *r;
   2.222 +
   2.223 +	array_init(&list);
   2.224 +	find_packages(set, count, packages, &list);
   2.225 +
   2.226 +	while (list.size > 0) {
   2.227 +		array_init(&unsatisfied);
   2.228 +		new = razor_set_remove_internal(set, &list, &unsatisfied);
   2.229 +		array_release(&list);
   2.230 +		razor_set_destroy(set);
   2.231 +		set = new;
   2.232 +
   2.233 +		props = set->properties.data;
   2.234 +		array_init(&list);
   2.235 +		uend = unsatisfied.data + unsatisfied.size;
   2.236 +		for (u = unsatisfied.data; u < uend; u++) {
   2.237 +			if (props[*u].type == RAZOR_PROPERTY_REQUIRES) {
   2.238 +				r = list_first(&props[*u].packages, &set->package_pool);
   2.239 +				while (r) {
   2.240 +					p = array_add(&list, sizeof *p);
   2.241 +					*p = r->data;
   2.242 +					r = list_next(r);
   2.243 +				}
   2.244 +			}
   2.245 +		}
   2.246 +
   2.247 +		array_release(&unsatisfied);
   2.248 +	}
   2.249 +
   2.250 +	array_release(&list);
   2.251 +	return set;
   2.252 +}
   2.253 +
   2.254  /* The diff order matters.  We should sort the packages so that a
   2.255   * REMOVE of a package comes before the INSTALL, and so that all
   2.256   * requires for a package have been installed before the package.
     3.1 --- a/razor.h	Wed Feb 20 16:54:03 2008 -0500
     3.2 +++ b/razor.h	Thu Feb 21 12:09:13 2008 -0500
     3.3 @@ -65,6 +65,8 @@
     3.4  struct razor_set *razor_set_update(struct razor_set *set,
     3.5  				   struct razor_set *upstream,
     3.6  				   int count, const char **packages);
     3.7 +struct razor_set *razor_set_remove(struct razor_set *set,
     3.8 +				   int count, const char **packages);
     3.9  
    3.10  typedef void (*razor_package_callback_t)(const char *name,
    3.11  					 const char *old_version,
     4.1 --- a/test-driver.c	Wed Feb 20 16:54:03 2008 -0500
     4.2 +++ b/test-driver.c	Thu Feb 21 12:09:13 2008 -0500
     4.3 @@ -209,11 +209,13 @@
     4.4  static void
     4.5  end_transaction(struct test_context *ctx)
     4.6  {
     4.7 -	/* FIXME: removes */
     4.8  	ctx->system_set = razor_set_update(ctx->system_set,
     4.9  					   ctx->repo_set,
    4.10  					   ctx->n_install_pkgs,
    4.11  					   (const char **)ctx->install_pkgs);
    4.12 +	ctx->system_set = razor_set_remove(ctx->system_set,
    4.13 +					   ctx->n_remove_pkgs,
    4.14 +					   (const char **)ctx->remove_pkgs);
    4.15  
    4.16  	while (ctx->n_install_pkgs--)
    4.17  		free(ctx->install_pkgs[ctx->n_install_pkgs]);
    4.18 @@ -277,12 +279,6 @@
    4.19  {
    4.20  	ctx->in_result = 0;
    4.21  
    4.22 -	/* FIXME */
    4.23 -	if (ctx->n_remove_pkgs) {
    4.24 -		printf ("  (ignoring because of unimplemented remove)\n");
    4.25 -		return;
    4.26 -	}
    4.27 -
    4.28  	if (ctx->system_set && ctx->result_set) {
    4.29  		ctx->result_errors = 0;
    4.30  		razor_set_diff(ctx->system_set, ctx->result_set,