In the past, we have created some virsh options with less-than-stellar names. For back-compat reasons, those names must continue to parse, but we don't want to document them in help output. This introduces a new option type, an alias, which points to a canonical option name later in the option list. I'm actually quite impressed that our code has already been factored to do all option parsing through common entry points, such that I got this added in relatively few lines of code! * tools/virsh.c (VSH_OT_ALIAS): New option type. (opts_echo): Hook up an alias, for easy testing. (vshCmddefOptParse, vshCmddefHelp, vshCmddefGetOption): Allow for aliases. * tests/virshtest.c (mymain): Test new feature. --- tests/virshtest.c | 6 ++++++ tools/virsh.c | 28 ++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/tests/virshtest.c b/tests/virshtest.c index 6474c19..87b1336 100644 --- a/tests/virshtest.c +++ b/tests/virshtest.c @@ -386,6 +386,12 @@ mymain(void) DO_TEST(30, "--shell a\n", "echo \t '-'\"-\" \t --shell \t a"); + /* Tests of alias handling. */ + DO_TEST(31, "hello\n", "echo", "--string", "hello"); + DO_TEST(32, "hello\n", "echo --string hello"); + DO_TEST(33, "hello\n", "echo", "--str", "hello"); + DO_TEST(34, "hello\n", "echo --str hello"); + # undef DO_TEST VIR_FREE(custom_uri); diff --git a/tools/virsh.c b/tools/virsh.c index aef050f..77cf4ac 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -138,7 +138,8 @@ typedef enum { VSH_OT_STRING, /* optional string option */ VSH_OT_INT, /* optional or mandatory int option */ VSH_OT_DATA, /* string data (as non-option) */ - VSH_OT_ARGV /* remaining arguments */ + VSH_OT_ARGV, /* remaining arguments */ + VSH_OT_ALIAS, /* alternate spelling for a later argument */ } vshCmdOptType; /* @@ -190,7 +191,8 @@ typedef struct { const char *name; /* the name of option, or NULL for list end */ vshCmdOptType type; /* option type */ unsigned int flags; /* flags */ - const char *help; /* non-NULL help string */ + const char *help; /* non-NULL help string; or for VSH_OT_ALIAS + * the name of a later public option */ } vshCmdOptDef; /* @@ -15209,6 +15211,7 @@ static const vshCmdInfo info_echo[] = { static const vshCmdOptDef opts_echo[] = { {"shell", VSH_OT_BOOL, 0, N_("escape for shell use")}, {"xml", VSH_OT_BOOL, 0, N_("escape for XML use")}, + {"str", VSH_OT_ALIAS, 0, "string"}, {"string", VSH_OT_ARGV, 0, N_("arguments to echo")}, {NULL, 0, 0, NULL} }; @@ -17256,6 +17259,18 @@ vshCmddefOptParse(const vshCmdDef *cmd, uint32_t *opts_need_arg, return -1; /* bool options can't be mandatory */ continue; } + if (opt->type == VSH_OT_ALIAS) { + int j; + if (opt->flags || !opt->help) + return -1; /* alias options are tracked by the original name */ + for (j = i + 1; cmd->opts[j].name; j++) { + if (STREQ(opt->help, cmd->opts[j].name)) + break; + } + if (!cmd->opts[j].name) + return -1; /* alias option must map to a later option name */ + continue; + } if (opt->flags & VSH_OFLAG_REQ_OPT) { if (opt->flags & VSH_OFLAG_REQ) *opts_required |= 1 << i; @@ -17287,6 +17302,10 @@ vshCmddefGetOption(vshControl *ctl, const vshCmdDef *cmd, const char *name, const vshCmdOptDef *opt = &cmd->opts[i]; if (STREQ(opt->name, name)) { + if (opt->type == VSH_OT_ALIAS) { + name = opt->help; + continue; + } if ((*opts_seen & (1 << i)) && opt->type != VSH_OT_ARGV) { vshError(ctl, _("option --%s already seen"), name); return NULL; @@ -17465,6 +17484,9 @@ vshCmddefHelp(vshControl *ctl, const char *cmdname) : _("[<%s>]..."); } break; + case VSH_OT_ALIAS: + /* aliases are intentionally undocumented */ + continue; default: assert(0); } @@ -17506,6 +17528,8 @@ vshCmddefHelp(vshControl *ctl, const char *cmdname) shortopt ? _("[--%s] <string>") : _("<%s>"), opt->name); break; + case VSH_OT_ALIAS: + continue; default: assert(0); } -- 1.7.7.6 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list