mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-17 13:07:54 +02:00
Merge 3a3d8b8357 into merged_master (Bitcoin PR #16097)
This commit is contained in:
commit
9c3480fea9
13 changed files with 401 additions and 349 deletions
|
|
@ -274,22 +274,24 @@ public:
|
|||
* This method also tracks when the -no form was supplied, and if so,
|
||||
* checks whether there was a double-negative (-nofoo=0 -> -foo=1).
|
||||
*
|
||||
* If there was not a double negative, it removes the "no" from the key,
|
||||
* and returns true, indicating the caller should clear the args vector
|
||||
* to indicate a negated option.
|
||||
* If there was not a double negative, it removes the "no" from the key
|
||||
* and clears the args vector to indicate a negated option.
|
||||
*
|
||||
* If there was a double negative, it removes "no" from the key, sets the
|
||||
* value to "1" and returns false.
|
||||
* value to "1" and pushes the key and the updated value to the args vector.
|
||||
*
|
||||
* If there was no "no", it leaves key and value untouched and returns
|
||||
* false.
|
||||
* If there was no "no", it leaves key and value untouched and pushes them
|
||||
* to the args vector.
|
||||
*
|
||||
* Where an option was negated can be later checked using the
|
||||
* IsArgNegated() method. One use case for this is to have a way to disable
|
||||
* options that are not normally boolean (e.g. using -nodebuglogfile to request
|
||||
* that debug log output is not sent to any file at all).
|
||||
*/
|
||||
static bool InterpretNegatedOption(std::string& key, std::string& val)
|
||||
|
||||
NODISCARD static bool InterpretOption(std::string key, std::string val, unsigned int flags,
|
||||
std::map<std::string, std::vector<std::string>>& args,
|
||||
std::string& error)
|
||||
{
|
||||
assert(key[0] == '-');
|
||||
|
||||
|
|
@ -300,31 +302,25 @@ static bool InterpretNegatedOption(std::string& key, std::string& val)
|
|||
++option_index;
|
||||
}
|
||||
if (key.substr(option_index, 2) == "no") {
|
||||
bool bool_val = InterpretBool(val);
|
||||
key.erase(option_index, 2);
|
||||
if (!bool_val ) {
|
||||
if (flags & ArgsManager::ALLOW_BOOL) {
|
||||
if (InterpretBool(val)) {
|
||||
args[key].clear();
|
||||
return true;
|
||||
}
|
||||
// Double negatives like -nofoo=0 are supported (but discouraged)
|
||||
LogPrintf("Warning: parsed potentially confusing double-negative %s=%s\n", key, val);
|
||||
val = "1";
|
||||
} else {
|
||||
return true;
|
||||
error = strprintf("Negating of %s is meaningless and therefore forbidden", key.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
args[key].push_back(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
ArgsManager::ArgsManager() :
|
||||
/* These options would cause cross-contamination if values for
|
||||
* mainnet were used while running on regtest/testnet (or vice-versa).
|
||||
* Setting them as section_only_args ensures that sharing a config file
|
||||
* between mainnet and regtest/testnet won't cause problems due to these
|
||||
* parameters by accident. */
|
||||
m_network_only_args{
|
||||
"-addnode", "-connect",
|
||||
"-port", "-bind",
|
||||
"-rpcport", "-rpcbind",
|
||||
"-wallet",
|
||||
}
|
||||
ArgsManager::ArgsManager()
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
|
@ -390,6 +386,7 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin
|
|||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
std::string key(argv[i]);
|
||||
if (key == "-") break; //bitcoin-tx using stdin
|
||||
std::string val;
|
||||
size_t is_index = key.find('=');
|
||||
if (is_index != std::string::npos) {
|
||||
|
|
@ -409,19 +406,14 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin
|
|||
if (key.length() > 1 && key[1] == '-')
|
||||
key.erase(0, 1);
|
||||
|
||||
// Check for -nofoo
|
||||
if (InterpretNegatedOption(key, val)) {
|
||||
m_override_args[key].clear();
|
||||
} else {
|
||||
m_override_args[key].push_back(val);
|
||||
}
|
||||
|
||||
// Check that the arg is known
|
||||
if (!(IsSwitchChar(key[0]) && key.size() == 1)) {
|
||||
if (!IsArgKnown(key)) {
|
||||
error = strprintf("Invalid parameter %s", key.c_str());
|
||||
const unsigned int flags = FlagsOfKnownArg(key);
|
||||
if (flags) {
|
||||
if (!InterpretOption(key, val, flags, m_override_args, error)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
error = strprintf("Invalid parameter %s", key.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -438,21 +430,30 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ArgsManager::IsArgKnown(const std::string& key) const
|
||||
unsigned int ArgsManager::FlagsOfKnownArg(const std::string& key) const
|
||||
{
|
||||
assert(key[0] == '-');
|
||||
|
||||
size_t option_index = key.find('.');
|
||||
std::string arg_no_net;
|
||||
if (option_index == std::string::npos) {
|
||||
arg_no_net = key;
|
||||
option_index = 1;
|
||||
} else {
|
||||
arg_no_net = std::string("-") + key.substr(option_index + 1, std::string::npos);
|
||||
++option_index;
|
||||
}
|
||||
if (key.substr(option_index, 2) == "no") {
|
||||
option_index += 2;
|
||||
}
|
||||
|
||||
const std::string base_arg_name = '-' + key.substr(option_index);
|
||||
|
||||
LOCK(cs_args);
|
||||
for (const auto& arg_map : m_available_args) {
|
||||
if (arg_map.second.count(arg_no_net)) return true;
|
||||
const auto search = arg_map.second.find(base_arg_name);
|
||||
if (search != arg_map.second.end()) {
|
||||
return search->second.m_flags;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return ArgsManager::NONE;
|
||||
}
|
||||
|
||||
std::vector<std::string> ArgsManager::GetArgs(const std::string& strArg) const
|
||||
|
|
@ -544,24 +545,29 @@ void ArgsManager::ForceSetArg(const std::string& strArg, const std::string& strV
|
|||
m_override_args[strArg] = {strValue};
|
||||
}
|
||||
|
||||
void ArgsManager::AddArg(const std::string& name, const std::string& help, const bool debug_only, const OptionsCategory& cat)
|
||||
void ArgsManager::AddArg(const std::string& name, const std::string& help, unsigned int flags, const OptionsCategory& cat)
|
||||
{
|
||||
// Split arg name from its help param
|
||||
size_t eq_index = name.find('=');
|
||||
if (eq_index == std::string::npos) {
|
||||
eq_index = name.size();
|
||||
}
|
||||
std::string arg_name = name.substr(0, eq_index);
|
||||
|
||||
LOCK(cs_args);
|
||||
std::map<std::string, Arg>& arg_map = m_available_args[cat];
|
||||
auto ret = arg_map.emplace(name.substr(0, eq_index), Arg(name.substr(eq_index, name.size() - eq_index), help, debug_only));
|
||||
auto ret = arg_map.emplace(arg_name, Arg{name.substr(eq_index, name.size() - eq_index), help, flags});
|
||||
assert(ret.second); // Make sure an insertion actually happened
|
||||
|
||||
if (flags & ArgsManager::NETWORK_ONLY) {
|
||||
m_network_only_args.emplace(arg_name);
|
||||
}
|
||||
}
|
||||
|
||||
void ArgsManager::AddHiddenArgs(const std::vector<std::string>& names)
|
||||
{
|
||||
for (const std::string& name : names) {
|
||||
AddArg(name, "", false, OptionsCategory::HIDDEN);
|
||||
AddArg(name, "", ArgsManager::ALLOW_ANY, OptionsCategory::HIDDEN);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -623,7 +629,7 @@ std::string ArgsManager::GetHelpMessage() const
|
|||
if (arg_map.first == OptionsCategory::HIDDEN) break;
|
||||
|
||||
for (const auto& arg : arg_map.second) {
|
||||
if (show_debug || !arg.second.m_debug_only) {
|
||||
if (show_debug || !(arg.second.m_flags & ArgsManager::DEBUG_ONLY)) {
|
||||
std::string name;
|
||||
if (arg.second.m_help_param.empty()) {
|
||||
name = arg.first;
|
||||
|
|
@ -644,7 +650,7 @@ bool HelpRequested(const ArgsManager& args)
|
|||
|
||||
void SetupHelpOptions(ArgsManager& args)
|
||||
{
|
||||
args.AddArg("-?", "Print this help message and exit", false, OptionsCategory::OPTIONS);
|
||||
args.AddArg("-?", "Print this help message and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
||||
args.AddHiddenArgs({"-h", "-help"});
|
||||
}
|
||||
|
||||
|
|
@ -876,22 +882,18 @@ bool ArgsManager::ReadConfigStream(std::istream& stream, const std::string& file
|
|||
return false;
|
||||
}
|
||||
for (const std::pair<std::string, std::string>& option : options) {
|
||||
std::string strKey = std::string("-") + option.first;
|
||||
std::string strValue = option.second;
|
||||
|
||||
if (InterpretNegatedOption(strKey, strValue)) {
|
||||
m_config_args[strKey].clear();
|
||||
const std::string strKey = std::string("-") + option.first;
|
||||
const unsigned int flags = FlagsOfKnownArg(strKey);
|
||||
if (flags) {
|
||||
if (!InterpretOption(strKey, option.second, flags, m_config_args, error)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
m_config_args[strKey].push_back(strValue);
|
||||
}
|
||||
|
||||
// Check that the arg is known
|
||||
if (!IsArgKnown(strKey)) {
|
||||
if (!ignore_invalid_keys) {
|
||||
if (ignore_invalid_keys) {
|
||||
LogPrintf("Ignoring unknown configuration value %s\n", option.first);
|
||||
} else {
|
||||
error = strprintf("Invalid configuration value %s", option.first.c_str());
|
||||
return false;
|
||||
} else {
|
||||
LogPrintf("Ignoring unknown configuration value %s\n", option.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue