From 38e3f5463878a29e675be8430135e36b552c0ac1 Mon Sep 17 00:00:00 2001 From: Timo Teräs Date: Wed, 8 Oct 2014 15:29:27 +0300 Subject: rework option parsing to have a group structure Add also a new 'commit' group that is the common options for all applets that can commit package changes. --- src/add.c | 36 +++--- src/apk.c | 330 ++++++++++++++++++++++++++++------------------------- src/apk_applet.h | 17 ++- src/apk_database.h | 8 +- src/audit.c | 34 +++--- src/del.c | 26 +++-- src/dot.c | 28 +++-- src/fetch.c | 34 +++--- src/fix.c | 30 ++--- src/index.c | 42 ++++--- src/info.c | 16 ++- src/search.c | 34 +++--- src/upgrade.c | 40 ++++--- src/ver.c | 34 +++--- 14 files changed, 390 insertions(+), 319 deletions(-) (limited to 'src') diff --git a/src/add.c b/src/add.c index 2a0a36c..9583ff2 100644 --- a/src/add.c +++ b/src/add.c @@ -21,8 +21,7 @@ struct add_ctx { unsigned short solver_flags; }; -static int add_parse(void *ctx, struct apk_db_options *dbopts, - int optch, int optindex, const char *optarg) +static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg) { struct add_ctx *actx = (struct add_ctx *) ctx; @@ -37,11 +36,28 @@ static int add_parse(void *ctx, struct apk_db_options *dbopts, actx->virtpkg = optarg; break; default: - return -1; + return -ENOTSUP; } return 0; } +static const struct apk_option options_applet[] = { + { 0x10000, "initdb", "Initialize database" }, + { 'u', "upgrade", "Prefer to upgrade package" }, + { 't', "virtual", + "Instead of adding all the packages to 'world', create a new virtual " + "package with the listed dependencies and add that to 'world'; the " + "actions of the command are easily reverted by deleting the virtual " + "package", required_argument, "NAME" }, +}; + +static const struct apk_option_group optgroup_applet = { + .name = "Add", + .options = options_applet, + .num_options = ARRAY_SIZE(options_applet), + .parse = option_parse_applet, +}; + static int non_repository_check(struct apk_database *db) { if (apk_flags & APK_FORCE) @@ -149,16 +165,6 @@ static int add_main(void *ctx, struct apk_database *db, struct apk_string_array return r; } -static struct apk_option add_options[] = { - { 0x10000, "initdb", "Initialize database" }, - { 'u', "upgrade", "Prefer to upgrade package" }, - { 't', "virtual", - "Instead of adding all the packages to 'world', create a new virtual " - "package with the listed dependencies and add that to 'world'; the " - "actions of the command are easily reverted by deleting the virtual " - "package", required_argument, "NAME" }, -}; - static struct apk_applet apk_add = { .name = "add", .help = "Add PACKAGEs to 'world' and install (or upgrade) " @@ -166,9 +172,7 @@ static struct apk_applet apk_add = { .arguments = "PACKAGE...", .open_flags = APK_OPENF_WRITE, .context_size = sizeof(struct add_ctx), - .num_options = ARRAY_SIZE(add_options), - .options = add_options, - .parse = add_parse, + .optgroups = { &optgroup_global, &optgroup_commit, &optgroup_applet }, .main = add_main, }; diff --git a/src/apk.c b/src/apk.c index e677e88..5c333d2 100644 --- a/src/apk.c +++ b/src/apk.c @@ -35,12 +35,116 @@ #include "apk_print.h" #include "apk_io.h" +static const struct apk_option_group *default_optgroups[] = { &optgroup_global, NULL }; static struct list_head apk_applet_list; #define foreach_applet(iter) list_for_each_entry(iter, &apk_applet_list, node) char **apk_argv; -static struct apk_option generic_options[] = { +static void version(void) +{ + printf("apk-tools " APK_VERSION ", compiled for " APK_DEFAULT_ARCH ".\n" +#ifdef TEST_MODE + "TEST MODE BUILD. NOT FOR PRODUCTION USE.\n" +#endif + ); +} + +static struct apk_repository_list *apk_repository_new(const char *url) +{ + struct apk_repository_list *r = calloc(1, sizeof(struct apk_repository_list)); + if (r) { + r->url = url; + list_init(&r->list); + } + return r; +} + +static int option_parse_global(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg) +{ + struct apk_repository_list *repo; + + switch (optch) { + case 'h': return -EINVAL; + case 'p': + dbopts->root = optarg; + break; + case 0x107: + dbopts->keys_dir = optarg; + break; + case 0x108: + dbopts->repositories_file = optarg; + break; + case 'X': + repo = apk_repository_new(optarg); + if (repo) list_add(&repo->list, &dbopts->repository_list); + break; + case 'q': + apk_verbosity--; + break; + case 'v': + apk_verbosity++; + break; + case 'V': + version(); + return -ESHUTDOWN; + case 'f': + apk_flags |= APK_FORCE; + break; + case 'i': + apk_flags |= APK_INTERACTIVE; + break; + case 'U': + apk_flags |= APK_UPDATE_CACHE; + break; + case 0x101: + apk_flags |= APK_PROGRESS; + break; + case 0x110: + apk_flags &= ~APK_PROGRESS; + break; + case 0x10f: + apk_progress_fd = atoi(optarg); + break; + case 0x103: + apk_flags |= APK_ALLOW_UNTRUSTED; + break; + case 0x104: + apk_flags |= APK_SIMULATE; + break; + case 0x106: + apk_flags |= APK_PURGE; + break; + case 0x105: + dbopts->lock_wait = atoi(optarg); + break; + case 0x109: + apk_flags |= APK_NO_NETWORK; + break; + case 0x112: + dbopts->arch = optarg; + break; + case 0x114: + puts(APK_DEFAULT_ARCH); + return -ESHUTDOWN; +#ifdef TEST_MODE + case 0x200: + *apk_string_array_add(&test_repos) = (char*) optarg; + break; + case 0x201: + test_installed_db = optarg; + break; + case 0x202: + test_world = optarg; + break; +#endif + default: + return -ENOTSUP; + } + return 0; +} + +static const struct apk_option options_global[] = { { 'h', "help", "Show generic help or applet specific help" }, { 'p', "root", "Install packages to DIR", required_argument, "DIR" }, @@ -55,12 +159,9 @@ static struct apk_option generic_options[] = { { 0x101, "progress", "Show a progress bar" }, { 0x10f, "progress-fd", "Write progress to fd", required_argument, "FD" }, { 0x110, "no-progress", "Disable progress bar even for TTYs" }, - { 0x102, "clean-protected", "Do not create .apk-new files in " - "configuration dirs" }, { 0x106, "purge", "Delete also modified configuration files (pkg removal) " "and uninstalled packages from cache (cache clean)" }, - { 0x103, "allow-untrusted", "Blindly install packages with untrusted " - "signatures or no signature at all" }, + { 0x103, "allow-untrusted", "Install packages with untrusted signature or no signature" }, { 0x104, "simulate", "Show what would be done without actually " "doing it" }, { 0x105, "wait", "Wait for TIME seconds to get an exclusive " @@ -71,8 +172,6 @@ static struct apk_option generic_options[] = { { 0x108, "repositories-file", "Override repositories file", required_argument, "REPOFILE" }, { 0x109, "no-network", "Do not use network (cache is still used)" }, - { 0x113, "no-scripts", "Do not execute any scripts" }, - { 0x111, "overlay-from-stdin", "Read list of overlay files from stdin" }, { 0x112, "arch", "Use architecture with --root", required_argument, "ARCH" }, { 0x114, "print-arch", "Print default arch and exit" }, @@ -83,22 +182,45 @@ static struct apk_option generic_options[] = { #endif }; -static int version(void) -{ - printf("apk-tools " APK_VERSION ", compiled for " APK_DEFAULT_ARCH ".\n"); -#ifdef TEST_MODE - printf("TEST MODE BUILD. NOT FOR PRODUCTION USE.\n"); -#endif - return 0; -} +const struct apk_option_group optgroup_global = { + .name = "Global", + .options = options_global, + .num_options = ARRAY_SIZE(options_global), + .parse = option_parse_global, +}; -static int show_arch(void) +static int option_parse_commit(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg) { - puts(APK_DEFAULT_ARCH); + switch (optch) { + case 0x102: + apk_flags |= APK_CLEAN_PROTECTED; + break; + case 0x111: + apk_flags |= APK_OVERLAY_FROM_STDIN; + break; + case 0x113: + apk_flags |= APK_NO_SCRIPTS; + break; + default: + return -ENOTSUP; + } return 0; } -static int format_option(char *buf, size_t len, struct apk_option *o, +static const struct apk_option options_commit[] = { + { 0x102, "clean-protected", "Do not create .apk-new files in configuration dirs" }, + { 0x111, "overlay-from-stdin", "Read list of overlay files from stdin" }, + { 0x113, "no-scripts", "Do not execute any scripts" }, +}; + +const struct apk_option_group optgroup_commit = { + .name = "Commit", + .options = options_commit, + .num_options = ARRAY_SIZE(options_commit), + .parse = option_parse_commit, +}; + +static int format_option(char *buf, size_t len, const struct apk_option *o, const char *separator) { int i = 0; @@ -116,28 +238,31 @@ static int format_option(char *buf, size_t len, struct apk_option *o, return i; } -static void print_usage(const char *cmd, const char *args, int num_opts, - struct apk_option *opts) +static void print_usage(const char *cmd, const char *args, const struct apk_option_group **optgroups) { struct apk_indent indent = { .indent = 11 }; + const struct apk_option *opts; char word[128]; - int i, j; + int g, i, j; indent.x = printf("\nusage: apk %s", cmd) - 1; - for (i = 0; i < num_opts; i++) - if (opts[i].name != NULL) { + for (g = 0; optgroups[g]; g++) { + opts = optgroups[g]->options; + for (i = 0; i < optgroups[g]->num_options; i++) { + if (!opts[i].name) continue; j = 0; word[j++] = '['; j += format_option(&word[j], sizeof(word) - j, &opts[i], "|"); word[j++] = ']'; apk_print_indented(&indent, APK_BLOB_PTR_LEN(word, j)); } + } if (args != NULL) apk_print_indented(&indent, APK_BLOB_STR(args)); printf("\n"); } -static void print_options(int num_opts, struct apk_option *opts) +static void print_options(int num_opts, const struct apk_option *opts) { struct apk_indent indent = { .indent = 26 }; char word[128]; @@ -153,12 +278,14 @@ static void print_options(int num_opts, struct apk_option *opts) static int usage(struct apk_applet *applet) { + const struct apk_option_group **optgroups = default_optgroups; + int i; + version(); if (applet == NULL) { struct apk_applet *a; - print_usage("COMMAND", "[ARGS]...", - ARRAY_SIZE(generic_options), generic_options); + print_usage("COMMAND", "[ARGS]...", default_optgroups); printf("\nThe following commands are available:\n"); foreach_applet(a) { @@ -170,19 +297,18 @@ static int usage(struct apk_applet *applet) } else { struct apk_indent indent = { .indent = 2 }; - print_usage(applet->name, applet->arguments, - applet->num_options, applet->options); + if (applet->optgroups[0]) optgroups = applet->optgroups; + print_usage(applet->name, applet->arguments, applet->optgroups); printf("\nDescription:\n"); apk_print_indented_words(&indent, applet->help); printf("\n"); } - printf("\nGeneric options:\n"); - print_options(ARRAY_SIZE(generic_options), generic_options); - if (applet != NULL && applet->num_options > 0) { - printf("\nOptions for %s command:\n", applet->name); - print_options(applet->num_options, applet->options); + for (i = 0; optgroups[i]; i++) { + printf("\n%s options:\n", optgroups[i]->name); + print_options(optgroups[i]->num_options, optgroups[i]->options); } + printf("\nThis apk has coffee making abilities.\n"); return 1; @@ -227,18 +353,7 @@ static struct apk_applet *deduce_applet(int argc, char **argv) return NULL; } -static struct apk_repository_list *apk_repository_new(const char *url) -{ - struct apk_repository_list *r = calloc(1, - sizeof(struct apk_repository_list)); - if (r) { - r->url = url; - list_init(&r->list); - } - return r; -} - -static void merge_options(struct option *opts, struct apk_option *ao, int num) +static void merge_options(struct option *opts, const struct apk_option *ao, int num) { int i; @@ -314,17 +429,16 @@ int main(int argc, char **argv) struct apk_applet *applet; char short_options[256], *sopt; struct option *opt, *all_options; - int r, optindex, num_options; + int i, p, r, num_options; void *ctx = NULL; - struct apk_repository_list *repo = NULL; struct apk_database db; struct apk_db_options dbopts; + const struct apk_option_group **optgroups = default_optgroups; struct apk_string_array *args; #ifdef TEST_MODE const char *test_installed_db = NULL; const char *test_world = NULL; struct apk_string_array *test_repos; - int i; apk_string_array_init(&test_repos); #endif @@ -343,21 +457,19 @@ int main(int argc, char **argv) setup_terminal(); applet = deduce_applet(argc, argv); - num_options = ARRAY_SIZE(generic_options) + 1; - if (applet != NULL) - num_options += applet->num_options; + if (applet && applet->optgroups[0]) optgroups = applet->optgroups; + + for (i = 0, num_options = 0; optgroups[i]; i++) + num_options += optgroups[i]->num_options; all_options = alloca(sizeof(struct option) * num_options); - merge_options(&all_options[0], generic_options, - ARRAY_SIZE(generic_options)); + for (i = r = 0; optgroups[i]; r += optgroups[i]->num_options, i++) + merge_options(&all_options[r], optgroups[i]->options, optgroups[i]->num_options); if (applet != NULL) { - merge_options(&all_options[ARRAY_SIZE(generic_options)], - applet->options, applet->num_options); if (applet->context_size != 0) ctx = calloc(1, applet->context_size); dbopts.open_flags = applet->open_flags; apk_flags |= applet->forced_flags; } - for (opt = all_options, sopt = short_options; opt->name != NULL; opt++) { if (opt->flag == NULL && opt->val <= 0xff && isalnum(opt->val)) { @@ -371,106 +483,11 @@ int main(int argc, char **argv) setup_automatic_flags(); fetchConnectionCacheInit(16, 1); - optindex = 0; - while ((r = getopt_long(argc, argv, short_options, - all_options, &optindex)) != -1) { - switch (r) { - case 0: - break; - case 'h': - r = usage(applet); - goto err; - case 'p': - dbopts.root = optarg; - break; - case 0x107: - dbopts.keys_dir = optarg; - break; - case 0x108: - dbopts.repositories_file = optarg; - break; - case 'X': - repo = apk_repository_new(optarg); - if (repo) - list_add(&repo->list, &dbopts.repository_list); - break; - case 'q': - apk_verbosity--; - break; - case 'v': - apk_verbosity++; - break; - case 'V': - r = version(); - goto err; - case 'f': - apk_flags |= APK_FORCE; - break; - case 'i': - apk_flags |= APK_INTERACTIVE; - break; - case 'U': - apk_flags |= APK_UPDATE_CACHE; - break; - case 0x101: - apk_flags |= APK_PROGRESS; - break; - case 0x110: - apk_flags &= ~APK_PROGRESS; - break; - case 0x10f: - apk_progress_fd = atoi(optarg); - break; - case 0x102: - apk_flags |= APK_CLEAN_PROTECTED; - break; - case 0x103: - apk_flags |= APK_ALLOW_UNTRUSTED; - break; - case 0x104: - apk_flags |= APK_SIMULATE; - break; - case 0x106: - apk_flags |= APK_PURGE; - break; - case 0x105: - dbopts.lock_wait = atoi(optarg); - break; - case 0x109: - apk_flags |= APK_NO_NETWORK; - break; - case 0x113: - apk_flags |= APK_NO_SCRIPTS; - break; - case 0x111: - apk_flags |= APK_OVERLAY_FROM_STDIN; - break; - case 0x112: - dbopts.arch = optarg; - break; - case 0x114: - r = show_arch(); - goto err; -#ifdef TEST_MODE - case 0x200: - *apk_string_array_add(&test_repos) = (char*) optarg; - break; - case 0x201: - test_installed_db = optarg; - break; - case 0x202: - test_world = optarg; - break; -#endif - default: - if (applet == NULL || applet->parse == NULL || - applet->parse(ctx, &dbopts, r, - optindex - ARRAY_SIZE(generic_options), - optarg) != 0) { - r = usage(applet); - goto err; - } - break; + while ((p = getopt_long(argc, argv, short_options, all_options, NULL)) != -1) { + for (i = 0; optgroups[i]; i++) { + r = optgroups[i]->parse(ctx, &dbopts, p, optarg); + if (r == 0) break; + if (r != -ENOTSUP) goto err_and_usage; } } @@ -552,6 +569,7 @@ int main(int argc, char **argv) r = applet->main(ctx, &db, args); apk_db_close(&db); +err_and_usage: if (r == -EINVAL) r = usage(applet); err: diff --git a/src/apk_applet.h b/src/apk_applet.h index d11c259..e459435 100644 --- a/src/apk_applet.h +++ b/src/apk_applet.h @@ -12,6 +12,7 @@ #ifndef APK_APPLET_H #define APK_APPLET_H +#include #include #include "apk_defines.h" #include "apk_database.h" @@ -24,23 +25,31 @@ struct apk_option { const char *arg_name; }; +struct apk_option_group { + const char *name; + int num_options; + const struct apk_option *options; + + int (*parse)(void *ctx, struct apk_db_options *dbopts, + int optch, const char *optarg); +}; + struct apk_applet { struct list_head node; const char *name; const char *arguments; const char *help; + const struct apk_option_group *optgroups[4]; unsigned int open_flags, forced_flags; int context_size; - int num_options; - struct apk_option *options; - int (*parse)(void *ctx, struct apk_db_options *dbopts, - int optch, int optindex, const char *optarg); int (*main)(void *ctx, struct apk_database *db, struct apk_string_array *args); }; +extern const struct apk_option_group optgroup_global, optgroup_commit; + void apk_applet_register(struct apk_applet *); typedef void (*apk_init_func_t)(void); diff --git a/src/apk_database.h b/src/apk_database.h index 7d95011..731a5fd 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -118,10 +118,10 @@ struct apk_repository_list { struct apk_db_options { int lock_wait; unsigned long open_flags; - char *root; - char *arch; - char *keys_dir; - char *repositories_file; + const char *root; + const char *arch; + const char *keys_dir; + const char *repositories_file; struct list_head repository_list; }; diff --git a/src/audit.c b/src/audit.c index 4710e82..0d1ca5c 100644 --- a/src/audit.c +++ b/src/audit.c @@ -37,8 +37,7 @@ struct audit_ctx { unsigned packages_only : 1; }; -static int audit_parse(void *ctx, struct apk_db_options *dbopts, - int optch, int optindex, const char *optarg) +static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg) { struct audit_ctx *actx = (struct audit_ctx *) ctx; @@ -59,11 +58,27 @@ static int audit_parse(void *ctx, struct apk_db_options *dbopts, actx->recursive = 1; break; default: - return -1; + return -ENOTSUP; } return 0; } +static const struct apk_option options_applet[] = { + { 0x10000, "backup", "List all modified configuration files (in " + "protected_paths.d) that need to be backed up" }, + { 0x10001, "system", "Verify checksums of all installed non-configuration files " }, + { 0x10002, "check-permissions", "Check file and directory uid/gid/mode too" }, + { 'r', "recursive", "List individually all entries in new directories" }, + { 0x10003, "packages", "List only the changed packages (or names only with -q)" }, +}; + +static const struct apk_option_group optgroup_applet = { + .name = "Audit", + .options = options_applet, + .num_options = ARRAY_SIZE(options_applet), + .parse = option_parse_applet, +}; + struct audit_tree_ctx { struct audit_ctx *actx; struct apk_database *db; @@ -326,24 +341,13 @@ static int audit_main(void *ctx, struct apk_database *db, struct apk_string_arra return r; } -static struct apk_option audit_options[] = { - { 0x10000, "backup", "List all modified configuration files (in " - "protected_paths.d) that need to be backed up" }, - { 0x10001, "system", "Verify checksums of all installed non-configuration files " }, - { 0x10002, "check-permissions", "Check file and directory uid/gid/mode too" }, - { 'r', "recursive", "List individually all entries in new directories" }, - { 0x10003, "packages", "List only the changed packages (or names only with -q)" }, -}; - static struct apk_applet apk_audit = { .name = "audit", .help = "Audit the directories for changes", .arguments = "[directory to audit]...", .open_flags = APK_OPENF_READ|APK_OPENF_NO_SCRIPTS|APK_OPENF_NO_REPOS, .context_size = sizeof(struct audit_ctx), - .num_options = ARRAY_SIZE(audit_options), - .options = audit_options, - .parse = audit_parse, + .optgroups = { &optgroup_global, &optgroup_applet }, .main = audit_main, }; diff --git a/src/del.c b/src/del.c index 8cfdfcf..fb9b1c2 100644 --- a/src/del.c +++ b/src/del.c @@ -20,8 +20,7 @@ struct del_ctx { struct apk_dependency_array *world; }; -static int del_parse(void *pctx, struct apk_db_options *db, - int optch, int optindex, const char *optarg) +static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int optch, const char *optarg) { struct del_ctx *ctx = (struct del_ctx *) pctx; @@ -30,11 +29,23 @@ static int del_parse(void *pctx, struct apk_db_options *db, ctx->recursive_delete = 1; break; default: - return -1; + return -ENOTSUP; } return 0; } +static const struct apk_option options_applet[] = { + { 'r', "rdepends", "Recursively delete all top-level reverse " + "dependencies too" }, +}; + +static const struct apk_option_group optgroup_applet = { + .name = "Delete", + .options = options_applet, + .num_options = ARRAY_SIZE(options_applet), + .parse = option_parse_applet, +}; + struct not_deleted_ctx { struct apk_indent indent; struct apk_name *name; @@ -137,20 +148,13 @@ static int del_main(void *pctx, struct apk_database *db, struct apk_string_array return r; } -static struct apk_option del_options[] = { - { 'r', "rdepends", "Recursively delete all top-level reverse " - "dependencies too" }, -}; - static struct apk_applet apk_del = { .name = "del", .help = "Remove PACKAGEs from 'world' and uninstall them", .arguments = "PACKAGE...", .open_flags = APK_OPENF_WRITE, .context_size = sizeof(struct del_ctx), - .num_options = ARRAY_SIZE(del_options), - .options = del_options, - .parse = del_parse, + .optgroups = { &optgroup_global, &optgroup_commit, &optgroup_applet }, .main = del_main, }; diff --git a/src/dot.c b/src/dot.c index ccf5435..9c8ed4e 100644 --- a/src/dot.c +++ b/src/dot.c @@ -24,8 +24,7 @@ struct dot_ctx { int installed_only : 1; }; -static int dot_parse(void *pctx, struct apk_db_options *dbopts, - int optch, int optindex, const char *optarg) +static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int optch, const char *optarg) { struct dot_ctx *ctx = (struct dot_ctx *) pctx; @@ -38,11 +37,24 @@ static int dot_parse(void *pctx, struct apk_db_options *dbopts, dbopts->open_flags &= ~APK_OPENF_NO_INSTALLED; break; default: - return -1; + return -ENOTSUP; } return 0; } +static const struct apk_option options_applet[] = { + { 0x10000, "errors", "Output only parts of the graph which are considered " + "erroneous: e.g. cycles and missing packages" }, + { 0x10001, "installed", "Consider only installed packages" }, +}; + +static const struct apk_option_group optgroup_applet = { + .name = "Dot", + .options = options_applet, + .num_options = ARRAY_SIZE(options_applet), + .parse = option_parse_applet, +}; + static void start_graph(struct dot_ctx *ctx) { if (ctx->not_empty) @@ -155,21 +167,13 @@ static int dot_main(void *pctx, struct apk_database *db, struct apk_string_array return 0; } -static struct apk_option dot_options[] = { - { 0x10000, "errors", "Output only parts of the graph which are considered " - "erroneous: e.g. cycles and missing packages" }, - { 0x10001, "installed", "Consider only installed packages" }, -}; - static struct apk_applet apk_dot = { .name = "dot", .help = "Generate graphviz graphs", .arguments = "PKGMASK...", .open_flags = APK_OPENF_READ | APK_OPENF_NO_STATE, .context_size = sizeof(struct dot_ctx), - .num_options = ARRAY_SIZE(dot_options), - .options = dot_options, - .parse = dot_parse, + .optgroups = { &optgroup_global, &optgroup_applet }, .main = dot_main, }; diff --git a/src/fetch.c b/src/fetch.c index 22ea648..3c40963 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -67,8 +67,7 @@ static int cup(void) return write(STDOUT_FILENO, buf, len) != len; } -static int fetch_parse(void *ctx, struct apk_db_options *dbopts, - int optch, int optindex, const char *optarg) +static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg) { struct fetch_ctx *fctx = (struct fetch_ctx *) ctx; @@ -86,11 +85,27 @@ static int fetch_parse(void *ctx, struct apk_db_options *dbopts, fctx->outdir_fd = openat(AT_FDCWD, optarg, O_RDONLY | O_CLOEXEC); break; default: - return -1; + return -ENOTSUP; } return 0; } +static const struct apk_option options_applet[] = { + { 'L', "link", "Create hard links if possible" }, + { 'R', "recursive", "Fetch the PACKAGE and all its dependencies" }, + { 's', "stdout", + "Dump the .apk to stdout (incompatible with -o, -R, --progress)" }, + { 'o', "output", "Directory to place the PACKAGEs to", + required_argument, "DIR" }, +}; + +static const struct apk_option_group optgroup_applet = { + .name = "Fetch", + .options = options_applet, + .num_options = ARRAY_SIZE(options_applet), + .parse = option_parse_applet, +}; + static void progress_cb(void *pctx, size_t bytes_done) { struct fetch_ctx *ctx = (struct fetch_ctx *) pctx; @@ -263,15 +278,6 @@ static int fetch_main(void *pctx, struct apk_database *db, struct apk_string_arr return ctx->errors; } -static struct apk_option fetch_options[] = { - { 'L', "link", "Create hard links if possible" }, - { 'R', "recursive", "Fetch the PACKAGE and all its dependencies" }, - { 's', "stdout", - "Dump the .apk to stdout (incompatible with -o, -R, --progress)" }, - { 'o', "output", "Directory to place the PACKAGEs to", - required_argument, "DIR" }, -}; - static struct apk_applet apk_fetch = { .name = "fetch", .help = "Download PACKAGEs from global repositories to a local directory", @@ -279,9 +285,7 @@ static struct apk_applet apk_fetch = { .open_flags = APK_OPENF_READ | APK_OPENF_NO_STATE | APK_OPENF_NO_INSTALLED_REPO, .context_size = sizeof(struct fetch_ctx), - .num_options = ARRAY_SIZE(fetch_options), - .options = fetch_options, - .parse = fetch_parse, + .optgroups = { &optgroup_global, &optgroup_applet }, .main = fetch_main, }; diff --git a/src/fix.c b/src/fix.c index df85c2c..f6fd579 100644 --- a/src/fix.c +++ b/src/fix.c @@ -22,8 +22,7 @@ struct fix_ctx { int fix_directory_permissions : 1; }; -static int fix_parse(void *pctx, struct apk_db_options *dbopts, - int optch, int optindex, const char *optarg) +static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int optch, const char *optarg) { struct fix_ctx *ctx = (struct fix_ctx *) pctx; switch (optch) { @@ -40,11 +39,25 @@ static int fix_parse(void *pctx, struct apk_db_options *dbopts, ctx->fix_directory_permissions = 1; break; default: - return -1; + return -ENOTSUP; } return 0; } +static const struct apk_option options_applet[] = { + { 'd', "depends", "Fix all dependencies too" }, + { 'r', "reinstall", "Reinstall the package (default)" }, + { 'u', "upgrade", "Prefer to upgrade package" }, + { 0x10000, "directory-permissions", "Reset all directory permissions" }, +}; + +static const struct apk_option_group optgroup_applet = { + .name = "Fix", + .options = options_applet, + .num_options = ARRAY_SIZE(options_applet), + .parse = option_parse_applet, +}; + static int mark_recalculate(apk_hash_item item, void *ctx) { struct apk_db_dir *dir = (struct apk_db_dir *) item; @@ -84,13 +97,6 @@ static int fix_main(void *pctx, struct apk_database *db, struct apk_string_array return apk_solver_commit(db, 0, db->world); } -static struct apk_option fix_options[] = { - { 'd', "depends", "Fix all dependencies too" }, - { 'r', "reinstall", "Reinstall the package (default)" }, - { 'u', "upgrade", "Prefer to upgrade package" }, - { 0x10000, "directory-permissions", "Reset all directory permissions" }, -}; - static struct apk_applet apk_fix = { .name = "fix", .help = "Repair package or upgrade it without modifying main " @@ -98,9 +104,7 @@ static struct apk_applet apk_fix = { .arguments = "PACKAGE...", .open_flags = APK_OPENF_WRITE, .context_size = sizeof(struct fix_ctx), - .num_options = ARRAY_SIZE(fix_options), - .options = fix_options, - .parse = fix_parse, + .optgroups = { &optgroup_global, &optgroup_commit, &optgroup_applet }, .main = fix_main, }; diff --git a/src/index.c b/src/index.c index a783095..2fe8cb4 100644 --- a/src/index.c +++ b/src/index.c @@ -32,8 +32,7 @@ struct index_ctx { int method; }; -static int index_parse(void *ctx, struct apk_db_options *dbopts, - int optch, int optindex, const char *optarg) +static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg) { struct index_ctx *ictx = (struct index_ctx *) ctx; @@ -51,11 +50,31 @@ static int index_parse(void *ctx, struct apk_db_options *dbopts, ictx->rewrite_arch = apk_blob_atomize(APK_BLOB_STR(optarg)); break; default: - return -1; + return -ENOTSUP; } return 0; } +static const struct apk_option options_applet[] = { + { 'o', "output", "Write the generated index to FILE", + required_argument, "FILE" }, + { 'x', "index", "Read INDEX to speed up new index creation by reusing " + "the information from an old index", + required_argument, "INDEX" }, + { 'd', "description", "Embed TEXT as description and version " + "information of the repository index", + required_argument, "TEXT" }, + { 0x10000, "rewrite-arch", "Use ARCH as architecture for all packages", + required_argument, "ARCH" }, +}; + +static const struct apk_option_group optgroup_applet = { + .name = "Index", + .options = options_applet, + .num_options = ARRAY_SIZE(options_applet), + .parse = option_parse_applet, +}; + static int index_read_file(struct apk_database *db, struct index_ctx *ictx) { struct apk_file_info fi; @@ -237,28 +256,13 @@ static int index_main(void *ctx, struct apk_database *db, struct apk_string_arra return 0; } -static struct apk_option index_options[] = { - { 'o', "output", "Write the generated index to FILE", - required_argument, "FILE" }, - { 'x', "index", "Read INDEX to speed up new index creation by reusing " - "the information from an old index", - required_argument, "INDEX" }, - { 'd', "description", "Embed TEXT as description and version " - "information of the repository index", - required_argument, "TEXT" }, - { 0x10000, "rewrite-arch", "Use ARCH as architecture for all packages", - required_argument, "ARCH" }, -}; - static struct apk_applet apk_index = { .name = "index", .help = "Create repository index file from FILEs", .arguments = "FILE...", .open_flags = APK_OPENF_READ | APK_OPENF_NO_STATE | APK_OPENF_NO_REPOS, .context_size = sizeof(struct index_ctx), - .num_options = ARRAY_SIZE(index_options), - .options = index_options, - .parse = index_parse, + .optgroups = { &optgroup_global, &optgroup_applet }, .main = index_main, }; diff --git a/src/info.c b/src/info.c index 9af28f4..4e2c430 100644 --- a/src/info.c +++ b/src/info.c @@ -341,8 +341,7 @@ static void print_name_info(struct apk_database *db, const char *match, struct a info_subaction(ctx, p->pkg); } -static int info_parse(void *pctx, struct apk_db_options *dbopts, - int optch, int optindex, const char *optarg) +static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int optch, const char *optarg) { struct info_ctx *ctx = (struct info_ctx *) pctx; @@ -423,7 +422,7 @@ static int info_main(void *ctx, struct apk_database *db, struct apk_string_array return 0; } -static struct apk_option info_options[] = { +static const struct apk_option options_applet[] = { { 'L', "contents", "List contents of the PACKAGE" }, { 'e', "installed", "Check if PACKAGE is installed" }, { 'W', "who-owns", "Print the package owning the specified file" }, @@ -440,15 +439,20 @@ static struct apk_option info_options[] = { { 'a', "all", "Print all information about PACKAGE" }, }; +static const struct apk_option_group optgroup_applet = { + .name = "Info", + .options = options_applet, + .num_options = ARRAY_SIZE(options_applet), + .parse = option_parse_applet, +}; + static struct apk_applet apk_info = { .name = "info", .help = "Give detailed information about PACKAGEs or repositores", .arguments = "PACKAGE...", .open_flags = APK_OPENF_READ, .context_size = sizeof(struct info_ctx), - .num_options = ARRAY_SIZE(info_options), - .options = info_options, - .parse = info_parse, + .optgroups = { &optgroup_global, &optgroup_applet }, .main = info_main, }; diff --git a/src/search.c b/src/search.c index 84fcbb1..4e7c730 100644 --- a/src/search.c +++ b/src/search.c @@ -65,8 +65,7 @@ static void print_rdepends(struct search_ctx *ctx, struct apk_package *pkg) apk_pkg_foreach_reverse_dependency(pkg, ctx->matches, print_rdep_pkg, ctx); } -static int search_parse(void *ctx, struct apk_db_options *dbopts, - int optch, int optindex, const char *optarg) +static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg) { struct search_ctx *ictx = (struct search_ctx *) ctx; @@ -100,6 +99,23 @@ static int search_parse(void *ctx, struct apk_db_options *dbopts, return 0; } +static const struct apk_option options_applet[] = { + { 'a', "all", "Show all package versions (instead of latest only)" }, + { 'd', "description", "Search package descriptions (implies -a)" }, + { 'x', "exact", "Require exact match (instead of substring match)" }, + { 'e', NULL, "Synonym for -x (deprecated)" }, + { 'o', "origin", "Print origin package name instead of the subpackage" }, + { 'r', "rdepends", "Print reverse dependencies of package" }, + { 0x10000, "has-origin","List packages that have the given origin" }, +}; + +static const struct apk_option_group optgroup_applet = { + .name = "Search", + .options = options_applet, + .num_options = ARRAY_SIZE(options_applet), + .parse = option_parse_applet, +}; + static void print_result_pkg(struct search_ctx *ctx, struct apk_package *pkg) { char **pmatch; @@ -177,25 +193,13 @@ static int search_main(void *pctx, struct apk_database *db, struct apk_string_ar return 0; } -static struct apk_option search_options[] = { - { 'a', "all", "Show all package versions (instead of latest only)" }, - { 'd', "description", "Search package descriptions (implies -a)" }, - { 'x', "exact", "Require exact match (instead of substring match)" }, - { 'e', NULL, "Synonym for -x (deprecated)" }, - { 'o', "origin", "Print origin package name instead of the subpackage" }, - { 'r', "rdepends", "Print reverse dependencies of package" }, - { 0x10000, "has-origin","List packages that have the given origin" }, -}; - static struct apk_applet apk_search = { .name = "search", .help = "Search package by PATTERNs or by indexed dependencies", .arguments = "PATTERN", .open_flags = APK_OPENF_READ | APK_OPENF_NO_STATE, .context_size = sizeof(struct search_ctx), - .num_options = ARRAY_SIZE(search_options), - .options = search_options, - .parse = search_parse, + .optgroups = { &optgroup_global, &optgroup_applet }, .main = search_main, }; diff --git a/src/upgrade.c b/src/upgrade.c index a188908..1429aec 100644 --- a/src/upgrade.c +++ b/src/upgrade.c @@ -23,8 +23,7 @@ struct upgrade_ctx { int no_self_upgrade : 1; }; -static int upgrade_parse(void *ctx, struct apk_db_options *dbopts, - int optch, int optindex, const char *optarg) +static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg) { struct upgrade_ctx *uctx = (struct upgrade_ctx *) ctx; @@ -44,6 +43,26 @@ static int upgrade_parse(void *ctx, struct apk_db_options *dbopts, return 0; } +static const struct apk_option options_applet[] = { + { 'a', "available", + "Resets versioned world dependencies, and changes to prefer " + "replacing or downgrading packages (instead of holding them) " + "if the currently installed package is no longer available " + "from any repository" }, + { 'l', "latest", + "Select latest version of package (if it is not pinned), and " + "print error if it cannot be installed due to other dependencies" }, + { 0x10000, "no-self-upgrade", + "Do not do early upgrade of 'apk-tools' package" }, +}; + +static const struct apk_option_group optgroup_applet = { + .name = "Upgrade", + .options = options_applet, + .num_options = ARRAY_SIZE(options_applet), + .parse = option_parse_applet, +}; + int apk_do_self_upgrade(struct apk_database *db, unsigned short solver_flags) { struct apk_name *name; @@ -128,27 +147,12 @@ static int upgrade_main(void *ctx, struct apk_database *db, struct apk_string_ar return r; } -static struct apk_option upgrade_options[] = { - { 'a', "available", - "Resets versioned world dependencies, and changes to prefer " - "replacing or downgrading packages (instead of holding them) " - "if the currently installed package is no longer available " - "from any repository" }, - { 'l', "latest", - "Select latest version of package (if it is not pinned), and " - "print error if it cannot be installed due to other dependencies" }, - { 0x10000, "no-self-upgrade", - "Do not do early upgrade of 'apk-tools' package" }, -}; - static struct apk_applet apk_upgrade = { .name = "upgrade", .help = "Upgrade currently installed packages to match repositories", .open_flags = APK_OPENF_WRITE, .context_size = sizeof(struct upgrade_ctx), - .num_options = ARRAY_SIZE(upgrade_options), - .options = upgrade_options, - .parse = upgrade_parse, + .optgroups = { &optgroup_global, &optgroup_commit, &optgroup_applet }, .main = upgrade_main, }; diff --git a/src/ver.c b/src/ver.c index 6469db4..53ef062 100644 --- a/src/ver.c +++ b/src/ver.c @@ -68,11 +68,10 @@ static int ver_validate(struct apk_database *db, struct apk_string_array *args) return errors; } -static int ver_parse(void *ctx, struct apk_db_options *dbopts, - int opt, int optindex, const char *optarg) +static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg) { struct ver_ctx *ictx = (struct ver_ctx *) ctx; - switch (opt) { + switch (optch) { case 'I': ictx->action = ver_indexes; break; @@ -96,6 +95,22 @@ static int ver_parse(void *ctx, struct apk_db_options *dbopts, return 0; } +static const struct apk_option options_applet[] = { + { 'I', "indexes", "Print description and versions of indexes" }, + { 't', "test", "Compare two given versions, output '<', '=' or '>'" }, + { 'c', "check", "Check the given version strings, output any that are invalid" }, + { 'a', "all", "Consider packages from all repository tags" }, + { 'l', "limit", "Limit output to packages with status matching one of LIMCHARs", + required_argument, "LIMCHARs" }, +}; + +static const struct apk_option_group optgroup_applet = { + .name = "Version", + .options = options_applet, + .num_options = ARRAY_SIZE(options_applet), + .parse = option_parse_applet, +}; + static void 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; @@ -181,24 +196,13 @@ static int ver_main(void *pctx, struct apk_database *db, struct apk_string_array return 0; } -static struct apk_option ver_options[] = { - { 'I', "indexes", "Print description and versions of indexes" }, - { 't', "test", "Compare two given versions, output '<', '=' or '>'" }, - { 'c', "check", "Check the given version strings, output any that are invalid" }, - { 'a', "all", "Consider packages from all repository tags" }, - { 'l', "limit", "Limit output to packages with status matching one of LIMCHARs", - required_argument, "LIMCHARs" }, -}; - static struct apk_applet apk_ver = { .name = "version", .help = "Compare package versions (in installed database vs. available) " "or do tests on literal version strings", .open_flags = APK_OPENF_READ, .context_size = sizeof(struct ver_ctx), - .num_options = ARRAY_SIZE(ver_options), - .options = ver_options, - .parse = ver_parse, + .optgroups = { &optgroup_global, &optgroup_applet }, .main = ver_main, }; -- cgit v1.2.3-60-g2f50