1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-14 10:13:05 +02:00
pgbackrest/build/lib/pgBackRestBuild/Config/BuildDefine.pm
David Steele 4a5bd002c0 Move pgBackRest::Version module to pgBackRestDoc::ProjectInfo.
The primary source for project info is now src/version.h.

The pgBackRestDoc::ProjectInfo module loads the project info from src/version.h at runtime so there is no need to update it.
2020-03-10 17:57:02 -04:00

586 lines
20 KiB
Perl

####################################################################################################################################
# Auto-Generate Command and Option Configuration Definition Enums, Constants and Data
####################################################################################################################################
package pgBackRestBuild::Config::BuildDefine;
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 Storable qw(dclone);
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::Data;
####################################################################################################################################
# Constants
####################################################################################################################################
use constant BLDLCL_FILE_DEFINE => 'define';
use constant BLDLCL_DATA_COMMAND => '01-dataCommand';
use constant BLDLCL_DATA_OPTION => '02-dataOption';
use constant BLDLCL_ENUM_COMMAND => '01-enumCommand';
use constant BLDLCL_ENUM_OPTION_TYPE => '02-enumOptionType';
use constant BLDLCL_ENUM_OPTION => '03-enumOption';
####################################################################################################################################
# Definitions for constants and data to build
####################################################################################################################################
my $strSummary = 'Command and Option Definition';
my $rhBuild =
{
&BLD_FILE =>
{
&BLDLCL_FILE_DEFINE =>
{
&BLD_SUMMARY => $strSummary,
&BLD_ENUM =>
{
&BLDLCL_ENUM_COMMAND =>
{
&BLD_SUMMARY => 'Command define',
&BLD_NAME => 'ConfigDefineCommand',
},
&BLDLCL_ENUM_OPTION_TYPE =>
{
&BLD_SUMMARY => 'Option type define',
&BLD_NAME => 'ConfigDefineOptionType',
},
&BLDLCL_ENUM_OPTION =>
{
&BLD_SUMMARY => 'Option define',
&BLD_NAME => 'ConfigDefineOption',
},
},
&BLD_DATA =>
{
&BLDLCL_DATA_COMMAND =>
{
&BLD_SUMMARY => 'Command define data',
},
&BLDLCL_DATA_OPTION =>
{
&BLD_SUMMARY => 'Option define data',
},
},
},
},
};
####################################################################################################################################
# Generate enum names
####################################################################################################################################
sub buildConfigDefineCommandEnum
{
return bldEnum('cfgDefCmd', shift)
}
push @EXPORT, qw(buildConfigDefineCommandEnum);
sub buildConfigDefineOptionTypeEnum
{
return bldEnum('cfgDefOptType', shift);
}
push @EXPORT, qw(buildConfigDefineOptionTypeEnum);
sub buildConfigDefineOptionEnum
{
return bldEnum('cfgDefOpt', shift);
}
push @EXPORT, qw(buildConfigDefineOptionEnum);
####################################################################################################################################
# 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
####################################################################################################################################
sub renderAllowList
{
my $ryAllowList = shift;
my $bCommandIndent = shift;
my $strIndent = $bCommandIndent ? ' ' : '';
return
"${strIndent} CFGDEFDATA_OPTION_OPTIONAL_ALLOW_LIST\n" .
"${strIndent} (\n" .
"${strIndent} " . join(",\n${strIndent} ", bldQuoteList($ryAllowList)) .
"\n" .
"${strIndent} )\n";
}
sub renderDepend
{
my $rhDepend = shift;
my $bCommandIndent = shift;
my $strIndent = $bCommandIndent ? ' ' : '';
my $strDependOption = $rhDepend->{&CFGDEF_DEPEND_OPTION};
my $ryDependList = $rhDepend->{&CFGDEF_DEPEND_LIST};
if (defined($ryDependList))
{
my @stryQuoteList;
foreach my $strItem (@{$ryDependList})
{
push(@stryQuoteList, "\"${strItem}\"");
}
return
"${strIndent} CFGDEFDATA_OPTION_OPTIONAL_DEPEND_LIST\n" .
"${strIndent} (\n" .
"${strIndent} " . buildConfigDefineOptionEnum($strDependOption) . ",\n" .
"${strIndent} " . join(",\n${strIndent} ", bldQuoteList($ryDependList)) .
"\n" .
"${strIndent} )\n";
}
return
"${strIndent} CFGDEFDATA_OPTION_OPTIONAL_DEPEND(" . buildConfigDefineOptionEnum($strDependOption) . ")\n";
}
sub renderOptional
{
my $rhOptional = shift;
my $bCommand = shift;
my $rhOptionHelp = shift;
my $oManifest = shift;
my $oDocRender = shift;
my $strCommand = shift;
my $strOption = shift;
my $strIndent = $bCommand ? ' ' : '';
my $strBuildSourceOptional;
my $bSingleLine = false;
if (defined($rhOptional->{&CFGDEF_ALLOW_LIST}))
{
$strBuildSourceOptional .=
(defined($strBuildSourceOptional) && !$bSingleLine ? "\n" : '') .
renderAllowList($rhOptional->{&CFGDEF_ALLOW_LIST}, $bCommand);
$bSingleLine = false;
}
if (defined($rhOptional->{&CFGDEF_ALLOW_RANGE}))
{
my @fyRange = @{$rhOptional->{&CFGDEF_ALLOW_RANGE}};
$strBuildSourceOptional .=
(defined($strBuildSourceOptional) && !$bSingleLine ? "\n" : '') .
"${strIndent} CFGDEFDATA_OPTION_OPTIONAL_ALLOW_RANGE(" . $fyRange[0] . ', ' . $fyRange[1] . ")\n";
$bSingleLine = true;
}
if (defined($rhOptional->{&CFGDEF_DEPEND}))
{
$strBuildSourceOptional .=
(defined($strBuildSourceOptional) && !$bSingleLine ? "\n" : '') .
renderDepend($rhOptional->{&CFGDEF_DEPEND}, $bCommand);
$bSingleLine = defined($rhOptional->{&CFGDEF_DEPEND}{&CFGDEF_DEPEND_LIST}) ? false : true;
}
if (defined($rhOptional->{&CFGDEF_DEFAULT}))
{
$strBuildSourceOptional .=
(defined($strBuildSourceOptional) && !$bSingleLine ? "\n" : '') .
"${strIndent} CFGDEFDATA_OPTION_OPTIONAL_DEFAULT(\"" . $rhOptional->{&CFGDEF_DEFAULT} . "\")\n";
$bSingleLine = true;
}
if (defined($rhOptional->{&CFGDEF_PREFIX}))
{
$strBuildSourceOptional .=
(defined($strBuildSourceOptional) && !$bSingleLine ? "\n" : '') .
"${strIndent} CFGDEFDATA_OPTION_OPTIONAL_PREFIX(\"" . $rhOptional->{&CFGDEF_PREFIX} . "\")\n";
$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 .=
(defined($strBuildSourceOptional) && !$bSingleLine ? "\n" : '') .
"${strIndent} CFGDEFDATA_OPTION_OPTIONAL_REQUIRED(" .
($rhOptional->{&CFGDEF_REQUIRED} ? 'true' : 'false') . ")\n";
$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;
}
####################################################################################################################################
# Build configuration constants and data
####################################################################################################################################
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 $rhEnum = $rhBuild->{&BLD_FILE}{&BLDLCL_FILE_DEFINE}{&BLD_ENUM}{&BLDLCL_ENUM_COMMAND};
my $strBuildSource =
"static ConfigDefineCommandData configDefineCommandData[] = CFGDEFDATA_COMMAND_LIST\n" .
"(";
foreach my $strCommand (cfgDefineCommandList())
{
# Get command help
my $hCommandHelp = $hConfigHelp->{&CONFIG_HELP_COMMAND}{$strCommand};
# Build C enum
my $strCommandEnum = buildConfigDefineCommandEnum($strCommand);
push(@{$rhEnum->{&BLD_LIST}}, $strCommandEnum);
# 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 .=
" )\n";
};
$strBuildSource .=
")\n";
$rhBuild->{&BLD_FILE}{&BLDLCL_FILE_DEFINE}{&BLD_DATA}{&BLDLCL_DATA_COMMAND}{&BLD_SOURCE} = $strBuildSource;
# Build option type constants
#-------------------------------------------------------------------------------------------------------------------------------
$rhEnum = $rhBuild->{&BLD_FILE}{&BLDLCL_FILE_DEFINE}{&BLD_ENUM}{&BLDLCL_ENUM_OPTION_TYPE};
foreach my $strOptionType (cfgDefineOptionTypeList())
{
# Build C enum
my $strOptionTypeEnum = buildConfigDefineOptionTypeEnum($strOptionType);
push(@{$rhEnum->{&BLD_LIST}}, $strOptionTypeEnum);
};
# Build option constants and data
#-------------------------------------------------------------------------------------------------------------------------------
my $rhConfigDefine = cfgDefine();
$rhEnum = $rhBuild->{&BLD_FILE}{&BLDLCL_FILE_DEFINE}{&BLD_ENUM}{&BLDLCL_ENUM_OPTION};
$strBuildSource =
"static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST\n" .
"(";
foreach my $strOption (sort(keys(%{$rhConfigDefine})))
{
# Get option help
my $hOptionHelp = $hConfigHelp->{&CONFIG_HELP_OPTION}{$strOption};
# Build C enum
my $strOptionEnum = buildConfigDefineOptionEnum($strOption);
push(@{$rhEnum->{&BLD_LIST}}, $strOptionEnum);
# Build option data
my $rhOption = $rhConfigDefine->{$strOption};
my $strOptionPrefix = $rhOption->{&CFGDEF_PREFIX};
$strBuildSource .=
"\n" .
" // " . (qw{-} x 125) . "\n" .
" CFGDEFDATA_OPTION\n" .
" (\n";
my $bRequired = $rhOption->{&CFGDEF_REQUIRED};
$strBuildSource .=
" CFGDEFDATA_OPTION_NAME(\"${strOption}\")\n" .
" CFGDEFDATA_OPTION_REQUIRED(" . ($bRequired ? 'true' : 'false') . ")\n" .
" CFGDEFDATA_OPTION_SECTION(cfgDefSection" .
(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_INDEX_TOTAL(" . $rhOption->{&CFGDEF_INDEX_TOTAL} . ")\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" .
" (\n";
foreach my $strCommand (cfgDefineCommandList())
{
if (defined($rhOption->{&CFGDEF_COMMAND}{$strCommand}))
{
$strBuildSource .=
" CFGDEFDATA_OPTION_COMMAND(" . buildConfigDefineCommandEnum($strCommand) . ")\n";
}
}
$strBuildSource .=
" )\n";
# Render optional data
my $strBuildSourceOptional = renderOptional($rhOption, false, $hOptionHelp, $oManifest, $oDocRender);
# Render command overrides
foreach my $strCommand (cfgDefineCommandList())
{
my $strBuildSourceOptionalCommand;
my $rhCommand = $rhOption->{&CFGDEF_COMMAND}{$strCommand};
if (defined($rhCommand))
{
$strBuildSourceOptionalCommand = renderOptional(
$rhCommand, true, $hConfigHelp->{&CONFIG_HELP_COMMAND}{$strCommand}{&CONFIG_HELP_OPTION}{$strOption},
$oManifest, $oDocRender, $strCommand, $strOption);
if (defined($strBuildSourceOptionalCommand))
{
$strBuildSourceOptional .=
(defined($strBuildSourceOptional) ? "\n" : '') .
" CFGDEFDATA_OPTION_OPTIONAL_COMMAND_OVERRIDE\n" .
" (\n" .
" CFGDEFDATA_OPTION_OPTIONAL_COMMAND(" . buildConfigDefineCommandEnum($strCommand) . ")\n" .
"\n" .
$strBuildSourceOptionalCommand .
" )\n";
}
}
};
if (defined($strBuildSourceOptional))
{
$strBuildSource .=
"\n" .
" CFGDEFDATA_OPTION_OPTIONAL_LIST\n" .
" (\n" .
$strBuildSourceOptional .
" )\n";
}
$strBuildSource .=
" )\n";
}
$strBuildSource .=
")\n";
$rhBuild->{&BLD_FILE}{&BLDLCL_FILE_DEFINE}{&BLD_DATA}{&BLDLCL_DATA_OPTION}{&BLD_SOURCE} = $strBuildSource;
return $rhBuild;
}
push @EXPORT, qw(buildConfigDefine);
1;