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-03-06 21:39:48 +0200
commit65b46f7462e1acad19884da67a9a59996a642847 (patch)
tree1997054daa45211d97bc273f0a50ccdfe2084ff5
parent5f84463a34bd8c63a3ff649ae550c68934adaa5b (diff)
downloadapk-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.h16
-rw-r--r--src/app_del.c20
-rw-r--r--src/app_fetch.c20
-rw-r--r--src/app_fix.c11
-rw-r--r--src/app_info.c9
-rw-r--r--src/app_list.c11
-rw-r--r--src/app_manifest.c10
-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.c147
-rw-r--r--src/solver.c2
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)