2015-09-08 13:31:24 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# DOC CONFIG MODULE
|
|
|
|
####################################################################################################################################
|
2015-10-28 11:10:36 +02:00
|
|
|
package BackRestDoc::Common::DocConfig;
|
2015-09-08 13:31:24 +02:00
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings FATAL => qw(all);
|
|
|
|
use Carp qw(confess);
|
|
|
|
|
|
|
|
use Exporter qw(import);
|
|
|
|
our @EXPORT = qw();
|
|
|
|
use File::Basename qw(dirname);
|
|
|
|
|
|
|
|
use lib dirname($0) . '/../lib';
|
2016-04-14 15:30:54 +02:00
|
|
|
use pgBackRest::Common::Log;
|
|
|
|
use pgBackRest::Common::String;
|
|
|
|
use pgBackRest::Config::Config;
|
|
|
|
use pgBackRest::Config::ConfigHelp;
|
|
|
|
use pgBackRest::FileCommon;
|
2015-09-08 13:31:24 +02:00
|
|
|
|
2015-10-28 11:10:36 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# Help types
|
|
|
|
####################################################################################################################################
|
|
|
|
use constant CONFIG_HELP_NAME => 'name';
|
|
|
|
use constant CONFIG_HELP_EXAMPLE => 'example';
|
2015-09-08 13:31:24 +02:00
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# CONSTRUCTOR
|
|
|
|
####################################################################################################################################
|
|
|
|
sub new
|
|
|
|
{
|
|
|
|
my $class = shift; # Class name
|
|
|
|
|
|
|
|
# Create the class hash
|
|
|
|
my $self = {};
|
|
|
|
bless $self, $class;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
(
|
|
|
|
my $strOperation,
|
|
|
|
$self->{oDoc},
|
|
|
|
$self->{oDocRender}
|
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
2016-05-26 15:09:42 +02:00
|
|
|
__PACKAGE__ . '->new', \@_,
|
2015-09-08 13:31:24 +02:00
|
|
|
{name => 'oDoc'},
|
|
|
|
{name => 'oDocRender'}
|
|
|
|
);
|
|
|
|
|
|
|
|
$self->process();
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
{name => 'self', value => $self}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# process
|
|
|
|
#
|
|
|
|
# Parse the xml doc into commands and options.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub process
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
2016-05-26 15:09:42 +02:00
|
|
|
my $strOperation = logDebugParam(__PACKAGE__ . '->process');
|
2015-09-08 13:31:24 +02:00
|
|
|
|
|
|
|
# Iterate through all commands
|
|
|
|
my $oDoc = $self->{oDoc};
|
|
|
|
my $oConfigHash = {};
|
|
|
|
|
2016-05-19 16:25:04 +02:00
|
|
|
foreach my $strCommand (sort(keys(%{commandHashGet()})))
|
2015-09-08 13:31:24 +02:00
|
|
|
{
|
|
|
|
if ($strCommand eq CMD_REMOTE)
|
|
|
|
{
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
|
|
|
|
my $oCommandDoc = $oDoc->nodeGet('operation')->nodeGet('command-list')->nodeGetById('command', $strCommand);
|
|
|
|
|
|
|
|
$$oConfigHash{&CONFIG_HELP_COMMAND}{$strCommand} = {};
|
|
|
|
my $oCommand = $$oConfigHash{&CONFIG_HELP_COMMAND}{$strCommand};
|
|
|
|
|
|
|
|
$$oCommand{&CONFIG_HELP_SUMMARY} = $oCommandDoc->nodeGet('summary')->textGet();
|
|
|
|
$$oCommand{&CONFIG_HELP_DESCRIPTION} = $oCommandDoc->textGet();
|
|
|
|
}
|
|
|
|
|
|
|
|
# Iterate through all options
|
|
|
|
my $oOptionRule = optionRuleGet();
|
|
|
|
|
2016-05-19 16:25:04 +02:00
|
|
|
foreach my $strOption (sort(keys(%{$oOptionRule})))
|
2015-09-08 13:31:24 +02:00
|
|
|
{
|
|
|
|
if ($strOption =~ /^test/ || $strOption eq 'no-fork')
|
|
|
|
{
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Iterate through all commands
|
2016-05-19 16:25:04 +02:00
|
|
|
my @stryCommandList = sort(keys(%{defined($$oOptionRule{$strOption}{&OPTION_RULE_COMMAND}) ?
|
|
|
|
$$oOptionRule{$strOption}{&OPTION_RULE_COMMAND} : $$oConfigHash{&CONFIG_HELP_COMMAND}}));
|
2015-09-08 13:31:24 +02:00
|
|
|
|
|
|
|
foreach my $strCommand (@stryCommandList)
|
|
|
|
{
|
|
|
|
if (!defined($$oConfigHash{&CONFIG_HELP_COMMAND}{$strCommand}))
|
|
|
|
{
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
|
2015-09-09 21:40:54 +02:00
|
|
|
if (ref(\$$oOptionRule{$strOption}{&OPTION_RULE_COMMAND}{$strCommand}) eq 'SCALAR' &&
|
|
|
|
$$oOptionRule{$strOption}{&OPTION_RULE_COMMAND}{$strCommand} == false)
|
|
|
|
{
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
my $oCommandDoc = $oDoc->nodeGet('operation')->nodeGet('command-list')->nodeGetById('command', $strCommand);
|
|
|
|
|
|
|
|
# First check if the option is documented in the command
|
|
|
|
my $oOptionDoc;
|
|
|
|
my $strOptionSource;
|
|
|
|
my $oCommandOptionList = $oCommandDoc->nodeGet('option-list', false);
|
|
|
|
|
|
|
|
if (defined($oCommandOptionList))
|
|
|
|
{
|
|
|
|
$oOptionDoc = $oCommandOptionList->nodeGetById('option', $strOption, false);
|
|
|
|
|
|
|
|
$strOptionSource = CONFIG_HELP_SOURCE_COMMAND if (defined($oOptionDoc));
|
|
|
|
}
|
|
|
|
|
|
|
|
# If the option wasn't found keep looking
|
|
|
|
my $strSection;
|
|
|
|
|
|
|
|
if (!defined($oOptionDoc))
|
|
|
|
{
|
|
|
|
# Next see if it's documented in the section
|
|
|
|
if (defined($$oOptionRule{$strOption}{&OPTION_RULE_SECTION}))
|
|
|
|
{
|
2016-04-14 15:30:54 +02:00
|
|
|
# &log(INFO, " trying section ${strSection}");
|
|
|
|
foreach my $oSectionNode ($oDoc->nodeGet('config')->nodeGet('config-section-list')->nodeList())
|
2015-09-08 13:31:24 +02:00
|
|
|
{
|
2016-04-14 15:30:54 +02:00
|
|
|
my $oOptionDocCheck = $oSectionNode->nodeGetById('config-key-list')
|
|
|
|
->nodeGetById('config-key', $strOption, false);
|
|
|
|
|
|
|
|
if ($oOptionDocCheck)
|
2015-09-08 13:31:24 +02:00
|
|
|
{
|
2016-04-14 15:30:54 +02:00
|
|
|
if (defined($oOptionDoc))
|
|
|
|
{
|
|
|
|
confess 'option exists in more than one section';
|
|
|
|
}
|
|
|
|
|
|
|
|
$oOptionDoc = $oOptionDocCheck;
|
|
|
|
$strOptionSource = CONFIG_HELP_SOURCE_SECTION;
|
|
|
|
$strSection = $oSectionNode->paramGet('id');
|
2015-09-08 13:31:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
# If no section is defined then look in the default command option list
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$oOptionDoc = $oDoc->nodeGet('operation')->nodeGet('operation-general')->nodeGet('option-list')
|
|
|
|
->nodeGetById('option', $strOption, false);
|
|
|
|
|
|
|
|
$strOptionSource = CONFIG_HELP_SOURCE_DEFAULT if (defined($oOptionDoc));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# If the option wasn't found then error
|
|
|
|
if (!defined($oOptionDoc))
|
|
|
|
{
|
|
|
|
confess &log(ERROR, "unable to find option '${strOption}' for command '${strCommand}'")
|
|
|
|
}
|
|
|
|
|
2016-04-14 15:30:54 +02:00
|
|
|
# if the option is documented in the command then it should be accessible from the command line only.
|
|
|
|
if (!defined($strSection))
|
|
|
|
{
|
|
|
|
if (defined($$oOptionRule{$strOption}{&OPTION_RULE_SECTION}))
|
|
|
|
{
|
|
|
|
&log(ERROR, "option ${strOption} defined in command ${strCommand} must not have " . OPTION_RULE_SECTION .
|
|
|
|
" defined");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
# Store the option in the command
|
|
|
|
$$oConfigHash{&CONFIG_HELP_COMMAND}{$strCommand}{&CONFIG_HELP_OPTION}{$strOption}{&CONFIG_HELP_SOURCE} = $strOptionSource;
|
|
|
|
|
|
|
|
my $oCommandOption = $$oConfigHash{&CONFIG_HELP_COMMAND}{$strCommand}{&CONFIG_HELP_OPTION}{$strOption};
|
|
|
|
|
|
|
|
$$oCommandOption{&CONFIG_HELP_SUMMARY} = $oOptionDoc->nodeGet('summary')->textGet();
|
|
|
|
$$oCommandOption{&CONFIG_HELP_DESCRIPTION} = $oOptionDoc->textGet();
|
2015-10-28 11:10:36 +02:00
|
|
|
$$oCommandOption{&CONFIG_HELP_EXAMPLE} = $oOptionDoc->fieldGet('example');
|
|
|
|
|
|
|
|
$$oCommandOption{&CONFIG_HELP_NAME} = $oOptionDoc->paramGet('name');
|
2015-09-08 13:31:24 +02:00
|
|
|
|
|
|
|
# If the option did not come from the command also store in global option list. This prevents duplication of commonly
|
|
|
|
# used options.
|
|
|
|
if ($strOptionSource ne CONFIG_HELP_SOURCE_COMMAND)
|
|
|
|
{
|
|
|
|
$$oConfigHash{&CONFIG_HELP_OPTION}{$strOption}{&CONFIG_HELP_SUMMARY} = $$oCommandOption{&CONFIG_HELP_SUMMARY};
|
|
|
|
|
|
|
|
my $oOption = $$oConfigHash{&CONFIG_HELP_OPTION}{$strOption};
|
|
|
|
|
|
|
|
if (defined($strSection))
|
|
|
|
{
|
|
|
|
$$oOption{&CONFIG_HELP_SECTION} = $strSection;
|
|
|
|
}
|
|
|
|
|
2015-10-28 11:10:36 +02:00
|
|
|
$$oOption{&CONFIG_HELP_NAME} = $oOptionDoc->paramGet('name');
|
2015-09-08 13:31:24 +02:00
|
|
|
$$oOption{&CONFIG_HELP_DESCRIPTION} = $$oCommandOption{&CONFIG_HELP_DESCRIPTION};
|
2015-10-28 11:10:36 +02:00
|
|
|
$$oOption{&CONFIG_HELP_EXAMPLE} = $oOptionDoc->fieldGet('example');
|
2015-09-08 13:31:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Store the config hash
|
|
|
|
$self->{oConfigHash} = $oConfigHash;
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
logDebugReturn($strOperation);
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# helpDataWrite
|
|
|
|
#
|
|
|
|
# Write help data into a perl module so it can be accessed by backrest for command-line help.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub helpDataWrite
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
2015-11-22 23:44:01 +02:00
|
|
|
my
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
$oManifest
|
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
2016-05-26 15:09:42 +02:00
|
|
|
__PACKAGE__ . '->helpDataWrite', \@_,
|
2015-11-22 23:44:01 +02:00
|
|
|
{name => 'oManifest'}
|
|
|
|
);
|
2015-09-08 13:31:24 +02:00
|
|
|
|
|
|
|
# Iterate options
|
|
|
|
my $oConfigHash = $self->{oConfigHash};
|
|
|
|
my $strOptionData;
|
|
|
|
|
2016-05-19 16:25:04 +02:00
|
|
|
foreach my $strOption (sort(keys(%{$$oConfigHash{&CONFIG_HELP_OPTION}})))
|
2015-09-08 13:31:24 +02:00
|
|
|
{
|
|
|
|
my $oOptionHash = $$oConfigHash{&CONFIG_HELP_OPTION}{$strOption};
|
|
|
|
|
|
|
|
if (defined($strOptionData))
|
|
|
|
{
|
|
|
|
$strOptionData .= ",\n\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# Format the option for output
|
|
|
|
$strOptionData .=
|
|
|
|
' # ' . uc($strOption) . " Option Help\n" .
|
|
|
|
' #' . ('-' x 123) . "\n" .
|
|
|
|
" '${strOption}' =>\n" .
|
|
|
|
" {\n" .
|
|
|
|
(defined($$oOptionHash{&CONFIG_HELP_SECTION}) ? ' ' . &CONFIG_HELP_SECTION .
|
|
|
|
' => \'' . $$oOptionHash{&CONFIG_HELP_SECTION} . "',\n" : '') .
|
|
|
|
' ' . &CONFIG_HELP_SUMMARY . " =>\n" .
|
2016-02-23 16:25:22 +02:00
|
|
|
helpDataWriteFormatText($oManifest, $self->{oDocRender}, $$oOptionHash{&CONFIG_HELP_SUMMARY}, 16, 112) . ",\n" .
|
2015-09-08 13:31:24 +02:00
|
|
|
' ' . &CONFIG_HELP_DESCRIPTION . " =>\n" .
|
2016-02-23 16:25:22 +02:00
|
|
|
helpDataWriteFormatText($oManifest, $self->{oDocRender}, $$oOptionHash{&CONFIG_HELP_DESCRIPTION}, 16, 112) . "\n" .
|
2015-09-08 13:31:24 +02:00
|
|
|
" }";
|
|
|
|
}
|
|
|
|
|
|
|
|
# Iterate commands
|
|
|
|
my $strCommandData;
|
|
|
|
|
2016-05-19 16:25:04 +02:00
|
|
|
foreach my $strCommand (sort(keys(%{$$oConfigHash{&CONFIG_HELP_COMMAND}})))
|
2015-09-08 13:31:24 +02:00
|
|
|
{
|
|
|
|
my $oCommandHash = $$oConfigHash{&CONFIG_HELP_COMMAND}{$strCommand};
|
|
|
|
|
|
|
|
if (defined($strCommandData))
|
|
|
|
{
|
|
|
|
$strCommandData .= ",\n\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# Format the command for output
|
|
|
|
$strCommandData .=
|
|
|
|
' # ' . uc($strCommand) . " Command Help\n" .
|
|
|
|
' #' . ('-' x 123) . "\n" .
|
|
|
|
" '${strCommand}' =>\n" .
|
|
|
|
" {\n" .
|
|
|
|
' ' . &CONFIG_HELP_SUMMARY . " =>\n" .
|
2016-02-23 16:25:22 +02:00
|
|
|
helpDataWriteFormatText($oManifest, $self->{oDocRender}, $$oCommandHash{&CONFIG_HELP_SUMMARY}, 16, 112) . ",\n" .
|
2015-09-08 13:31:24 +02:00
|
|
|
' ' . &CONFIG_HELP_DESCRIPTION . " =>\n" .
|
2016-02-23 16:25:22 +02:00
|
|
|
helpDataWriteFormatText($oManifest, $self->{oDocRender}, $$oCommandHash{&CONFIG_HELP_DESCRIPTION}, 16, 112) . ",\n" .
|
2015-09-08 13:31:24 +02:00
|
|
|
"\n";
|
|
|
|
|
|
|
|
# Iterate options
|
|
|
|
my $strOptionData;
|
|
|
|
my $bExtraLinefeed = false;
|
|
|
|
|
|
|
|
if (defined($$oCommandHash{&CONFIG_HELP_OPTION}))
|
|
|
|
{
|
|
|
|
$strCommandData .=
|
|
|
|
' ' . CONFIG_HELP_OPTION . " =>\n" .
|
|
|
|
" {\n";
|
|
|
|
|
2016-05-19 16:25:04 +02:00
|
|
|
foreach my $strOption (sort(keys(%{$$oCommandHash{&CONFIG_HELP_OPTION}})))
|
2015-09-08 13:31:24 +02:00
|
|
|
{
|
|
|
|
my $oOptionHash = $$oCommandHash{&CONFIG_HELP_OPTION}{$strOption};
|
|
|
|
|
|
|
|
if (defined($strOptionData))
|
|
|
|
{
|
|
|
|
$strOptionData .= ",\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# If option came from the command then output details
|
|
|
|
if ($$oOptionHash{&CONFIG_HELP_SOURCE} eq CONFIG_HELP_SOURCE_COMMAND)
|
|
|
|
{
|
|
|
|
if (defined($strOptionData))
|
|
|
|
{
|
|
|
|
$strOptionData .= "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# Format the command option for output
|
|
|
|
$strOptionData .=
|
|
|
|
' # ' . uc($strOption) . " Option Help\n" .
|
|
|
|
' #' . ('-' x 115) . "\n" .
|
|
|
|
" '${strOption}' =>\n" .
|
|
|
|
" {\n" .
|
|
|
|
' ' . &CONFIG_HELP_SUMMARY . " =>\n" .
|
2016-02-23 16:25:22 +02:00
|
|
|
helpDataWriteFormatText($oManifest, $self->{oDocRender},
|
|
|
|
$$oOptionHash{&CONFIG_HELP_SUMMARY}, 24, 104) . ",\n" .
|
2015-09-08 13:31:24 +02:00
|
|
|
' ' . &CONFIG_HELP_DESCRIPTION . " =>\n" .
|
2016-02-23 16:25:22 +02:00
|
|
|
helpDataWriteFormatText($oManifest, $self->{oDocRender},
|
|
|
|
$$oOptionHash{&CONFIG_HELP_DESCRIPTION}, 24, 104) . "\n" .
|
2015-09-08 13:31:24 +02:00
|
|
|
" }";
|
|
|
|
|
|
|
|
$bExtraLinefeed = true;
|
|
|
|
}
|
|
|
|
# Else output a reference to indicate the option is in the global option list
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ($bExtraLinefeed)
|
|
|
|
{
|
|
|
|
$strOptionData .= "\n";
|
|
|
|
$bExtraLinefeed = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$strOptionData .=
|
|
|
|
" '${strOption}' => '" . $$oOptionHash{&CONFIG_HELP_SOURCE} . "'";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$strCommandData .=
|
|
|
|
$strOptionData . "\n" .
|
|
|
|
" }\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
$strCommandData .=
|
|
|
|
" }";
|
|
|
|
}
|
|
|
|
|
|
|
|
# Format the perl module
|
|
|
|
my $strHelpData =
|
|
|
|
('#' x 132) . "\n" .
|
|
|
|
"# CONFIG HELP DATA MODULE\n" .
|
|
|
|
"#\n" .
|
|
|
|
"# This module is automatically generated by doc.pl and should never be manually edited.\n" .
|
|
|
|
('#' x 132) . "\n" .
|
2016-04-14 15:30:54 +02:00
|
|
|
"package pgBackRest::Config::ConfigHelpData;\n" .
|
2015-09-08 13:31:24 +02:00
|
|
|
"\n" .
|
|
|
|
"use strict;\n" .
|
|
|
|
"use warnings FATAL => qw(all);\n" .
|
|
|
|
"use Carp qw(confess);\n" .
|
|
|
|
"\n" .
|
|
|
|
"use Exporter qw(import);\n" .
|
|
|
|
" our \@EXPORT = qw();\n" .
|
|
|
|
"\n" .
|
|
|
|
('#' x 132) . "\n" .
|
|
|
|
"# Data used by the ConfigHelp module to generate command-line help\n" .
|
|
|
|
('#' x 132) . "\n" .
|
|
|
|
"my \$oConfigHelpData =\n".
|
|
|
|
"{\n" .
|
|
|
|
" # Option Help\n" .
|
|
|
|
' #' . ('-' x 127) . "\n" .
|
|
|
|
" " . CONFIG_HELP_OPTION . " =>\n" .
|
|
|
|
" {\n" .
|
|
|
|
$strOptionData . "\n" .
|
|
|
|
" },\n" .
|
|
|
|
"\n" .
|
|
|
|
" # Command Help\n" .
|
|
|
|
' #' . ('-' x 127) . "\n" .
|
|
|
|
" " . CONFIG_HELP_COMMAND . " =>\n" .
|
|
|
|
" {\n" .
|
|
|
|
$strCommandData . "\n" .
|
|
|
|
" }\n" .
|
|
|
|
"};\n" .
|
|
|
|
"\n" .
|
|
|
|
('#' x 132) . "\n" .
|
|
|
|
"# configHelpDataGet\n" .
|
|
|
|
('#' x 132) . "\n" .
|
|
|
|
"sub configHelpDataGet\n" .
|
|
|
|
"{\n" .
|
|
|
|
" return \$oConfigHelpData;\n" .
|
|
|
|
"}\n" .
|
|
|
|
"\n" .
|
|
|
|
"push \@EXPORT, qw(configHelpDataGet);\n" .
|
|
|
|
"\n" .
|
|
|
|
"1;\n";
|
|
|
|
|
|
|
|
# Write the perl module into the lib path
|
2016-04-14 15:30:54 +02:00
|
|
|
fileStringWrite(dirname(dirname($0)) . '/lib/pgBackRest/Config/ConfigHelpData.pm', $strHelpData, false);
|
2015-09-08 13:31:24 +02:00
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
logDebugReturn($strOperation);
|
|
|
|
}
|
|
|
|
|
2016-02-23 16:25:22 +02:00
|
|
|
# Helper function for helpDataWrite() used to format text by quoting it and splitting lines so it looks good in the module.
|
|
|
|
sub helpDataWriteFormatText
|
|
|
|
{
|
|
|
|
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 perl special characters
|
|
|
|
$strLine =~ s/\@/\\@/g;
|
|
|
|
$strLine =~ s/\$/\\\$/g;
|
|
|
|
$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;
|
|
|
|
}
|
|
|
|
|
2015-10-28 11:10:36 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# helpConfigDocGet
|
|
|
|
#
|
|
|
|
# Get the xml for configuration help.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub helpConfigDocGet
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
2016-05-26 15:09:42 +02:00
|
|
|
my $strOperation = logDebugParam(__PACKAGE__ . '->helpConfigDocGet');
|
2015-10-28 11:10:36 +02:00
|
|
|
|
|
|
|
# Build a hash of the sections
|
|
|
|
my $oConfigHash = $self->{oConfigHash};
|
|
|
|
my $oConfigDoc = $self->{oDoc}->nodeGet('config');
|
|
|
|
my $oSectionHash = {};
|
|
|
|
|
2016-05-19 16:25:04 +02:00
|
|
|
foreach my $strOption (sort(keys(%{$$oConfigHash{&CONFIG_HELP_OPTION}})))
|
2015-10-28 11:10:36 +02:00
|
|
|
{
|
|
|
|
my $oOption = $$oConfigHash{&CONFIG_HELP_OPTION}{$strOption};
|
|
|
|
|
|
|
|
if (defined($$oOption{&CONFIG_HELP_SECTION}))
|
|
|
|
{
|
|
|
|
$$oSectionHash{$$oOption{&CONFIG_HELP_SECTION}}{$strOption} = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
my $oDoc = new BackRestDoc::Common::Doc();
|
|
|
|
$oDoc->paramSet('title', $oConfigDoc->paramGet('title'));
|
|
|
|
|
2016-05-16 23:01:48 +02:00
|
|
|
# set the description for use as a meta tag
|
|
|
|
$oDoc->fieldSet('description', $oConfigDoc->fieldGet('description'));
|
|
|
|
|
2015-10-28 11:10:36 +02:00
|
|
|
# Output the introduction
|
|
|
|
my $oIntroSectionDoc = $oDoc->nodeAdd('section', undef, {id => 'introduction'});
|
|
|
|
$oIntroSectionDoc->nodeAdd('title')->textSet('Introduction');
|
|
|
|
$oIntroSectionDoc->textSet($oConfigDoc->textGet());
|
|
|
|
|
2016-05-19 16:25:04 +02:00
|
|
|
foreach my $strSection (sort(keys(%{$oSectionHash})))
|
2015-10-28 11:10:36 +02:00
|
|
|
{
|
|
|
|
my $oSectionElement = $oDoc->nodeAdd('section', undef, {id => "section-${strSection}"});
|
|
|
|
|
|
|
|
my $oSectionDoc = $oConfigDoc->nodeGet('config-section-list')->nodeGetById('config-section', $strSection);
|
|
|
|
|
|
|
|
$oSectionElement->
|
|
|
|
nodeAdd('title')->textSet(
|
|
|
|
{name => 'text',
|
2016-04-14 15:30:54 +02:00
|
|
|
children=> [$oSectionDoc->paramGet('name') . ' Options (', {name => 'id', value => $strSection}, ')']});
|
2015-10-28 11:10:36 +02:00
|
|
|
|
2016-05-19 16:25:04 +02:00
|
|
|
foreach my $strOption (sort(keys(%{$$oSectionHash{$strSection}})))
|
2015-10-28 11:10:36 +02:00
|
|
|
{
|
|
|
|
$self->helpOptionGet(undef, $strOption, $oSectionElement, $$oConfigHash{&CONFIG_HELP_OPTION}{$strOption});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
{name => 'oDoc', value => $oDoc}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# helpCommandDocGet
|
|
|
|
#
|
|
|
|
# Get the xml for command help.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub helpCommandDocGet
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
2016-05-26 15:09:42 +02:00
|
|
|
my $strOperation = logDebugParam(__PACKAGE__ . '->helpCommandDocGet');
|
2015-10-28 11:10:36 +02:00
|
|
|
|
|
|
|
# Working variables
|
|
|
|
my $oConfigHash = $self->{oConfigHash};
|
|
|
|
my $oOperationDoc = $self->{oDoc}->nodeGet('operation');
|
|
|
|
my $oOptionRule = optionRuleGet();
|
|
|
|
|
|
|
|
my $oDoc = new BackRestDoc::Common::Doc();
|
|
|
|
$oDoc->paramSet('title', $oOperationDoc->paramGet('title'));
|
|
|
|
|
2016-05-16 23:01:48 +02:00
|
|
|
# set the description for use as a meta tag
|
|
|
|
$oDoc->fieldSet('description', $oOperationDoc->fieldGet('description'));
|
|
|
|
|
2015-10-28 11:10:36 +02:00
|
|
|
# Output the introduction
|
|
|
|
my $oIntroSectionDoc = $oDoc->nodeAdd('section', undef, {id => 'introduction'});
|
|
|
|
$oIntroSectionDoc->nodeAdd('title')->textSet('Introduction');
|
|
|
|
$oIntroSectionDoc->textSet($oOperationDoc->textGet());
|
|
|
|
|
2016-05-19 16:25:04 +02:00
|
|
|
foreach my $strCommand (sort(keys(%{$$oConfigHash{&CONFIG_HELP_COMMAND}})))
|
2015-10-28 11:10:36 +02:00
|
|
|
{
|
|
|
|
my $oCommandHash = $$oConfigHash{&CONFIG_HELP_COMMAND}{$strCommand};
|
|
|
|
my $oSectionElement = $oDoc->nodeAdd('section', undef, {id => "command-${strCommand}"});
|
|
|
|
|
|
|
|
my $oCommandDoc = $oOperationDoc->nodeGet('command-list')->nodeGetById('command', $strCommand);
|
|
|
|
|
|
|
|
$oSectionElement->
|
|
|
|
nodeAdd('title')->textSet(
|
|
|
|
{name => 'text',
|
|
|
|
children=> [$oCommandDoc->paramGet('name') . ' Command (', {name => 'id', value => $strCommand}, ')']});
|
|
|
|
|
|
|
|
$oSectionElement->textSet($$oCommandHash{&CONFIG_HELP_DESCRIPTION});
|
|
|
|
|
|
|
|
# use Data::Dumper;
|
|
|
|
# confess Dumper($oDoc->{oDoc});
|
|
|
|
|
|
|
|
if (defined($$oCommandHash{&CONFIG_HELP_OPTION}))
|
|
|
|
{
|
|
|
|
my $oCategory = {};
|
|
|
|
|
|
|
|
foreach my $strOption (sort(keys(%{$$oCommandHash{&CONFIG_HELP_OPTION}})))
|
|
|
|
{
|
2016-02-23 16:25:22 +02:00
|
|
|
my ($oOption, $strCategory) = helpCommandDocGetOptionFind($oConfigHash, $oOptionRule, $strCommand, $strOption);
|
2015-10-28 11:10:36 +02:00
|
|
|
|
|
|
|
$$oCategory{$strCategory}{$strOption} = $oOption;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Iterate sections
|
|
|
|
foreach my $strCategory (sort(keys(%{$oCategory})))
|
|
|
|
{
|
|
|
|
my $oOptionListElement = $oSectionElement->nodeAdd('section', undef, {id => "category-${strCategory}"});
|
|
|
|
|
|
|
|
$oOptionListElement->
|
|
|
|
nodeAdd('title')->textSet(ucfirst($strCategory) . ' Options');
|
|
|
|
|
|
|
|
# Iterate options
|
|
|
|
foreach my $strOption (sort(keys(%{$$oCategory{$strCategory}})))
|
|
|
|
{
|
|
|
|
$self->helpOptionGet($strCommand, $strOption, $oOptionListElement,
|
|
|
|
$$oCommandHash{&CONFIG_HELP_OPTION}{$strOption});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
{name => 'oDoc', value => $oDoc}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-02-23 16:25:22 +02:00
|
|
|
# Helper function for helpCommandDocGet() 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 helpCommandDocGetOptionFind
|
|
|
|
{
|
|
|
|
my $oConfigHelpData = shift;
|
|
|
|
my $oOptionRule = shift;
|
|
|
|
my $strCommand = shift;
|
|
|
|
my $strOption = shift;
|
|
|
|
|
|
|
|
my $strSection = CONFIG_HELP_COMMAND;
|
|
|
|
my $oOption = $$oConfigHelpData{&CONFIG_HELP_COMMAND}{$strCommand}{&CONFIG_HELP_OPTION}{$strOption};
|
|
|
|
|
|
|
|
if ($$oOption{&CONFIG_HELP_SOURCE} eq CONFIG_HELP_SOURCE_DEFAULT)
|
|
|
|
{
|
|
|
|
$strSection = CONFIG_SECTION_GENERAL;
|
|
|
|
}
|
|
|
|
elsif ($$oOption{&CONFIG_HELP_SOURCE} eq CONFIG_HELP_SOURCE_SECTION)
|
|
|
|
{
|
|
|
|
$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_STANZA && $strSection ne CONFIG_SECTION_EXPIRE) ||
|
|
|
|
$strSection eq $strCommand)
|
|
|
|
{
|
|
|
|
$strSection = CONFIG_HELP_COMMAND;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $oOption, $strSection;
|
|
|
|
}
|
|
|
|
|
2015-10-28 11:10:36 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# helpOptionGet
|
|
|
|
#
|
|
|
|
# Get the xml for an option.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub helpOptionGet
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
my $strCommand = shift;
|
|
|
|
my $strOption = shift;
|
|
|
|
my $oParentElement = shift;
|
|
|
|
my $oOptionHash = shift;
|
|
|
|
|
|
|
|
# Create the option section
|
|
|
|
my $oOptionElement = $oParentElement->nodeAdd('section', undef, {id => "option-${strOption}"});
|
|
|
|
|
|
|
|
# Set the option section title
|
|
|
|
$oOptionElement->
|
|
|
|
nodeAdd('title')->textSet(
|
|
|
|
{name => 'text',
|
|
|
|
children=> [$$oOptionHash{&CONFIG_HELP_NAME} . ' Option (', {name => 'id', value => "--${strOption}"}, ')']});
|
|
|
|
|
|
|
|
# Add the option summary and description
|
|
|
|
$oOptionElement->
|
|
|
|
nodeAdd('p')->textSet($$oOptionHash{&CONFIG_HELP_SUMMARY});
|
|
|
|
|
|
|
|
$oOptionElement->
|
|
|
|
nodeAdd('p')->textSet($$oOptionHash{&CONFIG_HELP_DESCRIPTION});
|
|
|
|
|
|
|
|
# Get the default value (or required=n if there is no default)
|
|
|
|
my $strCodeBlock;
|
|
|
|
|
2016-04-14 15:30:54 +02:00
|
|
|
if (defined(optionDefault($strOption, $strCommand)))
|
2015-10-28 11:10:36 +02:00
|
|
|
{
|
|
|
|
my $strDefault;
|
|
|
|
|
|
|
|
if ($strOption eq OPTION_CONFIG || $strOption eq OPTION_CONFIG_REMOTE)
|
|
|
|
{
|
|
|
|
$strDefault = '/etc/{[backrest-exe]}.conf';
|
|
|
|
}
|
|
|
|
elsif ($strOption eq OPTION_COMMAND_REMOTE)
|
|
|
|
{
|
|
|
|
$strDefault = '[INSTALL-PATH]/{[backrest-exe]}';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (optionTypeTest($strOption, OPTION_TYPE_BOOLEAN))
|
|
|
|
{
|
|
|
|
$strDefault = optionDefault($strOption, $strCommand) ? 'y' : 'n';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$strDefault = optionDefault($strOption, $strCommand);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$strCodeBlock = "default: ${strDefault}";
|
|
|
|
}
|
|
|
|
# This won't work correctly until there is some notion of dependency
|
|
|
|
# elsif (optionRequired($strOption, $strCommand))
|
|
|
|
# {
|
|
|
|
# $strCodeBlock = 'required: y';
|
|
|
|
# }
|
|
|
|
|
|
|
|
# Get the allowed range if it exists
|
|
|
|
my ($strRangeMin, $strRangeMax) = optionRange($strOption, $strCommand);
|
|
|
|
|
|
|
|
if (defined($strRangeMin))
|
|
|
|
{
|
|
|
|
$strCodeBlock .= (defined($strCodeBlock) ? "\n" : '') . "allowed: ${strRangeMin}-${strRangeMax}";
|
|
|
|
}
|
|
|
|
|
|
|
|
# Get the example
|
|
|
|
my $strExample;
|
|
|
|
|
|
|
|
if (defined($strCommand))
|
|
|
|
{
|
|
|
|
if (optionTypeTest($strOption, OPTION_TYPE_BOOLEAN))
|
|
|
|
{
|
|
|
|
if ($$oOptionHash{&CONFIG_HELP_EXAMPLE} ne 'n' && $$oOptionHash{&CONFIG_HELP_EXAMPLE} ne 'y')
|
|
|
|
{
|
|
|
|
confess &log(ERROR, "option ${strOption} example should be boolean but value is: " .
|
|
|
|
$$oOptionHash{&CONFIG_HELP_EXAMPLE});
|
|
|
|
}
|
|
|
|
|
|
|
|
$strExample = '--' . ($$oOptionHash{&CONFIG_HELP_EXAMPLE} eq 'n' ? 'no-' : '') . $strOption;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$strExample = "--${strOption}=" . $$oOptionHash{&CONFIG_HELP_EXAMPLE};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$strExample = "${strOption}=" . $$oOptionHash{&CONFIG_HELP_EXAMPLE};
|
|
|
|
}
|
|
|
|
|
|
|
|
$strCodeBlock .= (defined($strCodeBlock) ? "\n" : '') . "example: ${strExample}";
|
|
|
|
|
|
|
|
$oOptionElement->
|
|
|
|
nodeAdd('code-block')->valueSet($strCodeBlock);
|
|
|
|
}
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
1;
|