# [RFC PATCH] parse-options: disallow double-negations of options starting with no-

9 messages from 2017-04-19 to 2017-04-19. Participants: Jacob Keller, Ævar Arnfjörð Bjarmason, René Scharfe, Jeff King.
Thread: https://gitlist.dev/t/45742

## Jacob Keller, 2017-04-19 09:08

Subject: [RFC PATCH] parse-options: disallow double-negations of options starting with no-
Message-ID: <20170419090820.20279-1-jacob.e.keller@intel.com>
URL: https://gitlist.dev/e/20170419090820.20279-1-jacob.e.keller%40intel.com

```
From: Jacob Keller <jacob.keller@gmail.com>

Many options can be negated by prefixing the option with "no-", for
example "--3way" can be prefixed with "--no-3way" to disable it. Since
0f1930c58754 ("parse-options: allow positivation of options
starting, with no-", 2012-02-25) we have also had support to negate
options which start with "no-" by using the positive wording.

This leads to the confusing (and non-documented) case that you can still
prefix options beginning with "no-" by a second "no-" to negate them.
That is, we allow "no-no-hardlinks" to negate the "no-hardlinks" option.

This can be confusing to the user so lets just disallow the
double-negative forms. If the long_name begins with "no-" then we simply
don't allow the regular negation format, and only allow the option to be
negated by the positive form.

Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
---
I started going about implementing an OPT_NEGBOOL as suggested by Peff,
but realized this might just be simpler, and we already support the
positive format for the negation, so we don't lose expressiveness. We
*might* want to tie this to an option flag instead so that it only kicks
in if the option specifically requests it. Thoughts?

 parse-options.c          | 3 +++
 t/t0040-parse-options.sh | 5 ++++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/parse-options.c b/parse-options.c
index a23a1e67f04f..8e024c569f52 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -299,6 +299,9 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
 				}
 				continue;
 			}
+			/* avoid double-negate on long_name */
+			if (starts_with(long_name, "no-"))
+				continue;
 			flags |= OPT_UNSET;
 			if (!skip_prefix(arg + 3, long_name, &rest)) {
 				/* abbreviated and negated? */
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index 74d2cd76fe56..abccfa5f265f 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -88,7 +88,6 @@ test_expect_success 'OPT_BOOL() is idempotent #1' 'check boolean: 1 --yes --yes'
 test_expect_success 'OPT_BOOL() is idempotent #2' 'check boolean: 1 -DB'
 
 test_expect_success 'OPT_BOOL() negation #1' 'check boolean: 0 -D --no-yes'
-test_expect_success 'OPT_BOOL() negation #2' 'check boolean: 0 -D --no-no-doubt'
 
 test_expect_success 'OPT_BOOL() no negation #1' 'check_unknown_i18n --fear'
 test_expect_success 'OPT_BOOL() no negation #2' 'check_unknown_i18n --no-no-fear'
@@ -392,4 +391,8 @@ test_expect_success '--no-verbose resets multiple verbose to 0' '
 	test-parse-options --expect="verbose: 0" -v -v -v --no-verbose
 '
 
+test_expect_success 'double negation not accepted' '
+	test_must_fail test-parse-options --expect="boolean: 0" --no-no-doubt
+'
+
 test_done
-- 
2.12.2.882.g942b4cedeff1.dirty


```

## Ævar Arnfjörð Bjarmason, 2017-04-19 09:34

Subject: Re: [RFC PATCH] parse-options: disallow double-negations of options starting with no-
Message-ID: <CACBZZX5_fJ9w_K4H8R-NMi7kiR5QkR35pRqvzDRr_=rhMSQvfg@mail.gmail.com>
URL: https://gitlist.dev/e/CACBZZX5_fJ9w_K4H8R-NMi7kiR5QkR35pRqvzDRr_%3DrhMSQvfg%40mail.gmail.com
In-Reply-To: <20170419090820.20279-1-jacob.e.keller@intel.com>

```
On Wed, Apr 19, 2017 at 11:08 AM, Jacob Keller <jacob.e.keller@intel.com> wrote:
> Many options can be negated by prefixing the option with "no-", for
> example "--3way" can be prefixed with "--no-3way" to disable it. Since
> 0f1930c58754 ("parse-options: allow positivation of options
> starting, with no-", 2012-02-25) we have also had support to negate
> options which start with "no-" by using the positive wording.
>
> This leads to the confusing (and non-documented) case that you can still
> prefix options beginning with "no-" by a second "no-" to negate them.
> That is, we allow "no-no-hardlinks" to negate the "no-hardlinks" option.
>
> This can be confusing to the user so lets just disallow the
> double-negative forms. If the long_name begins with "no-" then we simply
> don't allow the regular negation format, and only allow the option to be
> negated by the positive form.

Looks good to me. Addresses the bug I was trying to fix much better
than my patch.

```

## René Scharfe, 2017-04-19 12:58

Subject: Re: [RFC PATCH] parse-options: disallow double-negations of options starting with no-
Message-ID: <68ed1250-534d-dc16-874e-ea14b592f8fd@web.de>
URL: https://gitlist.dev/e/68ed1250-534d-dc16-874e-ea14b592f8fd%40web.de
In-Reply-To: <20170419090820.20279-1-jacob.e.keller@intel.com>

```
Am 19.04.2017 um 11:08 schrieb Jacob Keller:
> From: Jacob Keller <jacob.keller@gmail.com>
> 
> Many options can be negated by prefixing the option with "no-", for
> example "--3way" can be prefixed with "--no-3way" to disable it. Since
> 0f1930c58754 ("parse-options: allow positivation of options
> starting, with no-", 2012-02-25) we have also had support to negate
> options which start with "no-" by using the positive wording.
> 
> This leads to the confusing (and non-documented) case that you can still
> prefix options beginning with "no-" by a second "no-" to negate them.
> That is, we allow "no-no-hardlinks" to negate the "no-hardlinks" option.
> 
> This can be confusing to the user so lets just disallow the
> double-negative forms. If the long_name begins with "no-" then we simply
> don't allow the regular negation format, and only allow the option to be
> negated by the positive form.

Your patch is a modernized version of my old one, so I'm fine with it.

But I wonder how --no-no-x being treated the same as --x can be 
confusing.  https://en.wikipedia.org/wiki/Double_negative explains it, I 
think -- in some languages and dialects multiple negatives increase 
negativity instead of cancelling themselves out pairwise.  So users 
would expect to get no x with --no-x and even less of it with --no-no-x?

> Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
> ---
> I started going about implementing an OPT_NEGBOOL as suggested by Peff,
> but realized this might just be simpler, and we already support the
> positive format for the negation, so we don't lose expressiveness. We
> *might* want to tie this to an option flag instead so that it only kicks
> in if the option specifically requests it. Thoughts?

Do you mean that there should be a flag for allowing double negation? 
In which situation would it be useful?

Or do you mean that negation should be disabled by default and would 
have to be enabled explicitly, unlike the current situation where it is 
enabled by default and can be turned off with PARSE_OPT_NONEG?  That 
depends on how often we'd want to disable negation, I guess.  For 
boolean flags it probably makes sense to allow it by default.

>   parse-options.c          | 3 +++
>   t/t0040-parse-options.sh | 5 ++++-
>   2 files changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/parse-options.c b/parse-options.c
> index a23a1e67f04f..8e024c569f52 100644
> --- a/parse-options.c
> +++ b/parse-options.c
> @@ -299,6 +299,9 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
>   				}
>   				continue;
>   			}
> +			/* avoid double-negate on long_name */
> +			if (starts_with(long_name, "no-"))
> +				continue;
>   			flags |= OPT_UNSET;
>   			if (!skip_prefix(arg + 3, long_name, &rest)) {
>   				/* abbreviated and negated? */
> diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
> index 74d2cd76fe56..abccfa5f265f 100755
> --- a/t/t0040-parse-options.sh
> +++ b/t/t0040-parse-options.sh
> @@ -88,7 +88,6 @@ test_expect_success 'OPT_BOOL() is idempotent #1' 'check boolean: 1 --yes --yes'
>   test_expect_success 'OPT_BOOL() is idempotent #2' 'check boolean: 1 -DB'
>   
>   test_expect_success 'OPT_BOOL() negation #1' 'check boolean: 0 -D --no-yes'
> -test_expect_success 'OPT_BOOL() negation #2' 'check boolean: 0 -D --no-no-doubt'
>   
>   test_expect_success 'OPT_BOOL() no negation #1' 'check_unknown_i18n --fear'
>   test_expect_success 'OPT_BOOL() no negation #2' 'check_unknown_i18n --no-no-fear'
> @@ -392,4 +391,8 @@ test_expect_success '--no-verbose resets multiple verbose to 0' '
>   	test-parse-options --expect="verbose: 0" -v -v -v --no-verbose
>   '
>   
> +test_expect_success 'double negation not accepted' '
> +	test_must_fail test-parse-options --expect="boolean: 0" --no-no-doubt
> +'
> +
>   test_done

Using check_unknown_i18n like in the test for --no-no-fear would be 
shorter and more consistent.

René

```

## Jeff King, 2017-04-19 15:10

Subject: Re: [RFC PATCH] parse-options: disallow double-negations of options starting with no-
Message-ID: <20170419151005.wolvxiacjqxoqrq3@sigill.intra.peff.net>
URL: https://gitlist.dev/e/20170419151005.wolvxiacjqxoqrq3%40sigill.intra.peff.net
In-Reply-To: <20170419090820.20279-1-jacob.e.keller@intel.com>

```
On Wed, Apr 19, 2017 at 02:08:20AM -0700, Jacob Keller wrote:

> From: Jacob Keller <jacob.keller@gmail.com>
> 
> Many options can be negated by prefixing the option with "no-", for
> example "--3way" can be prefixed with "--no-3way" to disable it. Since
> 0f1930c58754 ("parse-options: allow positivation of options
> starting, with no-", 2012-02-25) we have also had support to negate
> options which start with "no-" by using the positive wording.
> 
> This leads to the confusing (and non-documented) case that you can still
> prefix options beginning with "no-" by a second "no-" to negate them.
> That is, we allow "no-no-hardlinks" to negate the "no-hardlinks" option.
> 
> This can be confusing to the user so lets just disallow the
> double-negative forms. If the long_name begins with "no-" then we simply
> don't allow the regular negation format, and only allow the option to be
> negated by the positive form.
> 
> Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
> ---
> I started going about implementing an OPT_NEGBOOL as suggested by Peff,
> but realized this might just be simpler, and we already support the
> positive format for the negation, so we don't lose expressiveness. We
> *might* want to tie this to an option flag instead so that it only kicks
> in if the option specifically requests it. Thoughts?

Yeah, if we are going to do anything, this is the right thing to do.

I am on the fence on whether it actually needs addressing or not. Sure,
--no-no-foo looks silly, but if the only way it happens is that the user
typed it, it doesn't seem so bad to me to respect it. I am tempted to
say we should support arbitrary levels of "no-" parsing as an easter
egg, but that is probably silly. :)

So I am fine with this patch, or without it.

-Peff

```

## Jacob Keller, 2017-04-19 20:54

Subject: Re: [RFC PATCH] parse-options: disallow double-negations of options starting with no-
Message-ID: <CA+P7+xqo6BJ8LXy8EVvq0JXPD4r-jZ6boOGT=2XY8SVnWfVMcQ@mail.gmail.com>
URL: https://gitlist.dev/e/CA%2BP7%2Bxqo6BJ8LXy8EVvq0JXPD4r-jZ6boOGT%3D2XY8SVnWfVMcQ%40mail.gmail.com
In-Reply-To: <20170419151005.wolvxiacjqxoqrq3@sigill.intra.peff.net>

```
On Wed, Apr 19, 2017 at 8:10 AM, Jeff King <peff@peff.net> wrote:
> On Wed, Apr 19, 2017 at 02:08:20AM -0700, Jacob Keller wrote:
>
>> From: Jacob Keller <jacob.keller@gmail.com>
>>
>> Many options can be negated by prefixing the option with "no-", for
>> example "--3way" can be prefixed with "--no-3way" to disable it. Since
>> 0f1930c58754 ("parse-options: allow positivation of options
>> starting, with no-", 2012-02-25) we have also had support to negate
>> options which start with "no-" by using the positive wording.
>>
>> This leads to the confusing (and non-documented) case that you can still
>> prefix options beginning with "no-" by a second "no-" to negate them.
>> That is, we allow "no-no-hardlinks" to negate the "no-hardlinks" option.
>>
>> This can be confusing to the user so lets just disallow the
>> double-negative forms. If the long_name begins with "no-" then we simply
>> don't allow the regular negation format, and only allow the option to be
>> negated by the positive form.
>>
>> Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
>> ---
>> I started going about implementing an OPT_NEGBOOL as suggested by Peff,
>> but realized this might just be simpler, and we already support the
>> positive format for the negation, so we don't lose expressiveness. We
>> *might* want to tie this to an option flag instead so that it only kicks
>> in if the option specifically requests it. Thoughts?
>
> Yeah, if we are going to do anything, this is the right thing to do.
>
> I am on the fence on whether it actually needs addressing or not. Sure,
> --no-no-foo looks silly, but if the only way it happens is that the user
> typed it, it doesn't seem so bad to me to respect it. I am tempted to
> say we should support arbitrary levels of "no-" parsing as an easter
> egg, but that is probably silly. :)
>
> So I am fine with this patch, or without it.
>
> -Peff

This is why it's an RFC. I don't really feel that it's too much of a
problem. As for the reason why I thought it might want a flag itself
is because of concerns raised earlier that we might have something
liek

OPT_BOOL( ... "no-stage" ...)
OPT_INT(... "stage" ....)

or something already which might be broken and the only proper way to
disable no-stage is no-no-stage?

Is this actually a concern? I thought this was a comment raised by you
earlier as an objection to a change unless we specifically flagged
them as OPT_NEGBOOL()

Thanks,
Jake

```

## Jeff King, 2017-04-19 21:00

Subject: Re: [RFC PATCH] parse-options: disallow double-negations of options starting with no-
Message-ID: <20170419210028.sky24qda7kp4pl5y@sigill.intra.peff.net>
URL: https://gitlist.dev/e/20170419210028.sky24qda7kp4pl5y%40sigill.intra.peff.net
In-Reply-To: <CA+P7+xqo6BJ8LXy8EVvq0JXPD4r-jZ6boOGT=2XY8SVnWfVMcQ@mail.gmail.com>

```
On Wed, Apr 19, 2017 at 01:54:06PM -0700, Jacob Keller wrote:

> This is why it's an RFC. I don't really feel that it's too much of a
> problem. As for the reason why I thought it might want a flag itself
> is because of concerns raised earlier that we might have something
> liek
> 
> OPT_BOOL( ... "no-stage" ...)
> OPT_INT(... "stage" ....)
> 
> or something already which might be broken and the only proper way to
> disable no-stage is no-no-stage?
> 
> Is this actually a concern? I thought this was a comment raised by you
> earlier as an objection to a change unless we specifically flagged
> them as OPT_NEGBOOL()

I think the breakage in that case would be caused by "--no-stage" taking
over "--stage" as well. And your patch doesn't change that; it happened
already in 2012.

Your patch only affects the --no-no- form, which I think we would never
want. I don't think it needs callers to trigger it explicitly.

-Peff

```

## Jacob Keller, 2017-04-19 21:22

Subject: Re: [RFC PATCH] parse-options: disallow double-negations of options starting with no-
Message-ID: <CA+P7+xpahRim9H1cHuHmzjGggYt2qbvxrDYyi+ri0QsDEUAkcw@mail.gmail.com>
URL: https://gitlist.dev/e/CA%2BP7%2BxpahRim9H1cHuHmzjGggYt2qbvxrDYyi%2Bri0QsDEUAkcw%40mail.gmail.com
In-Reply-To: <20170419210028.sky24qda7kp4pl5y@sigill.intra.peff.net>

```
On Wed, Apr 19, 2017 at 2:00 PM, Jeff King <peff@peff.net> wrote:
> On Wed, Apr 19, 2017 at 01:54:06PM -0700, Jacob Keller wrote:
>
>> This is why it's an RFC. I don't really feel that it's too much of a
>> problem. As for the reason why I thought it might want a flag itself
>> is because of concerns raised earlier that we might have something
>> liek
>>
>> OPT_BOOL( ... "no-stage" ...)
>> OPT_INT(... "stage" ....)
>>
>> or something already which might be broken and the only proper way to
>> disable no-stage is no-no-stage?
>>
>> Is this actually a concern? I thought this was a comment raised by you
>> earlier as an objection to a change unless we specifically flagged
>> them as OPT_NEGBOOL()
>
> I think the breakage in that case would be caused by "--no-stage" taking
> over "--stage" as well. And your patch doesn't change that; it happened
> already in 2012.
>
> Your patch only affects the --no-no- form, which I think we would never
> want. I don't think it needs callers to trigger it explicitly.
>
> -Peff

Right, I was just thinking in the weird cause were we *do* have a
"no-option" that does want the "no-no-option" to negate it. Maybe this
isn't ever a thing and we don't need to worry at all..?

Thanks,
Jake

```

## Jacob Keller, 2017-04-19 21:23

Subject: Re: [RFC PATCH] parse-options: disallow double-negations of options starting with no-
Message-ID: <CA+P7+xoMMPHwkaDiZWjD5gCoKh4iWGaVQ+206i8kS9aFM5zcEg@mail.gmail.com>
URL: https://gitlist.dev/e/CA%2BP7%2BxoMMPHwkaDiZWjD5gCoKh4iWGaVQ%2B206i8kS9aFM5zcEg%40mail.gmail.com
In-Reply-To: <CA+P7+xpahRim9H1cHuHmzjGggYt2qbvxrDYyi+ri0QsDEUAkcw@mail.gmail.com>

```
On Wed, Apr 19, 2017 at 2:22 PM, Jacob Keller <jacob.keller@gmail.com> wrote:
> On Wed, Apr 19, 2017 at 2:00 PM, Jeff King <peff@peff.net> wrote:
>> On Wed, Apr 19, 2017 at 01:54:06PM -0700, Jacob Keller wrote:
>>
>>> This is why it's an RFC. I don't really feel that it's too much of a
>>> problem. As for the reason why I thought it might want a flag itself
>>> is because of concerns raised earlier that we might have something
>>> liek
>>>
>>> OPT_BOOL( ... "no-stage" ...)
>>> OPT_INT(... "stage" ....)
>>>
>>> or something already which might be broken and the only proper way to
>>> disable no-stage is no-no-stage?
>>>
>>> Is this actually a concern? I thought this was a comment raised by you
>>> earlier as an objection to a change unless we specifically flagged
>>> them as OPT_NEGBOOL()
>>
>> I think the breakage in that case would be caused by "--no-stage" taking
>> over "--stage" as well. And your patch doesn't change that; it happened
>> already in 2012.
>>
>> Your patch only affects the --no-no- form, which I think we would never
>> want. I don't think it needs callers to trigger it explicitly.
>>
>> -Peff
>
> Right, I was just thinking in the weird cause were we *do* have a
> "no-option" that does want the "no-no-option" to negate it. Maybe this
> isn't ever a thing and we don't need to worry at all..?
>
> Thanks,
> Jake

And in this case the same PARSE_OPT_FLAG would be used to also not do
the "no-option" negates to "option" as well, since the options point
would be something liek "this option starts with no- but negates
normally even though we don't normally allow that"

```

## Jeff King, 2017-04-19 21:24

Subject: Re: [RFC PATCH] parse-options: disallow double-negations of options starting with no-
Message-ID: <20170419212423.i6jnu3q2npnbq2gz@sigill.intra.peff.net>
URL: https://gitlist.dev/e/20170419212423.i6jnu3q2npnbq2gz%40sigill.intra.peff.net
In-Reply-To: <CA+P7+xpahRim9H1cHuHmzjGggYt2qbvxrDYyi+ri0QsDEUAkcw@mail.gmail.com>

```
On Wed, Apr 19, 2017 at 02:22:47PM -0700, Jacob Keller wrote:

> > I think the breakage in that case would be caused by "--no-stage" taking
> > over "--stage" as well. And your patch doesn't change that; it happened
> > already in 2012.
> >
> > Your patch only affects the --no-no- form, which I think we would never
> > want. I don't think it needs callers to trigger it explicitly.
> 
> Right, I was just thinking in the weird cause were we *do* have a
> "no-option" that does want the "no-no-option" to negate it. Maybe this
> isn't ever a thing and we don't need to worry at all..?

Yeah, my assumption is that we don't need to worry about that case.

-Peff

```
