summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2023-03-04 13:54:54 +0200
committerTimo Teräs <timo.teras@iki.fi>2023-04-11 20:47:43 +0300
commit67f5a753e50da8737dc28b0ea2c2194b21d76fdd (patch)
tree657a81a529d2733eecae1837cc48ac25abe73357
parentefb55ce650d3cac9a607560d840f95c1127e68f5 (diff)
downloadapk-tools-67f5a753e50da8737dc28b0ea2c2194b21d76fdd.tar.gz
apk-tools-67f5a753e50da8737dc28b0ea2c2194b21d76fdd.tar.bz2
apk-tools-67f5a753e50da8737dc28b0ea2c2194b21d76fdd.tar.xz
apk-tools-67f5a753e50da8737dc28b0ea2c2194b21d76fdd.zip
db, apps: sort display results based on package names
-rw-r--r--src/apk_database.h16
-rw-r--r--src/app_del.c21
-rw-r--r--src/app_fetch.c21
-rw-r--r--src/app_fix.c11
-rw-r--r--src/app_info.c9
-rw-r--r--src/app_list.c22
-rw-r--r--src/app_manifest.c12
-rw-r--r--src/app_policy.c8
-rw-r--r--src/app_search.c9
-rw-r--r--src/app_upgrade.c7
-rw-r--r--src/app_version.c16
-rw-r--r--src/commit.c2
-rw-r--r--src/database.c137
-rw-r--r--src/solver.c2
14 files changed, 191 insertions, 102 deletions
diff --git a/src/apk_database.h b/src/apk_database.h
index a0a62ca..194fe06 100644
--- a/src/apk_database.h
+++ b/src/apk_database.h
@@ -162,6 +162,7 @@ struct apk_database {
int no_chroot : 1;
int compat_newfeatures : 1;
int compat_notinstallable : 1;
+ int sorted_names : 1;
struct apk_dependency_array *world;
struct apk_protected_path_array *protected_paths;
@@ -175,6 +176,7 @@ struct apk_database {
} repositories;
struct {
+ struct apk_name_array *sorted_names;
struct apk_hash names;
struct apk_hash packages;
} available;
@@ -198,6 +200,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);
@@ -269,8 +275,12 @@ 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);
#endif
diff --git a/src/app_del.c b/src/app_del.c
index 7d3cf36..06deb43 100644
--- a/src/app_del.c
+++ b/src/app_del.c
@@ -85,12 +85,14 @@ 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 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, 0);
@@ -98,6 +100,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,
@@ -112,8 +115,8 @@ 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,
- struct apk_name *name, void *pctx)
+static int delete_name(struct apk_database *db, const char *match,
+ struct apk_name *name, void *pctx)
{
struct del_ctx *ctx = (struct del_ctx *) pctx;
struct apk_package *pkg;
@@ -121,7 +124,7 @@ static void delete_name(struct apk_database *db, const char *match,
if (!name) {
apk_error("No such package: %s", match);
ctx->errors++;
- return;
+ return 0;
}
pkg = apk_pkg_get_installed(name);
@@ -129,6 +132,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_database *db, struct apk_string_array *args)
@@ -141,7 +145,7 @@ static int del_main(void *pctx, struct apk_database *db, struct apk_string_array
int r = 0;
apk_dependency_array_copy(&ctx->world, db->world);
- apk_name_foreach_matching(db, args, apk_foreach_genid(), delete_name, ctx);
+ 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);
@@ -152,10 +156,7 @@ static int del_main(void *pctx, struct apk_database *db, struct apk_string_array
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);
+ 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 0cc1918..ea2ca13 100644
--- a/src/app_fetch.c
+++ b/src/app_fetch.c
@@ -235,7 +235,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) {
@@ -244,13 +244,15 @@ static void mark_name_flags(struct apk_database *db, const char *match, struct a
.result_mask = APK_DEPMASK_ANY,
};
- if (!IS_ERR_OR_NULL(name)) {
- name->auto_select_virtual = 1;
- apk_deps_add(&ctx->world, &dep);
- } else {
+ if (!name) {
ctx->errors++;
mark_error(ctx, match, name);
+ return 0;
}
+
+ name->auto_select_virtual = 1;
+ apk_deps_add(&ctx->world, &dep);
+ return 0;
}
static void mark_names_recursive(struct apk_database *db, struct apk_string_array *args, void *pctx)
@@ -271,7 +273,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;
@@ -284,10 +286,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)
@@ -346,12 +349,12 @@ static int fetch_main(void *pctx, struct apk_database *db, struct apk_string_arr
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);
+ 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);
+ 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 ccd1e3c..5169176 100644
--- a/src/app_fix.c
+++ b/src/app_fix.c
@@ -74,15 +74,18 @@ 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 fix_ctx *ctx = pctx;
if (!name) {
apk_error("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_database *db, struct apk_string_array *args)
@@ -103,7 +106,7 @@ static int fix_main(void *pctx, struct apk_database *db, struct apk_string_array
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 8454f0f..2cdbad6 100644
--- a/src/app_info.c
+++ b/src/app_info.c
@@ -350,18 +350,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) \
@@ -454,9 +455,7 @@ static int info_main(void *ctx, struct apk_database *db, struct apk_string_array
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 0693f4b..13ab0a7 100644
--- a/src/app_list.c
+++ b/src/app_list.c
@@ -147,8 +147,7 @@ static void iterate_providers(const struct apk_name *name, const struct list_ctx
{
struct apk_provider *p;
- foreach_array_item(p, name->providers)
- {
+ foreach_array_item(p, name->providers) {
if (!ctx->match_providers && p->pkg->name != name)
continue;
@@ -159,22 +158,20 @@ 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;
- if (name == NULL)
- return;
+ if (!name) return 0;
- if (ctx->match_depends)
- {
+ if (ctx->match_depends) {
struct apk_name **pname;
-
foreach_array_item(pname, name->rdepends)
iterate_providers(*pname, ctx);
- }
- else
+ } else {
iterate_providers(name, ctx);
+ }
+ return 0;
}
#define LIST_OPTIONS(OPT) \
@@ -242,10 +239,7 @@ static int list_main(void *pctx, struct apk_database *db, struct apk_string_arra
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 cd5b2ef..e476872 100644
--- a/src/app_manifest.c
+++ b/src/app_manifest.c
@@ -100,23 +100,25 @@ static void process_file(struct apk_database *db, const char *match)
if (r < 0) apk_error("%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 *ctx, struct apk_database *db, struct apk_string_array *args)
{
- apk_name_foreach_matching(db, args, apk_foreach_genid(), process_match, NULL);
+ if (!args->num) return 0;
+ apk_db_foreach_sorted_name(db, args, process_match, NULL);
return 0;
}
diff --git a/src/app_policy.c b/src/app_policy.c
index 954eb9d..519257a 100644
--- a/src/app_policy.c
+++ b/src/app_policy.c
@@ -15,13 +15,13 @@
extern const char * const apk_installed_file;
-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_provider *p;
struct apk_repository *repo;
int i, j, num = 0;
- if (!name) return;
+ if (!name) return 0;
/*
zlib1g policy:
@@ -58,11 +58,13 @@ zlib1g policy:
}
}
}
+ return 0;
}
static int policy_main(void *ctx, struct apk_database *db, struct apk_string_array *args)
{
- apk_name_foreach_matching(db, args, apk_foreach_genid(), print_policy, NULL);
+ if (!args->num) return 0;
+ apk_db_foreach_sorted_name(db, args, print_policy, NULL);
return 0;
}
diff --git a/src/app_search.c b/src/app_search.c
index 866bb7a..3651ec6 100644
--- a/src/app_search.c
+++ b/src/app_search.c
@@ -143,13 +143,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)
@@ -163,6 +163,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)
@@ -193,9 +194,7 @@ static int search_main(void *pctx, struct apk_database *db, struct apk_string_ar
*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 bc6ccb1..c618cb6 100644
--- a/src/app_upgrade.c
+++ b/src/app_upgrade.c
@@ -136,17 +136,18 @@ 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 upgrade_ctx *uctx = (struct upgrade_ctx *) pctx;
if (!name) {
apk_error("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_database *db, struct apk_string_array *args)
@@ -206,7 +207,7 @@ static int upgrade_main(void *ctx, struct apk_database *db, struct apk_string_ar
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 d5d9c88..2a8cdb8 100644
--- a/src/app_version.c
+++ b/src/app_version.c
@@ -107,7 +107,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 ver_ctx *ctx = (struct ver_ctx *) pctx;
struct apk_package *pkg;
@@ -119,10 +119,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;
@@ -148,10 +148,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_verbosity <= 0) {
printf("%s\n", pkg->name->name);
- return;
+ return 0;
}
tag = APK_DEFAULT_REPOSITORY_TAG;
@@ -167,6 +167,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_database *db, struct apk_string_array *args)
@@ -186,10 +187,7 @@ static int ver_main(void *pctx, struct apk_database *db, struct apk_string_array
if (apk_verbosity > 0)
printf("%-42sAvailable:\n", "Installed:");
- 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 f582ec2..79438db 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -155,7 +155,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 a4c7f97..3dc72f2 100644
--- a/src/database.c
+++ b/src/database.c
@@ -221,6 +221,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;
}
@@ -1515,6 +1516,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;
}
@@ -1836,6 +1838,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);
@@ -2986,8 +2989,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;
};
@@ -2995,16 +2997,9 @@ 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) {
+ if (!ctx->filter->num) {
ctx->cb(ctx->db, NULL, name, ctx->cb_ctx);
return 0;
}
@@ -3012,50 +3007,132 @@ static int match_names(apk_hash_item item, void *pctx)
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;
+ break;
}
}
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 || !filter->num) return 0;
- if (filter == NULL || filter->num == 0) {
- if (!(match & APK_FOREACH_NULL_MATCHES_ALL))
- return;
- apk_string_array_init(&mctx.filter);
- goto all;
- }
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 walk_all = 0;
+ char **pmatch;
+ struct apk_name *name;
+ struct apk_name *results[128], **res;
+ size_t i, num_res = 0;
+ int r;
+
+ 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 {
+ walk_all = 1;
+ filter = NULL;
}
- 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 || !filter->num) {
+ cb(db, NULL, name, cb_ctx);
+ continue;
+ }
+ 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 8021df2..345656c 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -1024,7 +1024,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)