]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
vsh: Allow one optional positional argument
authorPeter Krempa <pkrempa@redhat.com>
Thu, 14 Mar 2024 15:21:58 +0000 (16:21 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Tue, 2 Apr 2024 12:24:29 +0000 (14:24 +0200)
We already allow a optional positional _ARGV argument but there's no
reason why any other argument type could not be allowed this way.

Add checks that there's just one such argument and it's placed after
required positional arguments.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
tools/vsh.c

index cbddc5ed924ad7fc3715445fba094b376f87f696..80057654c864372186ac89b50536727e4b59cdae 100644 (file)
@@ -249,6 +249,7 @@ vshCmddefCheckInternals(vshControl *ctl,
 {
     size_t i;
     bool seenOptionalOption = false;
+    const char *seenOptionalPositionalOption = NULL;
     g_auto(virBuffer) complbuf = VIR_BUFFER_INITIALIZER;
     g_auto(virBuffer) posbuf = VIR_BUFFER_INITIALIZER;
 
@@ -350,10 +351,21 @@ vshCmddefCheckInternals(vshControl *ctl,
             }
         }
 
-        /* require that positional non-argv options are required */
-        if (opt->positional && !opt->required && opt->type != VSH_OT_ARGV) {
-            vshError(ctl, "positional argument '%s' of command '%s' must be required",
-                     opt->name, cmd->name);
+        /* allow at most one optional positional option */
+        if (opt->positional && !opt->required) {
+            if (seenOptionalPositionalOption) {
+                vshError(ctl, "multiple optional positional arguments (%s, %s) of command '%s' are not allowed",
+                         seenOptionalPositionalOption, opt->name, cmd->name);
+                return -1;
+            }
+
+            seenOptionalPositionalOption = opt->name;
+        }
+
+        /* all optional positional arguments must be defined after the required ones */
+        if (seenOptionalPositionalOption && opt->positional && opt->required) {
+            vshError(ctl, "required positional argument '%s' declared after an optional positional argument '%s' of command '%s'",
+                     opt->name, seenOptionalPositionalOption, cmd->name);
             return -1;
         }