mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-06 11:13:02 +02:00
ArgsManager: automate checking for correct command options
This commit is contained in:
@@ -387,6 +387,40 @@ std::optional<const ArgsManager::Command> ArgsManager::GetCommand() const
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ArgsManager::CheckCommandOptions(const std::string& command, std::vector<std::string>* errors) const
|
||||
{
|
||||
LOCK(cs_args);
|
||||
|
||||
auto command_options = m_available_args.find(OptionsCategory::COMMAND_OPTIONS);
|
||||
if (command_options == m_available_args.end()) {
|
||||
// There are no command-specific options at all, so everything is fine
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto command_args = m_command_args.find(command);
|
||||
auto is_valid_opt = [&](const auto& opt) EXCLUSIVE_LOCKS_REQUIRED(cs_args) -> bool {
|
||||
if (command_args == m_command_args.end()) {
|
||||
// Caller may not have checked that command actually exists
|
||||
// before calling this function. In that case, treat it as
|
||||
// having no valid command-specific options.
|
||||
return false;
|
||||
} else {
|
||||
return command_args->second.contains(opt);
|
||||
}
|
||||
};
|
||||
|
||||
bool ok = true;
|
||||
for (const auto& [arg, _] : command_options->second) {
|
||||
if (!GetSetting_(arg).isNull() && !is_valid_opt(arg)) {
|
||||
ok = false;
|
||||
if (errors != nullptr) {
|
||||
errors->emplace_back(strprintf("The %s option cannot be used with the '%s' command.", arg, command));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
std::vector<std::string> ArgsManager::GetArgs(const std::string& strArg) const
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
|
||||
@@ -225,6 +225,16 @@ public:
|
||||
*/
|
||||
std::optional<const Command> GetCommand() const EXCLUSIVE_LOCKS_REQUIRED(!cs_args);
|
||||
|
||||
/**
|
||||
* Check that any command-specific options the user specified are valid
|
||||
* for the given command.
|
||||
*
|
||||
* @param[in] command The command being run.
|
||||
* @param[out] errors If non-null, populated with a message for each invalid option.
|
||||
* @return false if any command-specific options were specified that are not valid for this command
|
||||
*/
|
||||
bool CheckCommandOptions(const std::string& command, std::vector<std::string>* errors = nullptr) const EXCLUSIVE_LOCKS_REQUIRED(!cs_args);
|
||||
|
||||
/**
|
||||
* Get blocks directory path
|
||||
*
|
||||
|
||||
@@ -93,9 +93,12 @@ static void WalletShowInfo(CWallet* wallet_instance)
|
||||
|
||||
bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command)
|
||||
{
|
||||
if (args.IsArgSet("-dumpfile") && command != "dump" && command != "createfromdump") {
|
||||
tfm::format(std::cerr, "The -dumpfile option can only be used with the \"dump\" and \"createfromdump\" commands.\n");
|
||||
return false;
|
||||
{
|
||||
std::vector<std::string> details;
|
||||
if (!args.CheckCommandOptions(command, &details)) {
|
||||
tfm::format(std::cerr, "Error: Invalid arguments provided:\n%s\n", util::MakeUnorderedList(details));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ((command == "create" || command == "createfromdump") && !args.IsArgSet("-wallet")) {
|
||||
tfm::format(std::cerr, "Wallet name must be provided when creating a new wallet.\n");
|
||||
|
||||
@@ -421,6 +421,7 @@ class ToolWalletTest(BitcoinTestFramework):
|
||||
assert not (self.nodes[0].wallets_path / "legacy").exists()
|
||||
self.assert_raises_tool_error("Invalid parameter -descriptors", "-wallet=legacy", "-descriptors=false", "create")
|
||||
assert not (self.nodes[0].wallets_path / "legacy").exists()
|
||||
self.assert_raises_tool_error("The -dumpfile option cannot be used with the 'create' command.", "-wallet=legacy", "-dumpfile=wallet.dump", "create")
|
||||
|
||||
def test_no_create_unnamed(self):
|
||||
self.log.info("Test that unnamed (default) wallets cannot be created")
|
||||
|
||||
Reference in New Issue
Block a user