-
Notifications
You must be signed in to change notification settings - Fork 38.6k
Track negated options in the option parser #12713
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Looks good, thanks for splitting it out. utACK 6ad2a13 |
|
utACK 6ad2a13cfdd46899c28f21899e107ee7d4c07877 (Also noting that |
|
Yeah I didn't want to add support for strings like "no" "disabled" etc. because I don't think there was ever an intention to support non-integer parameters in the first place. If we wanted to support that it's easy enough. You can also use |
|
utACK 6ad2a13 |
|
ACK 6ad2a13cfdd46899c28f21899e107ee7d4c07877. |
src/util.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not throw an error if it's a stupid value? IMHO, for instance, -txindex=foo should fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking more about this, with proper argument validation we might as well reject false as a value for a boolean argument. This was never supported, so it feels weird to special case it now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@promag Two reasons. First, such a change would not be backwards compatible (a minor point, see below). A better reason is that it enables the -printtoconsole change to have a way of disabling the debug log file without actually adding new command line arguments. In other words, I first test if -debuglogfile boolean parses as "false" (i.e. -nodebuglogfile or -debuglogfile=0), and if it's not false I re-parse it as a string. There are already a lot of possible flags to give Bitcoin, and if we can re-use existing functionality without adding new flags that seems better to me.
@MarcoFalke I actually agree, as accepting false opens the door for disabled, untrue, nil, void, zip, null, non, nein, ad infinitum.
My preferred semantics would be: -nofoo sets foo to false. Also -foo=0 sets foo to false. Which is exactly what the intention of the existing code seems to be. I only handled the false flag as there is existing code committed in the Bitcoin repository that relies on it.
I started this endeavor just wanting to get bitcoind printing to stdout when run in interactive mode. Whatever semantics allow that to happen are fine with me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I first test if -debuglogfile boolean parses as "false" (i.e. -nodebuglogfile or -debuglogfile=0), and if it's not false I re-parse it as a string.
Feel free to discount this opinion, but if the option is -debuglogfile=<filename>, I would hope that -debuglogfile=0 or -debuglogfile=false would just create log debug log files 0 or false respectively, instead of disabling logging.
Like João and Marco, I would also want ambiguous values passed as boolean options to trigger errors.
I guess I'm not so much a fan of option parsing trying to be very clever.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to what @ryanofsky says; if backwards-compatability is not a constraint, doing the least clever thing seems most consistent and likely to lead to the most maintainable code, and long term least confusion for users.
(This PR seems like an improvement in readability of the argument parsing code, so any further simplification might be for another changeset.)
6ad2a13 to
e944ec9
Compare
|
utACK e944ec998fbd232b05ec9471ae6f19d1d32e0719 Would you mind updating the OP, which ends up in the merge commit? |
This is a change in behaviour. If I take the changes to the unit test, but not the changes to util.cpp, the unit tests fail. If I take the changes to util.cpp, but not the change to wallet_resendwallettransactions.py, then wallet_resendwallettransactions.py fails. EDIT: the reason for this is that atoi reference: http://www.cplusplus.com/reference/cstdlib/atoi/ . The first non-whitespace character in false is not a digit, so atoi("false') = 0 |
|
These are all easy to implement. I can make I'm not really sure what to do, as this has gotten an unusual amount of debate for something that is frankly quite banal. I got three different suggestions for how to disable the flag in the original PR:
If there is not consensus on whether we should change this I will just drop this change altogether and add a brand new flag in the original PR (-disablelogfile). |
From my reading of the feedback, I think if you go with |
|
ACK e944ec9. This behavior as well as code seems slightly simpler than before, with more I'll note we accept some pretty wacky combinations even after this change though, |
|
@ryanofsky I will put up another version of this diff with that change. |
e944ec9 to
b6597eb
Compare
|
Handle arguments like This change keeps track of whether an option was passed with the if (gArgs.IsArgInverted("-debuglogfile")) {
....
}to see if the debug log file should be disabled. I also removed some gratuitous boost and string copies. @jnewbery @MarcoFalke You guys figure out how you want the |
ff3f2c3 to
8ef4c69
Compare
|
Updated for more consistent naming -- instead of "negated" and "inverted" I now always use the negated terminology. |
8ef4c69 to
6b95d6b
Compare
maflcko
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re-utACK 6b95d6b (Changes were to get rid of some boost usage and expose IsArgNegated, which I slightly object to)
| * @param strArg Argument to get (e.g. "-foo") | ||
| * @return true if the argument was passed negated | ||
| */ | ||
| bool IsArgNegated(const std::string& strArg) const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should expose this in the code base. Historically, -nofoo always implied -foo=0, so use cases within the code base should always compare with the string "0" to check if foo was unset.
Yes, I know that that would forbid use cases, such as -myfile=0, but imo that is acceptable and desirable to keep previous behavior.
Edit: This is bike shedding, so feel free to ignore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Historically, -nofoo always implied -foo=0, so use cases within the code base should always compare with the string "0" to check if foo was unset.
This is true for boolean options, and should still be true with this PR. I don't think it was ever historically true that specifying "0" or "false" for path type options would disable those options. At least this isn't the case currently for -conf -debuglogfile -pid -rpccookiefile -wallet or other path options. So whether or not special path strings are a good idea (I think they are a bad idea), I don't think there is a historic argument for having them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to raise the point that we specifically check for the string "0" in some non-bool arguments to see if they are disabled. E.g. -connect=0 or -debug=0. So in case someone were to use IsArgNegated for those, it would break it.
Again, only bike-shedding here, so please ignore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @ryanofsky that not being able to create a log file named "0" (or "false") is weird. Tracking negation makes the arguments more strongly typed in a sense. I also felt like it made my printtoconsole change a little easier to understand, because it removes the code that calls GetBoolArg() on a non-boolean field.
|
Concept ACK the behaviour change. Making only the exact string "0" evaluate to false seems like better behaviour to me. Tested ACK the negated argument change. ACK the variable name changes. Tested ACK the WIN32 boost::algorithm -> std::transform change on linux (by commenting out the #ifdef WIN32 in This needs release notes since it's a subtle change to the way that arguments are parsed. |
ryanofsky
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK 6b95d6b.
It seems to me though that this is doing two different things that don't need to be tied to together:
- Introducing a nice
IsArgNegatedAPI that provides a consistent way of disabling non-bool options, especially features that read or write to files. - Interpreting
-foo=barand similar strings as false instead of true.
Second change seems fine, but IMO would probably be better off in a separate PR. It could also be tweaked to accept more false strings, and should definitely be documented.
src/util.cpp
Outdated
| if (strValue.empty()) | ||
| return true; | ||
| return (atoi(strValue) != 0); | ||
| return val != "0"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think would be a little better to not change InterpretBool here. This seems making a backwards incompatible change in a PR that would otherwise be backwards compatible. If there is actually a reason to make a change here, it would be good to document it. I think the following table might summarize:
| Argument | Previous | Current |
|---|---|---|
-foo |
true | true |
-foo= |
true | true |
-foo=1 |
true | true |
-foo=0 |
false | false |
-foo=-0 |
false | true |
-foo=+0 |
false | true |
-foo=00 |
false | true |
-foo=bar |
false | true |
-foo=0bar |
false | true |
-foo=1bar |
true | true |
Also, if you want to change this function here, I don't think there is any downside to treating strings like false and no as false, since GetBoolArg() should only be called on bool options, not path options.
| } | ||
| key.erase(1, 2); | ||
| m_negated_args.insert(key); | ||
| val = bool_val ? "0" : "1"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of munging the string value, it seems like it would be slightly better just to avoid inserting new entries into the arg maps when bool_val is true. But this would require updating Get*Arg functions to check the m_negated_args map in addition to the normal maps, so I understand why you didn't do this here. And it's pretty much an internal implementation detail, so it could be saved for a future improvement.
| BOOST_CHECK(testArgs.GetArgs("-ccc").size() == 2); | ||
| } | ||
|
|
||
| BOOST_AUTO_TEST_CASE(util_GetBoolArg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great tests!
|
Re-ACK 6b95d6b. +1 on documenting the change in behavior for flags in release notes. |
PR bitcoin#12713 changed the interpretation for negation of non-boolean options (e.g. -noconnect) to no longer set the option to 0, but to remove it from the options. I think this is better because it gets rid of the special meaning of '0'. However it needs to be documented. I attempt to do so in this PR. Addreses bitcoin#14064.
… options e9a78e9 doc: Change documentation for =0 for non-boolean options (Wladimir J. van der Laan) Pull request description: PR bitcoin#12713 changed the interpretation for negation of non-boolean options (e.g. -noconnect) to no longer set the option to `0`, but to remove it from the options. I think this is better because it gets rid of the special meaning of `'0'`. However it needs to be documented. I attempt to do so in this PR. Addresses bitcoin#14064. There might be options I missed, please help check: - `-connect` - `-proxy` - `-onion` - `-debug` - `-debuglogfile` Needs a manpage update. Tree-SHA512: a69e63e04a6c8bf6f61a58ddc0f5ebd4b9af7a2e0ea5174e668f2e3edd31a541910a125605ca4bfccf3aca6e59267d98a66de9d1e73650f48c8a1828d315d35d
PR bitcoin#12713 changed the interpretation for negation of non-boolean options (e.g. -noconnect) to no longer set the option to 0, but to remove it from the options. I think this is better because it gets rid of the special meaning of '0'. However it needs to be documented. I attempt to do so in this PR. Addreses bitcoin#14064. Github-Pull: bitcoin#14100 Rebased-From: e9a78e9
PR bitcoin#12713 changed the interpretation for negation of non-boolean options (e.g. -noconnect) to no longer set the option to 0, but to remove it from the options. I think this is better because it gets rid of the special meaning of '0'. However it needs to be documented. I attempt to do so in this PR. Addreses bitcoin#14064. Github-Pull: bitcoin#14100 Rebased-From: e9a78e9
PR bitcoin#12713 changed the interpretation for negation of non-boolean options (e.g. -noconnect) to no longer set the option to 0, but to remove it from the options. I think this is better because it gets rid of the special meaning of '0'. However it needs to be documented. I attempt to do so in this PR. Addreses bitcoin#14064. Github-Pull: bitcoin#14100 Rebased-From: e9a78e9
PR bitcoin#12713 changed the interpretation for negation of non-boolean options (e.g. -noconnect) to no longer set the option to 0, but to remove it from the options. I think this is better because it gets rid of the special meaning of '0'. However it needs to be documented. I attempt to do so in this PR. Addreses bitcoin#14064.
PR bitcoin#12713 changed the interpretation for negation of non-boolean options (e.g. -noconnect) to no longer set the option to 0, but to remove it from the options. I think this is better because it gets rid of the special meaning of '0'. However it needs to be documented. I attempt to do so in this PR. Addreses bitcoin#14064.
f7683cb Track negated arguments in the argument paser. (Evan Klitzke) 4f872b2 Add additional tests for GetBoolArg() (Evan Klitzke) Pull request description: This change explicitly enable tracking negated options in the option parser. A negated option is one passed with a `-no` prefix. For example, `-nofoo` is the negated form of `-foo`. Negated options were originally added in the 0.6 release. The change here allows code to explicitly distinguish between cases like `-nofoo` and `-foo=0`, which was not possible previously. The option parser does not have any changed semantics as a result of this change, and existing code will parse options just as it did before. The motivation for this change is to provide a way to disable options that are otherwise not boolean options. For example, the `-debuglogfile` option is normally interpreted as a string, where the value is the log file name. With this change a user can pass in `-nodebuglogfile` and the code can see that it was explicitly negated, and use that to disable the log file. This change originally split out from bitcoin#12689. Tree-SHA512: cd5a7354eb03d2d402863c7b69e512cad382781d9b8f18c1ab104fc46d45a712530818d665203082da39572c8a42313c5be09306dc2a7227cdedb20ef7314823
4709ff8 remove now unused gArgs wrappers (Fuzzbawls) cc40f8d Manual prep for gArg wrapper removal (Fuzzbawls) b3c843c scripted-diff: stop using the gArgs wrappers (Fuzzbawls) 5ce3844 Migrate g_logger fields to gArgs (Fuzzbawls) 72a6f56 Track negated arguments in the argument paser. (Fuzzbawls) 3142e1b Add additional tests for GetBoolArg() (Fuzzbawls) 4aef2f3 Fix constness of ArgsManager methods (Fuzzbawls) 13fd27d Fix indentation after 'Remove redundant calls to gArgs.IsArgSet()' (Fuzzbawls) a4114f3 Util: Remove redundant calls to gArgs.IsArgSet() (Fuzzbawls) 92e7227 Util: Small improvements in gArgs usage (Fuzzbawls) a8b26e7 Util: Put mapMultiArgs inside ArgsManager (Fuzzbawls) d2f2e25 scripted-diff: Util: Encapsulate mapMultiArgs behind gArgs (Fuzzbawls) b2abc59 Util: Create ArgsManager class... (Fuzzbawls) 8c4d9c5 Add a ForceSetArg method for testing (Fuzzbawls) 59d6529 Lock mapArgs/mapMultiArgs access in util (Fuzzbawls) f7f2689 Un-expose mapArgs from util.h (Fuzzbawls) 7894b07 Get rid of mapArgs direct access in ZMQ construction (Matt Corallo) b28789f Introduce (and use) an IsArgSet accessor method (Fuzzbawls) 4d8ecf9 Fix non-const mapMultiArgs[] access after init. (Fuzzbawls) 391388d Remove arguments to ReadConfigFile (Fuzzbawls) Pull request description: This is a cumulation of several upstream backports surrounding the argument parsing code. Included here are the following upstream PRs: - bitcoin#9243 - bitcoin#9494 - bitcoin#10118 - bitcoin#10901 - bitcoin#12713 - bitcoin#10607 I've also refactored the global logging argument parsing to match, as that was an "out-of-order" PR that was previously backported to match our previous state. ACKs for top commit: random-zebra: utACK 4709ff8 furszy: cool encapsulation, utACK 4709ff8 and merging Tree-SHA512: 74c8dc1b2280b726eff44855e9908f3563d4ef6493f296ebfafe240ac6470bc45cbc75baac614ed59dfda9e1377b7da7d47a695dfc05e364cada2468bb99a258
f7683cb Track negated arguments in the argument paser. (Evan Klitzke) 4f872b2 Add additional tests for GetBoolArg() (Evan Klitzke) Pull request description: This change explicitly enable tracking negated options in the option parser. A negated option is one passed with a `-no` prefix. For example, `-nofoo` is the negated form of `-foo`. Negated options were originally added in the 0.6 release. The change here allows code to explicitly distinguish between cases like `-nofoo` and `-foo=0`, which was not possible previously. The option parser does not have any changed semantics as a result of this change, and existing code will parse options just as it did before. The motivation for this change is to provide a way to disable options that are otherwise not boolean options. For example, the `-debuglogfile` option is normally interpreted as a string, where the value is the log file name. With this change a user can pass in `-nodebuglogfile` and the code can see that it was explicitly negated, and use that to disable the log file. This change originally split out from bitcoin#12689. Tree-SHA512: cd5a7354eb03d2d402863c7b69e512cad382781d9b8f18c1ab104fc46d45a712530818d665203082da39572c8a42313c5be09306dc2a7227cdedb20ef7314823
… options e9a78e9 doc: Change documentation for =0 for non-boolean options (Wladimir J. van der Laan) Pull request description: PR bitcoin#12713 changed the interpretation for negation of non-boolean options (e.g. -noconnect) to no longer set the option to `0`, but to remove it from the options. I think this is better because it gets rid of the special meaning of `'0'`. However it needs to be documented. I attempt to do so in this PR. Addresses bitcoin#14064. There might be options I missed, please help check: - `-connect` - `-proxy` - `-onion` - `-debug` - `-debuglogfile` Needs a manpage update. Tree-SHA512: a69e63e04a6c8bf6f61a58ddc0f5ebd4b9af7a2e0ea5174e668f2e3edd31a541910a125605ca4bfccf3aca6e59267d98a66de9d1e73650f48c8a1828d315d35d # Conflicts: # src/init.cpp
… options e9a78e9 doc: Change documentation for =0 for non-boolean options (Wladimir J. van der Laan) Pull request description: PR bitcoin#12713 changed the interpretation for negation of non-boolean options (e.g. -noconnect) to no longer set the option to `0`, but to remove it from the options. I think this is better because it gets rid of the special meaning of `'0'`. However it needs to be documented. I attempt to do so in this PR. Addresses bitcoin#14064. There might be options I missed, please help check: - `-connect` - `-proxy` - `-onion` - `-debug` - `-debuglogfile` Needs a manpage update. Tree-SHA512: a69e63e04a6c8bf6f61a58ddc0f5ebd4b9af7a2e0ea5174e668f2e3edd31a541910a125605ca4bfccf3aca6e59267d98a66de9d1e73650f48c8a1828d315d35d # Conflicts: # src/init.cpp
This change explicitly enable tracking negated options in the option parser. A negated option is one passed with a
-noprefix. For example,-nofoois the negated form of-foo. Negated options were originally added in the 0.6 release.The change here allows code to explicitly distinguish between cases like
-nofooand-foo=0, which was not possible previously. The option parser does not have any changed semantics as a result of this change, and existing code will parse options just as it did before.The motivation for this change is to provide a way to disable options that are otherwise not boolean options. For example, the
-debuglogfileoption is normally interpreted as a string, where the value is the log file name. With this change a user can pass in-nodebuglogfileand the code can see that it was explicitly negated, and use that to disable the log file.This change originally split out from #12689.