pkg: apk_pkg_foreach_* add matching generation

So same package it is possible to not match same package multiple
times. Use generation count, so this is handled cleanly during
recursion, like in the use case of search applet.
cute-signatures
Timo Teräs 2013-06-15 20:39:05 +03:00
parent 5b02400b26
commit f79e3946a4
4 changed files with 64 additions and 71 deletions

View File

@ -37,11 +37,12 @@ struct apk_provider;
#define APK_SIGN_GENERATE 4
#define APK_SIGN_VERIFY_AND_GENERATE 5
#define APK_DEP_IRRELEVANT 0x00001
#define APK_DEP_SATISFIES 0x00002
#define APK_DEP_CONFLICTS 0x00004
#define APK_FOREACH_INSTALLED 0x10000
#define APK_FOREACH_MARKED 0x20000
#define APK_DEP_IRRELEVANT 0x01
#define APK_DEP_SATISFIES 0x02
#define APK_DEP_CONFLICTS 0x04
#define APK_FOREACH_INSTALLED 0x10
#define APK_FOREACH_MARKED 0x20
#define APK_FOREACH_GENID_MASK 0xffffff00
struct apk_sign_ctx {
int keys_fd;
@ -95,7 +96,8 @@ struct apk_package {
union {
struct apk_solver_package_state ss;
struct {
int marked;
unsigned int marked;
unsigned int foreach_genid;
union {
int state_int;
void *state_ptr;
@ -185,12 +187,14 @@ int apk_pkg_write_index_entry(struct apk_package *pkg, struct apk_ostream *os);
int apk_pkg_version_compare(struct apk_package *a, struct apk_package *b);
unsigned int apk_foreach_genid(void);
void apk_pkg_foreach_matching_dependency(
struct apk_package *pkg, struct apk_dependency_array *deps, int match, struct apk_package *mpkg,
struct apk_package *pkg, struct apk_dependency_array *deps,
unsigned int match, struct apk_package *mpkg,
void cb(struct apk_package *pkg0, struct apk_dependency *dep0, struct apk_package *pkg, void *ctx),
void *ctx);
void apk_pkg_foreach_reverse_dependency(
struct apk_package *pkg, int match,
struct apk_package *pkg, unsigned int match,
void cb(struct apk_package *pkg0, struct apk_dependency *dep0, struct apk_package *pkg, void *ctx),
void *ctx);

View File

@ -35,29 +35,10 @@ static int del_parse(void *pctx, struct apk_db_options *db,
return 0;
}
static void foreach_reverse_dependency(
struct apk_name *name, int match,
void cb(struct apk_package *pkg0, struct apk_dependency *dep0, struct apk_package *pkg, void *ctx),
void *ctx)
{
int installed = match & APK_FOREACH_INSTALLED;
int marked = match & APK_FOREACH_MARKED;
struct apk_provider *p0;
struct apk_package *pkg0;
foreach_array_item(p0, name->providers) {
pkg0 = p0->pkg;
if (installed && pkg0->ipkg == NULL)
continue;
if (marked && !pkg0->marked)
continue;
apk_pkg_foreach_reverse_dependency(pkg0, match, cb, ctx);
}
}
struct not_deleted_ctx {
struct apk_indent indent;
struct apk_package *pkg;
struct apk_name *name;
unsigned int matches;
int header;
};
@ -67,25 +48,17 @@ static void print_not_deleted_message(
{
struct not_deleted_ctx *ctx = (struct not_deleted_ctx *) pctx;
if (pkg == NULL)
return;
if (pkg->state_ptr == ctx->pkg)
return;
pkg->state_ptr = ctx->pkg;
if (!ctx->header) {
apk_message("World updated, but the following packages are not removed due to:");
ctx->header = 1;
}
if (!ctx->indent.indent) {
ctx->indent.x = printf(" %s:", ctx->pkg->name->name);
ctx->indent.x = printf(" %s:", ctx->name->name);
ctx->indent.indent = ctx->indent.x + 1;
}
apk_print_indented(&ctx->indent, APK_BLOB_STR(pkg->name->name));
apk_pkg_foreach_reverse_dependency(
pkg0, APK_FOREACH_MARKED | APK_DEP_SATISFIES,
print_not_deleted_message, pctx);
apk_print_indented(&ctx->indent, APK_BLOB_STR(pkg0->name->name));
apk_pkg_foreach_reverse_dependency(pkg0, ctx->matches, print_not_deleted_message, pctx);
}
static void delete_from_world(
@ -95,17 +68,21 @@ static void delete_from_world(
struct del_ctx *ctx = (struct del_ctx *) pctx;
apk_deps_del(&ctx->world, pkg0->name);
apk_pkg_foreach_reverse_dependency(
pkg0, APK_FOREACH_INSTALLED | APK_DEP_SATISFIES,
delete_from_world, pctx);
if (ctx->recursive_delete)
apk_pkg_foreach_reverse_dependency(
pkg0, APK_FOREACH_INSTALLED | APK_DEP_SATISFIES,
delete_from_world, pctx);
}
static int del_main(void *pctx, struct apk_database *db, int argc, char **argv)
{
struct del_ctx *ctx = (struct del_ctx *) pctx;
struct not_deleted_ctx ndctx = {};
struct apk_name **name;
struct apk_changeset changeset = {};
struct not_deleted_ctx ndctx = {};
struct apk_change *change;
struct apk_provider *p;
int i, r = 0;
apk_dependency_array_copy(&ctx->world, db->world);
@ -113,33 +90,27 @@ static int del_main(void *pctx, struct apk_database *db, int argc, char **argv)
name = alloca(argc * sizeof(struct apk_name*));
for (i = 0; i < argc; i++) {
name[i] = apk_db_get_name(db, APK_BLOB_STR(argv[i]));
apk_deps_del(&ctx->world, name[i]);
if (ctx->recursive_delete)
foreach_reverse_dependency(
name[i], APK_FOREACH_INSTALLED | APK_DEP_SATISFIES,
delete_from_world, ctx);
delete_from_world(apk_pkg_get_installed(name[i]), NULL, NULL, ctx);
}
r = apk_solver_solve(db, 0, ctx->world, &changeset);
if (r == 0) {
/* check for non-deleted package names */
struct apk_change *change;
foreach_array_item(change, changeset.changes) {
struct apk_package *pkg = change->new_pkg;
struct apk_dependency *p;
if (pkg == NULL)
continue;
pkg->marked = 1;
pkg->name->state_ptr = pkg;
foreach_array_item(p, pkg->provides)
p->name->state_ptr = pkg;
}
for (i = 0; i < argc; i++) {
ndctx.pkg = name[i]->state_ptr;
ndctx.indent.indent = 0;
foreach_reverse_dependency(
name[i], APK_FOREACH_MARKED | APK_DEP_SATISFIES,
print_not_deleted_message, &ndctx);
ndctx.name = name[i];
ndctx.matches = apk_foreach_genid() | APK_FOREACH_MARKED | APK_DEP_SATISFIES;
foreach_array_item(p, name[i]->providers) {
if (!p->pkg->marked)
continue;
print_not_deleted_message(p->pkg, NULL, NULL, &ndctx);
}
if (ndctx.indent.indent)
printf("\n");
}

View File

@ -1190,28 +1190,46 @@ int apk_pkg_version_compare(struct apk_package *a, struct apk_package *b)
return apk_version_compare_blob(*a->version, *b->version);
}
unsigned int apk_foreach_genid(void)
{
static unsigned int foreach_genid;
foreach_genid += (~APK_FOREACH_GENID_MASK) + 1;
return foreach_genid;
}
void apk_pkg_foreach_matching_dependency(
struct apk_package *pkg, struct apk_dependency_array *deps, int match, struct apk_package *mpkg,
struct apk_package *pkg, struct apk_dependency_array *deps,
unsigned int match, struct apk_package *mpkg,
void cb(struct apk_package *pkg0, struct apk_dependency *dep0, struct apk_package *pkg, void *ctx),
void *ctx)
{
unsigned int genid = match & APK_FOREACH_GENID_MASK;
struct apk_dependency *d;
if (genid && pkg->foreach_genid >= genid)
return;
if (pkg)
pkg->foreach_genid = genid;
foreach_array_item(d, deps) {
if (apk_dep_analyze(d, mpkg) & match)
if (apk_dep_analyze(d, mpkg) & match) {
cb(pkg, d, mpkg, ctx);
if (genid)
break;
}
}
}
static void foreach_reverse_dependency(
struct apk_package *pkg,
struct apk_name_array *rdepends,
int match,
unsigned int match,
void cb(struct apk_package *pkg0, struct apk_dependency *dep0, struct apk_package *pkg, void *ctx),
void *ctx)
{
int installed = match & APK_FOREACH_INSTALLED;
int marked = match & APK_FOREACH_MARKED;
unsigned int installed = match & APK_FOREACH_INSTALLED;
unsigned int marked = match & APK_FOREACH_MARKED;
unsigned int genid = match & APK_FOREACH_GENID_MASK;
struct apk_name **pname0, *name0;
struct apk_provider *p0;
struct apk_package *pkg0;
@ -1225,6 +1243,9 @@ static void foreach_reverse_dependency(
continue;
if (marked && !pkg0->marked)
continue;
if (genid && pkg0->foreach_genid >= genid)
continue;
pkg0->foreach_genid = genid;
foreach_array_item(d0, pkg0->depends) {
if (apk_dep_analyze(d0, pkg) & match)
cb(pkg0, d0, pkg, ctx);
@ -1234,7 +1255,7 @@ static void foreach_reverse_dependency(
}
void apk_pkg_foreach_reverse_dependency(
struct apk_package *pkg, int match,
struct apk_package *pkg, unsigned int match,
void cb(struct apk_package *pkg0, struct apk_dependency *dep0, struct apk_package *pkg, void *ctx),
void *ctx)
{

View File

@ -23,8 +23,8 @@ struct search_ctx {
int show_all : 1;
int search_exact : 1;
int search_description : 1;
int rdep_generation;
unsigned int matches;
int argc;
char **argv;
};
@ -53,19 +53,16 @@ static void print_origin_name(struct search_ctx *ctx, struct apk_package *pkg)
static void print_rdep_pkg(struct apk_package *pkg0, struct apk_dependency *dep0, struct apk_package *pkg, void *pctx)
{
struct search_ctx *ctx = (struct search_ctx *) pctx;
if (pkg0->state_int == ctx->rdep_generation)
return;
pkg0->state_int = ctx->rdep_generation;
ctx->print_package(ctx, pkg0);
}
static void print_rdepends(struct search_ctx *ctx, struct apk_package *pkg)
{
if (apk_verbosity > 0) {
ctx->rdep_generation++;
ctx->matches = apk_foreach_genid() | APK_DEP_SATISFIES;
printf(PKG_VER_FMT " is required by:\n", PKG_VER_PRINTF(pkg));
}
apk_pkg_foreach_reverse_dependency(pkg, APK_DEP_SATISFIES, print_rdep_pkg, ctx);
apk_pkg_foreach_reverse_dependency(pkg, ctx->matches, print_rdep_pkg, ctx);
}
static int search_parse(void *ctx, struct apk_db_options *dbopts,
@ -160,7 +157,7 @@ static int search_main(void *pctx, struct apk_database *db, int argc, char **arg
char s[256];
int i, l;
ctx->rdep_generation = 1;
ctx->matches = apk_foreach_genid() | APK_DEP_SATISFIES;
if (ctx->print_package == NULL)
ctx->print_package = print_package_name;
if (ctx->print_result == NULL)