Re: [PATCH v2] parse-options: don't emit "ambiguous option" for aliases

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Duy Nguyen <pclouds@xxxxxxxxx> writes:

> So an alternative is simply outsource the ambiguity decision back to
> git-clone. If the same situation appears again elsewhere, we'll need
> to sit back and fix it for real. But this way we don't potentially
> introduce any new traps.

Sounds like a sensibly safe approach.

> +/*
> + * Avoid ambiguation error between --recursive and --recurse-submodule
> + * because they are the same. --recurs can be expanded to any of them
> + * and it still works.
> + */
> +static int is_abbrev_ambiguous(const struct option *prev,
> +			       const struct option *next)
> +{
> +	const struct option *opts[] = { prev, next };

By looking at its caller, I think the caller keeps track of the
candidate it saw so far, and ask this function to see if the one it
is looking at right now (i.e. "this one") should be flagged as
conflicting with the other one (or "the other one").  So it probably
makes more sense to call them <it, the_other> or <it, prev> [*1*].

	Side note: *1* I would have used "this" instead of "it", but
	I vaguely recall there are those who want to use C++ aware
	static checkers and avoiding the identifier "this" is easy
	enough so ...

> +	int i, found = 0;
> +
> +	for (i = 0; i < ARRAY_SIZE(opts); i++) {
> +		if (!opts[i]->long_name)
> +			continue;
> +		if (!strcmp(opts[i]->long_name, "recursive"))
> +			found |= 1 << 0;
> +		if (!strcmp(opts[i]->long_name, "recurse-submodules"))
> +			found |= 1 << 1;
> +	}
> +
> +	return found != 3;
> +}

For any two options that share the prefix, unless they are
"recursive" and "recurse-submodules" pair, we say "that's
ambiguous".  But when they are these two specifically singled out,
we say it is OK.  Makes sense.

The above may be sufficient for this purpose, but I would have
expected that these groups of aliases would be the ones in the
table, not the <it, the_other> pair.  IOW, with helpers like these:

	static const char *recurse_submodules[] = {
		"recurse-submodules", "recursive", NULL,
	};

	static struct {
		const char **aliases;
	} disamb[] = {
		recurse_submodules,
	};
		
	static int has_string(const char *it, const char **array)
	{
		while (*array)
			if (!strcmp(it, *(array++)))
				return 1;
		return 0;
	}

the body would look something like:

	int j;

	for (j = 0; j < ARRAY_SIZE(disamb); j++) {
		/* it and other are from the same family? */
		if (it->long_name &&
		    has_string(it->long_name, disamb[j].aliases) &&
		    other->long_name &&
		    has_string(other->long_name, disamb[j].aliases))
			return 0;
	}
	return 1;

Perhaps?

I suspect that renaming the function (and the field in the context
struct) to .is_alias() and reverse the polarity of its return value
may make the flow of the logic at the caller side easier to follow?

> diff --git a/parse-options.c b/parse-options.c
> index cec74522e5..c0354e5a92 100644
> --- a/parse-options.c
> +++ b/parse-options.c
> @@ -294,7 +294,8 @@ static enum parse_opt_result parse_long_opt(
>  			if (!(p->flags & PARSE_OPT_KEEP_UNKNOWN) &&
>  			    !strncmp(long_name, arg, arg_end - arg)) {
>  is_abbreviated:
> -				if (abbrev_option) {
> +				if (abbrev_option &&
> +				    p->is_abbrev_ambiguous(abbrev_option, options)) {

The above suggestion would make the guard here to

			if (abbrev_option &&
			    !p->is_alias(abbrev_option, options)) {

That is, at this point, we know that the user may have used the
given string to name the "abbrev_option" we earlier saw (and made
sure it prefix matches the string), and now we are looking at
another one, options[0], that also prefix matches the string.  We
usually flag this case as a problematic ambiguity inside the body of
this if statement, but if one is an alias to the other, we do not do
so.

>  					/*
>  					 * If this is abbreviated, it is
>  					 * ambiguous. So when there is no



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux