Commit 38e3f546 authored by Timo Teräs's avatar Timo Teräs

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.
parent 275dd16c
......@@ -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,
};
......
This diff is collapsed.
......@@ -12,6 +12,7 @@
#ifndef APK_APPLET_H
#define APK_APPLET_H
#include <errno.h>
#include <getopt.h>
#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);
......
......@@ -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;
};
......
......@@ -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,
};
......
......@@ -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,
};
......
......@@ -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,
};
......
......@@ -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,
};
......
......@@ -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,
};
......
......@@ -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,
};
......
......@@ -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,
};
......
......@@ -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,
};
......
......@@ -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,
};
......
......@@ -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" },
};