summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2013-06-15 20:39:05 +0300
committerTimo Teräs <timo.teras@iki.fi>2013-06-15 22:25:23 +0300
commitf79e3946a40bf6beb2a38050a866c0fb1ed4bcf4 (patch)
treee49fefbf64cc88b24db54fe726386fb4950bea8c
parent5b02400b268e4e867a30cd76821ff7139502089e (diff)
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.
-rw-r--r--src/apk_package.h20
-rw-r--r--src/del.c71
-rw-r--r--src/package.c33
-rw-r--r--src/search.c11
4 files changed, 64 insertions, 71 deletions
diff --git a/src/apk_package.h b/src/apk_package.h
index b04bd79..979de5e 100644
--- a/src/apk_package.h
+++ b/src/apk_package.h
@@ -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);
diff --git a/src/del.c b/src/del.c
index 704245a..2e7de8b 100644
--- a/src/del.c
+++ b/src/del.c
@@ -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");
}
diff --git a/src/package.c b/src/package.c
index 31321e7..0fca1db 100644
--- a/src/package.c
+++ b/src/package.c
@@ -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)
{
diff --git a/src/search.c b/src/search.c
index 2f39f38..410becd 100644
--- a/src/search.c
+++ b/src/search.c
@@ -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)