diff options
author | Timo Teräs <timo.teras@iki.fi> | 2023-03-04 13:54:54 +0200 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2023-03-06 21:39:48 +0200 |
commit | 65b46f7462e1acad19884da67a9a59996a642847 (patch) | |
tree | 1997054daa45211d97bc273f0a50ccdfe2084ff5 | |
parent | 5f84463a34bd8c63a3ff649ae550c68934adaa5b (diff) | |
download | apk-tools-65b46f7462e1acad19884da67a9a59996a642847.tar.gz apk-tools-65b46f7462e1acad19884da67a9a59996a642847.tar.bz2 apk-tools-65b46f7462e1acad19884da67a9a59996a642847.tar.xz apk-tools-65b46f7462e1acad19884da67a9a59996a642847.zip |
db, apps: sort display results based on package names
-rw-r--r-- | src/apk_database.h | 16 | ||||
-rw-r--r-- | src/app_del.c | 20 | ||||
-rw-r--r-- | src/app_fetch.c | 20 | ||||
-rw-r--r-- | src/app_fix.c | 11 | ||||
-rw-r--r-- | src/app_info.c | 9 | ||||
-rw-r--r-- | src/app_list.c | 11 | ||||
-rw-r--r-- | src/app_manifest.c | 10 | ||||
-rw-r--r-- | src/app_policy.c | 8 | ||||
-rw-r--r-- | src/app_search.c | 9 | ||||
-rw-r--r-- | src/app_upgrade.c | 7 | ||||
-rw-r--r-- | src/app_version.c | 16 | ||||
-rw-r--r-- | src/commit.c | 2 | ||||
-rw-r--r-- | src/database.c | 147 | ||||
-rw-r--r-- | src/solver.c | 2 |
14 files changed, 189 insertions, 99 deletions
diff --git a/src/apk_database.h b/src/apk_database.h index dbdbb3d..bedc479 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -152,6 +152,7 @@ struct apk_database { int open_complete : 1; int compat_newfeatures : 1; int compat_notinstallable : 1; + int sorted_names : 1; struct apk_dependency_array *world; struct apk_id_cache *id_cache; @@ -165,6 +166,7 @@ struct apk_database { } repositories; struct { + struct apk_name_array *sorted_names; struct apk_hash names; struct apk_hash packages; } available; @@ -188,6 +190,10 @@ typedef union apk_database_or_void { void *ptr; } apk_database_t __attribute__ ((__transparent_union__)); +static inline int apk_name_cmp_display(const struct apk_name *a, const struct apk_name *b) { + return strcmp(a->name, b->name); +} + struct apk_name *apk_db_get_name(struct apk_database *db, apk_blob_t name); struct apk_name *apk_db_query_name(struct apk_database *db, apk_blob_t name); int apk_db_get_tag_id(struct apk_database *db, apk_blob_t tag); @@ -246,9 +252,13 @@ int apk_db_install_pkg(struct apk_database *db, struct apk_package *newpkg, apk_progress_cb cb, void *cb_ctx); -void apk_name_foreach_matching(struct apk_database *db, struct apk_string_array *filter, unsigned int match, - void (*cb)(struct apk_database *db, const char *match, struct apk_name *name, void *ctx), - void *ctx); +typedef int (*apk_db_foreach_name_cb)(struct apk_database *db, const char *match, struct apk_name *name, void *ctx); + +int apk_db_foreach_matching_name(struct apk_database *db, struct apk_string_array *filter, + apk_db_foreach_name_cb cb, void *ctx); + +int apk_db_foreach_sorted_name(struct apk_database *db, struct apk_string_array *filter, + apk_db_foreach_name_cb cb, void *ctx); static inline uint8_t apk_dbf_digest(struct apk_db_file *dbf) { diff --git a/src/app_del.c b/src/app_del.c index 1df4cc9..2a09ca6 100644 --- a/src/app_del.c +++ b/src/app_del.c @@ -87,13 +87,15 @@ static void print_not_deleted_pkg(struct apk_package *pkg0, struct apk_dependenc } } -static void print_not_deleted_name(struct apk_database *db, const char *match, - struct apk_name *name, void *pctx) +static int print_not_deleted_name(struct apk_database *db, const char *match, + struct apk_name *name, void *pctx) { struct apk_out *out = &db->ctx->out; struct not_deleted_ctx *ctx = (struct not_deleted_ctx *) pctx; struct apk_provider *p; + if (!name) return 0; + ctx->name = name; ctx->matches = apk_foreach_genid() | APK_FOREACH_MARKED | APK_DEP_SATISFIES; apk_print_indented_init(&ctx->indent, out, 0); @@ -101,6 +103,7 @@ static void print_not_deleted_name(struct apk_database *db, const char *match, if (p->pkg->marked) print_not_deleted_pkg(p->pkg, NULL, NULL, ctx); apk_print_indented_end(&ctx->indent); + return 0; } static void delete_pkg(struct apk_package *pkg0, struct apk_dependency *dep0, @@ -115,7 +118,7 @@ static void delete_pkg(struct apk_package *pkg0, struct apk_dependency *dep0, delete_pkg, pctx); } -static void delete_name(struct apk_database *db, const char *match, +static int delete_name(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) { struct apk_out *out = &db->ctx->out; @@ -125,7 +128,7 @@ static void delete_name(struct apk_database *db, const char *match, if (!name) { apk_err(out, "No such package: %s", match); ctx->errors++; - return; + return 0; } pkg = apk_pkg_get_installed(name); @@ -133,6 +136,7 @@ static void delete_name(struct apk_database *db, const char *match, delete_pkg(pkg, NULL, NULL, pctx); else apk_deps_del(&ctx->world, name); + return 0; } static int del_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *args) @@ -146,7 +150,7 @@ static int del_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *arg int r = 0; apk_dependency_array_copy(&ctx->world, db->world); - apk_name_foreach_matching(db, args, apk_foreach_genid(), delete_name, ctx); + if (args->num) apk_db_foreach_matching_name(db, args, delete_name, ctx); if (ctx->errors) return ctx->errors; r = apk_solver_solve(db, 0, ctx->world, &changeset); @@ -157,10 +161,8 @@ static int del_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *arg change->new_pkg->marked = 1; foreach_array_item(d, ctx->world) d->name->state_int = 1; - apk_name_foreach_matching( - db, args, - apk_foreach_genid() | APK_FOREACH_MARKED | APK_DEP_SATISFIES, - print_not_deleted_name, &ndctx); + if (args->num) + apk_db_foreach_sorted_name(db, args, print_not_deleted_name, &ndctx); if (ndctx.header) printf("\n"); diff --git a/src/app_fetch.c b/src/app_fetch.c index 7c57d89..3466ecb 100644 --- a/src/app_fetch.c +++ b/src/app_fetch.c @@ -230,7 +230,7 @@ static void mark_dep_flags(struct fetch_ctx *ctx, struct apk_dependency *dep) apk_deps_add(&ctx->world, dep); } -static void mark_name_flags(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) +static int mark_name_flags(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) { struct fetch_ctx *ctx = (struct fetch_ctx *) pctx; struct apk_dependency dep = (struct apk_dependency) { @@ -239,12 +239,13 @@ static void mark_name_flags(struct apk_database *db, const char *match, struct a .result_mask = APK_DEPMASK_ANY, }; - if (name) { - mark_dep_flags(ctx, &dep); - } else { + if (!name) { ctx->errors++; mark_error(ctx, match, name); + return 0; } + mark_dep_flags(ctx, &dep); + return 0; } static void mark_names_recursive(struct apk_database *db, struct apk_string_array *args, void *pctx) @@ -265,7 +266,7 @@ static void mark_names_recursive(struct apk_database *db, struct apk_string_arra apk_change_array_free(&changeset.changes); } -static void mark_name(struct apk_database *db, const char *match, struct apk_name *name, void *ctx) +static int mark_name(struct apk_database *db, const char *match, struct apk_name *name, void *ctx) { struct apk_package *pkg = NULL; struct apk_provider *p; @@ -278,10 +279,11 @@ static void mark_name(struct apk_database *db, const char *match, struct apk_nam if (!pkg) goto err; mark_package(ctx, pkg); - return; + return 0; err: mark_error(ctx, match, name); + return 0; } static int purge_package(void *pctx, int dirfd, const char *filename) @@ -343,12 +345,14 @@ static int fetch_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *a apk_dependency_array_init(&ctx->world); foreach_array_item(dep, db->world) mark_dep_flags(ctx, dep); - apk_name_foreach_matching(db, args, apk_foreach_genid(), mark_name_flags, ctx); + if (args->num) + apk_db_foreach_matching_name(db, args, mark_name_flags, ctx); if (ctx->errors == 0) mark_names_recursive(db, args, ctx); apk_dependency_array_free(&ctx->world); } else { - apk_name_foreach_matching(db, args, apk_foreach_genid(), mark_name, ctx); + if (args->num) + apk_db_foreach_matching_name(db, args, mark_name, ctx); } if (!ctx->errors) apk_hash_foreach(&db->available.packages, fetch_package, ctx); diff --git a/src/app_fix.c b/src/app_fix.c index 170f2c2..e6f5ddb 100644 --- a/src/app_fix.c +++ b/src/app_fix.c @@ -74,7 +74,7 @@ static void mark_fix(struct fix_ctx *ctx, struct apk_name *name) apk_solver_set_name_flags(name, ctx->solver_flags, ctx->fix_depends ? ctx->solver_flags : 0); } -static void set_solver_flags(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) +static int set_solver_flags(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) { struct apk_out *out = &db->ctx->out; struct fix_ctx *ctx = pctx; @@ -82,8 +82,11 @@ static void set_solver_flags(struct apk_database *db, const char *match, struct if (!name) { apk_err(out, "Package '%s' not found", match); ctx->errors++; - } else - mark_fix(ctx, name); + return 0; + } + + mark_fix(ctx, name); + return 0; } static int fix_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *args) @@ -105,7 +108,7 @@ static int fix_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *arg mark_fix(ctx, ipkg->pkg->name); } } else - apk_name_foreach_matching(db, args, apk_foreach_genid(), set_solver_flags, ctx); + apk_db_foreach_matching_name(db, args, set_solver_flags, ctx); if (ctx->errors) return ctx->errors; diff --git a/src/app_info.c b/src/app_info.c index 509798d..0336300 100644 --- a/src/app_info.c +++ b/src/app_info.c @@ -346,18 +346,19 @@ static void info_subaction(struct info_ctx *ctx, struct apk_package *pkg) } } -static void print_name_info(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) +static int print_name_info(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) { struct info_ctx *ctx = (struct info_ctx *) pctx; struct apk_provider *p; if (name == NULL) { ctx->errors++; - return; + return 0; } foreach_array_item(p, name->providers) info_subaction(ctx, p->pkg); + return 0; } #define INFO_OPTIONS(OPT) \ @@ -453,9 +454,7 @@ static int info_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *arg ictx->action(ictx, db, args); } else if (args->num > 0) { /* Print info on given names */ - apk_name_foreach_matching( - db, args, APK_FOREACH_NULL_MATCHES_ALL | apk_foreach_genid(), - print_name_info, ctx); + apk_db_foreach_sorted_name(db, args, print_name_info, ctx); } else { /* Print all installed packages */ list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) diff --git a/src/app_list.c b/src/app_list.c index 226535d..713950e 100644 --- a/src/app_list.c +++ b/src/app_list.c @@ -165,13 +165,12 @@ static void iterate_providers(const struct apk_name *name, const struct list_ctx } } -static void print_result(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) +static int print_result(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) { struct list_ctx *ctx = pctx; struct apk_name **pname; - if (name == NULL) - return; + if (!name) return 0; if (ctx->match_depends) { foreach_array_item(pname, name->rdepends) @@ -179,6 +178,7 @@ static void print_result(struct apk_database *db, const char *match, struct apk_ } else { iterate_providers(name, ctx); } + return 0; } #define LIST_OPTIONS(OPT) \ @@ -254,10 +254,7 @@ static int list_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *ar if (ctx->match_origin) args = NULL; - apk_name_foreach_matching( - db, args, APK_FOREACH_NULL_MATCHES_ALL | apk_foreach_genid(), - print_result, ctx); - + apk_db_foreach_sorted_name(db, args, print_result, ctx); return 0; } diff --git a/src/app_manifest.c b/src/app_manifest.c index a9d82d5..601f856 100644 --- a/src/app_manifest.c +++ b/src/app_manifest.c @@ -151,22 +151,24 @@ static void process_file(struct apk_database *db, const char *match) if (r < 0) apk_err(out, "%s: %s", match, apk_error_str(r)); } -static void process_match(struct apk_database *db, const char *match, struct apk_name *name, void *ctx) +static int process_match(struct apk_database *db, const char *match, struct apk_name *name, void *ctx) { struct apk_provider *p; - if (name == NULL) { + if (!name) { process_file(db, match); - return; + return 0; } foreach_array_item(p, name->providers) process_package(db, p->pkg); + return 0; } static int manifest_main(void *applet_ctx, struct apk_ctx *ac, struct apk_string_array *args) { - apk_name_foreach_matching(ac->db, args, apk_foreach_genid(), process_match, NULL); + if (!args->num) return 0; + apk_db_foreach_sorted_name(ac->db, args, process_match, NULL); return 0; } diff --git a/src/app_policy.c b/src/app_policy.c index a927a5f..7f263f6 100644 --- a/src/app_policy.c +++ b/src/app_policy.c @@ -13,14 +13,14 @@ #include "apk_version.h" #include "apk_print.h" -static void print_policy(struct apk_database *db, const char *match, struct apk_name *name, void *ctx) +static int print_policy(struct apk_database *db, const char *match, struct apk_name *name, void *ctx) { struct apk_out *out = &db->ctx->out; struct apk_provider *p; struct apk_repository *repo; int i, j, num = 0; - if (!name) return; + if (!name) return 0; /* zlib1g policy: @@ -57,11 +57,13 @@ zlib1g policy: } } } + return 0; } static int policy_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *args) { - apk_name_foreach_matching(ac->db, args, apk_foreach_genid(), print_policy, NULL); + if (!args->num) return 0; + apk_db_foreach_sorted_name(ac->db, args, print_policy, NULL); return 0; } diff --git a/src/app_search.c b/src/app_search.c index 4ac4243..846aed0 100644 --- a/src/app_search.c +++ b/src/app_search.c @@ -144,13 +144,13 @@ match: ctx->print_result(ctx, pkg); } -static void print_result(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) +static int print_result(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) { struct search_ctx *ctx = pctx; struct apk_provider *p; struct apk_package *pkg = NULL; - if (!name) return; + if (!name) return 0; if (ctx->show_all) { foreach_array_item(p, name->providers) @@ -164,6 +164,7 @@ static void print_result(struct apk_database *db, const char *match, struct apk_ if (pkg) print_result_pkg(ctx, pkg); } + return 0; } static int print_pkg(apk_hash_item item, void *pctx) @@ -196,9 +197,7 @@ static int search_main(void *pctx, struct apk_ctx *ac, struct apk_string_array * *pmatch = tmp; } } - apk_name_foreach_matching( - db, args, APK_FOREACH_NULL_MATCHES_ALL | apk_foreach_genid(), - print_result, ctx); + apk_db_foreach_sorted_name(db, args, print_result, ctx); return 0; } diff --git a/src/app_upgrade.c b/src/app_upgrade.c index e0ebcf5..77f1d2a 100644 --- a/src/app_upgrade.c +++ b/src/app_upgrade.c @@ -139,7 +139,7 @@ ret: return r; } -static void set_upgrade_for_name(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) +static int set_upgrade_for_name(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) { struct apk_out *out = &db->ctx->out; struct upgrade_ctx *uctx = (struct upgrade_ctx *) pctx; @@ -147,10 +147,11 @@ static void set_upgrade_for_name(struct apk_database *db, const char *match, str if (!name) { apk_err(out, "Package '%s' not found", match); uctx->errors++; - return; + return 0; } apk_solver_set_name_flags(name, uctx->ignore ? APK_SOLVERF_INSTALLED : APK_SOLVERF_UPGRADE, 0); + return 0; } static int upgrade_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *args) @@ -213,7 +214,7 @@ static int upgrade_main(void *ctx, struct apk_ctx *ac, struct apk_string_array * if (args->num > 0) { /* if specific packages are listed, we don't want to upgrade world. */ if (!uctx->ignore) solver_flags &= ~APK_SOLVERF_UPGRADE; - apk_name_foreach_matching(db, args, apk_foreach_genid(), set_upgrade_for_name, uctx); + apk_db_foreach_matching_name(db, args, set_upgrade_for_name, uctx); if (uctx->errors) return uctx->errors; } diff --git a/src/app_version.c b/src/app_version.c index a42ab63..9c80736 100644 --- a/src/app_version.c +++ b/src/app_version.c @@ -109,7 +109,7 @@ static const struct apk_option_group optgroup_applet = { .parse = option_parse_applet, }; -static void ver_print_package_status(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) +static int ver_print_package_status(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) { struct apk_out *out = &db->ctx->out; struct ver_ctx *ctx = (struct ver_ctx *) pctx; @@ -122,10 +122,10 @@ static void ver_print_package_status(struct apk_database *db, const char *match, int i, r = -1; unsigned short tag, allowed_repos; - if (!name) return; + if (!name) return 0; pkg = apk_pkg_get_installed(name); - if (!pkg) return; + if (!pkg) return 0; tag = pkg->ipkg->repository_tag; allowed_repos = db->repo_tags[tag].allowed_repos; @@ -151,10 +151,10 @@ static void ver_print_package_status(struct apk_database *db, const char *match, : APK_VERSION_UNKNOWN; opstr = apk_version_op_string(r); if ((ctx->limchars != NULL) && (strchr(ctx->limchars, *opstr) == NULL)) - return; + return 0; if (apk_out_verbosity(out) <= 0) { apk_out(out, "%s", pkg->name->name); - return; + return 0; } tag = APK_DEFAULT_REPOSITORY_TAG; @@ -170,6 +170,7 @@ static void ver_print_package_status(struct apk_database *db, const char *match, pkgname, opstr, BLOB_PRINTF(*latest), BLOB_PRINTF(db->repo_tags[tag].tag)); + return 0; } static int ver_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *args) @@ -190,10 +191,7 @@ static int ver_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *arg apk_msg(out, "%-42s%s", "Installed:", "Available:"); - apk_name_foreach_matching( - db, args, APK_FOREACH_NULL_MATCHES_ALL | apk_foreach_genid(), - ver_print_package_status, ctx); - + apk_db_foreach_sorted_name(db, args, ver_print_package_status, ctx); return 0; } diff --git a/src/commit.c b/src/commit.c index c9a4d5e..bca2557 100644 --- a/src/commit.c +++ b/src/commit.c @@ -158,7 +158,7 @@ static int sort_change(const void *a, const void *b) const struct apk_change *cb = b; const struct apk_name *na = ca->old_pkg ? ca->old_pkg->name : ca->new_pkg->name; const struct apk_name *nb = cb->old_pkg ? cb->old_pkg->name : cb->new_pkg->name; - return strcmp(na->name, nb->name); + return apk_name_cmp_display(na, nb); } static int cmp_remove(struct apk_change *change) diff --git a/src/database.c b/src/database.c index 39624f5..bbb9308 100644 --- a/src/database.c +++ b/src/database.c @@ -222,6 +222,7 @@ struct apk_name *apk_db_get_name(struct apk_database *db, apk_blob_t name) apk_name_array_init(&pn->rdepends); apk_name_array_init(&pn->rinstall_if); apk_hash_insert_hashed(&db->available.names, pn, hash); + db->sorted_names = 0; return pn; } @@ -1650,6 +1651,7 @@ void apk_db_init(struct apk_database *db) list_init(&db->installed.triggers); apk_dependency_array_init(&db->world); apk_protected_path_array_init(&db->protected_paths); + apk_name_array_init(&db->available.sorted_names); db->permanent = 1; db->root_fd = -1; } @@ -1944,6 +1946,7 @@ void apk_db_close(struct apk_database *db) apk_dependency_array_free(&db->world); + apk_name_array_free(&db->available.sorted_names); apk_hash_free(&db->available.packages); apk_hash_free(&db->available.names); apk_hash_free(&db->installed.files); @@ -3096,8 +3099,7 @@ ret_r: struct match_ctx { struct apk_database *db; struct apk_string_array *filter; - unsigned int match; - void (*cb)(struct apk_database *db, const char *match, struct apk_name *name, void *ctx); + apk_db_foreach_name_cb cb; void *cb_ctx; }; @@ -3105,67 +3107,138 @@ static int match_names(apk_hash_item item, void *pctx) { struct match_ctx *ctx = (struct match_ctx *) pctx; struct apk_name *name = (struct apk_name *) item; - unsigned int genid = ctx->match & APK_FOREACH_GENID_MASK; char **pmatch; - if (genid) { - if (name->foreach_genid >= genid) - return 0; - name->foreach_genid = genid; - } - - if (ctx->filter->num == 0) { - ctx->cb(ctx->db, NULL, name, ctx->cb_ctx); - return 0; - } + if (!ctx->filter) + return ctx->cb(ctx->db, NULL, name, ctx->cb_ctx); foreach_array_item(pmatch, ctx->filter) { - if (fnmatch(*pmatch, name->name, 0) == 0) { - ctx->cb(ctx->db, *pmatch, name, ctx->cb_ctx); - if (genid) - break; - } + if (fnmatch(*pmatch, name->name, 0) == 0) + return ctx->cb(ctx->db, *pmatch, name, ctx->cb_ctx); } return 0; } -void apk_name_foreach_matching(struct apk_database *db, struct apk_string_array *filter, unsigned int match, - void (*cb)(struct apk_database *db, const char *match, struct apk_name *name, void *ctx), - void *ctx) +int apk_db_foreach_matching_name( + struct apk_database *db, struct apk_string_array *filter, + apk_db_foreach_name_cb cb, void *ctx) { char **pmatch; - unsigned int genid = match & APK_FOREACH_GENID_MASK; struct apk_name *name; struct match_ctx mctx = { .db = db, - .filter = filter, - .match = match, .cb = cb, .cb_ctx = ctx, }; + int r; - if (filter == NULL || filter->num == 0) { - if (!(match & APK_FOREACH_NULL_MATCHES_ALL)) - return; - apk_string_array_init(&mctx.filter); - goto all; - } + if (!filter || !filter->num) goto all; + + mctx.filter = filter; foreach_array_item(pmatch, filter) if (strchr(*pmatch, '*') != NULL) goto all; foreach_array_item(pmatch, filter) { name = (struct apk_name *) apk_hash_get(&db->available.names, APK_BLOB_STR(*pmatch)); - if (genid && name) { - if (name->foreach_genid >= genid) + r = cb(db, *pmatch, name, ctx); + if (r) return r; + } + return 0; + +all: + return apk_hash_foreach(&db->available.names, match_names, &mctx); +} + +static int cmp_name(const void *a, const void *b) +{ + const struct apk_name * const* na = a, * const* nb = b; + return apk_name_cmp_display(*na, *nb); +} + +struct add_name_ctx { + struct apk_name_array *a; + size_t i; +}; + +static int add_name(apk_hash_item item, void *ctx) +{ + struct apk_name *name = (struct apk_name *) item; + struct add_name_ctx *a = ctx; + a->a->item[a->i++] = name; + return 0; +} + +static struct apk_name_array *apk_db_sorted_names(struct apk_database *db) +{ + if (!db->sorted_names) { + apk_name_array_resize(&db->available.sorted_names, db->available.names.num_items); + + struct add_name_ctx ctx = { .a = db->available.sorted_names, .i = 0 }; + apk_hash_foreach(&db->available.names, add_name, &ctx); + + qsort(db->available.sorted_names->item, db->available.sorted_names->num, + sizeof(db->available.sorted_names->item[0]), cmp_name); + db->sorted_names = 1; + } + return db->available.sorted_names; +} + +int apk_db_foreach_sorted_name(struct apk_database *db, struct apk_string_array *filter, + apk_db_foreach_name_cb cb, void *cb_ctx) +{ + int r, walk_all = 0; + char **pmatch; + struct apk_name *name; + struct apk_name *results[128], **res; + size_t i, num_res = 0; + + if (filter && filter->num) { + foreach_array_item(pmatch, filter) { + name = (struct apk_name *) apk_hash_get(&db->available.names, APK_BLOB_STR(*pmatch)); + if (strchr(*pmatch, '*')) { + walk_all = 1; + continue; + } + if (!name) { + cb(db, *pmatch, NULL, cb_ctx); + continue; + } + if (walk_all) continue; + if (num_res >= ARRAY_SIZE(results)) { + walk_all = 1; continue; - name->foreach_genid = genid; + } + results[num_res++] = name; } - cb(db, *pmatch, name, ctx); + } else { + filter = NULL; + walk_all = 1; } - return; -all: - apk_hash_foreach(&db->available.names, match_names, &mctx); + if (walk_all) { + struct apk_name_array *a = apk_db_sorted_names(db); + res = a->item; + num_res = a->num; + } else { + qsort(results, num_res, sizeof results[0], cmp_name); + res = results; + } + + for (i = 0; i < num_res; i++) { + name = res[i]; + if (!filter) { + r = cb(db, NULL, name, cb_ctx); + } else { + foreach_array_item(pmatch, filter) { + if (fnmatch(*pmatch, name->name, 0) == 0) { + r = cb(db, *pmatch, name, cb_ctx); + break; + } + } + } + if (r) return r; + } + return 0; } diff --git a/src/solver.c b/src/solver.c index 7327b71..f3ed321 100644 --- a/src/solver.c +++ b/src/solver.c @@ -1025,7 +1025,7 @@ static int free_package(apk_hash_item item, void *ctx) static int cmp_pkgname(const void *p1, const void *p2) { const struct apk_dependency *d1 = p1, *d2 = p2; - return strcmp(d1->name->name, d2->name->name); + return apk_name_cmp_display(d1->name, d2->name); } static int compare_name_dequeue(const struct apk_name *a, const struct apk_name *b) |