2015-03-08 20:05:41 +02:00
|
|
|
#!/usr/bin/perl
|
|
|
|
####################################################################################################################################
|
2016-04-14 15:30:54 +02:00
|
|
|
# doc.pl - PgBackRest Doc Builder
|
2015-03-08 20:05:41 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# Perl includes
|
|
|
|
####################################################################################################################################
|
|
|
|
use strict;
|
|
|
|
use warnings FATAL => qw(all);
|
|
|
|
use Carp qw(confess);
|
2016-09-06 15:44:50 +02:00
|
|
|
use English '-no_match_vars';
|
2015-03-08 20:05:41 +02:00
|
|
|
|
2015-07-06 23:59:44 +02:00
|
|
|
$SIG{__DIE__} = sub { Carp::confess @_ };
|
|
|
|
|
2015-08-07 20:43:53 +02:00
|
|
|
use Cwd qw(abs_path);
|
2015-03-08 20:05:41 +02:00
|
|
|
use File::Basename qw(dirname);
|
|
|
|
use Getopt::Long qw(GetOptions);
|
2015-08-07 20:43:53 +02:00
|
|
|
use Pod::Usage qw(pod2usage);
|
2015-11-22 23:44:01 +02:00
|
|
|
use Storable;
|
2015-03-08 20:05:41 +02:00
|
|
|
|
2015-09-03 00:55:04 +02:00
|
|
|
use lib dirname($0) . '/lib';
|
2017-06-09 23:51:41 +02:00
|
|
|
use lib dirname(dirname($0)) . '/lib';
|
2017-08-25 22:47:47 +02:00
|
|
|
use lib dirname(dirname($0)) . '/build/lib';
|
2017-06-09 23:51:41 +02:00
|
|
|
use lib dirname(dirname($0)) . '/test/lib';
|
2016-11-04 13:56:26 +02:00
|
|
|
|
2015-10-28 11:10:36 +02:00
|
|
|
use BackRestDoc::Common::Doc;
|
|
|
|
use BackRestDoc::Common::DocConfig;
|
2015-11-22 23:44:01 +02:00
|
|
|
use BackRestDoc::Common::DocManifest;
|
2015-10-28 11:10:36 +02:00
|
|
|
use BackRestDoc::Common::DocRender;
|
2015-11-22 23:44:01 +02:00
|
|
|
use BackRestDoc::Html::DocHtmlSite;
|
|
|
|
use BackRestDoc::Latex::DocLatex;
|
2015-12-23 18:04:26 +02:00
|
|
|
use BackRestDoc::Markdown::DocMarkdown;
|
2015-09-03 00:55:04 +02:00
|
|
|
|
2016-09-06 15:44:50 +02:00
|
|
|
use pgBackRest::Common::Exception;
|
2016-04-14 15:30:54 +02:00
|
|
|
use pgBackRest::Common::Log;
|
|
|
|
use pgBackRest::Common::String;
|
2017-06-09 23:51:41 +02:00
|
|
|
use pgBackRest::Storage::Local;
|
|
|
|
use pgBackRest::Storage::Posix::Driver;
|
2016-04-14 15:30:54 +02:00
|
|
|
use pgBackRest::Version;
|
2015-03-08 20:05:41 +02:00
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# Usage
|
|
|
|
####################################################################################################################################
|
|
|
|
|
|
|
|
=head1 NAME
|
|
|
|
|
2015-07-02 16:05:13 +02:00
|
|
|
doc.pl - Generate pgBackRest documentation
|
2015-03-08 20:05:41 +02:00
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
|
2016-04-14 15:30:54 +02:00
|
|
|
doc.pl [options]
|
2015-03-08 20:05:41 +02:00
|
|
|
|
|
|
|
General Options:
|
2016-05-03 22:28:20 +02:00
|
|
|
--help Display usage and exit
|
|
|
|
--version Display pgBackRest version
|
|
|
|
--quiet Sets log level to ERROR
|
|
|
|
--log-level Log level for execution (e.g. ERROR, WARN, INFO, DEBUG)
|
2016-06-02 15:32:56 +02:00
|
|
|
--deploy Write exe.cache into resource for persistence
|
2016-05-03 22:28:20 +02:00
|
|
|
--no-exe Should commands be executed when building help? (for testing only)
|
2016-06-02 15:32:56 +02:00
|
|
|
--no-cache Don't use execution cache
|
|
|
|
--cache-only Only use the execution cache - don't attempt to generate it
|
2016-05-03 22:28:20 +02:00
|
|
|
--var Override variables defined in the XML
|
|
|
|
--doc-path Document path to render (manifest.xml should be located here)
|
|
|
|
--out Output types (html, pdf, markdown)
|
|
|
|
--require Require only certain sections of the document (to speed testing)
|
2016-11-17 23:35:11 +02:00
|
|
|
--include Include source in generation (links will reference website)
|
2016-06-02 15:32:56 +02:00
|
|
|
--exclude Exclude source from generation (links will reference website)
|
2016-11-17 23:35:11 +02:00
|
|
|
|
|
|
|
Keyword Options:
|
|
|
|
--keyword Keyword used to filter output
|
|
|
|
--keyword-add Add keyword without overriding 'default' keyword
|
|
|
|
--dev Add 'dev' keyword
|
|
|
|
--debug Add 'debug' keyword
|
|
|
|
--pre Add 'pre' keyword
|
2015-03-08 20:05:41 +02:00
|
|
|
=cut
|
|
|
|
|
2015-08-07 20:43:53 +02:00
|
|
|
####################################################################################################################################
|
2016-05-03 22:28:20 +02:00
|
|
|
# Load command line parameters and config (see usage above for details)
|
2015-08-07 20:43:53 +02:00
|
|
|
####################################################################################################################################
|
2016-05-03 22:28:20 +02:00
|
|
|
my $bHelp = false;
|
|
|
|
my $bVersion = false;
|
|
|
|
my $bQuiet = false;
|
|
|
|
my $strLogLevel = 'info';
|
|
|
|
my $bNoExe = false;
|
2016-06-02 15:32:56 +02:00
|
|
|
my $bNoCache = false;
|
|
|
|
my $bCacheOnly = false;
|
2016-05-03 22:28:20 +02:00
|
|
|
my $oVariableOverride = {};
|
|
|
|
my $strDocPath;
|
|
|
|
my @stryOutput;
|
|
|
|
my @stryKeyword;
|
2016-11-17 23:35:11 +02:00
|
|
|
my @stryKeywordAdd;
|
2016-05-03 22:28:20 +02:00
|
|
|
my @stryRequire;
|
2016-11-17 23:35:11 +02:00
|
|
|
my @stryInclude;
|
2016-06-02 15:32:56 +02:00
|
|
|
my @stryExclude;
|
|
|
|
my $bDeploy = false;
|
2016-10-06 03:22:42 +02:00
|
|
|
my $bDev = false;
|
2016-11-17 23:35:11 +02:00
|
|
|
my $bDebug = false;
|
|
|
|
my $bPre = false;
|
2015-08-07 20:43:53 +02:00
|
|
|
|
|
|
|
GetOptions ('help' => \$bHelp,
|
|
|
|
'version' => \$bVersion,
|
|
|
|
'quiet' => \$bQuiet,
|
2015-10-28 11:10:36 +02:00
|
|
|
'log-level=s' => \$strLogLevel,
|
2015-11-22 23:44:01 +02:00
|
|
|
'out=s@' => \@stryOutput,
|
|
|
|
'keyword=s@' => \@stryKeyword,
|
2016-11-17 23:35:11 +02:00
|
|
|
'keyword-add=s@' => \@stryKeywordAdd,
|
2015-11-22 23:44:01 +02:00
|
|
|
'require=s@' => \@stryRequire,
|
2016-11-17 23:35:11 +02:00
|
|
|
'include=s@' => \@stryInclude,
|
2016-06-02 15:32:56 +02:00
|
|
|
'exclude=s@' => \@stryExclude,
|
2015-11-22 23:44:01 +02:00
|
|
|
'no-exe', \$bNoExe,
|
2016-06-02 15:32:56 +02:00
|
|
|
'deploy', \$bDeploy,
|
|
|
|
'no-cache', \$bNoCache,
|
2016-10-06 03:22:42 +02:00
|
|
|
'dev', \$bDev,
|
2016-11-17 23:35:11 +02:00
|
|
|
'debug', \$bDebug,
|
|
|
|
'pre', \$bPre,
|
2016-06-02 15:32:56 +02:00
|
|
|
'cache-only', \$bCacheOnly,
|
2015-11-22 23:44:01 +02:00
|
|
|
'var=s%', $oVariableOverride,
|
|
|
|
'doc-path=s', \$strDocPath)
|
2015-08-07 20:43:53 +02:00
|
|
|
or pod2usage(2);
|
|
|
|
|
2016-06-02 15:32:56 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# Run in eval block to catch errors
|
|
|
|
####################################################################################################################################
|
|
|
|
eval
|
2015-08-07 20:43:53 +02:00
|
|
|
{
|
2016-06-02 15:32:56 +02:00
|
|
|
# Display version and exit if requested
|
|
|
|
if ($bHelp || $bVersion)
|
2015-08-07 20:43:53 +02:00
|
|
|
{
|
2016-06-27 02:53:45 +02:00
|
|
|
print BACKREST_NAME . ' ' . BACKREST_VERSION . " Documentation Builder\n";
|
2015-08-07 20:43:53 +02:00
|
|
|
|
2016-06-02 15:32:56 +02:00
|
|
|
if ($bHelp)
|
|
|
|
{
|
|
|
|
print "\n";
|
|
|
|
pod2usage();
|
|
|
|
}
|
2015-08-07 20:43:53 +02:00
|
|
|
|
2016-06-02 15:32:56 +02:00
|
|
|
exit 0;
|
|
|
|
}
|
2015-11-22 23:44:01 +02:00
|
|
|
|
2016-06-02 15:32:56 +02:00
|
|
|
# Disable cache when no exe
|
|
|
|
if ($bNoExe)
|
|
|
|
{
|
|
|
|
$bNoCache = true;
|
|
|
|
}
|
2015-11-22 23:44:01 +02:00
|
|
|
|
2016-06-02 15:32:56 +02:00
|
|
|
# Make sure options are set correctly for deploy
|
|
|
|
if ($bDeploy)
|
|
|
|
{
|
|
|
|
my $strError = 'cannot be specified for deploy';
|
2015-08-07 20:43:53 +02:00
|
|
|
|
2016-06-02 15:32:56 +02:00
|
|
|
!$bNoExe
|
|
|
|
or confess "--no-exe ${strError}";
|
2015-08-07 20:43:53 +02:00
|
|
|
|
2016-06-02 15:32:56 +02:00
|
|
|
!@stryRequire
|
|
|
|
or confess "--require ${strError}";
|
|
|
|
}
|
2015-09-08 13:31:24 +02:00
|
|
|
|
2017-02-11 17:26:54 +02:00
|
|
|
# one --include must be specified when --required is
|
|
|
|
if (@stryRequire && @stryInclude != 1)
|
|
|
|
{
|
|
|
|
confess "one --include is required when --require is specified";
|
|
|
|
}
|
|
|
|
|
2016-06-02 15:32:56 +02:00
|
|
|
# Set console log level
|
|
|
|
if ($bQuiet)
|
|
|
|
{
|
|
|
|
$strLogLevel = 'error';
|
|
|
|
}
|
2015-11-22 23:44:01 +02:00
|
|
|
|
2016-06-02 15:32:56 +02:00
|
|
|
# If no keyword was passed then use default
|
|
|
|
if (@stryKeyword == 0)
|
|
|
|
{
|
|
|
|
@stryKeyword = ('default');
|
|
|
|
}
|
2015-11-22 23:44:01 +02:00
|
|
|
|
2016-11-17 23:35:11 +02:00
|
|
|
# Push added keywords
|
|
|
|
push(@stryKeyword, @stryKeywordAdd);
|
|
|
|
|
|
|
|
# If --dev passed then add the dev keyword
|
2016-10-06 03:22:42 +02:00
|
|
|
if ($bDev)
|
|
|
|
{
|
|
|
|
push(@stryKeyword, 'dev');
|
|
|
|
}
|
|
|
|
|
2016-11-17 23:35:11 +02:00
|
|
|
# If --debug passed then add the debug keyword
|
|
|
|
if ($bDebug)
|
|
|
|
{
|
|
|
|
push(@stryKeyword, 'debug');
|
|
|
|
}
|
|
|
|
|
|
|
|
# If --pre passed then add the pre keyword
|
|
|
|
if ($bPre)
|
|
|
|
{
|
|
|
|
push(@stryKeyword, 'pre');
|
|
|
|
}
|
|
|
|
|
|
|
|
# Doesn't make sense to pass include and exclude
|
|
|
|
if (@stryInclude > 0 && @stryExclude > 0)
|
|
|
|
{
|
|
|
|
confess "cannot specify both --include and --exclude";
|
|
|
|
}
|
|
|
|
|
2016-10-05 15:09:30 +02:00
|
|
|
logLevelSet(undef, uc($strLogLevel), OFF);
|
2015-11-22 23:44:01 +02:00
|
|
|
|
2016-06-02 15:32:56 +02:00
|
|
|
# Get the base path
|
|
|
|
my $strBasePath = abs_path(dirname($0));
|
|
|
|
|
2017-06-09 23:51:41 +02:00
|
|
|
my $oStorageDoc = new pgBackRest::Storage::Local(
|
|
|
|
$strBasePath, new pgBackRest::Storage::Posix::Driver({bFileSync => false, bPathSync => false}));
|
|
|
|
|
2016-06-02 15:32:56 +02:00
|
|
|
if (!defined($strDocPath))
|
2015-11-22 23:44:01 +02:00
|
|
|
{
|
2016-06-02 15:32:56 +02:00
|
|
|
$strDocPath = $strBasePath;
|
2015-11-22 23:44:01 +02:00
|
|
|
}
|
|
|
|
|
2016-06-02 15:32:56 +02:00
|
|
|
my $strOutputPath = "${strDocPath}/output";
|
|
|
|
|
|
|
|
# Create the out path if it does not exist
|
|
|
|
if (!-e $strOutputPath)
|
2015-11-22 23:44:01 +02:00
|
|
|
{
|
2016-06-02 15:32:56 +02:00
|
|
|
mkdir($strOutputPath)
|
|
|
|
or confess &log(ERROR, "unable to create path ${strOutputPath}");
|
2015-11-22 23:44:01 +02:00
|
|
|
}
|
|
|
|
|
2016-06-02 15:32:56 +02:00
|
|
|
# Load the manifest
|
2016-06-24 14:12:58 +02:00
|
|
|
my $oManifest = new BackRestDoc::Common::DocManifest(
|
2017-06-09 23:51:41 +02:00
|
|
|
$oStorageDoc, \@stryKeyword, \@stryRequire, \@stryInclude, \@stryExclude, $oVariableOverride, $strDocPath, $bDeploy,
|
|
|
|
$bCacheOnly);
|
2016-06-02 15:32:56 +02:00
|
|
|
|
|
|
|
if (!$bNoCache)
|
|
|
|
{
|
|
|
|
$oManifest->cacheRead();
|
|
|
|
}
|
2015-11-22 23:44:01 +02:00
|
|
|
|
2016-06-02 15:32:56 +02:00
|
|
|
# If no outputs were given
|
|
|
|
if (@stryOutput == 0)
|
2015-12-23 18:04:26 +02:00
|
|
|
{
|
2016-06-02 15:32:56 +02:00
|
|
|
@stryOutput = $oManifest->renderList();
|
|
|
|
|
|
|
|
if ($oManifest->isBackRest())
|
|
|
|
{
|
|
|
|
push(@stryOutput, 'man');
|
|
|
|
}
|
2015-12-23 18:04:26 +02:00
|
|
|
}
|
2016-06-02 15:32:56 +02:00
|
|
|
|
|
|
|
for my $strOutput (@stryOutput)
|
2015-11-22 23:44:01 +02:00
|
|
|
{
|
2018-01-23 20:34:24 +02:00
|
|
|
if (!($strOutput eq 'man' && $oManifest->isBackRest()))
|
2016-06-02 15:32:56 +02:00
|
|
|
{
|
|
|
|
$oManifest->renderGet($strOutput);
|
|
|
|
}
|
|
|
|
|
|
|
|
&log(INFO, "render ${strOutput} output");
|
2016-06-02 15:25:12 +02:00
|
|
|
|
2016-06-02 15:32:56 +02:00
|
|
|
if ($strOutput eq 'markdown')
|
|
|
|
{
|
|
|
|
my $oMarkdown =
|
|
|
|
new BackRestDoc::Markdown::DocMarkdown
|
|
|
|
(
|
|
|
|
$oManifest,
|
|
|
|
"${strBasePath}/xml",
|
|
|
|
"${strOutputPath}/markdown",
|
|
|
|
!$bNoExe
|
|
|
|
);
|
|
|
|
|
|
|
|
$oMarkdown->process();
|
|
|
|
}
|
2018-01-23 20:34:24 +02:00
|
|
|
elsif ($strOutput eq 'man' && $oManifest->isBackRest())
|
2016-06-02 15:25:12 +02:00
|
|
|
{
|
2016-06-02 15:32:56 +02:00
|
|
|
# Generate the command-line help
|
2017-07-26 16:22:22 +02:00
|
|
|
my $oRender = new BackRestDoc::Common::DocRender('text', $oManifest, !$bNoExe);
|
2016-06-02 15:32:56 +02:00
|
|
|
my $oDocConfig =
|
|
|
|
new BackRestDoc::Common::DocConfig(
|
|
|
|
new BackRestDoc::Common::Doc("${strBasePath}/xml/reference.xml"), $oRender);
|
|
|
|
|
2018-01-23 20:34:24 +02:00
|
|
|
$oStorageDoc->pathCreate(
|
|
|
|
"${strBasePath}/output/man", {strMode => '0770', bIgnoreExists => true, bCreateParent => true});
|
|
|
|
$oStorageDoc->put("${strBasePath}/output/man/" . lc(BACKREST_NAME) . '.1.txt', $oDocConfig->manGet($oManifest));
|
2016-06-02 15:25:12 +02:00
|
|
|
}
|
2016-06-02 15:32:56 +02:00
|
|
|
elsif ($strOutput eq 'html')
|
2016-06-02 15:25:12 +02:00
|
|
|
{
|
2016-06-02 15:32:56 +02:00
|
|
|
my $oHtmlSite =
|
|
|
|
new BackRestDoc::Html::DocHtmlSite
|
|
|
|
(
|
|
|
|
$oManifest,
|
|
|
|
"${strBasePath}/xml",
|
|
|
|
"${strOutputPath}/html",
|
|
|
|
"${strBasePath}/resource/html/default.css",
|
|
|
|
defined($oManifest->variableGet('project-favicon')) ?
|
|
|
|
"${strBasePath}/resource/html/" . $oManifest->variableGet('project-favicon') : undef,
|
|
|
|
defined($oManifest->variableGet('project-logo')) ?
|
|
|
|
"${strBasePath}/resource/" . $oManifest->variableGet('project-logo') : undef,
|
|
|
|
!$bNoExe
|
|
|
|
);
|
|
|
|
|
|
|
|
$oHtmlSite->process();
|
|
|
|
}
|
|
|
|
elsif ($strOutput eq 'pdf')
|
|
|
|
{
|
|
|
|
my $oLatex =
|
|
|
|
new BackRestDoc::Latex::DocLatex
|
|
|
|
(
|
|
|
|
$oManifest,
|
|
|
|
"${strBasePath}/xml",
|
|
|
|
"${strOutputPath}/latex",
|
|
|
|
"${strBasePath}/resource/latex/preamble.tex",
|
|
|
|
!$bNoExe
|
|
|
|
);
|
|
|
|
|
|
|
|
$oLatex->process();
|
2016-06-02 15:25:12 +02:00
|
|
|
}
|
2015-11-22 23:44:01 +02:00
|
|
|
}
|
2016-06-02 15:32:56 +02:00
|
|
|
|
|
|
|
# Cache the manifest (mostly useful for testing rendering changes in the code)
|
|
|
|
if (!$bNoCache && !$bCacheOnly)
|
2015-11-22 23:44:01 +02:00
|
|
|
{
|
2016-06-02 15:32:56 +02:00
|
|
|
$oManifest->cacheWrite();
|
2015-11-22 23:44:01 +02:00
|
|
|
}
|
2016-09-06 15:44:50 +02:00
|
|
|
|
|
|
|
# Exit with success
|
|
|
|
exit 0;
|
|
|
|
}
|
2016-06-02 15:32:56 +02:00
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# Check for errors
|
|
|
|
####################################################################################################################################
|
2016-09-06 15:44:50 +02:00
|
|
|
or do
|
2016-06-02 15:32:56 +02:00
|
|
|
{
|
2016-09-06 15:44:50 +02:00
|
|
|
# If a backrest exception then return the code
|
2017-10-16 16:47:31 +02:00
|
|
|
exit $EVAL_ERROR->code() if (isException(\$EVAL_ERROR));
|
2016-06-02 15:32:56 +02:00
|
|
|
|
2016-09-06 15:44:50 +02:00
|
|
|
# Else output the unhandled error
|
|
|
|
print $EVAL_ERROR;
|
|
|
|
exit ERROR_UNHANDLED;
|
|
|
|
};
|
2015-11-22 23:44:01 +02:00
|
|
|
|
2016-09-06 15:44:50 +02:00
|
|
|
# It shouldn't be possible to get here
|
|
|
|
&log(ASSERT, 'execution reached invalid location in ' . __FILE__ . ', line ' . __LINE__);
|
|
|
|
exit ERROR_ASSERT;
|