From: Dan Winship Date: Thu, 21 Feb 2008 17:09:13 +0000 (-0500) Subject: Add support for removing packages X-Git-Tag: 0.1~231 X-Git-Url: http://project.juiblex.co.uk/git/?a=commitdiff_plain;h=2c9835a79a844327c061d4a0927d8683ddc65c0f;p=razor2.git%2F.git Add support for removing packages Should be redone to avoid rebuilding the set multiple times First two tests pass now --- diff --git a/main.c b/main.c index b52fbcb..78ffea7 100644 --- a/main.c +++ b/main.c @@ -339,6 +339,22 @@ command_update(int argc, const char *argv[]) return 0; } +static int +command_remove(int argc, const char *argv[]) +{ + struct razor_set *set; + + set = razor_set_open(repo_filename); + if (set == NULL) + return 1; + set = razor_set_remove(set, argc, argv); + razor_set_write(set, updated_repo_filename); + razor_set_destroy(set); + printf("wrote system-updated.repo\n"); + + return 0; +} + static void print_diff(const char *name, const char *old_version, const char *new_version, void *data) @@ -483,6 +499,7 @@ static struct { { "import-rpms", "import rpms from the given directory", command_import_rpms }, { "validate", "validate a package set", command_validate }, { "update", "update all or specified packages", command_update }, + { "remove", "remove specified packages", command_remove }, { "diff", "show diff between two package sets", command_diff }, { "install", "install rpm", command_install } }; diff --git a/razor.c b/razor.c index 9d441ee..598f3a7 100644 --- a/razor.c +++ b/razor.c @@ -676,7 +676,7 @@ build_file_tree(struct razor_importer *importer) e = array_add(&importer->set->files, sizeof *e); e->name = root.name; e->flags = RAZOR_ENTRY_LAST; - e->start = 1; + e->start = importer->files.size ? 1 : 0; list_set_empty(&e->packages); serialize_files(importer->set, &root, &importer->set->files); @@ -1093,12 +1093,10 @@ razor_set_validate(struct razor_set *set, struct array *unsatisfied) if (r->type != RAZOR_PROPERTY_REQUIRES) continue; - if (r->name != p->name) { - p = r; - while (p < end && p->name == r->name && - p->type == r->type) - p++; - } + p = r; + while (p < end && p->name == r->name && + p->type == r->type) + p++; /* If there is more than one version of a provides, * seek to the end for the highest version. */ @@ -1396,6 +1394,7 @@ add_file(struct razor_merger *merger, const char *name) return e - (struct razor_entry *)merger->set->files.data; } +/* FIXME. Blah */ static int fix_file_map(uint32_t *map, struct razor_entry *files, @@ -1534,22 +1533,31 @@ merge_one_directory(struct razor_merger *merger, struct merge_directory *md) static void merge_files(struct razor_merger *merger) { - struct razor_entry *root1, *root2; + struct razor_entry *root; struct merge_directory md; uint32_t *map1, *map2; map1 = merger->source1.file_map; map2 = merger->source2.file_map; - root1 = (struct razor_entry *) merger->source1.set->files.data; - root2 = (struct razor_entry *) merger->source2.set->files.data; - - /* FIXME. Blah */ - fix_file_map(map1, root1, root1); - fix_file_map(map2, root2, root2); md.merged = add_file(merger, ""); - md.dir1 = root1->start; - md.dir2 = root2->start; + + if (merger->source1.set->files.size) { + root = (struct razor_entry *) merger->source1.set->files.data; + if (root->start) + fix_file_map(map1, root, root); + md.dir1 = root->start; + } else + md.dir1 = 0; + + if (merger->source2.set->files.size) { + root = (struct razor_entry *) merger->source2.set->files.data; + if (root->start) + fix_file_map(map2, root, root); + md.dir2 = root->start; + } else + md.dir2 = 0; + merge_one_directory(merger, &md); } @@ -1644,35 +1652,8 @@ struct razor_set * razor_merger_finish(struct razor_merger *merger) { struct razor_set *result; - - result = merger->set; - hashtable_release(&merger->table); - free(merger); - - return result; -} - -/* Add packages from 'upstream' to 'set'. The packages to add are - * specified by the 'packages' array, which is a sorted list of - * package indexes. Returns a newly allocated package set. Does not - * enforce validity of the resulting package set. - * - * This looks more complicated than it is. An easy way to merge two - * package sets would be to just use a razor_importer, but that - * requires resorting, and is thus O(n log n). We can do this in a - * linear sweep, but it gets a little more complicated. - */ -struct razor_set * -razor_set_add(struct razor_set *set, struct razor_set *upstream, - struct array *packages) -{ - struct razor_merger *merger; struct razor_package *p, *pend; - merger = razor_merger_create(set, upstream); - - merge_packages(merger, packages); - /* As we built the package list, we filled out a bitvector of * the properties that are referenced by the packages in the * new set. Now we do a parallel loop through the properties @@ -1710,6 +1691,33 @@ razor_set_add(struct razor_set *set, struct razor_set *upstream, rebuild_property_package_lists(merger->set); rebuild_file_package_lists(merger->set); + result = merger->set; + hashtable_release(&merger->table); + free(merger); + + return result; +} + +/* Add packages from 'upstream' to 'set'. The packages to add are + * specified by the 'packages' array, which is a sorted list of + * package indexes. Returns a newly allocated package set. Does not + * enforce validity of the resulting package set. + * + * This looks more complicated than it is. An easy way to merge two + * package sets would be to just use a razor_importer, but that + * requires resorting, and is thus O(n log n). We can do this in a + * linear sweep, but it gets a little more complicated. + */ +struct razor_set * +razor_set_add(struct razor_set *set, struct razor_set *upstream, + struct array *packages) +{ + struct razor_merger *merger; + + merger = razor_merger_create(set, upstream); + + merge_packages(merger, packages); + return razor_merger_finish(merger); } @@ -1839,6 +1847,108 @@ razor_set_update(struct razor_set *set, struct razor_set *upstream, return set; } +static struct razor_set * +razor_set_remove_internal(struct razor_set *set, struct array *list, + struct array *unsatisfied) +{ + struct razor_set *empty, *new; + struct razor_merger *merger; + struct razor_package *pkgs; + int pkg_count, remove_count, p, r; + struct array unsatisfied_before; + uint32_t *u, *uend, *ub, *ubend; + struct razor_property *props, *propsb; + char *pool, *poolb; + + array_init(&unsatisfied_before); + razor_set_validate(set, &unsatisfied_before); + + empty = razor_set_create(); + merger = razor_merger_create(set, empty); + + remove_count = list->size / sizeof (uint32_t); + pkg_count = set->packages.size / sizeof (struct razor_package); + pkgs = set->packages.data; + + for (p = 0; p < pkg_count; p++) { + for (r = 0; r < remove_count; r++) { + if (p == ((uint32_t *)list->data)[r]) + goto skip; + } + + add_package(merger, &pkgs[p], &merger->source1, 0); + skip: + ; + } + + new = razor_merger_finish(merger); + + razor_set_validate(new, unsatisfied); + + ubend = unsatisfied_before.data + unsatisfied_before.size; + uend = unsatisfied->data + unsatisfied->size; + props = new->properties.data; + propsb = set->properties.data; + pool = new->string_pool.data; + poolb = set->string_pool.data; + + for (u = unsatisfied->data; u < uend; u++) { + for (ub = unsatisfied_before.data; ub < ubend; ub++) { + if (!strcmp (&pool[props[*u].name], + &poolb[propsb[*ub].name]) && + props[*u].relation == propsb[*ub].relation && + !strcmp (&pool[props[*u].version], + &poolb[propsb[*ub].version])) { + *(u--) = *(--uend); + break; + } + } + } + + unsatisfied->size = (void *)uend - unsatisfied->data; + return new; +} + +struct razor_set * +razor_set_remove(struct razor_set *set, int count, const char **packages) +{ + struct razor_set *new; + struct array list, unsatisfied; + struct razor_property *props; + uint32_t *u, *uend, *p; + struct list *r; + + array_init(&list); + find_packages(set, count, packages, &list); + + while (list.size > 0) { + array_init(&unsatisfied); + new = razor_set_remove_internal(set, &list, &unsatisfied); + array_release(&list); + razor_set_destroy(set); + set = new; + + props = set->properties.data; + array_init(&list); + uend = unsatisfied.data + unsatisfied.size; + for (u = unsatisfied.data; u < uend; u++) { + if (props[*u].type == RAZOR_PROPERTY_REQUIRES) { + r = list_first(&props[*u].packages, &set->package_pool); + while (r) { + p = array_add(&list, sizeof *p); + *p = r->data; + r = list_next(r); + } + } + } + + array_release(&unsatisfied); + } + + array_release(&list); + return set; +} + /* The diff order matters. We should sort the packages so that a * REMOVE of a package comes before the INSTALL, and so that all * requires for a package have been installed before the package. diff --git a/razor.h b/razor.h index 6ecd950..6ce9b95 100644 --- a/razor.h +++ b/razor.h @@ -65,6 +65,8 @@ void razor_set_list_unsatisfied(struct razor_set *set); struct razor_set *razor_set_update(struct razor_set *set, struct razor_set *upstream, int count, const char **packages); +struct razor_set *razor_set_remove(struct razor_set *set, + int count, const char **packages); typedef void (*razor_package_callback_t)(const char *name, const char *old_version, diff --git a/test-driver.c b/test-driver.c index 7857807..64f3504 100644 --- a/test-driver.c +++ b/test-driver.c @@ -209,11 +209,13 @@ start_transaction(struct test_context *ctx, const char **atts) static void end_transaction(struct test_context *ctx) { - /* FIXME: removes */ ctx->system_set = razor_set_update(ctx->system_set, ctx->repo_set, ctx->n_install_pkgs, (const char **)ctx->install_pkgs); + ctx->system_set = razor_set_remove(ctx->system_set, + ctx->n_remove_pkgs, + (const char **)ctx->remove_pkgs); while (ctx->n_install_pkgs--) free(ctx->install_pkgs[ctx->n_install_pkgs]); @@ -277,12 +279,6 @@ end_result(struct test_context *ctx) { ctx->in_result = 0; - /* FIXME */ - if (ctx->n_remove_pkgs) { - printf (" (ignoring because of unimplemented remove)\n"); - return; - } - if (ctx->system_set && ctx->result_set) { ctx->result_errors = 0; razor_set_diff(ctx->system_set, ctx->result_set,