mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-14 10:13:05 +02:00
425 lines
15 KiB
Perl
425 lines
15 KiB
Perl
####################################################################################################################################
|
|
# CONFIG HELP MODULE
|
|
####################################################################################################################################
|
|
package pgBackRest::Config::ConfigHelp;
|
|
|
|
use strict;
|
|
use warnings FATAL => qw(all);
|
|
use Carp qw(confess);
|
|
|
|
use Exporter qw(import);
|
|
our @EXPORT = qw();
|
|
use File::Basename qw(dirname);
|
|
|
|
use pgBackRest::Common::Exception;
|
|
use pgBackRest::Common::Ini;
|
|
use pgBackRest::Common::Log;
|
|
use pgBackRest::Common::String;
|
|
use pgBackRest::Config::Config;
|
|
use pgBackRest::Version;
|
|
|
|
####################################################################################################################################
|
|
# Help types
|
|
####################################################################################################################################
|
|
use constant CONFIG_HELP_COMMAND => 'command';
|
|
push @EXPORT, qw(CONFIG_HELP_COMMAND);
|
|
use constant CONFIG_HELP_CURRENT => 'current';
|
|
push @EXPORT, qw(CONFIG_HELP_CURRENT);
|
|
use constant CONFIG_HELP_DEFAULT => 'default';
|
|
push @EXPORT, qw(CONFIG_HELP_DEFAULT);
|
|
use constant CONFIG_HELP_DESCRIPTION => 'description';
|
|
push @EXPORT, qw(CONFIG_HELP_DESCRIPTION);
|
|
use constant CONFIG_HELP_OPTION => 'option';
|
|
push @EXPORT, qw(CONFIG_HELP_OPTION);
|
|
use constant CONFIG_HELP_SECTION => 'section';
|
|
push @EXPORT, qw(CONFIG_HELP_SECTION);
|
|
use constant CONFIG_HELP_SUMMARY => 'summary';
|
|
push @EXPORT, qw(CONFIG_HELP_SUMMARY);
|
|
|
|
use constant CONFIG_HELP_SOURCE => 'source';
|
|
push @EXPORT, qw(CONFIG_HELP_SOURCE);
|
|
use constant CONFIG_HELP_SOURCE_DEFAULT => 'default';
|
|
push @EXPORT, qw(CONFIG_HELP_SOURCE_DEFAULT);
|
|
use constant CONFIG_HELP_SOURCE_SECTION => CONFIG_HELP_SECTION;
|
|
push @EXPORT, qw(CONFIG_HELP_SOURCE_SECTION);
|
|
use constant CONFIG_HELP_SOURCE_COMMAND => CONFIG_HELP_COMMAND;
|
|
push @EXPORT, qw(CONFIG_HELP_SOURCE_COMMAND);
|
|
|
|
####################################################################################################################################
|
|
# Config Section Types
|
|
####################################################################################################################################
|
|
use constant CONFIG_SECTION_COMMAND => 'command';
|
|
push @EXPORT, qw(CONFIG_SECTION_COMMAND);
|
|
use constant CONFIG_SECTION_GENERAL => 'general';
|
|
push @EXPORT, qw(CONFIG_SECTION_GENERAL);
|
|
use constant CONFIG_SECTION_LOG => 'log';
|
|
push @EXPORT, qw(CONFIG_SECTION_LOG);
|
|
use constant CONFIG_SECTION_EXPIRE => 'expire';
|
|
push @EXPORT, qw(CONFIG_SECTION_EXPIRE);
|
|
use constant CONFIG_SECTION_REPOSITORY => 'repository';
|
|
push @EXPORT, qw(CONFIG_SECTION_REPOSITORY);
|
|
|
|
####################################################################################################################################
|
|
# configHelp
|
|
#
|
|
# Display command-line help.
|
|
####################################################################################################################################
|
|
sub configHelp
|
|
{
|
|
my $strCommand = shift;
|
|
my $strOption = shift;
|
|
my $bVersion = shift;
|
|
my $bConfigResult = shift;
|
|
|
|
# Load module dynamically
|
|
require pgBackRest::Config::ConfigHelpData;
|
|
pgBackRest::Config::ConfigHelpData->import();
|
|
|
|
# Get config data
|
|
my $oConfigHelpData = configHelpDataGet();
|
|
|
|
# Build version
|
|
my $strVersion = (!$bConfigResult ? "\n" : '') . BACKREST_NAME . ' ' . BACKREST_VERSION;
|
|
|
|
# Display version
|
|
if ($bVersion)
|
|
{
|
|
syswrite(*STDOUT, "${strVersion}\n");
|
|
return;
|
|
}
|
|
|
|
# Build the title
|
|
my $strTitle;
|
|
my $strHelp;
|
|
|
|
# Since there's no command this will be general help
|
|
if (!defined($strCommand))
|
|
{
|
|
$strTitle = "General"
|
|
}
|
|
# Else check the command
|
|
else
|
|
{
|
|
$strCommand = lc($strCommand);
|
|
|
|
if (defined($oConfigHelpData->{&CONFIG_HELP_COMMAND}{$strCommand}))
|
|
{
|
|
$strTitle = "'${strCommand}' command";
|
|
|
|
# And check the option
|
|
if (defined($strOption))
|
|
{
|
|
$strOption = lc($strOption);
|
|
|
|
if (defined($$oConfigHelpData{&CONFIG_HELP_COMMAND}{$strCommand}{&CONFIG_HELP_OPTION}{$strOption}))
|
|
{
|
|
$strTitle .= " - '${strOption}' option";
|
|
}
|
|
else
|
|
{
|
|
$strHelp = "Invalid option '${strOption}' for command '${strCommand}'";
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$strHelp = "Invalid command '${strCommand}'";
|
|
}
|
|
}
|
|
|
|
# Build the help
|
|
my $strMore;
|
|
|
|
if (!defined($strHelp))
|
|
{
|
|
my $iScreenWidth = 80;
|
|
|
|
# General help
|
|
if (!defined($strCommand))
|
|
{
|
|
$strHelp =
|
|
"Usage:\n" .
|
|
" " . BACKREST_EXE . " [options] [command]\n\n" .
|
|
"Commands:\n";
|
|
|
|
# Find longest command length
|
|
my $iCommandLength = 0;
|
|
|
|
foreach my $strCommand (sort(keys(%{$$oConfigHelpData{&CONFIG_HELP_COMMAND}})))
|
|
{
|
|
if (length($strCommand) > $iCommandLength)
|
|
{
|
|
$iCommandLength = length($strCommand);
|
|
}
|
|
}
|
|
|
|
# Output commands
|
|
foreach my $strCommand (sort(keys(%{$$oConfigHelpData{&CONFIG_HELP_COMMAND}})))
|
|
{
|
|
my $oCommand = $$oConfigHelpData{&CONFIG_HELP_COMMAND}{$strCommand};
|
|
|
|
$strHelp .= " ${strCommand}" . (' ' x ($iCommandLength - length($strCommand)));
|
|
$strHelp .=
|
|
' ' .
|
|
configHelpFormatText($$oCommand{&CONFIG_HELP_SUMMARY}, 4 + $iCommandLength + 2, false, $iScreenWidth + 1) .
|
|
"\n";
|
|
}
|
|
|
|
$strMore = '[command]';
|
|
}
|
|
# Else command help
|
|
elsif (!defined($strOption))
|
|
{
|
|
my $oCommand = $$oConfigHelpData{&CONFIG_HELP_COMMAND}{$strCommand};
|
|
|
|
$strHelp =
|
|
configHelpFormatText($$oCommand{&CONFIG_HELP_SUMMARY} . "\n\n" .
|
|
$$oCommand{&CONFIG_HELP_DESCRIPTION}, 0, true, $iScreenWidth + 1);
|
|
|
|
# Find longest option length and unique list of sections
|
|
my $iOptionLength = 0;
|
|
my $oSection = {};
|
|
|
|
if (defined($$oCommand{&CONFIG_HELP_OPTION}))
|
|
{
|
|
foreach my $strOption (sort(keys(%{$$oCommand{&CONFIG_HELP_OPTION}})))
|
|
{
|
|
if (length($strOption) > $iOptionLength)
|
|
{
|
|
$iOptionLength = length($strOption);
|
|
}
|
|
|
|
my ($oOption, $strSection) = configHelpOptionFind($oConfigHelpData, $strCommand, $strOption);
|
|
|
|
$$oSection{$strSection}{$strOption} = $oOption;
|
|
}
|
|
|
|
# Iterate sections
|
|
foreach my $strSection (sort(keys(%{$oSection})))
|
|
{
|
|
$strHelp .=
|
|
"\n\n" . ucfirst($strSection) . " Options:\n";
|
|
|
|
# Iterate options
|
|
foreach my $strOption (sort(keys(%{$$oSection{$strSection}})))
|
|
{
|
|
$strHelp .= "\n";
|
|
|
|
my $iIndent = 4 + $iOptionLength + 2;
|
|
my $oOption = $$oSection{$strSection}{$strOption};
|
|
|
|
# Set current and default values
|
|
my $strDefault = '';
|
|
|
|
if ($$oOption{&CONFIG_HELP_CURRENT} || $$oOption{&CONFIG_HELP_DEFAULT})
|
|
{
|
|
$strDefault = undef;
|
|
|
|
if ($$oOption{&CONFIG_HELP_CURRENT})
|
|
{
|
|
$strDefault .= 'current=' . $$oOption{&CONFIG_HELP_CURRENT};
|
|
}
|
|
|
|
if ($$oOption{&CONFIG_HELP_DEFAULT})
|
|
{
|
|
if (defined($strDefault))
|
|
{
|
|
$strDefault .= ', ';
|
|
}
|
|
|
|
$strDefault .= 'default=' . $$oOption{&CONFIG_HELP_DEFAULT};
|
|
}
|
|
|
|
$strDefault = " [${strDefault}]";
|
|
}
|
|
|
|
# Output help
|
|
$strHelp .= " --${strOption}" . (' ' x ($iOptionLength - length($strOption)));
|
|
$strHelp .= ' ' . configHelpFormatText(lcfirst(substr($$oOption{&CONFIG_HELP_SUMMARY}, 0,
|
|
length($$oOption{&CONFIG_HELP_SUMMARY}) - 1)) .
|
|
$strDefault, $iIndent, false, $iScreenWidth + 1);
|
|
}
|
|
}
|
|
|
|
$strMore = "${strCommand} [option]";
|
|
$strHelp .= "\n";
|
|
}
|
|
}
|
|
# Else option help
|
|
else
|
|
{
|
|
my ($oOption) = configHelpOptionFind($oConfigHelpData, $strCommand, $strOption);
|
|
|
|
# Set current and default values
|
|
my $strDefault = '';
|
|
|
|
if ($$oOption{&CONFIG_HELP_CURRENT} || $$oOption{&CONFIG_HELP_DEFAULT})
|
|
{
|
|
$strDefault = undef;
|
|
|
|
if ($$oOption{&CONFIG_HELP_CURRENT})
|
|
{
|
|
$strDefault = 'current: ' . $$oOption{&CONFIG_HELP_CURRENT};
|
|
}
|
|
|
|
if ($$oOption{&CONFIG_HELP_DEFAULT})
|
|
{
|
|
if (defined($strDefault))
|
|
{
|
|
$strDefault .= "\n";
|
|
}
|
|
|
|
$strDefault .= 'default: ' . $$oOption{&CONFIG_HELP_DEFAULT};
|
|
}
|
|
|
|
$strDefault = "\n\n${strDefault}";
|
|
}
|
|
|
|
# Output help
|
|
$strHelp =
|
|
configHelpFormatText($$oOption{&CONFIG_HELP_SUMMARY} . "\n\n" . $$oOption{&CONFIG_HELP_DESCRIPTION} .
|
|
$strDefault, 0, true, $iScreenWidth + 1);
|
|
}
|
|
}
|
|
|
|
# Output help
|
|
syswrite(*STDOUT, "${strVersion} -" . (defined($strTitle) ? " ${strTitle}" : '') . " help\n\n${strHelp}\n" .
|
|
(defined($strMore) ? 'Use \'' . BACKREST_EXE . " help ${strMore}' for more information.\n" : ''));
|
|
}
|
|
|
|
push @EXPORT, qw(configHelp);
|
|
|
|
# Helper function for configHelp() to make output look good on a console
|
|
sub configHelpFormatText
|
|
{
|
|
my $strTextIn = shift;
|
|
my $iIndent = shift;
|
|
my $bIndentFirst = shift;
|
|
my $iLength = shift;
|
|
|
|
my @stryText = split("\n", trim($strTextIn));
|
|
my $strText;
|
|
my $iIndex = 0;
|
|
|
|
foreach my $strLine (@stryText)
|
|
{
|
|
if (defined($strText))
|
|
{
|
|
$strText .= "\n";
|
|
}
|
|
|
|
my $strPart;
|
|
my $bFirst = true;
|
|
|
|
do
|
|
{
|
|
($strPart, $strLine) = stringSplit($strLine, ' ', $iLength - $iIndent);
|
|
|
|
if (!$bFirst || $bIndentFirst)
|
|
{
|
|
if (!$bFirst)
|
|
{
|
|
$strText .= "\n";
|
|
}
|
|
|
|
$strText .= ' ' x $iIndent;
|
|
}
|
|
|
|
$strText .= trim($strPart);
|
|
|
|
$bFirst = false;
|
|
}
|
|
while (defined($strLine));
|
|
|
|
$iIndex++;
|
|
}
|
|
|
|
return $strText;
|
|
}
|
|
|
|
# Helper function for configHelp() to find options. The option may be stored with the command or in the option list depending on
|
|
# whether it's generic or command-specific
|
|
sub configHelpOptionFind
|
|
{
|
|
my $oConfigHelpData = shift;
|
|
my $strCommand = shift;
|
|
my $strOption = shift;
|
|
|
|
my $strSection = CONFIG_HELP_COMMAND;
|
|
my $oOption = $$oConfigHelpData{&CONFIG_HELP_COMMAND}{$strCommand}{&CONFIG_HELP_OPTION}{$strOption};
|
|
my $iCommandId = cfgCommandId($strCommand);
|
|
my $iOptionId = cfgOptionId($strOption);
|
|
|
|
# If not found then this is an indexed value
|
|
if ($iOptionId eq -1)
|
|
{
|
|
my $strPrefix = substr($strOption, 0, index($strOption, '-'));
|
|
$iOptionId = cfgOptionId("${strPrefix}1" . substr($strOption, index($strOption, '-')));
|
|
|
|
# If still not found then error
|
|
if ($iOptionId eq -1)
|
|
{
|
|
confess &log(ASSERT, "option '${strOption}' not found in help");
|
|
}
|
|
}
|
|
|
|
if (ref(\$oOption) eq 'SCALAR')
|
|
{
|
|
$oOption = $$oConfigHelpData{&CONFIG_HELP_OPTION}{$strOption};
|
|
|
|
if (defined($$oOption{&CONFIG_HELP_SECTION}))
|
|
{
|
|
$strSection = $$oOption{&CONFIG_HELP_SECTION};
|
|
|
|
if ($strSection eq CONFIG_SECTION_COMMAND)
|
|
{
|
|
$strSection = CONFIG_SECTION_GENERAL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$strSection = CONFIG_SECTION_GENERAL;
|
|
}
|
|
|
|
if (($strSection ne CONFIG_SECTION_GENERAL && $strSection ne CONFIG_SECTION_LOG &&
|
|
$strSection ne CONFIG_SECTION_REPOSITORY && $strSection ne CFGDEF_SECTION_STANZA &&
|
|
$strSection ne CONFIG_SECTION_EXPIRE) ||
|
|
$strSection eq $strCommand)
|
|
{
|
|
$strSection = CONFIG_HELP_COMMAND;
|
|
}
|
|
}
|
|
|
|
# Check if the current set value is default (some defaults are set at runtime and are not in the defines)
|
|
if (defined(cfgOption($iOptionId, false, false)) && cfgOptionSource($iOptionId, false) eq CONFIG_HELP_SOURCE_DEFAULT)
|
|
{
|
|
$oOption->{&CONFIG_HELP_DEFAULT} = cfgOption($iOptionId, true, false);
|
|
}
|
|
|
|
# If no default is set see if there is a default in the defines
|
|
if (!defined($oOption->{&CONFIG_HELP_DEFAULT}) && defined(cfgDefOptionDefault($iCommandId, $iOptionId)))
|
|
{
|
|
$oOption->{&CONFIG_HELP_DEFAULT} = cfgDefOptionDefault($iCommandId, $iOptionId);
|
|
}
|
|
|
|
# Format the default properly if it is a boolean
|
|
if (defined($oOption->{&CONFIG_HELP_DEFAULT}) && cfgDefOptionType($iOptionId) eq CFGDEF_TYPE_BOOLEAN)
|
|
{
|
|
$oOption->{&CONFIG_HELP_DEFAULT} = $oOption->{&CONFIG_HELP_DEFAULT} ? 'y' : 'n';
|
|
}
|
|
|
|
if (defined(cfgOption($iOptionId, false, false)) && cfgOptionSource($iOptionId, false) ne CONFIG_HELP_SOURCE_DEFAULT)
|
|
{
|
|
$oOption->{&CONFIG_HELP_CURRENT} = cfgOption($iOptionId, true, false);
|
|
|
|
if (cfgDefOptionType($iOptionId) eq CFGDEF_TYPE_BOOLEAN)
|
|
{
|
|
$$oOption{&CONFIG_HELP_CURRENT} = $oOption->{&CONFIG_HELP_CURRENT} ? 'y' : 'n';
|
|
}
|
|
}
|
|
|
|
return $oOption, $strSection;
|
|
}
|
|
|
|
1;
|