1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-01-18 04:58:51 +02:00

Move help data from define.auto.c/config.auto.c to a pack.

The help data can be represented more compactly in a pack and this separates data needed for help from data needed for parsing, freeing each to have a more appropriate representation.
This commit is contained in:
David Steele 2020-12-16 15:59:36 -05:00
parent 996de0a3e6
commit f520ecc89a
16 changed files with 4346 additions and 2263 deletions

View File

@ -186,7 +186,6 @@ sub buildConfig
" (\n" .
" CONFIG_COMMAND_NAME(${strCommandConst})\n" .
"\n" .
" CONFIG_COMMAND_INTERNAL(" . ($rhCommand->{&CFGDEF_INTERNAL} ? 'true' : 'false') . ")\n" .
" CONFIG_COMMAND_LOG_FILE(" . ($rhCommand->{&CFGDEF_LOG_FILE} ? 'true' : 'false') . ")\n" .
" CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevel" . ucfirst(lc($rhCommand->{&CFGDEF_LOG_LEVEL_DEFAULT})) . ")\n" .
" CONFIG_COMMAND_LOCK_REQUIRED(" . ($rhCommand->{&CFGDEF_LOCK_REQUIRED} ? 'true' : 'false') . ")\n" .

View File

@ -82,69 +82,6 @@ sub buildConfigDefineOptionTypeEnum
push @EXPORT, qw(buildConfigDefineOptionTypeEnum);
####################################################################################################################################
# Helper function to format help text
####################################################################################################################################
sub helpFormatText
{
my $oManifest = shift;
my $oDocRender = shift;
my $oText = shift;
my $iIndent = shift;
my $iLength = shift;
# Split the string into lines for processing
my @stryText = split("\n", trim($oManifest->variableReplace($oDocRender->processText($oText))));
my $strText;
my $iIndex = 0;
foreach my $strLine (@stryText)
{
# Add a linefeed if this is not the first line
if (defined($strText))
{
$strText .= "\n";
}
# Escape special characters
$strLine =~ s/\"/\\"/g;
my $strPart;
my $bFirst = true;
# Split the line for output if it's too long
do
{
($strPart, $strLine) = stringSplit($strLine, ' ', defined($strPart) ? $iLength - 4 : $iLength);
$strText .= ' ' x $iIndent;
if (!$bFirst)
{
$strText .= " ";
}
$strText .= "\"${strPart}";
if (defined($strLine))
{
$strText .= "\"\n";
}
else
{
$strText .= ($iIndex + 1 < @stryText ? '\n' : '') . '"';
}
$bFirst = false;
}
while (defined($strLine));
$iIndex++;
}
return $strText;
}
####################################################################################################################################
# Helper functions for building optional option data
####################################################################################################################################
@ -199,9 +136,6 @@ sub renderOptional
{
my $rhOptional = shift;
my $bCommand = shift;
my $rhOptionHelp = shift;
my $oManifest = shift;
my $oDocRender = shift;
my $strCommand = shift;
my $strOption = shift;
@ -252,28 +186,6 @@ sub renderOptional
$bSingleLine = true;
}
# Output alternate name
if (!$bCommand && defined($rhOptionHelp->{&CONFIG_HELP_NAME_ALT}))
{
$strBuildSourceOptional .=
(defined($strBuildSourceOptional) && !$bSingleLine ? "\n" : '') .
"${strIndent} CFGDEFDATA_OPTION_OPTIONAL_HELP_NAME_ALT(" .
join(', ', bldQuoteList($rhOptionHelp->{&CONFIG_HELP_NAME_ALT})) . ")\n";
$bSingleLine = true;
}
if ($bCommand && defined($rhOptional->{&CFGDEF_INTERNAL}))
{
$strBuildSourceOptional .=
(defined($strBuildSourceOptional) && !$bSingleLine ? "\n" : '') .
"${strIndent} CFGDEFDATA_OPTION_OPTIONAL_INTERNAL(" . ($rhOptional->{&CFGDEF_INTERNAL} ? 'true' : 'false') .
")\n";
$bSingleLine = true;
}
if ($bCommand && defined($rhOptional->{&CFGDEF_REQUIRED}))
{
$strBuildSourceOptional .=
@ -284,26 +196,6 @@ sub renderOptional
$bSingleLine = true;
}
if ($bCommand && defined($rhOptionHelp) && defined($rhOptionHelp->{&CONFIG_HELP_SOURCE}) &&
$rhOptionHelp->{&CONFIG_HELP_SOURCE} eq CONFIG_HELP_SOURCE_COMMAND)
{
my $strSummary = helpFormatText($oManifest, $oDocRender, $rhOptionHelp->{&CONFIG_HELP_SUMMARY}, 0, 72);
if (length($strSummary) > 74)
{
confess("summary for command '${strCommand}', option '${strOption}' may not be greater than 72 characters");
}
$strBuildSourceOptional .=
(defined($strBuildSourceOptional) ? "\n" : '') .
"${strIndent} CFGDEFDATA_OPTION_OPTIONAL_HELP_SUMMARY(${strSummary})\n" .
"${strIndent} CFGDEFDATA_OPTION_OPTIONAL_HELP_DESCRIPTION\n" .
"${strIndent} (\n" .
helpFormatText($oManifest, $oDocRender, $rhOptionHelp->{&CONFIG_HELP_DESCRIPTION}, 20, 111) . "\n" .
"${strIndent} )\n";
}
return $strBuildSourceOptional;
}
@ -312,26 +204,6 @@ sub renderOptional
####################################################################################################################################
sub buildConfigDefine
{
# Load help data
#-------------------------------------------------------------------------------------------------------------------------------
require pgBackRestDoc::Common::Doc;
require pgBackRestDoc::Common::DocManifest;
my $strDocPath = abs_path(dirname($0) . '/../doc');
my $oStorageDoc = new pgBackRestTest::Common::Storage(
$strDocPath, new pgBackRestTest::Common::StoragePosix({bFileSync => false, bPathSync => false}));
my @stryEmpty = [];
my $oManifest = new pgBackRestDoc::Common::DocManifest(
$oStorageDoc, \@stryEmpty, \@stryEmpty, \@stryEmpty, \@stryEmpty, undef, $strDocPath, false, false);
my $oDocRender = new pgBackRestDoc::Common::DocRender('text', $oManifest, false);
my $oDocConfig =
new pgBackRestDoc::Common::DocConfig(
new pgBackRestDoc::Common::Doc("${strDocPath}/xml/reference.xml"), $oDocRender);
my $hConfigHelp = $oDocConfig->{oConfigHash};
# Build command constants and data
#-------------------------------------------------------------------------------------------------------------------------------
my $strBuildSource =
@ -340,42 +212,12 @@ sub buildConfigDefine
foreach my $strCommand (cfgDefineCommandList())
{
# Get command help
my $hCommandHelp = $hConfigHelp->{&CONFIG_HELP_COMMAND}{$strCommand};
# Build command data
$strBuildSource .=
"\n" .
" CFGDEFDATA_COMMAND\n" .
" (\n" .
" CFGDEFDATA_COMMAND_NAME(\"${strCommand}\")\n";
# Output help
if (defined($hCommandHelp))
{
$strBuildSource .=
"\n";
# Output command summary
my $strSummary = helpFormatText($oManifest, $oDocRender, $hCommandHelp->{&CONFIG_HELP_SUMMARY}, 0, 72);
if (length($strSummary) > 74)
{
confess("summary for command '${strCommand}' may not be greater than 72 characters");
}
$strBuildSource .=
" CFGDEFDATA_COMMAND_HELP_SUMMARY(${strSummary})\n";
# Output description
$strBuildSource .=
" CFGDEFDATA_COMMAND_HELP_DESCRIPTION\n" .
" (\n" .
helpFormatText($oManifest, $oDocRender, $hCommandHelp->{&CONFIG_HELP_DESCRIPTION}, 12, 119) . "\n" .
" )\n";
}
$strBuildSource .=
" CFGDEFDATA_COMMAND_NAME(\"${strCommand}\")\n" .
" )\n";
};
@ -405,9 +247,6 @@ sub buildConfigDefine
foreach my $strOption (sort(keys(%{$rhConfigDefine})))
{
# Get option help
my $hOptionHelp = $hConfigHelp->{&CONFIG_HELP_OPTION}{$strOption};
# Build option data
my $rhOption = $rhConfigDefine->{$strOption};
@ -428,46 +267,9 @@ sub buildConfigDefine
(defined($rhOption->{&CFGDEF_SECTION}) ? ucfirst($rhOption->{&CFGDEF_SECTION}) : 'CommandLine') .
")\n" .
" CFGDEFDATA_OPTION_TYPE(" . buildConfigDefineOptionTypeEnum($rhOption->{&CFGDEF_TYPE}) . ")\n" .
" CFGDEFDATA_OPTION_INTERNAL(" . ($rhOption->{&CFGDEF_INTERNAL} ? 'true' : 'false') . ")\n" .
"\n" .
" CFGDEFDATA_OPTION_SECURE(" . ($rhOption->{&CFGDEF_SECURE} ? 'true' : 'false') . ")\n";
if (defined($hOptionHelp))
{
$strBuildSource .=
"\n";
# Output section
my $strSection =
defined($hOptionHelp->{&CONFIG_HELP_SECTION}) ? $hOptionHelp->{&CONFIG_HELP_SECTION} : 'general';
if (length($strSection) > 72)
{
confess("section for option '${strOption}' may not be greater than 72 characters");
}
$strBuildSource .=
" CFGDEFDATA_OPTION_HELP_SECTION(\"${strSection}\")\n";
# Output summary
my $strSummary = helpFormatText($oManifest, $oDocRender, $hOptionHelp->{&CONFIG_HELP_SUMMARY}, 0, 72);
if (length($strSummary) > 74)
{
confess("summary for option '${strOption}' may not be greater than 72 characters");
}
$strBuildSource .=
" CFGDEFDATA_OPTION_HELP_SUMMARY(${strSummary})\n";
# Output description
$strBuildSource .=
" CFGDEFDATA_OPTION_HELP_DESCRIPTION\n" .
" (\n" .
helpFormatText($oManifest, $oDocRender, $hOptionHelp->{&CONFIG_HELP_DESCRIPTION}, 12, 119) . "\n" .
" )\n";
}
$strBuildSource .=
"\n" .
" CFGDEFDATA_OPTION_COMMAND_LIST\n" .
@ -486,7 +288,7 @@ sub buildConfigDefine
" )\n";
# Render optional data
my $strBuildSourceOptional = renderOptional($rhOption, false, $hOptionHelp, $oManifest, $oDocRender);
my $strBuildSourceOptional = renderOptional($rhOption, false);
# Render command overrides
foreach my $strCommand (cfgDefineCommandList())
@ -496,9 +298,7 @@ sub buildConfigDefine
if (defined($rhCommand))
{
$strBuildSourceOptionalCommand = renderOptional(
$rhCommand, true, $hConfigHelp->{&CONFIG_HELP_COMMAND}{$strCommand}{&CONFIG_HELP_OPTION}{$strOption},
$oManifest, $oDocRender, $strCommand, $strOption);
$strBuildSourceOptionalCommand = renderOptional($rhCommand, true, $strCommand, $strOption);
if (defined($strBuildSourceOptionalCommand))
{

View File

@ -0,0 +1,498 @@
####################################################################################################################################
# Auto-Generate Command and Option Help Pack
####################################################################################################################################
package pgBackRestBuild::Config::BuildHelp;
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use English '-no_match_vars';
use Cwd qw(abs_path);
use Exporter qw(import);
our @EXPORT = qw();
use File::Basename qw(dirname);
use pgBackRestDoc::Common::DocConfig;
use pgBackRestDoc::Common::DocRender;
use pgBackRestDoc::Common::Log;
use pgBackRestDoc::Common::String;
use pgBackRestDoc::ProjectInfo;
use pgBackRestBuild::Build::Common;
use pgBackRestBuild::Config::Build;
use pgBackRestBuild::Config::Data;
####################################################################################################################################
# Constants
####################################################################################################################################
use constant BLDLCL_FILE_DEFINE => 'help';
use constant BLDLCL_DATA_COMMAND => '01-command';
####################################################################################################################################
# Definitions for data to build
####################################################################################################################################
my $strSummary = 'Help Definition Pack';
my $rhBuild =
{
&BLD_FILE =>
{
&BLDLCL_FILE_DEFINE =>
{
&BLD_SUMMARY => $strSummary,
&BLD_DATA =>
{
&BLDLCL_DATA_COMMAND =>
{
&BLD_SUMMARY => 'Command help',
},
},
},
},
};
####################################################################################################################################
# Format pack tag
####################################################################################################################################
use constant PCK_TYPE_ARRAY => 'pckTypeArray';
use constant PCK_TYPE_BOOL => 'pckTypeBool';
use constant PCK_TYPE_OBJ => 'pckTypeObj';
use constant PCK_TYPE_STR => 'pckTypeStr';
# Pack an unsigned 64-bit integer to base-128 varint encoding and output to hex. This is a simplified version of
# pckWriteUInt64Internal() so see that function for more information.
sub packIntFormat
{
my $iValue = shift;
my $strResult = '';
while ($iValue >= 0x80)
{
# Encode the lower order 7 bits, adding the continuation bit to indicate there is more data
$strResult .= sprintf(" 0x%02X,", ($iValue & 0x7f) | 0x80);
# Shift the value to remove bits that have been encoded
$iValue >>= 7;
}
return $strResult . sprintf(" 0x%02X,", $iValue);
}
# Write pack field tag and data. This is a cut down version of pckWriteTag() so see that function for more information.
sub packTagFormat
{
my $strName = shift;
my $strType = shift;
my $iDelta = shift;
my $xData = shift;
my $iIndent = shift;
my $strIndent = ' ' x $iIndent;
# Pack delta bits and determine value for various pack. See pckWriteTag() for more detailed information.
my $iValue = undef;
my $iBits = undef;
if ($strType eq PCK_TYPE_STR || $strType eq PCK_TYPE_BOOL)
{
$iBits = $iDelta & 0x3;
$iDelta >>= 2;
if ($iDelta != 0)
{
$iBits |= 0x4;
}
if ($strType eq PCK_TYPE_STR)
{
$iBits |= 0x8;
$iValue = length($xData);
}
else
{
$iBits |= $xData ? 0x8 : 0;
undef($xData);
}
}
elsif ($strType eq PCK_TYPE_ARRAY || $strType eq PCK_TYPE_OBJ)
{
$iBits |= $iDelta & 0x7;
$iDelta >>= 3;
if ($iDelta != 0)
{
$iBits |= 0x8;
}
}
# Output pack type and bits
my $strResult = "${strIndent}${strType} << 4";
if ($iBits != 0)
{
$strResult .= sprintf(" | 0x%02X", $iBits);
}
$strResult .= ',';
# Output additional id delta when present
if ($iDelta > 0)
{
$strResult .= packIntFormat($iDelta);
}
# Output value when present
if (defined($iValue))
{
$strResult .= packIntFormat($iValue);
}
# Output pack name
$strResult .= " // ${strName}";
# Output data in hex format
if (defined($xData) && length($xData) > 0)
{
$strResult .= "\n${strIndent} ";
my $iLength = length($strIndent) + 4;
my $bLastLF = false;
my $bFirst = true;
# Loop through all chars
foreach my $iChar (unpack("W*", $xData))
{
# Encode char to hex
my $strOut = sprintf("0x%02X,", $iChar);
# Break on linefeeds to prevent diffs within a paragraph of text from cascading through all the data
if ($bLastLF && $iChar != 0xA)
{
$strResult .= "\n${strIndent} ";
$iLength = length($strIndent) + 4;
$bFirst = true;
}
$bLastLF = $iChar == 0xA;
# If this hex would exceed the line length then break and write on the next line
if ($iLength + length($strOut) + 1 > 132)
{
$strResult .= "\n${strIndent} ${strOut}";
$iLength = length($strIndent) + 4 + length($strOut);
}
# Else append the hex
else
{
$strResult .= ($bFirst ? '' : ' ') . "${strOut}";
$iLength += length($strOut) + ($bFirst ? 0 : 1);
$bFirst = false;
}
}
}
return $strResult . "\n";
}
####################################################################################################################################
# Build help data
####################################################################################################################################
sub buildConfigHelp
{
# Load help data
#-------------------------------------------------------------------------------------------------------------------------------
require pgBackRestDoc::Common::Doc;
require pgBackRestDoc::Common::DocManifest;
my $strDocPath = abs_path(dirname($0) . '/../doc');
my $oStorageDoc = new pgBackRestTest::Common::Storage(
$strDocPath, new pgBackRestTest::Common::StoragePosix({bFileSync => false, bPathSync => false}));
my @stryEmpty = [];
my $oManifest = new pgBackRestDoc::Common::DocManifest(
$oStorageDoc, \@stryEmpty, \@stryEmpty, \@stryEmpty, \@stryEmpty, undef, $strDocPath, false, false);
my $oDocRender = new pgBackRestDoc::Common::DocRender('text', $oManifest, false);
my $oDocConfig =
new pgBackRestDoc::Common::DocConfig(
new pgBackRestDoc::Common::Doc("${strDocPath}/xml/reference.xml"), $oDocRender);
my $hConfigHelp = $oDocConfig->{oConfigHash};
# Build command help
#-------------------------------------------------------------------------------------------------------------------------------
my $rhCommandDefine = cfgDefineCommand();
my $strBuildSource =
"static const unsigned char helpDataPack[] =\n" .
"{\n" .
" // Commands\n" .
" // " . (qw{-} x 125) . "\n";
$strBuildSource .= packTagFormat("Commands begin", PCK_TYPE_ARRAY, 0, undef, 4);
foreach my $strCommand (sort(keys(%{$rhCommandDefine})))
{
my $rhCommand = $rhCommandDefine->{$strCommand};
my $iDelta = 0;
# Get command help
my $rhCommandHelp = $hConfigHelp->{&CONFIG_HELP_COMMAND}{$strCommand};
if (!defined($rhCommandHelp))
{
confess "no help for command ${strCommand}"
}
# Build command data
$strBuildSource .=
"\n" .
" // ${strCommand} command\n" .
" // " . (qw{-} x 121) . "\n";
if ($rhCommand->{&CFGDEF_INTERNAL})
{
$strBuildSource .= packTagFormat("Internal", PCK_TYPE_BOOL, 0, true, 8);
}
else
{
$iDelta++;
}
my $strSummary = trim($oManifest->variableReplace($oDocRender->processText($rhCommandHelp->{&CONFIG_HELP_SUMMARY})));
if (length($strSummary) > 72)
{
confess("summary for command '${strCommand}' may not be greater than 72 characters");
}
$strBuildSource .= packTagFormat("Summary", PCK_TYPE_STR, $iDelta, $strSummary, 8);
$iDelta = 0;
$strBuildSource .= packTagFormat(
"Description", PCK_TYPE_STR, 0,
trim($oManifest->variableReplace($oDocRender->processText($rhCommandHelp->{&CONFIG_HELP_DESCRIPTION}))), 8);
};
$strBuildSource .=
"\n" .
" 0x00, // Commands end\n";
# Build option help
#-------------------------------------------------------------------------------------------------------------------------------
my $rhConfigDefine = cfgDefine();
$strBuildSource .=
"\n" .
" // Options\n" .
" // " . (qw{-} x 125) . "\n";
$strBuildSource .= packTagFormat("Options begin", PCK_TYPE_ARRAY, 0, undef, 4);
my $iDelta = 0;
foreach my $strOption (sort(keys(%{$rhConfigDefine})))
{
my $bFirst = true;
my $bInternal = false;
# Build option data
my $rhOption = $rhConfigDefine->{$strOption};
# Get option help
my $rhOptionHelp = $hConfigHelp->{&CONFIG_HELP_OPTION}{$strOption};
# Build command data
$strBuildSource .=
"\n" .
" // ${strOption} option\n" .
" // " . (qw{-} x 121) . "\n";
# Internal
if ($rhOption->{&CFGDEF_INTERNAL})
{
$strBuildSource .= packTagFormat("Internal", PCK_TYPE_BOOL, $iDelta, true, 8);
$iDelta = 0;
$bInternal = true;
}
else
{
$iDelta++;
}
if (defined($rhOptionHelp))
{
# Section
my $strSection = $rhOptionHelp->{&CONFIG_HELP_SECTION};
if (defined($strSection))
{
if (length($strSection) > 72)
{
confess("section for option '${strOption}' may not be greater than 72 characters");
}
$strBuildSource .= packTagFormat("Section", PCK_TYPE_STR, $iDelta, $strSection, 8);
$iDelta = 0;
}
else
{
$iDelta++;
}
# Summary
my $strSummary = trim($oManifest->variableReplace($oDocRender->processText($rhOptionHelp->{&CONFIG_HELP_SUMMARY})));
if (length($strSummary) > 72)
{
confess("summary for option '${strOption}' may not be greater than 72 characters");
}
$strBuildSource .= packTagFormat("Summary", PCK_TYPE_STR, $iDelta, $strSummary, 8);
$iDelta = 0;
# Description
$strBuildSource .= packTagFormat(
"Description", PCK_TYPE_STR, $iDelta,
trim($oManifest->variableReplace($oDocRender->processText($rhOptionHelp->{&CONFIG_HELP_DESCRIPTION}))), 8);
$bFirst = false;
}
else
{
$iDelta += 3;
}
# Output deprecated names
my $stryDeprecatedName = $rhOptionHelp->{&CONFIG_HELP_NAME_ALT};
if (defined($stryDeprecatedName))
{
$strBuildSource .=
($bFirst ? '' : "\n") .
packTagFormat("Deprecated names begin", PCK_TYPE_ARRAY, $iDelta, undef, 8);
$iDelta = 0;
foreach my $strDeprecatedName (@{$stryDeprecatedName})
{
$strBuildSource .= packTagFormat($strDeprecatedName, PCK_TYPE_STR, 0, $strDeprecatedName, 12);
}
$strBuildSource .=
" 0x00, // Deprecated names end\n";
$bFirst = false;
}
else
{
$iDelta++;
}
# Command overrides
my $strBuildSourceCommands;
my $iCommandId = 0;
my $iLastCommandId = 0;
foreach my $strCommand (sort(keys(%{$rhCommandDefine})))
{
my $rhCommand = $rhOption->{&CFGDEF_COMMAND}{$strCommand};
my $iDeltaCommand = 0;
my $strBuildSourceCommand;
if (defined($rhCommand))
{
if ($bInternal && defined($rhCommand->{&CFGDEF_INTERNAL}) && !$rhCommand->{&CFGDEF_INTERNAL})
{
confess("option '${strOption}' is internal but command '${strCommand}' override is not");
}
# Internal
if (defined($rhCommand->{&CFGDEF_INTERNAL}) && $bInternal != $rhCommand->{&CFGDEF_INTERNAL})
{
$strBuildSourceCommand .=
packTagFormat("Internal", PCK_TYPE_BOOL, $iDeltaCommand, true, 16);
$iDeltaCommand = 0;
}
else
{
$iDeltaCommand++;
}
my $rhCommandHelp = $hConfigHelp->{&CONFIG_HELP_COMMAND}{$strCommand}{&CONFIG_HELP_OPTION}{$strOption};
if (defined($rhCommandHelp->{&CONFIG_HELP_SOURCE}) &&
$rhCommandHelp->{&CONFIG_HELP_SOURCE} eq CONFIG_HELP_SOURCE_COMMAND)
{
# Summary
my $strSummary = trim(
$oManifest->variableReplace($oDocRender->processText($rhCommandHelp->{&CONFIG_HELP_SUMMARY})));
if (length($strSummary) > 72)
{
confess("summary for command '${strCommand}' option '${strOption}' may not be greater than 72 characters");
}
$strBuildSourceCommand .=
packTagFormat("Summary", PCK_TYPE_STR, $iDeltaCommand, $strSummary, 16);
$iDeltaCommand = 0;
# Description
$strBuildSourceCommand .= packTagFormat(
"Description", PCK_TYPE_STR, $iDeltaCommand,
trim($oManifest->variableReplace($oDocRender->processText($rhCommandHelp->{&CONFIG_HELP_DESCRIPTION}))),
16);
}
if (defined($strBuildSourceCommand))
{
$strBuildSourceCommands .=
"\n" .
packTagFormat(
"Command ${strCommand} override begin", PCK_TYPE_OBJ, $iCommandId - $iLastCommandId, undef, 12) .
$strBuildSourceCommand .
" 0x00, // Command ${strCommand} override end\n";
$iLastCommandId = $iCommandId + 1;
}
}
$iCommandId++;
}
if (defined($strBuildSourceCommands))
{
$strBuildSource .=
($bFirst ? '' : "\n") .
packTagFormat("Command overrides begin", PCK_TYPE_ARRAY, $iDelta, undef, 8) .
$strBuildSourceCommands . "\n" .
" 0x00, // Command overrides end\n";
$iDelta = 0;
$bFirst = false;
}
else
{
$iDelta++;
}
}
$strBuildSource .=
"\n" .
" 0x00, // Options end\n";
$strBuildSource .=
"\n" .
" 0x00, // Pack end\n" .
"};\n";
$rhBuild->{&BLD_FILE}{&BLDLCL_FILE_DEFINE}{&BLD_DATA}{&BLDLCL_DATA_COMMAND}{&BLD_SOURCE} = $strBuildSource;
return $rhBuild;
}
push @EXPORT, qw(buildConfigHelp);
1;

3707
src/command/help/help.auto.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -10,11 +10,17 @@ Help Command
#include "common/debug.h"
#include "common/io/fdWrite.h"
#include "common/memContext.h"
#include "common/type/pack.h"
#include "config/config.h"
#include "config/define.h"
#include "config/parse.h"
#include "version.h"
/***********************************************************************************************************************************
Include automatically generated help data pack
***********************************************************************************************************************************/
#include "command/help/help.auto.c"
/***********************************************************************************************************************************
Define the console width - use a fixed with of 80 since this should be safe on virtually all consoles
***********************************************************************************************************************************/
@ -140,6 +146,24 @@ helpRenderValue(const Variant *value, ConfigDefineOptionType type)
/***********************************************************************************************************************************
Render help to a string
***********************************************************************************************************************************/
// Stored unpacked command data
typedef struct HelpCommandData
{
bool internal; // Is the command internal?
String *summary; // Short summary of the command
String *description; // Full description of the command
} HelpCommandData;
// Stored unpacked option data
typedef struct HelpOptionData
{
bool internal; // Is the option internal?
String *section; // eg. general, command
String *summary; // Short summary of the option
String *description; // Full description of the option
StringList *deprecatedNames; // Deprecated names for the option
} HelpOptionData;
static String *
helpRender(void)
{
@ -149,6 +173,24 @@ helpRender(void)
MEM_CONTEXT_TEMP_BEGIN()
{
// Unpack command data
PackRead *pckHelp = pckReadNewBuf(BUF(helpDataPack, sizeof(helpDataPack)));
HelpCommandData *commandData = memNew(sizeof(HelpCommandData) * CFG_COMMAND_TOTAL);
pckReadArrayBeginP(pckHelp);
for (ConfigCommand commandId = 0; commandId < CFG_COMMAND_TOTAL; commandId++)
{
commandData[commandId] = (HelpCommandData)
{
.internal = pckReadBoolP(pckHelp),
.summary = pckReadStrP(pckHelp),
.description = pckReadStrP(pckHelp),
};
}
pckReadArrayEndP(pckHelp);
// Message for more help when it is available
const String *more = NULL;
@ -169,7 +211,7 @@ helpRender(void)
for (ConfigCommand commandId = 0; commandId < CFG_COMMAND_TOTAL; commandId++)
{
if (cfgCommandInternal(commandId))
if (commandData[commandId].internal)
continue;
if (strlen(cfgCommandName(commandId)) > commandSizeMax)
@ -179,13 +221,13 @@ helpRender(void)
// Output help for each command
for (ConfigCommand commandId = 0; commandId < CFG_COMMAND_TOTAL; commandId++)
{
if (cfgCommandInternal(commandId))
if (commandData[commandId].internal)
continue;
strCatFmt(
result, " %s%*s%s\n", cfgCommandName(commandId),
(int)(commandSizeMax - strlen(cfgCommandName(commandId)) + 2), "",
strZ(helpRenderText(STR(cfgDefCommandHelpSummary(commandId)), commandSizeMax + 6, false, CONSOLE_WIDTH)));
strZ(helpRenderText(commandData[commandId].summary, commandSizeMax + 6, false, CONSOLE_WIDTH)));
}
// Construct message for more help
@ -196,6 +238,71 @@ helpRender(void)
ConfigCommand commandId = cfgCommand();
const char *commandName = cfgCommandName(commandId);
// Unpack option data
HelpOptionData *optionData = memNew(sizeof(HelpOptionData) * CFG_OPTION_TOTAL);
pckReadArrayBeginP(pckHelp);
for (ConfigOption optionId = 0; optionId < CFG_OPTION_TOTAL; optionId++)
{
optionData[optionId] = (HelpOptionData)
{
.internal = pckReadBoolP(pckHelp),
.section = pckReadStrP(pckHelp, .defaultValue = STR("general")),
.summary = pckReadStrP(pckHelp),
.description = pckReadStrP(pckHelp),
};
// Unpack deprecated names
if (!pckReadNullP(pckHelp))
{
optionData[optionId].deprecatedNames = strLstNew();
pckReadArrayBeginP(pckHelp);
while (pckReadNext(pckHelp))
strLstAdd(optionData[optionId].deprecatedNames, pckReadStrP(pckHelp));
pckReadArrayEndP(pckHelp);
ASSERT(strLstSize(optionData[optionId].deprecatedNames) == 1);
}
// Unpack command overrides
if (!pckReadNullP(pckHelp))
{
pckReadArrayBeginP(pckHelp);
while (pckReadNext(pckHelp))
{
// Get command override id
ConfigCommand commandIdArray = pckReadId(pckHelp) - 1;
// Unpack override data
pckReadObjBeginP(pckHelp, .id = commandIdArray + 1);
bool internal = pckReadBoolP(pckHelp, .defaultValue = optionData[optionId].internal);
String *summary = pckReadStrP(pckHelp, .defaultValue = optionData[optionId].summary);
String *description = pckReadStrP(pckHelp, .defaultValue = optionData[optionId].description);
pckReadObjEndP(pckHelp);
// Only use overrides for the current command
if (commandId == commandIdArray)
{
optionData[optionId].internal = internal;
optionData[optionId].section = NULL;
optionData[optionId].summary = summary;
optionData[optionId].description = description;
}
}
pckReadArrayEndP(pckHelp);
}
}
pckReadArrayEndP(pckHelp);
// Output command part of title
strCatFmt(result, " - '%s' command", commandName);
@ -210,8 +317,8 @@ helpRender(void)
"%s\n"
"\n"
"%s\n",
strZ(helpRenderText(STR(cfgDefCommandHelpSummary(commandId)), 0, true, CONSOLE_WIDTH)),
strZ(helpRenderText(STR(cfgDefCommandHelpDescription(commandId)), 0, true, CONSOLE_WIDTH)));
strZ(helpRenderText(commandData[commandId].summary, 0, true, CONSOLE_WIDTH)),
strZ(helpRenderText(commandData[commandId].description, 0, true, CONSOLE_WIDTH)));
// Construct key/value of sections and options
KeyValue *optionKv = kvNew();
@ -219,12 +326,9 @@ helpRender(void)
for (unsigned int optionId = 0; optionId < CFG_OPTION_TOTAL; optionId++)
{
if (cfgDefOptionValid(commandId, optionId) && !cfgDefOptionInternal(commandId, optionId))
if (cfgDefOptionValid(commandId, optionId) && !optionData[optionId].internal)
{
const String *section = NULL;
if (cfgDefOptionHelpSection(optionId) != NULL)
section = strNew(cfgDefOptionHelpSection(optionId));
const String *section = optionData[optionId].section;
if (section == NULL ||
(!strEqZ(section, "general") && !strEqZ(section, "log") && !strEqZ(section, "repository") &&
@ -257,9 +361,8 @@ helpRender(void)
ConfigOption optionId = varInt(varLstGet(optionList, optionIdx));
// Get option summary
String *summary = strFirstLower(strNewN(
cfgDefOptionHelpSummary(commandId, optionId),
strlen(cfgDefOptionHelpSummary(commandId, optionId)) - 1));
String *summary = strFirstLower(
strNewN(strZ(optionData[optionId].summary), strSize(optionData[optionId].summary) - 1));
// Ouput current and default values if they exist
const String *defaultValue = helpRenderValue(cfgOptionDefault(optionId), cfgDefOptionType(optionId));
@ -328,8 +431,8 @@ helpRender(void)
"\n"
"%s\n",
cfgDefOptionName(option.id),
strZ(helpRenderText(STR(cfgDefOptionHelpSummary(commandId, option.id)), 0, true, CONSOLE_WIDTH)),
strZ(helpRenderText(STR(cfgDefOptionHelpDescription(commandId, option.id)), 0, true, CONSOLE_WIDTH)));
strZ(helpRenderText(optionData[option.id].summary, 0, true, CONSOLE_WIDTH)),
strZ(helpRenderText(optionData[option.id].description, 0, true, CONSOLE_WIDTH)));
// Ouput current and default values if they exist
const String *defaultValue = helpRenderValue(cfgOptionDefault(option.id), cfgDefOptionType(option.id));
@ -350,8 +453,8 @@ helpRender(void)
}
// Output alternate name (call it deprecated so the user will know not to use it)
if (cfgDefOptionHelpNameAlt(option.id))
strCatFmt(result, "\ndeprecated name: %s\n", cfgDefOptionHelpNameAltValue(option.id, 0));
if (optionData[option.id].deprecatedNames != NULL)
strCatFmt(result, "\ndeprecated name: %s\n", strZ(strLstJoin(optionData[option.id].deprecatedNames, ", ")));
}
}

View File

@ -37,7 +37,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_ARCHIVE_GET)
CONFIG_COMMAND_INTERNAL(false)
CONFIG_COMMAND_LOG_FILE(false)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelInfo)
CONFIG_COMMAND_LOCK_REQUIRED(false)
@ -50,7 +49,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_ARCHIVE_PUSH)
CONFIG_COMMAND_INTERNAL(false)
CONFIG_COMMAND_LOG_FILE(false)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelInfo)
CONFIG_COMMAND_LOCK_REQUIRED(false)
@ -63,7 +61,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_BACKUP)
CONFIG_COMMAND_INTERNAL(false)
CONFIG_COMMAND_LOG_FILE(true)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelInfo)
CONFIG_COMMAND_LOCK_REQUIRED(true)
@ -76,7 +73,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_CHECK)
CONFIG_COMMAND_INTERNAL(false)
CONFIG_COMMAND_LOG_FILE(false)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelInfo)
CONFIG_COMMAND_LOCK_REQUIRED(false)
@ -89,7 +85,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_EXPIRE)
CONFIG_COMMAND_INTERNAL(false)
CONFIG_COMMAND_LOG_FILE(true)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelInfo)
CONFIG_COMMAND_LOCK_REQUIRED(true)
@ -102,7 +97,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_HELP)
CONFIG_COMMAND_INTERNAL(false)
CONFIG_COMMAND_LOG_FILE(false)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelDebug)
CONFIG_COMMAND_LOCK_REQUIRED(false)
@ -115,7 +109,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_INFO)
CONFIG_COMMAND_INTERNAL(false)
CONFIG_COMMAND_LOG_FILE(false)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelDebug)
CONFIG_COMMAND_LOCK_REQUIRED(false)
@ -128,7 +121,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_REPO_CREATE)
CONFIG_COMMAND_INTERNAL(true)
CONFIG_COMMAND_LOG_FILE(false)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelInfo)
CONFIG_COMMAND_LOCK_REQUIRED(false)
@ -141,7 +133,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_REPO_GET)
CONFIG_COMMAND_INTERNAL(true)
CONFIG_COMMAND_LOG_FILE(false)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelDebug)
CONFIG_COMMAND_LOCK_REQUIRED(false)
@ -154,7 +145,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_REPO_LS)
CONFIG_COMMAND_INTERNAL(true)
CONFIG_COMMAND_LOG_FILE(false)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelDebug)
CONFIG_COMMAND_LOCK_REQUIRED(false)
@ -167,7 +157,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_REPO_PUT)
CONFIG_COMMAND_INTERNAL(true)
CONFIG_COMMAND_LOG_FILE(false)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelDebug)
CONFIG_COMMAND_LOCK_REQUIRED(false)
@ -180,7 +169,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_REPO_RM)
CONFIG_COMMAND_INTERNAL(true)
CONFIG_COMMAND_LOG_FILE(false)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelDebug)
CONFIG_COMMAND_LOCK_REQUIRED(false)
@ -193,7 +181,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_RESTORE)
CONFIG_COMMAND_INTERNAL(false)
CONFIG_COMMAND_LOG_FILE(true)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelInfo)
CONFIG_COMMAND_LOCK_REQUIRED(false)
@ -206,7 +193,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_STANZA_CREATE)
CONFIG_COMMAND_INTERNAL(false)
CONFIG_COMMAND_LOG_FILE(true)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelInfo)
CONFIG_COMMAND_LOCK_REQUIRED(true)
@ -219,7 +205,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_STANZA_DELETE)
CONFIG_COMMAND_INTERNAL(false)
CONFIG_COMMAND_LOG_FILE(true)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelInfo)
CONFIG_COMMAND_LOCK_REQUIRED(true)
@ -232,7 +217,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_STANZA_UPGRADE)
CONFIG_COMMAND_INTERNAL(false)
CONFIG_COMMAND_LOG_FILE(true)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelInfo)
CONFIG_COMMAND_LOCK_REQUIRED(true)
@ -245,7 +229,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_START)
CONFIG_COMMAND_INTERNAL(false)
CONFIG_COMMAND_LOG_FILE(true)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelInfo)
CONFIG_COMMAND_LOCK_REQUIRED(false)
@ -258,7 +241,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_STOP)
CONFIG_COMMAND_INTERNAL(false)
CONFIG_COMMAND_LOG_FILE(true)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelInfo)
CONFIG_COMMAND_LOCK_REQUIRED(false)
@ -271,7 +253,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_VERIFY)
CONFIG_COMMAND_INTERNAL(true)
CONFIG_COMMAND_LOG_FILE(true)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelInfo)
CONFIG_COMMAND_LOCK_REQUIRED(false)
@ -284,7 +265,6 @@ static ConfigCommandData configCommandData[CFG_COMMAND_TOTAL] = CONFIG_COMMAND_L
(
CONFIG_COMMAND_NAME(CFGCMD_VERSION)
CONFIG_COMMAND_INTERNAL(false)
CONFIG_COMMAND_LOG_FILE(false)
CONFIG_COMMAND_LOG_LEVEL_DEFAULT(logLevelDebug)
CONFIG_COMMAND_LOCK_REQUIRED(false)

View File

@ -18,7 +18,6 @@ typedef struct ConfigCommandData
{
const char *name;
bool internal:1;
bool lockRequired:1;
bool lockRemoteRequired:1;
unsigned int lockType:2;
@ -35,8 +34,6 @@ typedef struct ConfigCommandData
#define CONFIG_COMMAND(...) \
{__VA_ARGS__},
#define CONFIG_COMMAND_INTERNAL(internalParam) \
.internal = internalParam,
#define CONFIG_COMMAND_LOCK_REQUIRED(lockRequiredParam) \
.lockRequired = lockRequiredParam,
#define CONFIG_COMMAND_LOCK_REMOTE_REQUIRED(lockRemoteRequiredParam) \
@ -302,19 +299,6 @@ cfgExe(void)
FUNCTION_TEST_RETURN(configLocal->exe);
}
/**********************************************************************************************************************************/
bool
cfgCommandInternal(ConfigCommand commandId)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, commandId);
FUNCTION_TEST_END();
ASSERT(commandId < cfgCmdNone);
FUNCTION_TEST_RETURN(configCommandData[commandId].internal);
}
/**********************************************************************************************************************************/
bool
cfgLockRequired(void)

View File

@ -63,9 +63,6 @@ ConfigCommand cfgCommand(void);
// Current command role (async, local, remote)
ConfigCommandRole cfgCommandRole(void);
// Is this command internal-only?
bool cfgCommandInternal(ConfigCommand commandId);
// Get command name by id
const char *cfgCommandName(ConfigCommand commandId);

File diff suppressed because it is too large Load Diff

View File

@ -22,9 +22,6 @@ Map command names to ids and vice versa.
typedef struct ConfigDefineCommandData
{
const char *name; // Command name
const char *helpSummary; // Brief summary of the command
const char *helpDescription; // Full description of the command
} ConfigDefineCommandData;
// Command macros are intended to make the command definitions easy to read and to produce good diffs.
@ -38,11 +35,6 @@ typedef struct ConfigDefineCommandData
#define CFGDEFDATA_COMMAND_NAME(nameParam) \
.name = nameParam,
#define CFGDEFDATA_COMMAND_HELP_SUMMARY(helpSummaryParam) \
.helpSummary = helpSummaryParam,
#define CFGDEFDATA_COMMAND_HELP_DESCRIPTION(helpDescriptionParam) \
.helpDescription = helpDescriptionParam,
/***********************************************************************************************************************************
Define how an option is parsed and interacts with other options.
***********************************************************************************************************************************/
@ -50,16 +42,11 @@ typedef struct ConfigDefineOptionData
{
const char *name; // Option name
unsigned int type:3; // Option type (e.g. string, int, boolean, etc.)
unsigned int internal:1; // Is the option only used internally?
unsigned int section:2; // Config section (e.g. global, stanza, cmd-line)
bool required:1; // Is the option required?
bool secure:1; // Does the option need to be redacted on logs and cmd-line?
unsigned int commandValid:20; // Bitmap for commands that the option is valid for
const char *helpSection; // Classify the option
const char *helpSummary; // Brief summary of the option
const char *helpDescription; // Full description of the option
const void **data; // Optional data and command overrides
} ConfigDefineOptionData;
@ -73,8 +60,6 @@ typedef struct ConfigDefineOptionData
#define CFGDEFDATA_OPTION_NAME(nameParam) \
.name = nameParam,
#define CFGDEFDATA_OPTION_INTERNAL(internalParam) \
.internal = internalParam,
#define CFGDEFDATA_OPTION_REQUIRED(requiredParam) \
.required = requiredParam,
#define CFGDEFDATA_OPTION_SECTION(sectionParam) \
@ -84,13 +69,6 @@ typedef struct ConfigDefineOptionData
#define CFGDEFDATA_OPTION_TYPE(typeParam) \
.type = typeParam,
#define CFGDEFDATA_OPTION_HELP_SECTION(helpSectionParam) \
.helpSection = helpSectionParam,
#define CFGDEFDATA_OPTION_HELP_SUMMARY(helpSummaryParam) \
.helpSummary = helpSummaryParam,
#define CFGDEFDATA_OPTION_HELP_DESCRIPTION(helpDescriptionParam) \
.helpDescription = helpDescriptionParam,
// Define additional types of data that can be associated with an option. Because these types are rare they are not give dedicated
// fields and are instead packed into an array which is read at runtime. This may seem inefficient but they are only accessed a
// single time during parse so space efficiency is more important than performance.
@ -103,11 +81,7 @@ typedef enum
configDefDataTypeCommand,
configDefDataTypeDefault,
configDefDataTypeDepend,
configDefDataTypeInternal,
configDefDataTypeRequired,
configDefDataTypeHelpNameAlt,
configDefDataTypeHelpSummary,
configDefDataTypeHelpDescription,
} ConfigDefineDataType;
#define CFGDATA_OPTION_OPTIONAL_PUSH_LIST(type, size, data, ...) \
@ -153,20 +127,9 @@ typedef enum
#define CFGDEFDATA_OPTION_OPTIONAL_COMMAND(command) \
CFGDATA_OPTION_OPTIONAL_PUSH(configDefDataTypeCommand, 0, command),
#define CFGDEFDATA_OPTION_OPTIONAL_INTERNAL(commandOptionInternal) \
CFGDATA_OPTION_OPTIONAL_PUSH(configDefDataTypeInternal, 0, commandOptionInternal),
#define CFGDEFDATA_OPTION_OPTIONAL_REQUIRED(commandOptionRequired) \
CFGDATA_OPTION_OPTIONAL_PUSH(configDefDataTypeRequired, 0, commandOptionRequired),
#define CFGDEFDATA_OPTION_OPTIONAL_HELP_NAME_ALT(...) \
CFGDATA_OPTION_OPTIONAL_PUSH_LIST( \
configDefDataTypeHelpNameAlt, sizeof((const char *[]){__VA_ARGS__}) / sizeof(const char *), 0, __VA_ARGS__),
#define CFGDEFDATA_OPTION_OPTIONAL_HELP_SUMMARY(helpSummaryParam) \
CFGDATA_OPTION_OPTIONAL_PUSH_LIST(configDefDataTypeHelpSummary, 1, 0, helpSummaryParam),
#define CFGDEFDATA_OPTION_OPTIONAL_HELP_DESCRIPTION(helpDescriptionParam) \
CFGDATA_OPTION_OPTIONAL_PUSH_LIST(configDefDataTypeHelpDescription, 1, 0, helpDescriptionParam),
/***********************************************************************************************************************************
Include the automatically generated configuration data.
***********************************************************************************************************************************/
@ -270,31 +233,6 @@ cfgDefOptionTotal(void)
FUNCTION_TEST_RETURN(sizeof(configDefineOptionData) / sizeof(ConfigDefineOptionData));
}
/**********************************************************************************************************************************/
const char *
cfgDefCommandHelpDescription(ConfigCommand commandId)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, commandId);
FUNCTION_TEST_END();
ASSERT(commandId < cfgDefCommandTotal());
FUNCTION_TEST_RETURN(configDefineCommandData[commandId].helpDescription);
}
const char *
cfgDefCommandHelpSummary(ConfigCommand commandId)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, commandId);
FUNCTION_TEST_END();
ASSERT(commandId < cfgDefCommandTotal());
FUNCTION_TEST_RETURN(configDefineCommandData[commandId].helpSummary);
}
/**********************************************************************************************************************************/
bool
cfgDefOptionAllowList(ConfigCommand commandId, ConfigOption optionId)
@ -534,108 +472,6 @@ cfgDefOptionDependValueValid(ConfigCommand commandId, ConfigOption optionId, con
FUNCTION_TEST_RETURN(result);
}
/**********************************************************************************************************************************/
const char *
cfgDefOptionHelpDescription(ConfigCommand commandId, ConfigOption optionId)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, commandId);
FUNCTION_TEST_PARAM(ENUM, optionId);
FUNCTION_TEST_END();
ASSERT(commandId < cfgDefCommandTotal());
ASSERT(optionId < cfgDefOptionTotal());
CONFIG_DEFINE_DATA_FIND(commandId, optionId, configDefDataTypeHelpDescription);
const char *result = configDefineOptionData[optionId].helpDescription;
if (dataDefFound)
result = (char *)dataDefList[0];
FUNCTION_TEST_RETURN(result);
}
/**********************************************************************************************************************************/
bool
cfgDefOptionHelpNameAlt(ConfigOption optionId)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, optionId);
FUNCTION_TEST_END();
ASSERT(optionId < cfgDefOptionTotal());
CONFIG_DEFINE_DATA_FIND(-1, optionId, configDefDataTypeHelpNameAlt);
FUNCTION_TEST_RETURN(dataDefFound);
}
const char *
cfgDefOptionHelpNameAltValue(ConfigOption optionId, unsigned int valueId)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, optionId);
FUNCTION_TEST_PARAM(UINT, valueId);
FUNCTION_TEST_END();
ASSERT(optionId < cfgDefOptionTotal());
ASSERT(valueId < cfgDefOptionHelpNameAltValueTotal(optionId));
CONFIG_DEFINE_DATA_FIND(-1, optionId, configDefDataTypeHelpNameAlt);
FUNCTION_TEST_RETURN((char *)dataDefList[valueId]);
}
unsigned int
cfgDefOptionHelpNameAltValueTotal(ConfigOption optionId)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, optionId);
FUNCTION_TEST_END();
ASSERT(optionId < cfgDefOptionTotal());
CONFIG_DEFINE_DATA_FIND(-1, optionId, configDefDataTypeHelpNameAlt);
FUNCTION_TEST_RETURN(dataDefListSize);
}
/**********************************************************************************************************************************/
const char *
cfgDefOptionHelpSection(ConfigOption optionId)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, optionId);
FUNCTION_TEST_END();
ASSERT(optionId < cfgDefOptionTotal());
FUNCTION_TEST_RETURN(configDefineOptionData[optionId].helpSection);
}
/**********************************************************************************************************************************/
const char *
cfgDefOptionHelpSummary(ConfigCommand commandId, ConfigOption optionId)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, commandId);
FUNCTION_TEST_PARAM(ENUM, optionId);
FUNCTION_TEST_END();
ASSERT(commandId < cfgDefCommandTotal());
ASSERT(optionId < cfgDefOptionTotal());
CONFIG_DEFINE_DATA_FIND(commandId, optionId, configDefDataTypeHelpSummary);
const char *result = configDefineOptionData[optionId].helpSummary;
if (dataDefFound)
result = (char *)dataDefList[0];
FUNCTION_TEST_RETURN(result);
}
/**********************************************************************************************************************************/
int
cfgDefOptionId(const char *optionName)
@ -655,28 +491,6 @@ cfgDefOptionId(const char *optionName)
FUNCTION_TEST_RETURN(result);
}
/**********************************************************************************************************************************/
bool
cfgDefOptionInternal(ConfigCommand commandId, ConfigOption optionId)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, commandId);
FUNCTION_TEST_PARAM(ENUM, optionId);
FUNCTION_TEST_END();
ASSERT(commandId < cfgDefCommandTotal());
ASSERT(optionId < cfgDefOptionTotal());
CONFIG_DEFINE_DATA_FIND(commandId, optionId, configDefDataTypeInternal);
bool result = configDefineOptionData[optionId].internal;
if (dataDefFound)
result = (bool)dataDef;
FUNCTION_TEST_RETURN(result);
}
/**********************************************************************************************************************************/
bool
cfgDefOptionMulti(ConfigOption optionId)

View File

@ -32,10 +32,6 @@ Functions
// Command total
unsigned int cfgDefCommandTotal(void);
// Command help
const char *cfgDefCommandHelpDescription(ConfigCommand commandId);
const char *cfgDefCommandHelpSummary(ConfigCommand commandId);
// Option allow lists
bool cfgDefOptionAllowList(ConfigCommand commandId, ConfigOption optionId);
bool cfgDefOptionAllowListValueValid(ConfigCommand commandId, ConfigOption optionId, const char *value);
@ -55,24 +51,9 @@ unsigned int cfgDefOptionDependValueTotal(ConfigCommand commandId, ConfigOption
bool cfgDefOptionDependValueValid(ConfigCommand commandId, ConfigOption optionId, const char *value);
const char *cfgDefOptionDependValue(ConfigCommand commandId, ConfigOption optionId, unsigned int valueId);
// Option help
const char *cfgDefOptionHelpDescription(ConfigCommand commandId, ConfigOption optionId);
const char *cfgDefOptionHelpSummary(ConfigCommand commandId, ConfigOption optionId);
// Option help name alt
bool cfgDefOptionHelpNameAlt(ConfigOption optionId);
const char *cfgDefOptionHelpNameAltValue(ConfigOption optionId, unsigned int valueId);
unsigned int cfgDefOptionHelpNameAltValueTotal(ConfigOption optionId);
// Option help section
const char *cfgDefOptionHelpSection(ConfigOption optionId);
// Option id by name
int cfgDefOptionId(const char *optionName);
// Is the option for internal use only?
bool cfgDefOptionInternal(ConfigCommand commandId, ConfigOption optionId);
// Does the option accept multiple values?
bool cfgDefOptionMulti(ConfigOption optionId);

View File

@ -19,6 +19,10 @@ build/lib/pgBackRestBuild/Config/BuildDefine.pm:
class: build
type: perl
build/lib/pgBackRestBuild/Config/BuildHelp.pm:
class: build
type: perl
build/lib/pgBackRestBuild/Config/BuildParse.pm:
class: build
type: perl
@ -363,6 +367,10 @@ src/command/expire/expire.h:
class: core
type: c/h
src/command/help/help.auto.c:
class: core/auto
type: c
src/command/help/help.c:
class: core
type: c

View File

@ -365,7 +365,7 @@ unit:
test:
# ----------------------------------------------------------------------------------------------------------------------------
- name: define
total: 2
total: 1
coverage:
config/define: full
@ -659,6 +659,7 @@ unit:
coverage:
command/help/help: full
command/help/help.auto: noCode
# ----------------------------------------------------------------------------------------------------------------------------
- name: info

View File

@ -77,14 +77,12 @@ testRun(void)
TEST_RESULT_BOOL(
cfgDefOptionDependValueValid(cfgCmdRestore, cfgOptTarget, BOGUS_STR), false, "depend option value not valid");
TEST_RESULT_BOOL(cfgDefOptionInternal(cfgCmdRestore, cfgOptSet), false, "option set is not internal");
TEST_RESULT_BOOL(cfgDefOptionInternal(cfgCmdRestore, cfgOptPgHost), true, "option pg-host is internal");
TEST_RESULT_BOOL(cfgDefOptionMulti(cfgOptRecoveryOption), true, "recovery-option is multi");
TEST_RESULT_BOOL(cfgDefOptionMulti(cfgOptDbInclude), true, "db-include is multi");
TEST_RESULT_BOOL(cfgDefOptionMulti(cfgOptStartFast), false, "start-fast is not multi");
TEST_RESULT_BOOL(cfgDefOptionRequired(cfgCmdBackup, cfgOptConfig), true, "option required");
TEST_RESULT_BOOL(cfgDefOptionRequired(cfgCmdBackup, cfgOptForce), true, "option required");
TEST_RESULT_BOOL(cfgDefOptionRequired(cfgCmdRestore, cfgOptRepoHost), false, "option not required");
TEST_RESULT_BOOL(cfgDefOptionRequired(cfgCmdInfo, cfgOptStanza), false, "command option not required");
@ -105,42 +103,5 @@ testRun(void)
TEST_RESULT_BOOL(cfgDefOptionValid(cfgCmdInfo, cfgOptType), false, "option not valid");
}
// *****************************************************************************************************************************
if (testBegin("cfgDefCommandHelp*() and cfgDefOptionHelp*()"))
{
TEST_RESULT_BOOL(cfgDefOptionHelpNameAlt(cfgOptRepoHost), true, "name alt exists");
TEST_RESULT_BOOL(cfgDefOptionHelpNameAlt(cfgOptSet), false, "name alt not exists");
TEST_RESULT_INT(cfgDefOptionHelpNameAltValueTotal(cfgOptRepoHost), 1, "name alt value total");
TEST_RESULT_Z(cfgDefOptionHelpNameAltValue(cfgOptRepoHost, 0), "backup-host", "name alt value 0");
TEST_ERROR(
cfgDefOptionHelpNameAltValue(cfgOptRepoHost, 1), AssertError,
"assertion 'valueId < cfgDefOptionHelpNameAltValueTotal(optionId)' failed");
TEST_RESULT_Z(cfgDefCommandHelpSummary(cfgCmdBackup), "Backup a database cluster.", "backup command help summary");
TEST_RESULT_Z(
cfgDefCommandHelpDescription(cfgCmdBackup),
"pgBackRest does not have a built-in scheduler so it's best to run it from cron or some other scheduling mechanism.",
"backup command help description");
TEST_RESULT_Z(cfgDefOptionHelpSection(cfgOptDelta), "general", "delta option help section");
TEST_RESULT_Z(
cfgDefOptionHelpSummary(cfgCmdBackup, cfgOptBufferSize), "Buffer size for file operations.",
"backup command, delta option help summary");
TEST_RESULT_Z(
cfgDefOptionHelpSummary(cfgCmdBackup, cfgOptType), "Backup type.", "backup command, type option help summary");
TEST_RESULT_Z(
cfgDefOptionHelpDescription(cfgCmdBackup, cfgOptLogSubprocess),
"Enable file logging for any subprocesses created by this process using the log level specified by log-level-file.",
"backup command, log-subprocess option help description");
TEST_RESULT_Z(
cfgDefOptionHelpDescription(cfgCmdBackup, cfgOptType),
"The following backup types are supported:\n"
"\n"
"* full - all database cluster files will be copied and there will be no dependencies on previous backups.\n"
"* incr - incremental from the last successful backup.\n"
"* diff - like an incremental backup but always based on the last full backup.",
"backup command, type option help description");
}
FUNCTION_HARNESS_RESULT_VOID();
}

View File

@ -1121,7 +1121,6 @@ testRun(void)
setenv("PGBACKREST_REPO1_S3_KEY_SECRET", "xxx", true);
TEST_RESULT_VOID(configParse(strLstSize(argList), strLstPtr(argList), false), TEST_COMMAND_BACKUP " command");
TEST_RESULT_INT(cfgCommand(), cfgCmdBackup, " command is " TEST_COMMAND_BACKUP);
TEST_RESULT_BOOL(cfgCommandInternal(cfgCmdBackup), false, " backup command is not internal");
TEST_RESULT_BOOL(cfgLockRequired(), true, " backup command requires lock");
TEST_RESULT_UINT(cfgLockType(), lockTypeBackup, " backup command requires backup lock type");
TEST_RESULT_UINT(cfgLogLevelDefault(), logLevelInfo, " backup defaults to log level warn");

View File

@ -37,6 +37,7 @@ use pgBackRestBuild::Build;
use pgBackRestBuild::Build::Common;
use pgBackRestBuild::Config::Build;
use pgBackRestBuild::Config::BuildDefine;
use pgBackRestBuild::Config::BuildHelp;
use pgBackRestBuild::Config::BuildParse;
use pgBackRestBuild::Error::Build;
use pgBackRestBuild::Error::Data;
@ -573,6 +574,12 @@ eval
&BLD_PATH => 'config',
},
'configHelp' =>
{
&BLD_DATA => buildConfigHelp(),
&BLD_PATH => 'command/help',
},
'configDefine' =>
{
&BLD_DATA => buildConfigDefine(),