1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-14 10:13:05 +02:00

Remove cfgOptionId() and replace it with cfgParseOption().

cfgOptionId() did not recognize deprecated options which made the help command throw errors when they were specified on the command line. cfgParseOption() will correctly identify deprecated options.

cfgParseOption() can also be used in cfgParse() to reduce code duplication when parsing info out of the option value returned by optionFind().

Finally, code the option key index separately in parse.auto.c. For now they are simply added back together but future code will need them separated.
This commit is contained in:
David Steele 2020-10-20 11:24:26 -04:00
parent 6414ae9707
commit 41789d70d1
11 changed files with 578 additions and 547 deletions

View File

@ -143,7 +143,7 @@ sub buildConfigParse
}
my $strOptionVal =
($iOptionIdx > 1 ? "(" : '') . $strOptionEnum . ($iOptionIdx > 1 ? " + " . ($iOptionIdx - 1) . ')' : '');
($rhOption->{&CFGDEF_GROUP} ? "(" . ($iOptionIdx - 1) . " << PARSE_KEY_IDX_SHIFT) | " : '') . $strOptionEnum;
# Add option
$strBuildSource .=

View File

@ -12,6 +12,7 @@ Help Command
#include "common/memContext.h"
#include "config/config.h"
#include "config/define.h"
#include "config/parse.h"
#include "version.h"
/***********************************************************************************************************************************
@ -303,19 +304,21 @@ helpRender(void)
THROW(ParamInvalidError, "only one option allowed for option help");
// Ensure the option is valid
const char *optionName = strZ(strLstGet(cfgCommandParam(), 0));
ConfigOption optionId = cfgOptionId(optionName);
const String *optionName = strLstGet(cfgCommandParam(), 0);
CfgParseOptionResult option = cfgParseOption(optionName);
if (cfgOptionId(optionName) == -1)
if (!option.found)
{
if (cfgDefOptionId(optionName) != -1)
optionId = cfgOptionIdFromDefId(cfgDefOptionId(optionName), 0);
int optionId = cfgDefOptionId(strZ(optionName));
if (optionId == -1)
THROW_FMT(OptionInvalidError, "option '%s' is not valid for command '%s'", strZ(optionName), commandName);
else
THROW_FMT(OptionInvalidError, "option '%s' is not valid for command '%s'", optionName, commandName);
option.id = cfgOptionIdFromDefId((unsigned int)optionId, 0);
}
// Output option summary and description
ConfigDefineOption optionDefId = cfgOptionDefIdFromId(optionId);
ConfigDefineOption optionDefId = cfgOptionDefIdFromId(option.id);
strCatFmt(
result,
@ -324,16 +327,16 @@ helpRender(void)
"%s\n"
"\n"
"%s\n",
optionName,
cfgDefOptionName(optionDefId),
strZ(helpRenderText(STR(cfgDefOptionHelpSummary(commandId, optionDefId)), 0, true, CONSOLE_WIDTH)),
strZ(helpRenderText(STR(cfgDefOptionHelpDescription(commandId, optionDefId)), 0, true, CONSOLE_WIDTH)));
// Ouput current and default values if they exist
const String *defaultValue = helpRenderValue(cfgOptionDefault(optionId));
const String *defaultValue = helpRenderValue(cfgOptionDefault(option.id));
const String *value = NULL;
if (cfgOptionSource(optionId) != cfgSourceDefault)
value = helpRenderValue(cfgOption(optionId));
if (cfgOptionSource(option.id) != cfgSourceDefault)
value = helpRenderValue(cfgOption(option.id));
if (value != NULL || defaultValue != NULL)
{

View File

@ -713,25 +713,6 @@ cfgOptionIndex(ConfigOption optionId)
FUNCTION_TEST_RETURN(configOptionData[optionId].index);
}
/**********************************************************************************************************************************/
int
cfgOptionId(const char *optionName)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STRINGZ, optionName);
FUNCTION_TEST_END();
ASSERT(optionName != NULL);
int result = -1;
for (ConfigOption optionId = 0; optionId < CFG_OPTION_TOTAL; optionId++)
if (strcmp(optionName, configOptionData[optionId].name) == 0)
result = optionId;
FUNCTION_TEST_RETURN(result);
}
/**********************************************************************************************************************************/
ConfigOption
cfgOptionIdFromDefId(ConfigDefineOption optionDefId, unsigned int index)

View File

@ -193,9 +193,6 @@ ConfigDefineOption cfgOptionDefIdFromId(ConfigOption optionId);
// Parse a host option and extract the host and port (if it exists)
String *cfgOptionHostPort(ConfigOption optionId, unsigned int *port);
// Get option id by name
int cfgOptionId(const char *optionName);
// Get the id for this option define
ConfigOption cfgOptionIdFromDefId(ConfigDefineOption optionDefId, unsigned int index);

File diff suppressed because it is too large Load Diff

View File

@ -61,8 +61,12 @@ Parse option flags
// Indicate that option name has been deprecated and will be removed in a future release
#define PARSE_DEPRECATE_FLAG (1 << 27)
// Mask to exclude all flags and get at the actual option id (only 12 bits allowed for option id, the rest reserved for flags)
#define PARSE_OPTION_MASK 0xFFF
// Mask for option id (must be 0-255)
#define PARSE_OPTION_MASK 0xFF
// Shift and mask for option key index (must be 0-255)
#define PARSE_KEY_IDX_SHIFT 8
#define PARSE_KEY_IDX_MASK 0xFF
/***********************************************************************************************************************************
Include automatically generated data structure for getopt_long()
@ -84,23 +88,46 @@ typedef struct ParseOption
#define FUNCTION_LOG_PARSE_OPTION_FORMAT(value, buffer, bufferSize) \
typeToLog("ParseOption", buffer, bufferSize)
/***********************************************************************************************************************************
Find an option by name in the option list
***********************************************************************************************************************************/
static unsigned int
optionFind(const String *option)
/**********************************************************************************************************************************/
// Helper to parse the option info into a structure
__attribute__((always_inline)) static inline CfgParseOptionResult
cfgParseOptionInfo(int info)
{
unsigned int optionIdx = 0;
while (optionList[optionIdx].name != NULL)
return (CfgParseOptionResult)
{
if (strcmp(strZ(option), optionList[optionIdx].name) == 0)
.found = true,
.id = (info & PARSE_OPTION_MASK) + ((info >> PARSE_KEY_IDX_SHIFT) & PARSE_KEY_IDX_MASK),
.negate = info & PARSE_NEGATE_FLAG,
.reset = info & PARSE_RESET_FLAG,
.deprecated = info & PARSE_DEPRECATE_FLAG,
};
}
CfgParseOptionResult
cfgParseOption(const String *optionName)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STRING, optionName);
FUNCTION_TEST_END();
ASSERT(optionName != NULL);
// Search for the option
unsigned int findIdx = 0;
while (optionList[findIdx].name != NULL)
{
if (strEqZ(optionName, optionList[findIdx].name))
break;
optionIdx++;
findIdx++;
}
return optionIdx;
// If the option was found
if (optionList[findIdx].name != NULL)
FUNCTION_TEST_RETURN(cfgParseOptionInfo(optionList[findIdx].val));
FUNCTION_TEST_RETURN((CfgParseOptionResult){0});
}
/***********************************************************************************************************************************
@ -432,7 +459,7 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
// Phase 1: parse command line parameters
// -------------------------------------------------------------------------------------------------------------------------
int option; // Code returned by getopt_long
int optionValue; // Value returned by getopt_long
int optionListIdx; // Index of option is list (if an option was returned)
bool argFound = false; // Track args found to decide on error or help at the end
StringList *commandParamList = NULL; // List of command parameters
@ -449,9 +476,9 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
// Only the first non-option parameter should be treated as a command so track if the command has been set
bool commandSet = false;
while ((option = getopt_long((int)argListSize, (char **)argList, "-:", optionList, &optionListIdx)) != -1)
while ((optionValue = getopt_long((int)argListSize, (char **)argList, "-:", optionList, &optionListIdx)) != -1)
{
switch (option)
switch (optionValue)
{
// Parse arguments that are not options, i.e. commands and parameters passed to commands
case 1:
@ -517,71 +544,72 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
default:
{
// Get option id and flags from the option code
ConfigOption optionId = option & PARSE_OPTION_MASK;
bool negate = option & PARSE_NEGATE_FLAG;
bool reset = option & PARSE_RESET_FLAG;
CfgParseOptionResult option = cfgParseOptionInfo(optionValue);
// Make sure the option id is valid
ASSERT(optionId < CFG_OPTION_TOTAL);
ASSERT(option.id < CFG_OPTION_TOTAL);
// Error if this option is secure and cannot be passed on the command line
if (cfgDefOptionSecure(cfgOptionDefIdFromId(optionId)))
if (cfgDefOptionSecure(cfgOptionDefIdFromId(option.id)))
{
THROW_FMT(
OptionInvalidError,
"option '%s' is not allowed on the command-line\n"
"HINT: this option could expose secrets in the process list.\n"
"HINT: specify the option in a configuration file or an environment variable instead.",
cfgOptionName(optionId));
cfgOptionName(option.id));
}
// If the the option has not been found yet then set it
if (!parseOptionList[optionId].found)
if (!parseOptionList[option.id].found)
{
parseOptionList[optionId].found = true;
parseOptionList[optionId].negate = negate;
parseOptionList[optionId].reset = reset;
parseOptionList[optionId].source = cfgSourceParam;
parseOptionList[option.id].found = true;
parseOptionList[option.id].negate = option.negate;
parseOptionList[option.id].reset = option.reset;
parseOptionList[option.id].source = cfgSourceParam;
// Only set the argument if the option requires one
if (optionList[optionListIdx].has_arg == required_argument)
{
parseOptionList[optionId].valueList = strLstNew();
strLstAdd(parseOptionList[optionId].valueList, STR(optarg));
parseOptionList[option.id].valueList = strLstNew();
strLstAdd(parseOptionList[option.id].valueList, STR(optarg));
}
}
else
{
// Make sure option is not negated more than once. It probably wouldn't hurt anything to accept this case
// but there's no point in allowing the user to be sloppy.
if (parseOptionList[optionId].negate && negate)
THROW_FMT(OptionInvalidError, "option '%s' is negated multiple times", cfgOptionName(optionId));
if (parseOptionList[option.id].negate && option.negate)
THROW_FMT(OptionInvalidError, "option '%s' is negated multiple times", cfgOptionName(option.id));
// Make sure option is not reset more than once. Same justification as negate.
if (parseOptionList[optionId].reset && reset)
THROW_FMT(OptionInvalidError, "option '%s' is reset multiple times", cfgOptionName(optionId));
if (parseOptionList[option.id].reset && option.reset)
THROW_FMT(OptionInvalidError, "option '%s' is reset multiple times", cfgOptionName(option.id));
// Don't allow an option to be both negated and reset
if ((parseOptionList[optionId].reset && negate) || (parseOptionList[optionId].negate && reset))
THROW_FMT(OptionInvalidError, "option '%s' cannot be negated and reset", cfgOptionName(optionId));
if ((parseOptionList[option.id].reset && option.negate) ||
(parseOptionList[option.id].negate && option.reset))
{
THROW_FMT(OptionInvalidError, "option '%s' cannot be negated and reset", cfgOptionName(option.id));
}
// Don't allow an option to be both set and negated
if (parseOptionList[optionId].negate != negate)
THROW_FMT(OptionInvalidError, "option '%s' cannot be set and negated", cfgOptionName(optionId));
if (parseOptionList[option.id].negate != option.negate)
THROW_FMT(OptionInvalidError, "option '%s' cannot be set and negated", cfgOptionName(option.id));
// Don't allow an option to be both set and reset
if (parseOptionList[optionId].reset != reset)
THROW_FMT(OptionInvalidError, "option '%s' cannot be set and reset", cfgOptionName(optionId));
if (parseOptionList[option.id].reset != option.reset)
THROW_FMT(OptionInvalidError, "option '%s' cannot be set and reset", cfgOptionName(option.id));
// Add the argument
if (optionList[optionListIdx].has_arg == required_argument &&
cfgDefOptionMulti(cfgOptionDefIdFromId(optionId)))
cfgDefOptionMulti(cfgOptionDefIdFromId(option.id)))
{
strLstAdd(parseOptionList[optionId].valueList, strNew(optarg));
strLstAdd(parseOptionList[option.id].valueList, strNew(optarg));
}
// Error if the option does not accept multiple arguments
else
THROW_FMT(OptionInvalidError, "option '%s' cannot be set multiple times", cfgOptionName(optionId));
THROW_FMT(OptionInvalidError, "option '%s' cannot be set multiple times", cfgOptionName(option.id));
}
break;
@ -647,29 +675,28 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
const String *value = STR(equalPtr + 1);
// Find the option
unsigned int optionIdx = optionFind(key);
CfgParseOptionResult option = cfgParseOption(key);
// Warn if the option not found
if (optionList[optionIdx].name == NULL)
if (!option.found)
{
LOG_WARN_FMT("environment contains invalid option '%s'", strZ(key));
continue;
}
// Warn if negate option found in env
else if (optionList[optionIdx].val & PARSE_NEGATE_FLAG)
else if (option.negate)
{
LOG_WARN_FMT("environment contains invalid negate option '%s'", strZ(key));
continue;
}
// Warn if reset option found in env
else if (optionList[optionIdx].val & PARSE_RESET_FLAG)
else if (option.reset)
{
LOG_WARN_FMT("environment contains invalid reset option '%s'", strZ(key));
continue;
}
ConfigOption optionId = optionList[optionIdx].val & PARSE_OPTION_MASK;
ConfigDefineOption optionDefId = cfgOptionDefIdFromId(optionId);
ConfigDefineOption optionDefId = cfgOptionDefIdFromId(option.id);
// Continue if the option is not valid for this command
if (!cfgDefOptionValid(commandId, optionDefId))
@ -679,30 +706,30 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
THROW_FMT(OptionInvalidValueError, "environment variable '%s' must have a value", strZ(key));
// Continue if the option has already been specified on the command line
if (parseOptionList[optionId].found)
if (parseOptionList[option.id].found)
continue;
parseOptionList[optionId].found = true;
parseOptionList[optionId].source = cfgSourceConfig;
parseOptionList[option.id].found = true;
parseOptionList[option.id].source = cfgSourceConfig;
// Convert boolean to string
if (cfgDefOptionType(optionDefId) == cfgDefOptTypeBoolean)
{
if (strEqZ(value, "n"))
parseOptionList[optionId].negate = true;
parseOptionList[option.id].negate = true;
else if (!strEqZ(value, "y"))
THROW_FMT(OptionInvalidValueError, "environment boolean option '%s' must be 'y' or 'n'", strZ(key));
}
// Else split list/hash into separate values
else if (cfgDefOptionMulti(optionDefId))
{
parseOptionList[optionId].valueList = strLstNewSplitZ(value, ":");
parseOptionList[option.id].valueList = strLstNewSplitZ(value, ":");
}
// Else add the string value
else
{
parseOptionList[optionId].valueList = strLstNew();
strLstAdd(parseOptionList[optionId].valueList, value);
parseOptionList[option.id].valueList = strLstNew();
strLstAdd(parseOptionList[option.id].valueList, value);
}
}
}
@ -750,31 +777,30 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
String *key = strLstGet(keyList, keyIdx);
// Find the optionName in the main list
unsigned int optionIdx = optionFind(key);
CfgParseOptionResult option = cfgParseOption(key);
// Warn if the option not found
if (optionList[optionIdx].name == NULL)
if (!option.found)
{
LOG_WARN_FMT("configuration file contains invalid option '%s'", strZ(key));
continue;
}
// Warn if negate option found in config
else if (optionList[optionIdx].val & PARSE_NEGATE_FLAG)
else if (option.negate)
{
LOG_WARN_FMT("configuration file contains negate option '%s'", strZ(key));
continue;
}
// Warn if reset option found in config
else if (optionList[optionIdx].val & PARSE_RESET_FLAG)
else if (option.reset)
{
LOG_WARN_FMT("configuration file contains reset option '%s'", strZ(key));
continue;
}
ConfigOption optionId = optionList[optionIdx].val & PARSE_OPTION_MASK;
ConfigDefineOption optionDefId = cfgOptionDefIdFromId(optionId);
ConfigDefineOption optionDefId = cfgOptionDefIdFromId(option.id);
/// Warn if this option should be command-line only
// Warn if this option should be command-line only
if (cfgDefOptionSection(optionDefId) == cfgDefSectionCommandLine)
{
LOG_WARN_FMT("configuration file contains command-line only option '%s'", strZ(key));
@ -782,7 +808,7 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
}
// Make sure this option does not appear in the same section with an alternate name
const Variant *optionFoundKey = VARINT(optionId);
const Variant *optionFoundKey = VARINT(option.id);
const Variant *optionFoundName = kvGet(optionFound, optionFoundKey);
if (optionFoundName != NULL)
@ -820,20 +846,20 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
}
// Continue if this option has already been found in another section or command-line/environment
if (parseOptionList[optionId].found)
if (parseOptionList[option.id].found)
continue;
parseOptionList[optionId].found = true;
parseOptionList[optionId].source = cfgSourceConfig;
parseOptionList[option.id].found = true;
parseOptionList[option.id].source = cfgSourceConfig;
// Process list
if (iniSectionKeyIsList(config, section, key))
{
// Error if the option cannot be specified multiple times
if (!cfgDefOptionMulti(optionDefId))
THROW_FMT(OptionInvalidError, "option '%s' cannot be set multiple times", cfgOptionName(optionId));
THROW_FMT(OptionInvalidError, "option '%s' cannot be set multiple times", cfgOptionName(option.id));
parseOptionList[optionId].valueList = iniGetList(config, section, key);
parseOptionList[option.id].valueList = iniGetList(config, section, key);
}
else
{
@ -850,15 +876,15 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
if (cfgDefOptionType(optionDefId) == cfgDefOptTypeBoolean)
{
if (strEqZ(value, "n"))
parseOptionList[optionId].negate = true;
parseOptionList[option.id].negate = true;
else if (!strEqZ(value, "y"))
THROW_FMT(OptionInvalidValueError, "boolean option '%s' must be 'y' or 'n'", strZ(key));
}
// Else add the string value
else
{
parseOptionList[optionId].valueList = strLstNew();
strLstAdd(parseOptionList[optionId].valueList, value);
parseOptionList[option.id].valueList = strLstNew();
strLstAdd(parseOptionList[option.id].valueList, value);
}
}
}

View File

@ -12,4 +12,16 @@ Functions
// Parse the command-line arguments and config file to produce final config data
void configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel);
// Parse option name and return option info
typedef struct CfgParseOptionResult
{
bool found; // Was the option found?
ConfigOption id; // Option ID
bool negate; // Was the option negated?
bool reset; // Was the option reset?
bool deprecated; // Is the option deprecated?
} CfgParseOptionResult;
CfgParseOptionResult cfgParseOption(const String *optionName);
#endif

View File

@ -8,6 +8,7 @@ Configuration Protocol Handler
#include "common/log.h"
#include "common/memContext.h"
#include "config/config.h"
#include "config/parse.h"
#include "config/protocol.h"
/***********************************************************************************************************************************
@ -37,7 +38,12 @@ configProtocol(const String *command, const VariantList *paramList, ProtocolServ
VariantList *optionList = varLstNew();
for (unsigned int optionIdx = 0; optionIdx < varLstSize(paramList); optionIdx++)
varLstAdd(optionList, varDup(cfgOption(cfgOptionId(strZ(varStr(varLstGet(paramList, optionIdx)))))));
{
CfgParseOptionResult option = cfgParseOption(varStr(varLstGet(paramList, optionIdx)));
CHECK(option.found);
varLstAdd(optionList, varDup(cfgOption(option.id)));
}
protocolServerResponse(server, varNewVarLst(optionList));
}

View File

@ -309,7 +309,7 @@ testRun(void)
// -------------------------------------------------------------------------------------------------------------------------
optionHelp = strZ(strNewFmt(
"%s - 'archive-push' command - 'repo1-s3-host' option help\n"
"%s - 'archive-push' command - 'repo-s3-host' option help\n"
"\n"
"S3 repository host.\n"
"\n"
@ -379,6 +379,15 @@ testRun(void)
harnessCfgLoadRaw(strLstSize(argList), strLstPtr(argList)), "help for backup command, repo-hardlink option");
TEST_RESULT_STR_Z(helpRender(), optionHelp, " check text");
argList = strLstNew();
strLstAddZ(argList, "/path/to/pgbackrest");
strLstAddZ(argList, "help");
strLstAddZ(argList, "backup");
strLstAddZ(argList, "hardlink");
TEST_RESULT_VOID(
harnessCfgLoadRaw(strLstSize(argList), strLstPtr(argList)), "help for backup command, deprecated hardlink option");
TEST_RESULT_STR_Z(helpRender(), optionHelp, " check text");
// Check admonition
// -------------------------------------------------------------------------------------------------------------------------
optionHelp = strZ(strNewFmt(

View File

@ -24,9 +24,6 @@ testRun(void)
TEST_RESULT_INT(cfgOptionDefIdFromId(cfgOptPgHost + 6), cfgDefOptPgHost, "option id to def id");
TEST_RESULT_INT(cfgOptionId("target"), cfgOptTarget, "option id from name");
TEST_RESULT_INT(cfgOptionId(BOGUS_STR), -1, "option id from invalid option name");
TEST_ERROR(
cfgOptionIdFromDefId(999999, 6), AssertError,
"assertion 'optionId != CFG_OPTION_TOTAL' failed");

View File

@ -18,13 +18,15 @@ Test Configuration Parse
Option find test -- this is done a lot in the deprecated tests
***********************************************************************************************************************************/
static void
testOptionFind(const char *option, unsigned int value)
testOptionFind(const char *optionName, unsigned int optionId, unsigned int optionKeyIdx, bool negate, bool reset, bool deprecated)
{
// If not testing for a missing option, then add the option offset that is already added to each option in the list
if (value != 0)
value |= PARSE_OPTION_FLAG;
CfgParseOptionResult option = cfgParseOption(STR(optionName));
TEST_RESULT_INT(optionList[optionFind(strNew(option))].val, value, "check %s", option);
TEST_RESULT_BOOL(option.found, true, "check %s found", optionName);
TEST_RESULT_UINT(option.id, optionId + optionKeyIdx, "check %s id %u", optionName, optionId + optionKeyIdx);
TEST_RESULT_BOOL(option.negate, negate, "check %s negate %d", optionName, negate);
TEST_RESULT_BOOL(option.reset, reset, "check %s reset %d", optionName, reset);
TEST_RESULT_BOOL(option.deprecated, deprecated, "check %s deprecated %d", optionName, deprecated);
}
/***********************************************************************************************************************************
@ -1433,61 +1435,59 @@ testRun(void)
{
// Repository options
// -------------------------------------------------------------------------------------------------------------------------
testOptionFind("hardlink", PARSE_DEPRECATE_FLAG | cfgOptRepoHardlink);
testOptionFind("no-hardlink", PARSE_DEPRECATE_FLAG | PARSE_NEGATE_FLAG | cfgOptRepoHardlink);
testOptionFind("hardlink", cfgOptRepoHardlink, 0, false, false, true);
testOptionFind("no-hardlink", cfgOptRepoHardlink, 0, true, false, true);
testOptionFind("archive-queue-max", PARSE_DEPRECATE_FLAG | cfgOptArchivePushQueueMax);
testOptionFind("reset-archive-queue-max", PARSE_DEPRECATE_FLAG | PARSE_RESET_FLAG | cfgOptArchivePushQueueMax);
testOptionFind("archive-queue-max", cfgOptArchivePushQueueMax, 0, false, false, true);
testOptionFind("reset-archive-queue-max", cfgOptArchivePushQueueMax, 0, false, true, true);
testOptionFind("backup-cmd", PARSE_DEPRECATE_FLAG | cfgOptRepoHostCmd);
testOptionFind("backup-config", PARSE_DEPRECATE_FLAG | cfgOptRepoHostConfig);
testOptionFind("backup-host", PARSE_DEPRECATE_FLAG | cfgOptRepoHost);
testOptionFind("backup-ssh-port", PARSE_DEPRECATE_FLAG | cfgOptRepoHostPort);
testOptionFind("backup-user", PARSE_DEPRECATE_FLAG | cfgOptRepoHostUser);
testOptionFind("backup-cmd", cfgOptRepoHostCmd, 0, false, false, true);
testOptionFind("backup-config", cfgOptRepoHostConfig, 0, false, false, true);
testOptionFind("backup-host", cfgOptRepoHost, 0, false, false, true);
testOptionFind("backup-ssh-port", cfgOptRepoHostPort, 0, false, false, true);
testOptionFind("backup-user", cfgOptRepoHostUser, 0, false, false, true);
testOptionFind("repo-cipher-pass", PARSE_DEPRECATE_FLAG | cfgOptRepoCipherPass);
testOptionFind("repo-cipher-type", PARSE_DEPRECATE_FLAG | cfgOptRepoCipherType);
testOptionFind("repo-path", PARSE_DEPRECATE_FLAG | cfgOptRepoPath);
testOptionFind("repo-type", PARSE_DEPRECATE_FLAG | cfgOptRepoType);
testOptionFind("repo-cipher-pass", cfgOptRepoCipherPass, 0, false, false, true);
testOptionFind("repo-cipher-type", cfgOptRepoCipherType, 0, false, false, true);
testOptionFind("repo-path", cfgOptRepoPath, 0, false, false, true);
testOptionFind("repo-type", cfgOptRepoType, 0, false, false, true);
testOptionFind("repo-s3-bucket", PARSE_DEPRECATE_FLAG | cfgOptRepoS3Bucket);
testOptionFind("repo-s3-ca-file", PARSE_DEPRECATE_FLAG | cfgOptRepoS3CaFile);
testOptionFind("repo-s3-ca-path", PARSE_DEPRECATE_FLAG | cfgOptRepoS3CaPath);
testOptionFind("repo-s3-endpoint", PARSE_DEPRECATE_FLAG | cfgOptRepoS3Endpoint);
testOptionFind("repo-s3-host", PARSE_DEPRECATE_FLAG | cfgOptRepoS3Host);
testOptionFind("repo-s3-key", PARSE_DEPRECATE_FLAG | cfgOptRepoS3Key);
testOptionFind("repo-s3-key-secret", PARSE_DEPRECATE_FLAG | cfgOptRepoS3KeySecret);
testOptionFind("repo-s3-region", PARSE_DEPRECATE_FLAG | cfgOptRepoS3Region);
testOptionFind("repo-s3-verify-ssl", PARSE_DEPRECATE_FLAG | cfgOptRepoS3VerifyTls);
testOptionFind("repo1-s3-verify-ssl", PARSE_DEPRECATE_FLAG | cfgOptRepoS3VerifyTls);
testOptionFind("no-repo-s3-verify-ssl", PARSE_DEPRECATE_FLAG | PARSE_NEGATE_FLAG | cfgOptRepoS3VerifyTls);
testOptionFind("repo-s3-bucket", cfgOptRepoS3Bucket, 0, false, false, true);
testOptionFind("repo-s3-ca-file", cfgOptRepoS3CaFile, 0, false, false, true);
testOptionFind("repo-s3-ca-path", cfgOptRepoS3CaPath, 0, false, false, true);
testOptionFind("repo-s3-endpoint", cfgOptRepoS3Endpoint, 0, false, false, true);
testOptionFind("repo-s3-host", cfgOptRepoS3Host, 0, false, false, true);
testOptionFind("repo-s3-key", cfgOptRepoS3Key, 0, false, false, true);
testOptionFind("repo-s3-key-secret", cfgOptRepoS3KeySecret, 0, false, false, true);
testOptionFind("repo-s3-region", cfgOptRepoS3Region, 0, false, false, true);
testOptionFind("repo-s3-verify-ssl", cfgOptRepoS3VerifyTls, 0, false, false, true);
testOptionFind("repo1-s3-verify-ssl", cfgOptRepoS3VerifyTls, 0, false, false, true);
testOptionFind("no-repo-s3-verify-ssl", cfgOptRepoS3VerifyTls, 0, true, false, true);
// PostreSQL options
// -------------------------------------------------------------------------------------------------------------------------
testOptionFind("db-cmd", PARSE_DEPRECATE_FLAG | cfgOptPgHostCmd);
testOptionFind("db-config", PARSE_DEPRECATE_FLAG | cfgOptPgHostConfig);
testOptionFind("db-host", PARSE_DEPRECATE_FLAG | cfgOptPgHost);
testOptionFind("db-path", PARSE_DEPRECATE_FLAG | cfgOptPgPath);
testOptionFind("db-port", PARSE_DEPRECATE_FLAG | cfgOptPgPort);
testOptionFind("db-socket-path", PARSE_DEPRECATE_FLAG | cfgOptPgSocketPath);
testOptionFind("db-ssh-port", PARSE_DEPRECATE_FLAG | cfgOptPgHostPort);
testOptionFind("db-user", PARSE_DEPRECATE_FLAG | cfgOptPgHostUser);
testOptionFind("db-cmd", cfgOptPgHostCmd, 0, false, false, true);
testOptionFind("db-config", cfgOptPgHostConfig, 0, false, false, true);
testOptionFind("db-host", cfgOptPgHost, 0, false, false, true);
testOptionFind("db-path", cfgOptPgPath, 0, false, false, true);
testOptionFind("db-port", cfgOptPgPort, 0, false, false, true);
testOptionFind("db-socket-path", cfgOptPgSocketPath, 0, false, false, true);
testOptionFind("db-ssh-port", cfgOptPgHostPort, 0, false, false, true);
testOptionFind("db-user", cfgOptPgHostUser, 0, false, false, true);
testOptionFind("no-db-user", 0);
TEST_RESULT_BOOL(cfgParseOption(STR("no-db-user")).found, false, "no-db-user not found");
for (unsigned int optionIdx = 0; optionIdx < cfgDefOptionIndexTotal(cfgDefOptPgPath); optionIdx++)
// Only check 1-8 since 8 was the max index when these option names were deprecated
for (unsigned int optionIdx = 0; optionIdx < 8; optionIdx++)
{
testOptionFind(strZ(strNewFmt("db%u-cmd", optionIdx + 1)), PARSE_DEPRECATE_FLAG | (cfgOptPgHostCmd + optionIdx));
testOptionFind(
strZ(strNewFmt("db%u-config", optionIdx + 1)), PARSE_DEPRECATE_FLAG | (cfgOptPgHostConfig + optionIdx));
testOptionFind(strZ(strNewFmt("db%u-host", optionIdx + 1)), PARSE_DEPRECATE_FLAG | (cfgOptPgHost + optionIdx));
testOptionFind(strZ(strNewFmt("db%u-path", optionIdx + 1)), PARSE_DEPRECATE_FLAG | (cfgOptPgPath + optionIdx));
testOptionFind(strZ(strNewFmt("db%u-port", optionIdx + 1)), PARSE_DEPRECATE_FLAG | (cfgOptPgPort + optionIdx));
testOptionFind(
strZ(strNewFmt("db%u-socket-path", optionIdx + 1)), PARSE_DEPRECATE_FLAG | (cfgOptPgSocketPath + optionIdx));
testOptionFind(
strZ(strNewFmt("db%u-ssh-port", optionIdx + 1)), PARSE_DEPRECATE_FLAG | (cfgOptPgHostPort + optionIdx));
testOptionFind(strZ(strNewFmt("db%u-user", optionIdx + 1)), PARSE_DEPRECATE_FLAG | (cfgOptPgHostUser + optionIdx));
testOptionFind(strZ(strNewFmt("db%u-cmd", optionIdx + 1)), cfgOptPgHostCmd, optionIdx, false, false, true);
testOptionFind(strZ(strNewFmt("db%u-config", optionIdx + 1)), cfgOptPgHostConfig, optionIdx, false, false, true);
testOptionFind(strZ(strNewFmt("db%u-host", optionIdx + 1)), cfgOptPgHost, optionIdx, false, false, true);
testOptionFind(strZ(strNewFmt("db%u-path", optionIdx + 1)), cfgOptPgPath, optionIdx, false, false, true);
testOptionFind(strZ(strNewFmt("db%u-port", optionIdx + 1)), cfgOptPgPort, optionIdx, false, false, true);
testOptionFind(strZ(strNewFmt("db%u-socket-path", optionIdx + 1)), cfgOptPgSocketPath, optionIdx, false, false, true);
testOptionFind(strZ(strNewFmt("db%u-ssh-port", optionIdx + 1)), cfgOptPgHostPort, optionIdx, false, false, true);
testOptionFind(strZ(strNewFmt("db%u-user", optionIdx + 1)), cfgOptPgHostUser, optionIdx, false, false, true);
}
}