summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--parse-options.c33
-rwxr-xr-xt/t0040-parse-options.sh13
-rw-r--r--test-parse-options.c1
3 files changed, 35 insertions, 12 deletions
diff --git a/parse-options.c b/parse-options.c
index cc09c98ec3..15b32f741b 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -119,8 +119,8 @@ static int parse_long_opt(struct optparse_t *p, const char *arg,
const struct option *options)
{
const char *arg_end = strchr(arg, '=');
- const struct option *abbrev_option = NULL;
- int abbrev_flags = 0;
+ const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
+ int abbrev_flags = 0, ambiguous_flags = 0;
if (!arg_end)
arg_end = arg + strlen(arg);
@@ -137,16 +137,16 @@ static int parse_long_opt(struct optparse_t *p, const char *arg,
/* abbreviated? */
if (!strncmp(options->long_name, arg, arg_end - arg)) {
is_abbreviated:
- if (abbrev_option)
- return error("Ambiguous option: %s "
- "(could be --%s%s or --%s%s)",
- arg,
- (flags & OPT_UNSET) ?
- "no-" : "",
- options->long_name,
- (abbrev_flags & OPT_UNSET) ?
- "no-" : "",
- abbrev_option->long_name);
+ if (abbrev_option) {
+ /*
+ * If this is abbreviated, it is
+ * ambiguous. So when there is no
+ * exact match later, we need to
+ * error out.
+ */
+ ambiguous_option = abbrev_option;
+ ambiguous_flags = abbrev_flags;
+ }
if (!(flags & OPT_UNSET) && *arg_end)
p->opt = arg_end + 1;
abbrev_option = options;
@@ -176,6 +176,15 @@ is_abbreviated:
}
return get_value(p, options, flags);
}
+
+ if (ambiguous_option)
+ return error("Ambiguous option: %s "
+ "(could be --%s%s or --%s%s)",
+ arg,
+ (ambiguous_flags & OPT_UNSET) ? "no-" : "",
+ ambiguous_option->long_name,
+ (abbrev_flags & OPT_UNSET) ? "no-" : "",
+ abbrev_option->long_name);
if (abbrev_option)
return get_value(p, abbrev_option, abbrev_flags);
return error("unknown option `%s'", arg);
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index ae49424aa0..462fdf262f 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -18,6 +18,7 @@ string options
-s, --string <string>
get a string
--string2 <str> get another string
+ --st <st> get another string (pervert ordering)
EOF
@@ -90,4 +91,16 @@ test_expect_failure 'ambiguously abbreviated option' '
test $? != 129
'
+cat > expect << EOF
+boolean: 0
+integer: 0
+string: 123
+EOF
+
+test_expect_success 'non ambiguous option (after two options it abbreviates)' '
+ test-parse-options --st 123 > output 2> output.err &&
+ test ! -s output.err &&
+ git diff expect output
+'
+
test_done
diff --git a/test-parse-options.c b/test-parse-options.c
index 277cfe4d6d..4d3e2ec39e 100644
--- a/test-parse-options.c
+++ b/test-parse-options.c
@@ -18,6 +18,7 @@ int main(int argc, const char **argv)
OPT_GROUP("string options"),
OPT_STRING('s', "string", &string, "string", "get a string"),
OPT_STRING(0, "string2", &string, "str", "get another string"),
+ OPT_STRING(0, "st", &string, "st", "get another string (pervert ordering)"),
OPT_END(),
};
int i;