You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-11-29 22:28:02 +02:00
Added documentation in the user guide for delta restores, expiration, dedicated backup hosts, starting and stopping pgBackRest, and replication.
This commit is contained in:
@@ -15,6 +15,7 @@ use Scalar::Util qw(blessed);
|
||||
use lib dirname($0) . '/../lib';
|
||||
use BackRest::Common::Log;
|
||||
use BackRest::Common::String;
|
||||
use BackRest::FileCommon;
|
||||
|
||||
####################################################################################################################################
|
||||
# Operation constants
|
||||
@@ -27,8 +28,10 @@ use constant OP_DOC_NEW => OP_DOC .
|
||||
use constant OP_DOC_NODE_BLESS => OP_DOC . '->nodeBless';
|
||||
use constant OP_DOC_NODE_GET => OP_DOC . '->nodeGet';
|
||||
use constant OP_DOC_NODE_LIST => OP_DOC . '->nodeList';
|
||||
use constant OP_DOC_NODE_REMOVE => OP_DOC . '->nodeRemove';
|
||||
use constant OP_DOC_PARAM_GET => OP_DOC . '->paramGet';
|
||||
use constant OP_DOC_PARAM_SET => OP_DOC . '->paramSet';
|
||||
use constant OP_DOC_PARAM_TEST => OP_DOC . '->paramSet';
|
||||
use constant OP_DOC_PARSE => OP_DOC . '->parse';
|
||||
use constant OP_DOC_VALUE_GET => OP_DOC . '->valueGet';
|
||||
use constant OP_DOC_VALUE_SET => OP_DOC . '->valueSet';
|
||||
@@ -49,44 +52,60 @@ sub new
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
(
|
||||
my $strOperation,
|
||||
$self->{strFileName}
|
||||
$self->{strFileName},
|
||||
my $bCached
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
OP_DOC_NEW, \@_,
|
||||
{name => 'strFileName', required => false}
|
||||
{name => 'strFileName', required => false},
|
||||
{name => 'bCached', default => false}
|
||||
);
|
||||
|
||||
# Load the doc from a file if one has been defined
|
||||
if (defined($self->{strFileName}))
|
||||
{
|
||||
my $oParser = XML::Checker::Parser->new(ErrorContext => 2, Style => 'Tree');
|
||||
$oParser->set_sgml_search_path(dirname($self->{strFileName}) . '/dtd');
|
||||
|
||||
my $oTree;
|
||||
|
||||
eval
|
||||
if ($bCached)
|
||||
{
|
||||
local $XML::Checker::FAIL = sub
|
||||
{
|
||||
my $iCode = shift;
|
||||
$self->oDoc = XMLin(fileStringRead($self->{strFileName}));
|
||||
}
|
||||
else
|
||||
{
|
||||
my $oParser = XML::Checker::Parser->new(ErrorContext => 2, Style => 'Tree');
|
||||
|
||||
die XML::Checker::error_string($iCode, @_);
|
||||
if (-e dirname($0) . '/dtd')
|
||||
{
|
||||
$oParser->set_sgml_search_path(dirname($0) . '/dtd')
|
||||
}
|
||||
else
|
||||
{
|
||||
$oParser->set_sgml_search_path(dirname($0) . '/xml/dtd');
|
||||
}
|
||||
|
||||
my $oTree;
|
||||
|
||||
eval
|
||||
{
|
||||
local $XML::Checker::FAIL = sub
|
||||
{
|
||||
my $iCode = shift;
|
||||
|
||||
die XML::Checker::error_string($iCode, @_);
|
||||
};
|
||||
|
||||
$oTree = $oParser->parsefile($self->{strFileName});
|
||||
};
|
||||
|
||||
$oTree = $oParser->parsefile($self->{strFileName});
|
||||
};
|
||||
# Report any error that stopped parsing
|
||||
if ($@)
|
||||
{
|
||||
$@ =~ s/at \/.*?$//s; # remove module line number
|
||||
die "malformed xml in '$self->{strFileName}':\n" . trim($@);
|
||||
}
|
||||
|
||||
# Report any error that stopped parsing
|
||||
if ($@)
|
||||
{
|
||||
$@ =~ s/at \/.*?$//s; # remove module line number
|
||||
die "malformed xml in '$self->{strFileName}':\n" . trim($@);
|
||||
# Parse and build the doc
|
||||
$self->{oDoc} = $self->build($self->parse(${$oTree}[0], ${$oTree}[1]));
|
||||
}
|
||||
|
||||
# Parse and build the doc
|
||||
$self->{oDoc} = $self->build($self->parse(${$oTree}[0], ${$oTree}[1]));
|
||||
|
||||
}
|
||||
# Else create a blank doc
|
||||
else
|
||||
@@ -129,8 +148,8 @@ sub parse
|
||||
|
||||
my %oOut;
|
||||
my $iIndex = 0;
|
||||
my $bText = $strName eq 'text' || $strName eq 'li' || $strName eq 'code-block' || $strName eq 'p' || $strName eq 'title' ||
|
||||
$strName eq 'summary';
|
||||
my $bText = $strName eq 'text' || $strName eq 'li' || $strName eq 'p' || $strName eq 'title' ||
|
||||
$strName eq 'summary' || $strName eq 'table-cell' || $strName eq 'table-column';
|
||||
|
||||
# Store the node name
|
||||
$oOut{name} = $strName;
|
||||
@@ -244,7 +263,8 @@ sub build
|
||||
}
|
||||
}
|
||||
|
||||
if ($$oDoc{name} eq 'p' || $$oDoc{name} eq 'title' || $$oDoc{name} eq 'summary')
|
||||
if ($$oDoc{name} eq 'p' || $$oDoc{name} eq 'title' || $$oDoc{name} eq 'summary' ||
|
||||
$$oDoc{name} eq 'table-cell' || $$oDoc{name} eq 'table-column')
|
||||
{
|
||||
$$oOut{field}{text} = $oDoc;
|
||||
}
|
||||
@@ -255,7 +275,7 @@ sub build
|
||||
my $oSub = $$oDoc{children}[$iIndex];
|
||||
my $strName = $$oSub{name};
|
||||
|
||||
if ($strName eq 'text' || $strName eq 'code-block')
|
||||
if ($strName eq 'text')
|
||||
{
|
||||
$$oOut{field}{text} = $oSub;
|
||||
}
|
||||
@@ -351,6 +371,18 @@ sub nodeGet
|
||||
return $self->nodeGetById(shift, undef, shift);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# nodeTest
|
||||
#
|
||||
# Test that a node exists
|
||||
####################################################################################################################################
|
||||
sub nodeTest
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
return defined($self->nodeGetById(shift, undef, false));
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# nodeAdd
|
||||
#
|
||||
@@ -470,6 +502,55 @@ sub nodeList
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# nodeRemove
|
||||
#
|
||||
# Remove a child node.
|
||||
####################################################################################################################################
|
||||
sub nodeRemove
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$oChildRemove
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
OP_DOC_NODE_REMOVE, \@_,
|
||||
{name => 'oChildRemove', required => false, trace => true}
|
||||
);
|
||||
|
||||
my $bRemove = false;
|
||||
my $oDoc = $self->{oDoc};
|
||||
|
||||
# Error if there are no children
|
||||
if (!defined($$oDoc{children}))
|
||||
{
|
||||
confess &log(ERROR, "node has no children");
|
||||
}
|
||||
|
||||
for (my $iIndex = 0; $iIndex < @{$$oDoc{children}}; $iIndex++)
|
||||
{
|
||||
if ($$oDoc{children}[$iIndex] == $oChildRemove->{oDoc})
|
||||
{
|
||||
splice(@{$$oDoc{children}}, $iIndex, 1);
|
||||
$bRemove = true;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$bRemove)
|
||||
{
|
||||
confess &log(ERROR, "child was not found in node");
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn($strOperation);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# nameGet
|
||||
####################################################################################################################################
|
||||
@@ -539,6 +620,7 @@ sub paramGet
|
||||
$strOperation,
|
||||
$strName,
|
||||
$bRequired,
|
||||
$strDefault,
|
||||
$strType
|
||||
) =
|
||||
logDebugParam
|
||||
@@ -546,14 +628,20 @@ sub paramGet
|
||||
OP_DOC_PARAM_GET, \@_,
|
||||
{name => 'strName', trace => true},
|
||||
{name => 'bRequired', default => true, trace => true},
|
||||
{name => 'strDefault', required => false, trace => true},
|
||||
{name => 'strType', default => 'param', trace => true}
|
||||
);
|
||||
|
||||
my $strValue = ${$self->{oDoc}}{$strType}{$strName};
|
||||
|
||||
if (!defined($strValue) && $bRequired)
|
||||
if (!defined($strValue))
|
||||
{
|
||||
confess "${strType} '${strName}' in required in node '$self->{strName}'";
|
||||
if ($bRequired)
|
||||
{
|
||||
confess "${strType} '${strName}' in required in node '$self->{strName}'";
|
||||
}
|
||||
|
||||
$strValue = $strDefault;
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
@@ -564,6 +652,51 @@ sub paramGet
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# paramTest
|
||||
#
|
||||
# Test that a parameter exists or has a certain value.
|
||||
####################################################################################################################################
|
||||
sub paramTest
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strName,
|
||||
$strExpectedValue,
|
||||
$strType
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
OP_DOC_PARAM_TEST, \@_,
|
||||
{name => 'strName', trace => true},
|
||||
{name => 'strExpectedValue', required => false, trace => true},
|
||||
{name => 'strType', default => 'param', trace => true}
|
||||
);
|
||||
|
||||
my $bResult = true;
|
||||
my $strValue = $self->paramGet($strName, false, undef, $strType);
|
||||
|
||||
if (!defined($strValue))
|
||||
{
|
||||
$bResult = false;
|
||||
}
|
||||
elsif (defined($strExpectedValue) && $strValue ne $strExpectedValue)
|
||||
{
|
||||
$bResult = false;
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'bResult', value => $bResult, trace => true}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# paramSet
|
||||
#
|
||||
@@ -585,7 +718,7 @@ sub paramSet
|
||||
(
|
||||
OP_DOC_PARAM_SET, \@_,
|
||||
{name => 'strName', trace => true},
|
||||
{name => 'strValue', trace => true},
|
||||
{name => 'strValue', required => false, trace => true},
|
||||
{name => 'strType', default => 'param', trace => true}
|
||||
);
|
||||
|
||||
@@ -604,7 +737,19 @@ sub fieldGet
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
return $self->paramGet(shift, shift, 'field');
|
||||
return $self->paramGet(shift, shift, shift, 'field');
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# fieldTest
|
||||
#
|
||||
# Test if a field exists.
|
||||
####################################################################################################################################
|
||||
sub fieldTest
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
return $self->paramTest(shift, shift, 'field');
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
@@ -616,7 +761,7 @@ sub textGet
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
return $self->nodeBless($self->paramGet('text', shift, 'field'));
|
||||
return $self->nodeBless($self->paramGet('text', shift, shift, 'field'));
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
|
||||
@@ -235,18 +235,28 @@ sub helpDataWrite
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my $strOperation = logDebugParam(OP_DOC_CONFIG_HELP_DATA_WRITE);
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$oManifest
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
OP_DOC_CONFIG_HELP_DATA_WRITE, \@_,
|
||||
{name => 'oManifest'}
|
||||
);
|
||||
|
||||
# Internal function used to format text by quoting it and splitting lines so it looks good in the module.
|
||||
sub formatText
|
||||
{
|
||||
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($oDocRender->processText($oText)));
|
||||
my @stryText = split("\n", trim($oManifest->variableReplace($oDocRender->processText($oText))));
|
||||
my $strText;
|
||||
my $iIndex = 0;
|
||||
|
||||
@@ -321,9 +331,9 @@ sub helpDataWrite
|
||||
(defined($$oOptionHash{&CONFIG_HELP_SECTION}) ? ' ' . &CONFIG_HELP_SECTION .
|
||||
' => \'' . $$oOptionHash{&CONFIG_HELP_SECTION} . "',\n" : '') .
|
||||
' ' . &CONFIG_HELP_SUMMARY . " =>\n" .
|
||||
formatText($self->{oDocRender}, $$oOptionHash{&CONFIG_HELP_SUMMARY}, 16, 112) . ",\n" .
|
||||
formatText($oManifest, $self->{oDocRender}, $$oOptionHash{&CONFIG_HELP_SUMMARY}, 16, 112) . ",\n" .
|
||||
' ' . &CONFIG_HELP_DESCRIPTION . " =>\n" .
|
||||
formatText($self->{oDocRender}, $$oOptionHash{&CONFIG_HELP_DESCRIPTION}, 16, 112) . "\n" .
|
||||
formatText($oManifest, $self->{oDocRender}, $$oOptionHash{&CONFIG_HELP_DESCRIPTION}, 16, 112) . "\n" .
|
||||
" }";
|
||||
}
|
||||
|
||||
@@ -346,9 +356,9 @@ sub helpDataWrite
|
||||
" '${strCommand}' =>\n" .
|
||||
" {\n" .
|
||||
' ' . &CONFIG_HELP_SUMMARY . " =>\n" .
|
||||
formatText($self->{oDocRender}, $$oCommandHash{&CONFIG_HELP_SUMMARY}, 16, 112) . ",\n" .
|
||||
formatText($oManifest, $self->{oDocRender}, $$oCommandHash{&CONFIG_HELP_SUMMARY}, 16, 112) . ",\n" .
|
||||
' ' . &CONFIG_HELP_DESCRIPTION . " =>\n" .
|
||||
formatText($self->{oDocRender}, $$oCommandHash{&CONFIG_HELP_DESCRIPTION}, 16, 112) . ",\n" .
|
||||
formatText($oManifest, $self->{oDocRender}, $$oCommandHash{&CONFIG_HELP_DESCRIPTION}, 16, 112) . ",\n" .
|
||||
"\n";
|
||||
|
||||
# Iterate options
|
||||
@@ -385,9 +395,9 @@ sub helpDataWrite
|
||||
" '${strOption}' =>\n" .
|
||||
" {\n" .
|
||||
' ' . &CONFIG_HELP_SUMMARY . " =>\n" .
|
||||
formatText($self->{oDocRender}, $$oOptionHash{&CONFIG_HELP_SUMMARY}, 24, 104) . ",\n" .
|
||||
formatText($oManifest, $self->{oDocRender}, $$oOptionHash{&CONFIG_HELP_SUMMARY}, 24, 104) . ",\n" .
|
||||
' ' . &CONFIG_HELP_DESCRIPTION . " =>\n" .
|
||||
formatText($self->{oDocRender}, $$oOptionHash{&CONFIG_HELP_DESCRIPTION}, 24, 104) . "\n" .
|
||||
formatText($oManifest, $self->{oDocRender}, $$oOptionHash{&CONFIG_HELP_DESCRIPTION}, 24, 104) . "\n" .
|
||||
" }";
|
||||
|
||||
$bExtraLinefeed = true;
|
||||
@@ -612,7 +622,6 @@ sub helpCommandDocGet
|
||||
return $oOption, $strSection;
|
||||
}
|
||||
|
||||
|
||||
# Working variables
|
||||
my $oConfigHash = $self->{oConfigHash};
|
||||
my $oOperationDoc = $self->{oDoc}->nodeGet('operation');
|
||||
|
||||
621
doc/lib/BackRestDoc/Common/DocExecute.pm
Normal file
621
doc/lib/BackRestDoc/Common/DocExecute.pm
Normal file
@@ -0,0 +1,621 @@
|
||||
####################################################################################################################################
|
||||
# DOC EXECUTE MODULE
|
||||
####################################################################################################################################
|
||||
package BackRestDoc::Common::DocExecute;
|
||||
use parent 'BackRestDoc::Common::DocRender';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => qw(all);
|
||||
use Carp qw(confess);
|
||||
|
||||
use Exporter qw(import);
|
||||
our @EXPORT = qw();
|
||||
use File::Basename qw(dirname);
|
||||
use Storable qw(dclone);
|
||||
|
||||
use lib dirname($0) . '/../lib';
|
||||
use BackRest::Common::Ini;
|
||||
use BackRest::Common::Log;
|
||||
use BackRest::Common::String;
|
||||
use BackRest::FileCommon;
|
||||
|
||||
use lib dirname($0) . '/../test/lib';
|
||||
use BackRestTest::Common::ExecuteTest;
|
||||
use BackRestTest::Common::HostTest;
|
||||
|
||||
use BackRestDoc::Common::DocManifest;
|
||||
|
||||
####################################################################################################################################
|
||||
# Operation constants
|
||||
####################################################################################################################################
|
||||
use constant OP_DOC_EXECUTE => 'DocExecute';
|
||||
|
||||
use constant OP_DOC_EXECUTE_BACKREST_CONFIG => OP_DOC_EXECUTE . '->backrestConfig';
|
||||
use constant OP_DOC_EXECUTE_EXECUTE => OP_DOC_EXECUTE . '->execute';
|
||||
use constant OP_DOC_EXECUTE_NEW => OP_DOC_EXECUTE . '->new';
|
||||
use constant OP_DOC_EXECUTE_POSTGRES_CONFIG => OP_DOC_EXECUTE . '->postresConfig';
|
||||
use constant OP_DOC_EXECUTE_SECTION_CHILD_PROCESS => OP_DOC_EXECUTE . '->sectionChildProcess';
|
||||
|
||||
####################################################################################################################################
|
||||
# CONSTRUCTOR
|
||||
####################################################################################################################################
|
||||
sub new
|
||||
{
|
||||
my $class = shift; # Class name
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strType,
|
||||
$oManifest,
|
||||
$strRenderOutKey,
|
||||
$bExe
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
OP_DOC_EXECUTE_NEW, \@_,
|
||||
{name => 'strType'},
|
||||
{name => 'oManifest'},
|
||||
{name => 'strRenderOutKey'},
|
||||
{name => 'bExe'}
|
||||
);
|
||||
|
||||
# Create the class hash
|
||||
my $self = $class->SUPER::new($strType, $oManifest, $strRenderOutKey);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{bExe} = $bExe;
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'self', value => $self}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# execute
|
||||
####################################################################################################################################
|
||||
sub execute
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$oSection,
|
||||
$strHostName,
|
||||
$oCommand,
|
||||
$iIndent
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
OP_DOC_EXECUTE_EXECUTE, \@_,
|
||||
{name => 'oSection'},
|
||||
{name => 'strHostName'},
|
||||
{name => 'oCommand'},
|
||||
{name => 'iIndent', default => 1}
|
||||
);
|
||||
|
||||
# Working variables
|
||||
my $strCommand;
|
||||
my $strOutput;
|
||||
|
||||
if ($oCommand->fieldTest('actual-command'))
|
||||
{
|
||||
$strCommand = $oCommand->fieldGet('actual-command');
|
||||
$strOutput = $oCommand->fieldGet('actual-output', false);
|
||||
}
|
||||
else
|
||||
{
|
||||
# Command variables
|
||||
$strCommand = trim($oCommand->fieldGet('exe-cmd'));
|
||||
my $strUser = $oCommand->paramGet('user', false, 'postgres');
|
||||
my $bExeOutput = $oCommand->paramTest('output', 'y');
|
||||
my $strVariableKey = $oCommand->paramGet('variable-key', false);
|
||||
my $iExeExpectedError = $oCommand->paramGet('err-expect', false);
|
||||
|
||||
$strCommand = $self->{oManifest}->variableReplace(
|
||||
(defined($strUser) && $strUser eq 'vagrant' ? '' :
|
||||
('sudo ' . ($strUser eq 'root' ? '' : "-u ${strUser} "))) . $strCommand);
|
||||
|
||||
# Add continuation chars and proper spacing
|
||||
$strCommand =~ s/[ ]*\n[ ]*/ \\\n /smg;
|
||||
|
||||
if (!$oCommand->paramTest('show', 'n') && $self->{bExe} && $self->isRequired($oSection))
|
||||
{
|
||||
# Make sure that no lines are greater than 80 chars
|
||||
foreach my $strLine (split("\n", $strCommand))
|
||||
{
|
||||
if (length(trim($strLine)) > 80)
|
||||
{
|
||||
confess &log(ERROR, "command has a line > 80 characters:\n${strCommand}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&log(DEBUG, (' ' x $iIndent) . "execute: $strCommand");
|
||||
|
||||
if (!$oCommand->paramTest('skip', 'y'))
|
||||
{
|
||||
if ($self->{bExe} && $self->isRequired($oSection))
|
||||
{
|
||||
# Check that the host is valid
|
||||
my $oHost = $self->{host}{$strHostName};
|
||||
|
||||
if (!defined($oHost))
|
||||
{
|
||||
confess &log(ERROR, "cannot execute on host ${strHostName} because the host does not exist");
|
||||
}
|
||||
|
||||
my $oExec = $oHost->execute($strCommand,
|
||||
{iExpectedExitStatus => $iExeExpectedError,
|
||||
bSuppressError => $oCommand->paramTest('err-suppress', 'y'),
|
||||
iRetrySeconds => $oCommand->paramGet('retry', false)});
|
||||
$oExec->begin();
|
||||
$oExec->end();
|
||||
|
||||
if ($bExeOutput && defined($oExec->{strOutLog}) && $oExec->{strOutLog} ne '')
|
||||
{
|
||||
$strOutput = $oExec->{strOutLog};
|
||||
|
||||
# Trim off extra linefeeds before and after
|
||||
$strOutput =~ s/^\n+|\n$//g;
|
||||
|
||||
if ($strCommand =~ / pg\_backrest /)
|
||||
{
|
||||
$strOutput =~ s/^ //smg;
|
||||
$strOutput =~ s/^[0-9]{4}-[0-1][0-9]-[0-3][0-9] [0-2][0-9]:[0-6][0-9]:[0-6][0-9]\.[0-9]{3} T[0-9]{2} //smg;
|
||||
}
|
||||
}
|
||||
|
||||
if (defined($iExeExpectedError))
|
||||
{
|
||||
$strOutput .= trim($oExec->{strErrorLog});
|
||||
}
|
||||
|
||||
# Output is assigned to a var
|
||||
if (defined($strVariableKey))
|
||||
{
|
||||
$self->{oManifest}->variableSet($strVariableKey, trim($oExec->{strOutLog}));
|
||||
}
|
||||
elsif (!$oCommand->paramTest('filter', 'n') && $bExeOutput && defined($strOutput))
|
||||
{
|
||||
my $strHighLight = $self->{oManifest}->variableReplace($oCommand->fieldGet('exe-highlight', false));
|
||||
|
||||
if (!defined($strHighLight))
|
||||
{
|
||||
confess &log(ERROR, 'filter requires highlight definition: ' . $strCommand);
|
||||
}
|
||||
|
||||
my $iFilterContext = $oCommand->paramGet('filter-context', false, 2);
|
||||
|
||||
my @stryOutput = split("\n", $strOutput);
|
||||
undef($strOutput);
|
||||
# my $iFiltered = 0;
|
||||
my $iLastOutput = -1;
|
||||
|
||||
for (my $iIndex = 0; $iIndex < @stryOutput; $iIndex++)
|
||||
{
|
||||
if ($stryOutput[$iIndex] =~ /$strHighLight/)
|
||||
{
|
||||
# Determine the first line to output
|
||||
my $iFilterFirst = $iIndex - $iFilterContext;
|
||||
|
||||
# Don't go past the beginning
|
||||
$iFilterFirst = $iFilterFirst < 0 ? 0 : $iFilterFirst;
|
||||
|
||||
# Don't repeat lines that have already been output
|
||||
$iFilterFirst = $iFilterFirst <= $iLastOutput ? $iLastOutput + 1 : $iFilterFirst;
|
||||
|
||||
# Determine the last line to output
|
||||
my $iFilterLast = $iIndex + $iFilterContext;
|
||||
|
||||
# Don't got past the end
|
||||
$iFilterLast = $iFilterLast >= @stryOutput ? @stryOutput -1 : $iFilterLast;
|
||||
|
||||
# Mark filtered lines if any
|
||||
if ($iFilterFirst > $iLastOutput + 1)
|
||||
{
|
||||
my $iFiltered = $iFilterFirst - ($iLastOutput + 1);
|
||||
|
||||
if ($iFiltered > 1)
|
||||
{
|
||||
$strOutput .= (defined($strOutput) ? "\n" : '') .
|
||||
" [filtered ${iFiltered} lines of output]";
|
||||
}
|
||||
else
|
||||
{
|
||||
$iFilterFirst -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Output the lines
|
||||
for (my $iOutputIndex = $iFilterFirst; $iOutputIndex <= $iFilterLast; $iOutputIndex++)
|
||||
{
|
||||
$strOutput .= (defined($strOutput) ? "\n" : '') . $stryOutput[$iOutputIndex];
|
||||
}
|
||||
|
||||
$iLastOutput = $iFilterLast;
|
||||
}
|
||||
}
|
||||
|
||||
if (@stryOutput - 1 > $iLastOutput + 1)
|
||||
{
|
||||
my $iFiltered = (@stryOutput - 1) - ($iLastOutput + 1);
|
||||
|
||||
if ($iFiltered > 1)
|
||||
{
|
||||
$strOutput .= (defined($strOutput) ? "\n" : '') .
|
||||
" [filtered ${iFiltered} lines of output]";
|
||||
}
|
||||
else
|
||||
{
|
||||
$strOutput .= (defined($strOutput) ? "\n" : '') . $stryOutput[@stryOutput - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ($bExeOutput)
|
||||
{
|
||||
$strOutput = 'Output suppressed for testing';
|
||||
}
|
||||
}
|
||||
|
||||
if (defined($strVariableKey) && !defined($self->{oManifest}->variableGet($strVariableKey)))
|
||||
{
|
||||
$self->{oManifest}->variableSet($strVariableKey, '[Test Variable]');
|
||||
}
|
||||
|
||||
$oCommand->fieldSet('actual-command', $strCommand);
|
||||
$oCommand->fieldSet('actual-output', $strOutput);
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'strCommand', value => $strCommand, trace => true},
|
||||
{name => 'strOutput', value => $strOutput, trace => true}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# backrestConfig
|
||||
####################################################################################################################################
|
||||
sub backrestConfig
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$oSection,
|
||||
$oConfig,
|
||||
$iDepth
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
OP_DOC_EXECUTE_BACKREST_CONFIG, \@_,
|
||||
{name => 'oSection'},
|
||||
{name => 'oConfig'},
|
||||
{name => 'iDepth'}
|
||||
);
|
||||
|
||||
# Working variables
|
||||
my $strFile;
|
||||
my $strConfig;
|
||||
|
||||
if ($oConfig->fieldTest('actual-file'))
|
||||
{
|
||||
$strFile = $oConfig->fieldGet('actual-file');
|
||||
$strConfig = $oConfig->fieldGet('actual-config');
|
||||
}
|
||||
else
|
||||
{
|
||||
# Get filename
|
||||
$strFile = $self->{oManifest}->variableReplace($oConfig->paramGet('file'));
|
||||
|
||||
&log(DEBUG, (' ' x $iDepth) . 'process backrest config: ' . $strFile);
|
||||
|
||||
if ($self->{bExe} && $self->isRequired($oSection))
|
||||
{
|
||||
# Check that the host is valid
|
||||
my $strHostName = $self->{oManifest}->variableReplace($oConfig->paramGet('host'));
|
||||
my $oHost = $self->{host}{$strHostName};
|
||||
|
||||
if (!defined($oHost))
|
||||
{
|
||||
confess &log(ERROR, "cannot configure backrest on host ${strHostName} because the host does not exist");
|
||||
}
|
||||
|
||||
# Reset all options
|
||||
if ($oConfig->paramTest('reset', 'y'))
|
||||
{
|
||||
delete(${$self->{config}}{$strHostName}{$strFile})
|
||||
}
|
||||
|
||||
foreach my $oOption ($oConfig->nodeList('backrest-config-option'))
|
||||
{
|
||||
my $strSection = $oOption->paramGet('section');
|
||||
my $strKey = $oOption->paramGet('key');
|
||||
my $strValue;
|
||||
|
||||
if (!$oOption->paramTest('remove', 'y'))
|
||||
{
|
||||
$strValue = $self->{oManifest}->variableReplace(trim($oOption->valueGet(false)));
|
||||
}
|
||||
|
||||
if (!defined($strValue))
|
||||
{
|
||||
delete(${$self->{config}}{$strHostName}{$strFile}{$strSection}{$strKey});
|
||||
|
||||
if (keys(${$self->{config}}{$strHostName}{$strFile}{$strSection}) == 0)
|
||||
{
|
||||
delete(${$self->{config}}{$strHostName}{$strFile}{$strSection});
|
||||
}
|
||||
|
||||
&log(DEBUG, (' ' x ($iDepth + 1)) . "reset ${strSection}->${strKey}");
|
||||
}
|
||||
else
|
||||
{
|
||||
${$self->{config}}{$strHostName}{$strFile}{$strSection}{$strKey} = $strValue;
|
||||
&log(DEBUG, (' ' x ($iDepth + 1)) . "set ${strSection}->${strKey} = ${strValue}");
|
||||
}
|
||||
}
|
||||
|
||||
my $strLocalFile = "/home/vagrant/data/db-master/etc/pg_backrest.conf";
|
||||
|
||||
# Save the ini file
|
||||
iniSave($strLocalFile, $self->{config}{$strHostName}{$strFile}, true);
|
||||
|
||||
$strConfig = fileStringRead($strLocalFile);
|
||||
|
||||
$oHost->copyTo($strLocalFile, $strFile, $oConfig->paramGet('owner', false, 'postgres:postgres'), '640');
|
||||
}
|
||||
else
|
||||
{
|
||||
$strConfig = 'Config suppressed for testing';
|
||||
}
|
||||
|
||||
$oConfig->fieldSet('actual-file', $strFile);
|
||||
$oConfig->fieldSet('actual-config', $strConfig);
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'strFile', value => $strFile, trace => true},
|
||||
{name => 'strConfig', value => $strConfig, trace => true},
|
||||
{name => 'bShow', value => $oConfig->paramTest('show', 'n') ? false : true, trace => true}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# postgresConfig
|
||||
####################################################################################################################################
|
||||
sub postgresConfig
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$oSection,
|
||||
$oConfig,
|
||||
$iDepth
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
OP_DOC_EXECUTE_POSTGRES_CONFIG, \@_,
|
||||
{name => 'oSection'},
|
||||
{name => 'oConfig'},
|
||||
{name => 'iDepth'}
|
||||
);
|
||||
|
||||
# Working variables
|
||||
my $strFile;
|
||||
my $strConfig;
|
||||
|
||||
if ($oConfig->fieldTest('actual-file'))
|
||||
{
|
||||
$strFile = $oConfig->fieldGet('actual-file');
|
||||
$strConfig = $oConfig->fieldGet('actual-config');
|
||||
}
|
||||
else
|
||||
{
|
||||
# Get filename
|
||||
$strFile = $self->{oManifest}->variableReplace($oConfig->paramGet('file'));
|
||||
|
||||
if ($self->{bExe} && $self->isRequired($oSection))
|
||||
{
|
||||
# Check that the host is valid
|
||||
my $strHostName = $self->{oManifest}->variableReplace($oConfig->paramGet('host'));
|
||||
my $oHost = $self->{host}{$strHostName};
|
||||
|
||||
if (!defined($oHost))
|
||||
{
|
||||
confess &log(ERROR, "cannot configure postgres on host ${strHostName} because the host does not exist");
|
||||
}
|
||||
|
||||
my $strLocalFile = '/home/vagrant/data/db-master/etc/postgresql.conf';
|
||||
$oHost->copyFrom($strFile, $strLocalFile);
|
||||
|
||||
if (!defined(${$self->{'pg-config'}}{$strHostName}{$strFile}{base}) && $self->{bExe})
|
||||
{
|
||||
${$self->{'pg-config'}}{$strHostName}{$strFile}{base} = fileStringRead($strLocalFile);
|
||||
}
|
||||
|
||||
my $oConfigHash = $self->{'pg-config'}{$strHostName}{$strFile};
|
||||
my $oConfigHashNew;
|
||||
|
||||
if (!defined($$oConfigHash{old}))
|
||||
{
|
||||
$oConfigHashNew = {};
|
||||
$$oConfigHash{old} = {}
|
||||
}
|
||||
else
|
||||
{
|
||||
$oConfigHashNew = dclone($$oConfigHash{old});
|
||||
}
|
||||
|
||||
&log(DEBUG, (' ' x $iDepth) . 'process postgres config: ' . $strFile);
|
||||
|
||||
foreach my $oOption ($oConfig->nodeList('postgres-config-option'))
|
||||
{
|
||||
my $strKey = $oOption->paramGet('key');
|
||||
my $strValue = $self->{oManifest}->variableReplace(trim($oOption->valueGet()));
|
||||
|
||||
if ($strValue eq '')
|
||||
{
|
||||
delete($$oConfigHashNew{$strKey});
|
||||
|
||||
&log(DEBUG, (' ' x ($iDepth + 1)) . "reset ${strKey}");
|
||||
}
|
||||
else
|
||||
{
|
||||
$$oConfigHashNew{$strKey} = $strValue;
|
||||
&log(DEBUG, (' ' x ($iDepth + 1)) . "set ${strKey} = ${strValue}");
|
||||
}
|
||||
}
|
||||
|
||||
# Generate config text
|
||||
foreach my $strKey (sort(keys(%$oConfigHashNew)))
|
||||
{
|
||||
if (defined($strConfig))
|
||||
{
|
||||
$strConfig .= "\n";
|
||||
}
|
||||
|
||||
$strConfig .= "${strKey} = $$oConfigHashNew{$strKey}";
|
||||
}
|
||||
|
||||
# Save the conf file
|
||||
if ($self->{bExe})
|
||||
{
|
||||
fileStringWrite($strLocalFile, $$oConfigHash{base} .
|
||||
(defined($strConfig) ? "\n# pgBackRest Configuration\n${strConfig}\n" : ''));
|
||||
|
||||
$oHost->copyTo($strLocalFile, $strFile, 'postgres:postgres', '640');
|
||||
}
|
||||
|
||||
$$oConfigHash{old} = $oConfigHashNew;
|
||||
}
|
||||
else
|
||||
{
|
||||
$strConfig = 'Config suppressed for testing';
|
||||
}
|
||||
|
||||
$oConfig->fieldSet('actual-file', $strFile);
|
||||
$oConfig->fieldSet('actual-config', $strConfig);
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'strFile', value => $strFile, trace => true},
|
||||
{name => 'strConfig', value => $strConfig, trace => true},
|
||||
{name => 'bShow', value => $oConfig->paramTest('show', 'n') ? false : true, trace => true}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# sectionChildProcesss
|
||||
####################################################################################################################################
|
||||
sub sectionChildProcess
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$oSection,
|
||||
$oChild,
|
||||
$iDepth
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
OP_DOC_EXECUTE_SECTION_CHILD_PROCESS, \@_,
|
||||
{name => 'oSection'},
|
||||
{name => 'oChild'},
|
||||
{name => 'iDepth'}
|
||||
);
|
||||
|
||||
&log(DEBUG, (' ' x ($iDepth + 1)) . 'process child: ' . $oChild->nameGet());
|
||||
|
||||
# Execute a command
|
||||
if ($oChild->nameGet() eq 'host-add')
|
||||
{
|
||||
if ($self->{bExe} && $self->isRequired($oSection) && !$oChild->paramTest('created', true))
|
||||
{
|
||||
my $strName = $self->{oManifest}->variableReplace($oChild->paramGet('name'));
|
||||
my $strUser = $self->{oManifest}->variableReplace($oChild->paramGet('user'));
|
||||
my $strImage = $self->{oManifest}->variableReplace($oChild->paramGet('image'));
|
||||
my $strOS = $self->{oManifest}->variableReplace($oChild->paramGet('os', false));
|
||||
my $strMount = $self->{oManifest}->variableReplace($oChild->paramGet('mount', false));
|
||||
|
||||
if (defined($self->{host}{$strName}))
|
||||
{
|
||||
confess &log(ERROR, 'cannot add host ${strName} because the host already exists');
|
||||
}
|
||||
|
||||
my $oHost = new BackRestTest::Common::HostTest($strName, $strImage, $strUser, $strOS, $strMount);
|
||||
$self->{host}{$strName} = $oHost;
|
||||
$self->{oManifest}->variableSet("host-${strName}-ip", $oHost->{strIP});
|
||||
|
||||
# Execute cleanup commands
|
||||
foreach my $oExecute ($oChild->nodeList('execute'))
|
||||
{
|
||||
$self->execute($oSection, $strName, $oExecute, $iDepth + 1);
|
||||
}
|
||||
|
||||
$oHost->executeSimple("sh -c 'echo \"\" >> /etc/hosts\'");
|
||||
$oHost->executeSimple("sh -c 'echo \"# Test Hosts\" >> /etc/hosts'");
|
||||
|
||||
# Add all other host IPs to this host
|
||||
foreach my $strOtherHostName (sort(keys($self->{host})))
|
||||
{
|
||||
if ($strOtherHostName ne $strName)
|
||||
{
|
||||
my $oOtherHost = $self->{host}{$strOtherHostName};
|
||||
|
||||
$oHost->executeSimple("sh -c 'echo \"$oOtherHost->{strIP} ${strOtherHostName}\" >> /etc/hosts'");
|
||||
}
|
||||
}
|
||||
|
||||
# Add this host IP to all other hosts
|
||||
foreach my $strOtherHostName (sort(keys($self->{host})))
|
||||
{
|
||||
if ($strOtherHostName ne $strName)
|
||||
{
|
||||
my $oOtherHost = $self->{host}{$strOtherHostName};
|
||||
|
||||
$oOtherHost->executeSimple("sh -c 'echo \"$oHost->{strIP} ${strName}\" >> /etc/hosts'");
|
||||
}
|
||||
}
|
||||
|
||||
$oChild->paramSet('created', true);
|
||||
}
|
||||
}
|
||||
# Skip children that have already been processed and error on others
|
||||
elsif ($oChild->nameGet() ne 'title')
|
||||
{
|
||||
confess &log(ASSERT, 'unable to process child type ' . $oChild->nameGet());
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation
|
||||
);
|
||||
}
|
||||
|
||||
1;
|
||||
536
doc/lib/BackRestDoc/Common/DocManifest.pm
Normal file
536
doc/lib/BackRestDoc/Common/DocManifest.pm
Normal file
@@ -0,0 +1,536 @@
|
||||
####################################################################################################################################
|
||||
# DOC MANIFEST MODULE
|
||||
####################################################################################################################################
|
||||
package BackRestDoc::Common::DocManifest;
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => qw(all);
|
||||
use Carp qw(confess);
|
||||
|
||||
use Cwd qw(abs_path);
|
||||
use Exporter qw(import);
|
||||
our @EXPORT = qw();
|
||||
use File::Basename qw(dirname);
|
||||
use Scalar::Util qw(blessed);
|
||||
|
||||
use lib dirname($0) . '/../lib';
|
||||
use BackRest::Common::Log;
|
||||
use BackRest::Common::String;
|
||||
use BackRest::FileCommon;
|
||||
|
||||
####################################################################################################################################
|
||||
# Operation constants
|
||||
####################################################################################################################################
|
||||
use constant OP_DOC_MANIFEST => 'DocManifest';
|
||||
|
||||
use constant OP_DOC_MANIFEST_NEW => OP_DOC_MANIFEST . '->new';
|
||||
use constant OP_DOC_MANIFEST_RENDER_GET => OP_DOC_MANIFEST . '->renderGet';
|
||||
use constant OP_DOC_MANIFEST_RENDER_LIST => OP_DOC_MANIFEST . '->renderList';
|
||||
use constant OP_DOC_MANIFEST_RENDER_OUT_GET => OP_DOC_MANIFEST . '->renderOutGet';
|
||||
use constant OP_DOC_MANIFEST_RENDER_OUT_LIST => OP_DOC_MANIFEST . '->renderOutList';
|
||||
use constant OP_DOC_MANIFEST_SOURCE_GET => OP_DOC_MANIFEST . '->sourceGet';
|
||||
use constant OP_DOC_MANIFEST_VARIABLE_LIST_PARSE => OP_DOC_MANIFEST . '->variableListParse';
|
||||
|
||||
####################################################################################################################################
|
||||
# File constants
|
||||
####################################################################################################################################
|
||||
use constant FILE_MANIFEST => 'manifest.xml';
|
||||
|
||||
####################################################################################################################################
|
||||
# Render constants
|
||||
####################################################################################################################################
|
||||
use constant RENDER => 'render';
|
||||
use constant RENDER_FILE => 'file';
|
||||
|
||||
use constant RENDER_TYPE => 'type';
|
||||
use constant RENDER_TYPE_HTML => 'html';
|
||||
push @EXPORT, qw(RENDER_TYPE_HTML);
|
||||
use constant RENDER_TYPE_PDF => 'pdf';
|
||||
push @EXPORT, qw(RENDER_TYPE_PDF);
|
||||
|
||||
####################################################################################################################################
|
||||
# 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->{stryKeyword},
|
||||
$self->{stryRequire},
|
||||
my $oVariableOverride,
|
||||
$self->{strDocPath}
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
OP_DOC_MANIFEST_NEW, \@_,
|
||||
{name => 'stryKeyword'},
|
||||
{name => 'stryRequire'},
|
||||
{name => 'oVariableOverride', required => false},
|
||||
{name => 'strDocPath', required => false},
|
||||
);
|
||||
|
||||
# Set the base path if it was not passed in
|
||||
if (!defined($self->{strDocPath}))
|
||||
{
|
||||
$self->{strDocPath} = abs_path(dirname($0));
|
||||
}
|
||||
|
||||
# Load the manifest
|
||||
$self->{oManifestXml} = new BackRestDoc::Common::Doc("$self->{strDocPath}/manifest.xml");
|
||||
|
||||
# Iterate the sources
|
||||
$self->{oManifest} = {};
|
||||
|
||||
foreach my $oSource ($self->{oManifestXml}->nodeGet('source-list')->nodeList('source'))
|
||||
{
|
||||
my $oSourceHash = {};
|
||||
my $strKey = $oSource->paramGet('key');
|
||||
|
||||
logDebugMisc
|
||||
(
|
||||
$strOperation, 'load source',
|
||||
{name => 'strKey', value => $strKey}
|
||||
);
|
||||
|
||||
$$oSourceHash{doc} = new BackRestDoc::Common::Doc("$self->{strDocPath}/xml/${strKey}.xml");
|
||||
|
||||
# Read variables from source
|
||||
$self->variableListParse($$oSourceHash{doc}->nodeGet('variable-list', false), $oVariableOverride);
|
||||
|
||||
${$self->{oManifest}}{source}{$strKey} = $oSourceHash;
|
||||
}
|
||||
|
||||
# Iterate the renderers
|
||||
foreach my $oRender ($self->{oManifestXml}->nodeGet('render-list')->nodeList('render'))
|
||||
{
|
||||
my $oRenderHash = {};
|
||||
my $strType = $oRender->paramGet(RENDER_TYPE);
|
||||
|
||||
# Only one instance of each render type can be defined
|
||||
if (defined(${$self->{oManifest}}{&RENDER}{$strType}))
|
||||
{
|
||||
confess &log(ERROR, "render ${strType} has already been defined");
|
||||
}
|
||||
|
||||
# Get the file param
|
||||
$${oRenderHash}{file} = $oRender->paramGet(RENDER_FILE, false);
|
||||
|
||||
logDebugMisc
|
||||
(
|
||||
$strOperation, ' load render',
|
||||
{name => 'strType', value => $strType},
|
||||
{name => 'strFile', value => $${oRenderHash}{file}}
|
||||
);
|
||||
|
||||
# Error if file is set and render type is not pdf
|
||||
if (defined($${oRenderHash}{file}) && $strType ne RENDER_TYPE_PDF)
|
||||
{
|
||||
confess &log(ERROR, 'only the pdf render type can have file set')
|
||||
}
|
||||
|
||||
# Iterate the render sources
|
||||
foreach my $oRenderOut ($oRender->nodeList('render-source'))
|
||||
{
|
||||
my $oRenderOutHash = {};
|
||||
my $strKey = $oRenderOut->paramGet('key');
|
||||
my $strSource = $oRenderOut->paramGet('source', false, $strKey);
|
||||
|
||||
$$oRenderOutHash{source} = $strSource;
|
||||
|
||||
# Get the filename if this is a pdf
|
||||
$$oRenderOutHash{menu} = $oRenderOut->paramGet('menu', false);
|
||||
|
||||
if (defined($$oRenderOutHash{menu}) && $strType ne RENDER_TYPE_HTML)
|
||||
{
|
||||
confess &log(ERROR, 'only the html render type can have menu set')
|
||||
}
|
||||
|
||||
logDebugMisc
|
||||
(
|
||||
$strOperation, ' load render source',
|
||||
{name => 'strKey', value => $strKey},
|
||||
{name => 'strSource', value => $strSource},
|
||||
{name => 'strMenu', value => $${oRenderOutHash}{menu}}
|
||||
);
|
||||
|
||||
$${oRenderHash}{out}{$strKey} = $oRenderOutHash;
|
||||
}
|
||||
|
||||
${$self->{oManifest}}{render}{$strType} = $oRenderHash;
|
||||
}
|
||||
|
||||
# Read variables from manifest
|
||||
$self->variableListParse($self->{oManifestXml}->nodeGet('variable-list', false), $oVariableOverride);
|
||||
|
||||
# use Data::Dumper; confess Dumper($self->{oVariable});
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'self', value => $self}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# isBackRest
|
||||
#
|
||||
# Until all the backrest specific code can be abstracted, this function will identify when BackRest docs are being built.
|
||||
####################################################################################################################################
|
||||
sub isBackRest
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
return($self->variableTest('project-exe', 'pg_backrest'));
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# keywordMatch
|
||||
#
|
||||
# See if all the keywords were on the command line.
|
||||
####################################################################################################################################
|
||||
sub keywordMatch
|
||||
{
|
||||
my $self = shift;
|
||||
my $strKeywordRequired = shift;
|
||||
|
||||
if (defined($strKeywordRequired))
|
||||
{
|
||||
for my $strKeyword (split(',', $strKeywordRequired))
|
||||
{
|
||||
$strKeyword = trim($strKeyword);
|
||||
|
||||
if (!grep(/^$strKeyword$/, @{$self->{stryKeyword}}))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# variableListParse
|
||||
#
|
||||
# Parse a variable list and store variables.
|
||||
####################################################################################################################################
|
||||
sub variableListParse
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$oVariableList,
|
||||
$oVariableOverride
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
OP_DOC_MANIFEST_VARIABLE_LIST_PARSE, \@_,
|
||||
{name => '$oVariableList', required => false},
|
||||
{name => '$oVariableOverride', required => false}
|
||||
);
|
||||
|
||||
if (defined($oVariableList))
|
||||
{
|
||||
foreach my $oVariable ($oVariableList->nodeList('variable'))
|
||||
{
|
||||
if ($self->keywordMatch($oVariable->paramGet('keyword', false)))
|
||||
{
|
||||
my $strKey = $oVariable->paramGet('key');
|
||||
my $strValue = $oVariable->valueGet();
|
||||
|
||||
if ($oVariable->paramTest('eval', 'y'))
|
||||
{
|
||||
$strValue = eval $strValue;
|
||||
|
||||
if ($@)
|
||||
{
|
||||
confess &log(ERROR, "unable to evaluate ${strKey}: $@\n" . $oVariable->valueGet());
|
||||
}
|
||||
}
|
||||
|
||||
$self->variableSet($strKey, defined($$oVariableOverride{$strKey}) ? $$oVariableOverride{$strKey} : $strValue);
|
||||
|
||||
logDebugMisc
|
||||
(
|
||||
$strOperation, ' load variable',
|
||||
{name => 'strKey', value => $strKey},
|
||||
{name => 'strValue', value => $strValue}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn($strOperation);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# variableReplace
|
||||
#
|
||||
# Replace variables in the string.
|
||||
####################################################################################################################################
|
||||
sub variableReplace
|
||||
{
|
||||
my $self = shift;
|
||||
my $strBuffer = shift;
|
||||
my $strType = shift;
|
||||
|
||||
if (!defined($strBuffer))
|
||||
{
|
||||
return undef;
|
||||
}
|
||||
|
||||
foreach my $strName (sort(keys(%{$self->{oVariable}})))
|
||||
{
|
||||
my $strValue = $self->{oVariable}{$strName};
|
||||
|
||||
$strBuffer =~ s/\{\[$strName\]\}/$strValue/g;
|
||||
}
|
||||
|
||||
if (defined($strType) && $strType eq 'latex')
|
||||
{
|
||||
$strBuffer =~ s/\\\_/\_/g;
|
||||
$strBuffer =~ s/\_/\\\_/g;
|
||||
$strBuffer =~ s/\\\#/\#/g;
|
||||
$strBuffer =~ s/\#/\\\#/g;
|
||||
}
|
||||
|
||||
return $strBuffer;
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# variableSet
|
||||
#
|
||||
# Set a variable to be replaced later.
|
||||
####################################################################################################################################
|
||||
sub variableSet
|
||||
{
|
||||
my $self = shift;
|
||||
my $strKey = shift;
|
||||
my $strValue = shift;
|
||||
my $bForce = shift;
|
||||
|
||||
if (defined(${$self->{oVariable}}{$strKey}) && (!defined($bForce) || !$bForce))
|
||||
{
|
||||
confess &log(ERROR, "${strKey} variable is already defined");
|
||||
}
|
||||
|
||||
${$self->{oVariable}}{$strKey} = $self->variableReplace($strValue);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# variableGet
|
||||
#
|
||||
# Get the current value of a variable.
|
||||
####################################################################################################################################
|
||||
sub variableGet
|
||||
{
|
||||
my $self = shift;
|
||||
my $strKey = shift;
|
||||
|
||||
return ${$self->{oVariable}}{$strKey};
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# variableTest
|
||||
#
|
||||
# Test that a variable is defined or has an expected value.
|
||||
####################################################################################################################################
|
||||
sub variableTest
|
||||
{
|
||||
my $self = shift;
|
||||
my $strKey = shift;
|
||||
my $strExpectedValue = shift;
|
||||
|
||||
# Get the variable
|
||||
my $strValue = ${$self->{oVariable}}{$strKey};
|
||||
|
||||
# Return false if it is not defined
|
||||
if (!defined($strValue))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
# Return false if it does not equal the expected value
|
||||
if (defined($strExpectedValue) && $strValue ne $strExpectedValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# sourceGet
|
||||
####################################################################################################################################
|
||||
sub sourceGet
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strSource
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
OP_DOC_MANIFEST_SOURCE_GET, \@_,
|
||||
{name => 'strSource', trace => true}
|
||||
);
|
||||
|
||||
if (!defined(${$self->{oManifest}}{source}{$strSource}))
|
||||
{
|
||||
confess &log(ERROR, "source ${strSource} does not exist");
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'oSource', value => ${$self->{oManifest}}{source}{$strSource}}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# renderList
|
||||
####################################################################################################################################
|
||||
sub renderList
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my ($strOperation) = logDebugParam(OP_DOC_MANIFEST_RENDER_LIST);
|
||||
|
||||
# Check that the render output exists
|
||||
my @stryRender;
|
||||
|
||||
if (defined(${$self->{oManifest}}{render}))
|
||||
{
|
||||
@stryRender = sort(keys(${$self->{oManifest}}{render}));
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'stryRender', value => \@stryRender}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# renderGet
|
||||
####################################################################################################################################
|
||||
sub renderGet
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strType
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
OP_DOC_MANIFEST_RENDER_GET, \@_,
|
||||
{name => 'strType', trace => true}
|
||||
);
|
||||
|
||||
# Check that the render exists
|
||||
if (!defined(${$self->{oManifest}}{render}{$strType}))
|
||||
{
|
||||
confess &log(ERROR, "render type ${strType} does not exist");
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'oRenderOut', value => ${$self->{oManifest}}{render}{$strType}}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# renderOutList
|
||||
####################################################################################################################################
|
||||
sub renderOutList
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strType
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
OP_DOC_MANIFEST_RENDER_OUT_LIST, \@_,
|
||||
{name => 'strType'}
|
||||
);
|
||||
|
||||
# Check that the render output exists
|
||||
my @stryRenderOut;
|
||||
|
||||
if (defined(${$self->{oManifest}}{render}{$strType}))
|
||||
{
|
||||
@stryRenderOut = sort(keys(${$self->{oManifest}}{render}{$strType}{out}));
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'stryRenderOut', value => \@stryRenderOut}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# renderOutGet
|
||||
####################################################################################################################################
|
||||
sub renderOutGet
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strType,
|
||||
$strKey
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
OP_DOC_MANIFEST_RENDER_OUT_GET, \@_,
|
||||
{name => 'strType', trace => true},
|
||||
{name => 'strKey', trace => true}
|
||||
);
|
||||
|
||||
# use Data::Dumper; print Dumper(${$self->{oManifest}}{render});
|
||||
|
||||
if (!defined(${$self->{oManifest}}{render}{$strType}{out}{$strKey}))
|
||||
{
|
||||
confess &log(ERROR, "render out ${strKey} does not exist");
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'oRenderOut', value => ${$self->{oManifest}}{render}{$strType}{out}{$strKey}}
|
||||
);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -15,6 +15,8 @@ use lib dirname($0) . '/../lib';
|
||||
use BackRest::Common::Log;
|
||||
use BackRest::Common::String;
|
||||
|
||||
use BackRestDoc::Common::DocManifest;
|
||||
|
||||
####################################################################################################################################
|
||||
# Operation constants
|
||||
####################################################################################################################################
|
||||
@@ -26,8 +28,6 @@ use constant OP_DOC_RENDER_PROCESS_TEXT => OP_DOC_RE
|
||||
use constant OP_DOC_RENDER_NEW => OP_DOC_RENDER . '->new';
|
||||
use constant OP_DOC_RENDER_SAVE => OP_DOC_RENDER . '->save';
|
||||
|
||||
# use HTML::HTML5::Builder qw[:standard JQUERY];
|
||||
|
||||
####################################################################################################################################
|
||||
# Render tags for various output types
|
||||
####################################################################################################################################
|
||||
@@ -35,9 +35,10 @@ my $oRenderTag =
|
||||
{
|
||||
'markdown' =>
|
||||
{
|
||||
'quote' => ['"', '"'],
|
||||
'b' => ['**', '**'],
|
||||
'i' => ['_', '_'],
|
||||
'bi' => ['_**', '**_'],
|
||||
# 'bi' => ['_**', '**_'],
|
||||
'ul' => ["\n", "\n"],
|
||||
'ol' => ["\n", "\n"],
|
||||
'li' => ['- ', "\n"],
|
||||
@@ -48,17 +49,18 @@ my $oRenderTag =
|
||||
'param' => ['`', '`'],
|
||||
'setting' => ['`', '`'],
|
||||
'code' => ['`', '`'],
|
||||
'code-block' => ['```', '```'],
|
||||
'exe' => [undef, ''],
|
||||
# 'code-block' => ['```', '```'],
|
||||
# 'exe' => [undef, ''],
|
||||
'backrest' => [undef, ''],
|
||||
'postgres' => ['PostgreSQL', '']
|
||||
},
|
||||
|
||||
'text' =>
|
||||
{
|
||||
'quote' => ['"', '"'],
|
||||
'b' => ['', ''],
|
||||
'i' => ['', ''],
|
||||
'bi' => ['', ''],
|
||||
# 'bi' => ['', ''],
|
||||
'ul' => ["\n", "\n"],
|
||||
'ol' => ["\n", "\n"],
|
||||
'li' => ['* ', "\n"],
|
||||
@@ -76,15 +78,47 @@ my $oRenderTag =
|
||||
'postgres' => ['PostgreSQL', '']
|
||||
},
|
||||
|
||||
'latex' =>
|
||||
{
|
||||
'quote' => ['``', '"'],
|
||||
'b' => ['\textbf{', '}'],
|
||||
'i' => ['\textit{', '}'],
|
||||
# 'bi' => ['', ''],
|
||||
# 'ul' => ["\n", "\n"],
|
||||
# 'ol' => ["\n", "\n"],
|
||||
# 'li' => ['* ', "\n"],
|
||||
'id' => ['\textnormal{\texttt{', '}}'],
|
||||
'host' => ['\textnormal{\textbf{', '}}'],
|
||||
'file' => ['\textnormal{\texttt{', '}}'],
|
||||
'path' => ['\textnormal{\texttt{', '}}'],
|
||||
'cmd' => ['\textnormal{\texttt{', "}}"],
|
||||
'user' => ['\textnormal{\texttt{', '}}'],
|
||||
'br-option' => ['', ''],
|
||||
# 'param' => ['\texttt{', '}'],
|
||||
# 'setting' => ['\texttt{', '}'],
|
||||
'br-option' => ['\textnormal{\texttt{', '}}'],
|
||||
'br-setting' => ['\textnormal{\texttt{', '}}'],
|
||||
'pg-option' => ['\textnormal{\texttt{', '}}'],
|
||||
'pg-setting' => ['\textnormal{\texttt{', '}}'],
|
||||
'code' => ['\textnormal{\texttt{', '}}'],
|
||||
# 'code' => ['\texttt{', '}'],
|
||||
# 'code-block' => ['', ''],
|
||||
# 'exe' => [undef, ''],
|
||||
'backrest' => [undef, ''],
|
||||
'postgres' => ['PostgreSQL', '']
|
||||
},
|
||||
|
||||
'html' =>
|
||||
{
|
||||
'quote' => ['<q>', '</q>'],
|
||||
'b' => ['<b>', '</b>'],
|
||||
'i' => ['<i>', '</i>'],
|
||||
'bi' => ['<i><b>', '</b></i>'],
|
||||
# 'bi' => ['<i><b>', '</b></i>'],
|
||||
'ul' => ['<ul>', '</ul>'],
|
||||
'ol' => ['<ol>', '</ol>'],
|
||||
'li' => ['<li>', '</li>'],
|
||||
'id' => ['<span class="id">', '</span>'],
|
||||
'host' => ['<span class="host">', '</span>'],
|
||||
'file' => ['<span class="file">', '</span>'],
|
||||
'path' => ['<span class="path">', '</span>'],
|
||||
'cmd' => ['<span class="cmd">', '</span>'],
|
||||
@@ -93,9 +127,9 @@ my $oRenderTag =
|
||||
'br-setting' => ['<span class="br-setting">', '</span>'],
|
||||
'pg-option' => ['<span class="pg-option">', '</span>'],
|
||||
'pg-setting' => ['<span class="pg-setting">', '</span>'],
|
||||
'code' => ['<id>', '</id>'],
|
||||
'code' => ['<span class="id">', '</span>'],
|
||||
'code-block' => ['<code-block>', '</code-block>'],
|
||||
'exe' => ['<id>', '</id>'],
|
||||
'exe' => [undef, ''],
|
||||
'setting' => ['<span class="br-setting">', '</span>'], # !!! This will need to be fixed
|
||||
'backrest' => [undef, ''],
|
||||
'postgres' => ['<span class="postgres">PostgreSQL</span>', '']
|
||||
@@ -117,22 +151,76 @@ sub new
|
||||
(
|
||||
my $strOperation,
|
||||
$self->{strType},
|
||||
$self->{strProjectName},
|
||||
$self->{strExeName}
|
||||
$self->{oManifest},
|
||||
$self->{strRenderOutKey},
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
OP_DOC_RENDER_NEW, \@_,
|
||||
{name => 'strType'},
|
||||
{name => 'strProjectName'},
|
||||
{name => 'strExeName'}
|
||||
{name => 'oManifest'},
|
||||
{name => 'strRenderOutKey', required => false}
|
||||
);
|
||||
|
||||
$$oRenderTag{markdown}{backrest}[0] = $self->{strProjectName};
|
||||
$$oRenderTag{markdown}{exe}[0] = $self->{strExeName};
|
||||
$$oRenderTag{text}{backrest}[0] = $self->{strProjectName};
|
||||
$$oRenderTag{text}{exe}[0] = $self->{strExeName};
|
||||
$$oRenderTag{html}{backrest}[0] = "<span class=\"backrest\">$self->{strProjectName}</span>";
|
||||
# Initialize project tags
|
||||
$$oRenderTag{markdown}{backrest}[0] = "{[project]}";
|
||||
$$oRenderTag{markdown}{exe}[0] = "{[project-exe]}";
|
||||
|
||||
$$oRenderTag{text}{backrest}[0] = "{[project]}";
|
||||
$$oRenderTag{text}{exe}[0] = "{[project-exe]}";
|
||||
|
||||
$$oRenderTag{latex}{backrest}[0] = "{[project]}";
|
||||
$$oRenderTag{latex}{exe}[0] = "\\textnormal\{\\texttt\{[project-exe]}}\}\}";
|
||||
|
||||
$$oRenderTag{html}{backrest}[0] = "<span class=\"backrest\">{[project]}</span>";
|
||||
$$oRenderTag{html}{exe}[0] = "<span class=\"file\">{[project-exe]}</span>";
|
||||
|
||||
if (defined($self->{strRenderOutKey}))
|
||||
{
|
||||
# Copy page data to self
|
||||
my $oRenderOut = $self->{oManifest}->renderOutGet($self->{strType} eq 'latex' ? 'pdf' : $self->{strType}, $self->{strRenderOutKey});
|
||||
|
||||
# Get the reference if this is the backrest project
|
||||
if ($self->{oManifest}->isBackRest())
|
||||
{
|
||||
$self->{oReference} = new BackRestDoc::Common::DocConfig(${$self->{oManifest}->sourceGet('reference')}{doc}, $self);
|
||||
}
|
||||
|
||||
if (defined($$oRenderOut{source}) && $$oRenderOut{source} eq 'reference')
|
||||
{
|
||||
if ($self->{strRenderOutKey} eq 'configuration')
|
||||
{
|
||||
$self->{oDoc} = $self->{oReference}->helpConfigDocGet();
|
||||
}
|
||||
elsif ($self->{strRenderOutKey} eq 'command')
|
||||
{
|
||||
$self->{oDoc} = $self->{oReference}->helpCommandDocGet();
|
||||
}
|
||||
else
|
||||
{
|
||||
confess &log(ERROR, "cannot render $self->{strRenderOutKey} from source $$oRenderOut{source}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$self->{oDoc} = ${$self->{oManifest}->sourceGet($self->{strRenderOutKey})}{doc};
|
||||
}
|
||||
}
|
||||
|
||||
if (defined($self->{strRenderOutKey}))
|
||||
{
|
||||
# Build the doc
|
||||
$self->build($self->{oDoc});
|
||||
|
||||
# Get required sections
|
||||
foreach my $strPath (@{$self->{oManifest}->{stryRequire}})
|
||||
{
|
||||
if (defined(${$self->{oSection}}{$strPath}))
|
||||
{
|
||||
$self->required($strPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
@@ -142,6 +230,183 @@ sub new
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# variableReplace
|
||||
#
|
||||
# Replace variables in the string.
|
||||
####################################################################################################################################
|
||||
sub variableReplace
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
return $self->{oManifest}->variableReplace(shift, $self->{strType});
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# variableSet
|
||||
#
|
||||
# Set a variable to be replaced later.
|
||||
####################################################################################################################################
|
||||
sub variableSet
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
return $self->{oManifest}->variableSet(shift, shift);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# variableGet
|
||||
#
|
||||
# Get the current value of a variable.
|
||||
####################################################################################################################################
|
||||
sub variableGet
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
return $self->{oManifest}->variableGet(shift);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# build
|
||||
#
|
||||
# Build the section map and perform keyword matching.
|
||||
####################################################################################################################################
|
||||
sub build
|
||||
{
|
||||
my $self = shift;
|
||||
my $oNode = shift;
|
||||
my $oParent = shift;
|
||||
my $strPath = shift;
|
||||
|
||||
# &log(INFO, " node " . $oNode->nameGet());
|
||||
|
||||
my $strName = $oNode->nameGet();
|
||||
|
||||
if (defined($oParent))
|
||||
{
|
||||
if (!$self->{oManifest}->keywordMatch($oNode->paramGet('keyword', false)))
|
||||
{
|
||||
my $strDescription;
|
||||
|
||||
if (defined($oNode->nodeGet('title', false)))
|
||||
{
|
||||
$strDescription = $self->processText($oNode->nodeGet('title')->textGet());
|
||||
}
|
||||
|
||||
&log(DEBUG, " filtered ${strName}" . (defined($strDescription) ? ": ${strDescription}" : ''));
|
||||
|
||||
$oParent->nodeRemove($oNode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
&log(DEBUG, ' build document');
|
||||
$self->{oSection} = {};
|
||||
}
|
||||
|
||||
if ($strName eq 'section')
|
||||
{
|
||||
if (defined($strPath))
|
||||
{
|
||||
$oNode->paramSet('path-parent', $strPath);
|
||||
}
|
||||
|
||||
$strPath .= '/' . $oNode->paramGet('id');
|
||||
|
||||
&log(DEBUG, " path ${strPath}");
|
||||
${$self->{oSection}}{$strPath} = $oNode;
|
||||
$oNode->paramSet('path', $strPath);
|
||||
}
|
||||
|
||||
# Iterate all nodes
|
||||
foreach my $oChild ($oNode->nodeList(undef, false))
|
||||
{
|
||||
$self->build($oChild, $oNode, $strPath);
|
||||
}
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# required
|
||||
#
|
||||
# Build a list of required sections
|
||||
####################################################################################################################################
|
||||
sub required
|
||||
{
|
||||
my $self = shift;
|
||||
my $strPath = shift;
|
||||
my $bDepend = shift;
|
||||
|
||||
# If node is not found that means the path is invalid
|
||||
my $oNode = ${$self->{oSection}}{$strPath};
|
||||
|
||||
if (!defined($oNode))
|
||||
{
|
||||
confess &log(ERROR, "invalid path ${strPath}");
|
||||
}
|
||||
|
||||
# Only add sections that are listed dependencies
|
||||
if (!defined($bDepend) || $bDepend)
|
||||
{
|
||||
# Match section and all child sections
|
||||
foreach my $strChildPath (sort(keys($self->{oSection})))
|
||||
{
|
||||
if ($strChildPath =~ /^$strPath$/ || $strChildPath =~ /^$strPath\/.*$/)
|
||||
{
|
||||
&log(INFO, " require section: ${strChildPath}");
|
||||
|
||||
${$self->{oSectionRequired}}{$strChildPath} = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Get the path of the current section's parent
|
||||
my $strParentPath = $oNode->paramGet('path-parent', false);
|
||||
|
||||
if ($oNode->paramTest('depend'))
|
||||
{
|
||||
foreach my $strDepend (split(',', $oNode->paramGet('depend')))
|
||||
{
|
||||
if ($strDepend !~ /^\//)
|
||||
{
|
||||
if (!defined($strParentPath))
|
||||
{
|
||||
$strDepend = "/${strDepend}";
|
||||
}
|
||||
else
|
||||
{
|
||||
$strDepend = "${strParentPath}/${strDepend}";
|
||||
}
|
||||
}
|
||||
|
||||
$self->required($strDepend, true);
|
||||
}
|
||||
}
|
||||
elsif (defined($strParentPath))
|
||||
{
|
||||
$self->required($strParentPath, false);
|
||||
}
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# isRequired
|
||||
#
|
||||
# Is it required to execute the section statements?
|
||||
####################################################################################################################################
|
||||
sub isRequired
|
||||
{
|
||||
my $self = shift;
|
||||
my $oSection = shift;
|
||||
|
||||
if (!defined($self->{oSectionRequired}))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
my $strPath = $oSection->paramGet('path');
|
||||
|
||||
defined(${$self->{oSectionRequired}}{$strPath}) ? true : false;
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# process
|
||||
#
|
||||
@@ -168,7 +433,6 @@ sub process
|
||||
);
|
||||
|
||||
my $strType = $self->{strType};
|
||||
my $strProjectName = $self->{strProjectName};
|
||||
|
||||
my $strBuffer = "";
|
||||
my $bList = $oDoc->nameGet() =~ /.*-bullet-list$/;
|
||||
@@ -211,7 +475,7 @@ sub process
|
||||
$strBuffer .= 'v' . $oDoc->paramGet('version') . ': ';
|
||||
}
|
||||
|
||||
$strBuffer .= ($iDepth == 1 ? "${strProjectName}<br/>" : '') . $strTitle;
|
||||
$strBuffer .= ($iDepth == 1 ? "{[project]}<br/>" : '') . $strTitle;
|
||||
|
||||
if (defined($oDoc->paramGet('date', false)))
|
||||
{
|
||||
@@ -369,6 +633,10 @@ sub processTag
|
||||
|
||||
$strBuffer = '<a href="' . $strUrl . '">' . $oTag->valueGet() . '</a>';
|
||||
}
|
||||
elsif ($strType eq 'latex')
|
||||
{
|
||||
$strBuffer = $oTag->valueGet();
|
||||
}
|
||||
else
|
||||
{
|
||||
confess "tag link not valid for type ${strType}";
|
||||
@@ -439,6 +707,11 @@ sub processText
|
||||
{
|
||||
if (ref(\$oNode) eq "SCALAR")
|
||||
{
|
||||
if ($oNode =~ /\"/)
|
||||
{
|
||||
confess &log(ERROR, "unable to process quotes in string (use <quote> instead):\n${oNode}");
|
||||
}
|
||||
|
||||
$strBuffer .= $oNode;
|
||||
}
|
||||
else
|
||||
@@ -462,6 +735,17 @@ sub processText
|
||||
$strBuffer =~ s/^ //smg;
|
||||
# }
|
||||
|
||||
if ($strType eq 'latex')
|
||||
{
|
||||
$strBuffer =~ s/\&mdash\;/---/g;
|
||||
$strBuffer =~ s/\<\;/\</g;
|
||||
$strBuffer =~ s/\<\=/\$\\leq\$/g;
|
||||
$strBuffer =~ s/\>\=/\$\\geq\$/g;
|
||||
# $strBuffer =~ s/\_/\\_/g;
|
||||
}
|
||||
|
||||
$strBuffer = $self->variableReplace($strBuffer);
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
|
||||
Reference in New Issue
Block a user