threads / rfc / 45742

RFC patchparse-options: disallow double-negations of options starting with no-

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

## tl;dr

9 messages between Apr 19, 2017 and Apr 19, 2017. Diffs are folded; open one to read it.

replies: 8people: 5as markdown or json

Jacob Keller· Apr 19, 2017, 09:08 UTC · lore
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(-)
Show changes to 2 files +7 −1

parse-options.c, t/t0040-parse-options.sh

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· Apr 19, 2017, 09:34 UTC · re: Jacob Keller · lore

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

On Wed, Apr 19, 2017 at 11:08 AM, Jacob Keller <jacob.e.keller@intel.com> wrote:
Show 14 quoted lines
> 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· Apr 19, 2017, 12:58 UTC · re: Jacob Keller · lore

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

Am 19.04.2017 um 11:08 schrieb Jacob Keller:
Show 16 quoted lines
> 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?

Show 7 quoted lines
> 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.

Show 39 quoted lines
>   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· Apr 19, 2017, 15:10 UTC · re: Jacob Keller · lore

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

On Wed, Apr 19, 2017 at 02:08:20AM -0700, Jacob Keller wrote:
Show 24 quoted lines
> 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· Apr 19, 2017, 20:54 UTC · re: Jeff King · lore

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

On Wed, Apr 19, 2017 at 8:10 AM, Jeff King <peff@peff.net> wrote:
Show 38 quoted lines
> 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· Apr 19, 2017, 21:00 UTC · re: Jacob Keller · lore

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

On Wed, Apr 19, 2017 at 01:54:06PM -0700, Jacob Keller wrote:
Show 14 quoted lines
> 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· Apr 19, 2017, 21:22 UTC · re: Jeff King · lore

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

On Wed, Apr 19, 2017 at 2:00 PM, Jeff King <peff@peff.net> wrote:
Show 25 quoted lines
> 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· Apr 19, 2017, 21:23 UTC · re: Jacob Keller · lore

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

On Wed, Apr 19, 2017 at 2:22 PM, Jacob Keller <jacob.keller@gmail.com> wrote:
Show 33 quoted lines
> 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· Apr 19, 2017, 21:24 UTC · re: Jacob Keller · lore

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

On Wed, Apr 19, 2017 at 02:22:47PM -0700, Jacob Keller wrote:
Show 10 quoted lines
> > 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

← back to recent threads