diff --git a/src/apk_package.h b/src/apk_package.h index 44e463c..3d6ee29 100644 --- a/src/apk_package.h +++ b/src/apk_package.h @@ -37,9 +37,11 @@ struct apk_provider; #define APK_SIGN_GENERATE 4 #define APK_SIGN_VERIFY_AND_GENERATE 5 -#define APK_DEP_IRRELEVANT 0 -#define APK_DEP_SATISFIED 1 -#define APK_DEP_CONFLICTED 2 +#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 struct apk_sign_ctx { int keys_fd; @@ -92,8 +94,13 @@ struct apk_package { apk_hash_node hash_node; union { struct apk_solver_package_state ss; - int state_int; - void *state_ptr; + struct { + int marked; + union { + int state_int; + void *state_ptr; + }; + }; }; struct apk_name *name; struct apk_installed_package *ipkg; @@ -179,4 +186,13 @@ 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); +void apk_pkg_foreach_matching_dependency( + struct apk_package *pkg, struct apk_dependency_array *deps, 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, + void cb(struct apk_package *pkg0, struct apk_dependency *dep0, struct apk_package *pkg, void *ctx), + void *ctx); + #endif diff --git a/src/commit.c b/src/commit.c index a4ba492..a81bfc4 100644 --- a/src/commit.c +++ b/src/commit.c @@ -18,46 +18,6 @@ #include "apk_print.h" -static void foreach_package_reverse_dependency2( - struct apk_package *pkg, - struct apk_name_array *rdepends, - int match, - void cb(struct apk_package *pkg0, struct apk_dependency *d0, void *ctx), - void *ctx) -{ - int i, j, k; - - for (i = 0; i < rdepends->num; i++) { - struct apk_name *name0 = rdepends->item[i]; - - for (j = 0; j < name0->providers->num; j++) { - struct apk_package *pkg0 = name0->providers->item[j].pkg; - - for (k = 0; k < pkg0->depends->num; k++) { - struct apk_dependency *d0 = &pkg0->depends->item[k]; - if (apk_dep_analyze(d0, pkg) == match) - cb(pkg0, d0, ctx); - } - } - } -} - -static void foreach_package_reverse_dependency( - struct apk_package *pkg, - int match, - void cb(struct apk_package *pkg0, struct apk_dependency *d0, void *ctx), - void *ctx) -{ - int i; - - if (pkg == NULL) - return; - - foreach_package_reverse_dependency2(pkg, pkg->name->rdepends, match, cb, ctx); - for (i = 0; i < pkg->provides->num; i++) - foreach_package_reverse_dependency2(pkg, pkg->provides->item[i].name->rdepends, match, cb, ctx); -} - static inline int pkg_available(struct apk_database *db, struct apk_package *pkg) { if (pkg->repos & db->available_repos) @@ -472,14 +432,14 @@ static void print_conflicts(struct print_state *ps, struct apk_package *pkg) struct apk_dependency *d; foreach_array_item(p, pkg->name->providers) { - if (p->pkg == pkg || p->pkg->state_ptr == STATE_UNSET) + if (p->pkg == pkg || !p->pkg->marked) continue; label_start(ps, "conflicts:"); apk_print_indented_fmt(&ps->i, PKG_VER_FMT, PKG_VER_PRINTF(p->pkg)); } foreach_array_item(d, pkg->provides) { foreach_array_item(p, d->name->providers) { - if (p->pkg == pkg || p->pkg->state_ptr == STATE_UNSET) + if (p->pkg == pkg || !p->pkg->marked) continue; label_start(ps, "conflicts:"); apk_print_indented_fmt( @@ -492,15 +452,12 @@ static void print_conflicts(struct print_state *ps, struct apk_package *pkg) label_end(ps); } -static void print_dep(struct apk_package *pkg0, struct apk_dependency *d0, void *ctx) +static void print_dep(struct apk_package *pkg0, struct apk_dependency *d0, struct apk_package *pkg, void *ctx) { struct print_state *ps = (struct print_state *) ctx; - const char *label = (ps->match == APK_DEP_SATISFIED) ? "satisfies:" : "breaks:"; + const char *label = (ps->match & APK_DEP_SATISFIES) ? "satisfies:" : "breaks:"; char tmp[256]; - if (pkg0 != NULL && pkg0->state_ptr == STATE_UNSET) - return; - label_start(ps, label); if (pkg0 == NULL) apk_print_indented_fmt(&ps->i, "world[%s]", apk_dep_snprintf(tmp, sizeof(tmp), d0)); @@ -512,14 +469,9 @@ static void print_dep(struct apk_package *pkg0, struct apk_dependency *d0, void static void print_deps(struct print_state *ps, struct apk_package *pkg, int match) { - struct apk_dependency *d0; - ps->match = match; - foreach_array_item(d0, ps->world) { - if (apk_dep_analyze(d0, pkg) == match) - print_dep(NULL, d0, ps); - } - foreach_package_reverse_dependency(pkg, ps->match, print_dep, ps); + apk_pkg_foreach_matching_dependency(NULL, ps->world, ps->match, pkg, print_dep, ps); + apk_pkg_foreach_reverse_dependency(pkg, ps->match, print_dep, ps); label_end(ps); } @@ -532,9 +484,9 @@ static void analyze_package(struct print_state *ps, struct apk_package *pkg, uns print_pinning_errors(ps, pkg, tag); print_conflicts(ps, pkg); - print_deps(ps, pkg, APK_DEP_CONFLICTED); + print_deps(ps, pkg, APK_DEP_CONFLICTS | APK_FOREACH_MARKED); if (ps->label == NULL) - print_deps(ps, pkg, APK_DEP_SATISFIED); + print_deps(ps, pkg, APK_DEP_SATISFIES | APK_FOREACH_MARKED); } static void analyze_name(struct print_state *ps, struct apk_name *name) @@ -570,7 +522,7 @@ static void analyze_name(struct print_state *ps, struct apk_name *name) foreach_array_item(pname0, name->rdepends) { name0 = *pname0; foreach_array_item(p0, name0->providers) { - if (p0->pkg->state_ptr == STATE_UNSET) + if (!p0->pkg->marked) continue; foreach_array_item(d0, p0->pkg->depends) { if (d0->name != name || d0->conflict) @@ -652,7 +604,7 @@ void apk_solver_print_errors(struct apk_database *db, struct apk_package *pkg = change->new_pkg; if (pkg == NULL) continue; - pkg->state_int = STATE_PRESENT; + pkg->marked = 1; pkg->name->state_int = STATE_PRESENT; foreach_array_item(p, pkg->provides) p->name->state_int = STATE_PRESENT; diff --git a/src/del.c b/src/del.c index 305843d..704245a 100644 --- a/src/del.c +++ b/src/del.c @@ -15,11 +15,6 @@ #include "apk_print.h" #include "apk_solver.h" -enum { - INSTALLED_PACKAGES, - MARKED_PACKAGES, -}; - struct del_ctx { int recursive_delete : 1; struct apk_dependency_array *world; @@ -40,63 +35,23 @@ static int del_parse(void *pctx, struct apk_db_options *db, return 0; } -static void foreach_package_reverse_dependency2( - struct apk_package *pkg, struct apk_name_array *rdepends, - void (*cb)(struct apk_package *rdepend, void *ctx), void *ctx) -{ - int i, j, k; - - if (pkg == NULL) - return; - - for (i = 0; i < rdepends->num; i++) { - struct apk_name *name0 = rdepends->item[i]; - - for (j = 0; j < name0->providers->num; j++) { - struct apk_package *pkg0 = name0->providers->item[j].pkg; - - if (pkg0->ipkg == NULL) - continue; - - for (k = 0; k < pkg0->depends->num; k++) { - struct apk_dependency *dep = &pkg0->depends->item[k]; - if (apk_dep_is_materialized_or_provided(dep, pkg)) - break; - } - if (k >= pkg0->depends->num) - continue; - - cb(pkg0, ctx); - } - } -} - -static void foreach_package_reverse_dependency( - struct apk_package *pkg, - void (*cb)(struct apk_package *rdepend, void *ctx), void *ctx) -{ - int i; - - foreach_package_reverse_dependency2(pkg, pkg->name->rdepends, cb, ctx); - for (i = 0; i < pkg->provides->num; i++) - foreach_package_reverse_dependency2(pkg, pkg->provides->item[i].name->rdepends, cb, ctx); -} - static void foreach_reverse_dependency( - struct apk_name *name, int mode, - void (*cb)(struct apk_package *rdepend, void *ctx), void *ctx) + 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 i; + int installed = match & APK_FOREACH_INSTALLED; + int marked = match & APK_FOREACH_MARKED; + struct apk_provider *p0; + struct apk_package *pkg0; - for (i = 0; i < name->providers->num; i++) { - struct apk_package *pkg0 = name->providers->item[i].pkg; - - if (mode == INSTALLED_PACKAGES && pkg0->ipkg == NULL) + foreach_array_item(p0, name->providers) { + pkg0 = p0->pkg; + if (installed && pkg0->ipkg == NULL) continue; - if (mode == MARKED_PACKAGES && pkg0->state_int == 0) + if (marked && !pkg0->marked) continue; - - foreach_package_reverse_dependency(pkg0, cb, ctx); + apk_pkg_foreach_reverse_dependency(pkg0, match, cb, ctx); } } @@ -106,8 +61,9 @@ struct not_deleted_ctx { int header; }; -static void print_not_deleted_message(struct apk_package *pkg, - void *pctx) +static void print_not_deleted_message( + struct apk_package *pkg0, struct apk_dependency *dep0, + struct apk_package *pkg, void *pctx) { struct not_deleted_ctx *ctx = (struct not_deleted_ctx *) pctx; @@ -127,15 +83,21 @@ static void print_not_deleted_message(struct apk_package *pkg, } apk_print_indented(&ctx->indent, APK_BLOB_STR(pkg->name->name)); - foreach_package_reverse_dependency(pkg, print_not_deleted_message, pctx); + apk_pkg_foreach_reverse_dependency( + pkg0, APK_FOREACH_MARKED | APK_DEP_SATISFIES, + print_not_deleted_message, pctx); } -static void delete_from_world(struct apk_package *pkg, void *pctx) +static void delete_from_world( + struct apk_package *pkg0, struct apk_dependency *dep0, + struct apk_package *pkg, void *pctx) { struct del_ctx *ctx = (struct del_ctx *) pctx; - apk_deps_del(&ctx->world, pkg->name); - foreach_package_reverse_dependency(pkg, delete_from_world, pctx); + apk_deps_del(&ctx->world, pkg0->name); + 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) @@ -144,7 +106,7 @@ static int del_main(void *pctx, struct apk_database *db, int argc, char **argv) struct apk_name **name; struct apk_changeset changeset = {}; struct not_deleted_ctx ndctx = {}; - int i, j, r = 0; + int i, r = 0; apk_dependency_array_copy(&ctx->world, db->world); @@ -154,27 +116,29 @@ static int del_main(void *pctx, struct apk_database *db, int argc, char **argv) apk_deps_del(&ctx->world, name[i]); if (ctx->recursive_delete) foreach_reverse_dependency( - name[i], INSTALLED_PACKAGES, + name[i], APK_FOREACH_INSTALLED | APK_DEP_SATISFIES, delete_from_world, ctx); } r = apk_solver_solve(db, 0, ctx->world, &changeset); if (r == 0) { /* check for non-deleted package names */ - for (i = 0; i < changeset.changes->num; i++) { - struct apk_package *pkg = changeset.changes->item[i].new_pkg; + 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; - for (j = 0; j < pkg->provides->num; j++) - pkg->provides->item[j].name->state_ptr = pkg; - pkg->state_int = 1; + 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], MARKED_PACKAGES, + name[i], APK_FOREACH_MARKED | APK_DEP_SATISFIES, print_not_deleted_message, &ndctx); if (ndctx.indent.indent) printf("\n"); diff --git a/src/package.c b/src/package.c index e9eb45a..85c67b4 100644 --- a/src/package.c +++ b/src/package.c @@ -407,7 +407,7 @@ int apk_dep_analyze(struct apk_dependency *dep, struct apk_package *pkg) return APK_DEP_IRRELEVANT; if (dep->name == pkg->name) - return apk_dep_is_materialized(dep, pkg) ? APK_DEP_SATISFIED : APK_DEP_CONFLICTED; + return apk_dep_is_materialized(dep, pkg) ? APK_DEP_SATISFIES : APK_DEP_CONFLICTS; for (i = 0; i < pkg->provides->num; i++) { struct apk_provider p; @@ -416,7 +416,7 @@ int apk_dep_analyze(struct apk_dependency *dep, struct apk_package *pkg) continue; p = APK_PROVIDER_FROM_PROVIDES(pkg, &pkg->provides->item[i]); - return apk_dep_is_provided(dep, &p) ? APK_DEP_SATISFIED : APK_DEP_CONFLICTED; + return apk_dep_is_provided(dep, &p) ? APK_DEP_SATISFIES : APK_DEP_CONFLICTS; } return APK_DEP_IRRELEVANT; @@ -1213,3 +1213,58 @@ int apk_pkg_version_compare(struct apk_package *a, struct apk_package *b) return apk_version_compare_blob(*a->version, *b->version); } + +void apk_pkg_foreach_matching_dependency( + struct apk_package *pkg, struct apk_dependency_array *deps, int match, struct apk_package *mpkg, + void cb(struct apk_package *pkg0, struct apk_dependency *dep0, struct apk_package *pkg, void *ctx), + void *ctx) +{ + struct apk_dependency *d; + + foreach_array_item(d, deps) { + if (apk_dep_analyze(d, mpkg) & match) + cb(pkg, d, mpkg, ctx); + } +} + +static void foreach_reverse_dependency( + struct apk_package *pkg, + struct apk_name_array *rdepends, + 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_name **pname0, *name0; + struct apk_provider *p0; + struct apk_package *pkg0; + struct apk_dependency *d0; + + foreach_array_item(pname0, rdepends) { + name0 = *pname0; + foreach_array_item(p0, name0->providers) { + pkg0 = p0->pkg; + if (installed && pkg0->ipkg == NULL) + continue; + if (marked && !pkg0->marked) + continue; + foreach_array_item(d0, pkg0->depends) { + if (apk_dep_analyze(d0, pkg) & match) + cb(pkg0, d0, pkg, ctx); + } + } + } +} + +void apk_pkg_foreach_reverse_dependency( + struct apk_package *pkg, int match, + void cb(struct apk_package *pkg0, struct apk_dependency *dep0, struct apk_package *pkg, void *ctx), + void *ctx) +{ + struct apk_dependency *p; + + foreach_reverse_dependency(pkg, pkg->name->rdepends, match, cb, ctx); + foreach_array_item(p, pkg->provides) + foreach_reverse_dependency(pkg, p->name->rdepends, match, cb, ctx); +}