fetch, del: perform wildcard matching

ref #511
cute-signatures
Timo Teräs 2013-06-19 14:49:44 +03:00
parent a984fd3679
commit 9c54ef726c
2 changed files with 92 additions and 88 deletions

View File

@ -42,9 +42,8 @@ struct not_deleted_ctx {
int header; int header;
}; };
static void print_not_deleted_message( static void print_not_deleted_pkg(struct apk_package *pkg0, struct apk_dependency *dep0,
struct apk_package *pkg0, struct apk_dependency *dep0, struct apk_package *pkg, void *pctx)
struct apk_package *pkg, void *pctx)
{ {
struct not_deleted_ctx *ctx = (struct not_deleted_ctx *) pctx; struct not_deleted_ctx *ctx = (struct not_deleted_ctx *) pctx;
@ -58,76 +57,73 @@ static void print_not_deleted_message(
} }
apk_print_indented(&ctx->indent, APK_BLOB_STR(pkg0->name->name)); apk_print_indented(&ctx->indent, APK_BLOB_STR(pkg0->name->name));
apk_pkg_foreach_reverse_dependency(pkg0, ctx->matches, print_not_deleted_message, pctx); apk_pkg_foreach_reverse_dependency(pkg0, ctx->matches, print_not_deleted_pkg, pctx);
} }
static void delete_from_world( static void print_not_deleted_name(struct apk_database *db, const char *match,
struct apk_package *pkg0, struct apk_dependency *dep0, struct apk_name *name, void *pctx)
struct apk_package *pkg, void *pctx) {
struct not_deleted_ctx *ctx = (struct not_deleted_ctx *) pctx;
struct apk_provider *p;
ctx->indent.indent = 0;
ctx->name = name;
ctx->matches = apk_foreach_genid() | APK_FOREACH_MARKED | APK_DEP_SATISFIES;
foreach_array_item(p, name->providers)
if (p->pkg->marked)
print_not_deleted_pkg(p->pkg, NULL, NULL, ctx);
if (ctx->indent.indent)
printf("\n");
}
static void delete_pkg(struct apk_package *pkg0, struct apk_dependency *dep0,
struct apk_package *pkg, void *pctx)
{ {
struct del_ctx *ctx = (struct del_ctx *) pctx; struct del_ctx *ctx = (struct del_ctx *) pctx;
apk_deps_del(&ctx->world, pkg0->name); apk_deps_del(&ctx->world, pkg0->name);
if (ctx->recursive_delete) if (ctx->recursive_delete)
apk_pkg_foreach_reverse_dependency( apk_pkg_foreach_reverse_dependency(
pkg0, APK_FOREACH_INSTALLED | APK_DEP_SATISFIES, pkg0, APK_FOREACH_INSTALLED | APK_DEP_SATISFIES,
delete_from_world, pctx); delete_pkg, pctx);
}
static void delete_name(struct apk_database *db, const char *match,
struct apk_name *name, void *pctx)
{
struct apk_package *pkg;
pkg = apk_pkg_get_installed(name);
if (pkg != NULL)
delete_pkg(pkg, NULL, NULL, pctx);
} }
static int del_main(void *pctx, struct apk_database *db, struct apk_string_array *args) static int del_main(void *pctx, struct apk_database *db, struct apk_string_array *args)
{ {
struct del_ctx *ctx = (struct del_ctx *) pctx; struct del_ctx *ctx = (struct del_ctx *) pctx;
struct not_deleted_ctx ndctx = {}; struct not_deleted_ctx ndctx = {};
struct apk_name_array *names;
struct apk_name **pname;
struct apk_package *pkg;
struct apk_changeset changeset = {}; struct apk_changeset changeset = {};
struct apk_change *change; struct apk_change *change;
struct apk_provider *p; int r = 0;
int r = 0, i;
apk_name_array_init(&names);
apk_name_array_resize(&names, args->num);
apk_dependency_array_copy(&ctx->world, db->world); apk_dependency_array_copy(&ctx->world, db->world);
apk_name_foreach_matching(db, args, apk_foreach_genid(), delete_name, ctx);
for (i = 0; i < args->num; i++) {
names->item[i] = apk_db_get_name(db, APK_BLOB_STR(args->item[i]));
pkg = apk_pkg_get_installed(names->item[i]);
if (pkg != NULL)
delete_from_world(pkg, NULL, NULL, ctx);
}
r = apk_solver_solve(db, 0, ctx->world, &changeset); r = apk_solver_solve(db, 0, ctx->world, &changeset);
if (r == 0) { if (r == 0) {
/* check for non-deleted package names */ /* check for non-deleted package names */
foreach_array_item(change, changeset.changes) { foreach_array_item(change, changeset.changes)
struct apk_package *pkg = change->new_pkg; if (change->new_pkg != NULL)
if (pkg == NULL) change->new_pkg->marked = 1;
continue; apk_name_foreach_matching(db, args, apk_foreach_genid(),
pkg->marked = 1; print_not_deleted_name, &ndctx);
}
foreach_array_item(pname, names) {
ndctx.indent.indent = 0;
ndctx.name = *pname;
ndctx.matches = apk_foreach_genid() | APK_FOREACH_MARKED | APK_DEP_SATISFIES;
foreach_array_item(p, (*pname)->providers) {
if (!p->pkg->marked)
continue;
print_not_deleted_message(p->pkg, NULL, NULL, &ndctx);
}
if (ndctx.indent.indent)
printf("\n");
}
if (ndctx.header) if (ndctx.header)
printf("\n"); printf("\n");
apk_solver_commit_changeset(db, &changeset, ctx->world);
r = 0; r = apk_solver_commit_changeset(db, &changeset, ctx->world);
} else { } else {
apk_solver_print_errors(db, &changeset, ctx->world); apk_solver_print_errors(db, &changeset, ctx->world);
} }
apk_dependency_array_free(&ctx->world); apk_dependency_array_free(&ctx->world);
apk_name_array_free(&names);
return r; return r;
} }

View File

@ -187,13 +187,59 @@ static void mark_package(struct fetch_ctx *ctx, struct apk_package *pkg)
pkg->marked = 1; pkg->marked = 1;
} }
static void mark_error(struct fetch_ctx *ctx, const char *match, struct apk_name *name)
{
if (strchr(match, '*') != NULL)
return;
apk_message("%s: unable to select package (or it's dependencies)", name->name);
ctx->errors++;
}
static void mark_name_recursive(struct apk_database *db, const char *match, struct apk_name *name, void *ctx)
{
struct apk_changeset changeset = {};
struct apk_dependency dep = (struct apk_dependency) {
.name = name,
.version = &apk_null_blob,
.result_mask = APK_DEPMASK_ANY,
};
struct apk_dependency_array *world;
struct apk_change *change;
int r;
apk_dependency_array_init(&world);
*apk_dependency_array_add(&world) = dep;
r = apk_solver_solve(db, 0, world, &changeset);
apk_dependency_array_free(&world);
if (r == 0) {
foreach_array_item(change, changeset.changes)
mark_package(ctx, change->new_pkg);
} else
mark_error(ctx, match, name);
apk_change_array_free(&changeset.changes);
}
static void mark_name(struct apk_database *db, const char *match, struct apk_name *name, void *ctx)
{
struct apk_package *pkg = NULL;
struct apk_provider *p;
foreach_array_item(p, name->providers)
if (pkg == NULL || apk_pkg_version_compare(p->pkg, pkg) == APK_VERSION_GREATER)
pkg = p->pkg;
if (pkg != NULL)
mark_package(ctx, pkg);
else
mark_error(ctx, match, name);
}
static int fetch_main(void *pctx, struct apk_database *db, struct apk_string_array *args) static int fetch_main(void *pctx, struct apk_database *db, struct apk_string_array *args)
{ {
struct fetch_ctx *ctx = (struct fetch_ctx *) pctx; struct fetch_ctx *ctx = (struct fetch_ctx *) pctx;
struct apk_dependency_array *world; void *mark = (ctx->flags & FETCH_RECURSIVE) ? mark_name_recursive : mark_name;
struct apk_change *change;
char **parg;
int r = 0;
if (ctx->outdir_fd == 0) if (ctx->outdir_fd == 0)
ctx->outdir_fd = AT_FDCWD; ctx->outdir_fd = AT_FDCWD;
@ -205,46 +251,8 @@ static int fetch_main(void *pctx, struct apk_database *db, struct apk_string_arr
return 0; return 0;
} }
foreach_array_item(parg, args) {
struct apk_dependency dep = (struct apk_dependency) {
.name = apk_db_get_name(db, APK_BLOB_STR(*parg)),
.version = apk_blob_atomize(APK_BLOB_NULL),
.result_mask = APK_DEPMASK_ANY,
};
if (ctx->flags & FETCH_RECURSIVE) {
struct apk_changeset changeset = {};
apk_dependency_array_init(&world);
*apk_dependency_array_add(&world) = dep;
r = apk_solver_solve(db, 0, world, &changeset);
apk_dependency_array_free(&world);
if (r != 0) {
apk_error("%s: unable to get dependencies", dep.name->name);
ctx->errors++;
} else {
foreach_array_item(change, changeset.changes)
mark_package(ctx, change->new_pkg);
}
apk_change_array_free(&changeset.changes);
} else {
struct apk_package *pkg = NULL;
struct apk_provider *p;
foreach_array_item(p, dep.name->providers)
if (pkg == NULL || apk_pkg_version_compare(p->pkg, pkg) == APK_VERSION_GREATER)
pkg = p->pkg;
if (pkg == NULL) {
apk_message("%s: unable to select a version", dep.name->name);
ctx->errors++;
} else {
mark_package(ctx, pkg);
}
}
}
ctx->db = db; ctx->db = db;
apk_name_foreach_matching(db, args, apk_foreach_genid(), mark, ctx);
apk_hash_foreach(&db->available.packages, fetch_package, ctx); apk_hash_foreach(&db->available.packages, fetch_package, ctx);
return ctx->errors; return ctx->errors;