From 1eb0162208b37f577d35ba775f007202b285900a Mon Sep 17 00:00:00 2001
From: David Steele
Date: Mon, 9 Oct 2023 14:03:43 -0400
Subject: [PATCH] Build command and configuration reference in C.
Migrate generation of these files from help.xml to the intermediate documentation format. This allows us to share a lot of code that is already in C and remove duplicated code in Perl. More duplicate code can be removed in Perl once man generation is migrated.
Also update the unit test harness to allow testing of modules in the doc directory.
---
doc/doc.pl | 18 +
doc/lib/pgBackRestDoc/Common/DocConfig.pm | 395 ------------------
doc/lib/pgBackRestDoc/Common/DocRender.pm | 17 +-
doc/manifest.xml | 6 +-
doc/src/build/config/config.yaml | 97 +++++
doc/src/build/help/help.xml | 122 ++++++
doc/src/command/build/build.c | 36 ++
doc/src/command/build/build.h | 14 +
doc/src/command/build/reference.c | 339 +++++++++++++++
doc/src/command/build/reference.h | 20 +
doc/src/command/help/meson.build | 17 +
doc/src/config/load.c | 123 ++++++
doc/src/config/load.h | 13 +
doc/src/config/meson.build | 16 +
doc/src/main.c | 99 +++++
doc/src/meson.build | 75 ++++
doc/xml/dtd/doc.dtd | 2 +-
meson.build | 1 +
src/build/help/help.xml | 4 +-
test/ci.pl | 4 +-
test/define.yaml | 12 +
.../lib/pgBackRestTest/Common/CoverageTest.pm | 11 +-
test/src/command/test/build.c | 5 +-
test/src/module/doc/buildTest.c | 331 +++++++++++++++
test/src/module/test/testTest.c | 10 +-
25 files changed, 1366 insertions(+), 421 deletions(-)
create mode 100644 doc/src/build/config/config.yaml
create mode 100644 doc/src/build/help/help.xml
create mode 100644 doc/src/command/build/build.c
create mode 100644 doc/src/command/build/build.h
create mode 100644 doc/src/command/build/reference.c
create mode 100644 doc/src/command/build/reference.h
create mode 100644 doc/src/command/help/meson.build
create mode 100644 doc/src/config/load.c
create mode 100644 doc/src/config/load.h
create mode 100644 doc/src/config/meson.build
create mode 100644 doc/src/main.c
create mode 100644 doc/src/meson.build
create mode 100644 test/src/module/doc/buildTest.c
diff --git a/doc/doc.pl b/doc/doc.pl
index 45b6a9edb..35e261771 100755
--- a/doc/doc.pl
+++ b/doc/doc.pl
@@ -220,6 +220,24 @@ eval
$rhVariableOverride->{$strKey} = $rhKeyVariableOverride->{$strKey};
}
+ # Build C code
+ my $strBuildPath = "${strBasePath}/output/build";
+ my $strRepoPath = dirname($strBasePath);
+ my $strBuildNinja = "${strBuildPath}/build.ninja";
+
+ &log(INFO, "build C helper");
+
+ if (!-e $strBuildNinja)
+ {
+ executeTest("meson setup -Dwerror=true -Dfatal-errors=true -Dbuildtype=debug ${strBuildPath} ${strRepoPath}");
+ }
+
+ executeTest("ninja -C ${strBuildPath} doc/src/doc-pgbackrest");
+ executeTest(
+ "${strBuildPath}/doc/src/doc-pgbackrest --repo-path=${strRepoPath}" .
+ ($strLogLevel ne 'info' ? " --log-level=${strLogLevel}" : ''),
+ {bShowOutputAsync => true});
+
# Load the manifest
my $oManifest = new pgBackRestDoc::Common::DocManifest(
$oStorageDoc, \@stryRequire, \@stryInclude, \@stryExclude, $rhKeyVariableOverride, $rhVariableOverride,
diff --git a/doc/lib/pgBackRestDoc/Common/DocConfig.pm b/doc/lib/pgBackRestDoc/Common/DocConfig.pm
index d2cb3bae7..480813136 100644
--- a/doc/lib/pgBackRestDoc/Common/DocConfig.pm
+++ b/doc/lib/pgBackRestDoc/Common/DocConfig.pm
@@ -19,18 +19,11 @@ use pgBackRestDoc::ProjectInfo;
####################################################################################################################################
# Help types
####################################################################################################################################
-use constant CONFIG_HELP_BETA => 'beta';
use constant CONFIG_HELP_COMMAND => 'command';
push @EXPORT, qw(CONFIG_HELP_COMMAND);
-use constant CONFIG_HELP_CURRENT => 'current';
-use constant CONFIG_HELP_DEFAULT => 'default';
use constant CONFIG_HELP_DESCRIPTION => 'description';
push @EXPORT, qw(CONFIG_HELP_DESCRIPTION);
-use constant CONFIG_HELP_EXAMPLE => 'example';
use constant CONFIG_HELP_INTERNAL => 'internal';
-use constant CONFIG_HELP_NAME => 'name';
-use constant CONFIG_HELP_NAME_ALT => 'name-alt';
- push @EXPORT, qw(CONFIG_HELP_NAME_ALT);
use constant CONFIG_HELP_OPTION => 'option';
push @EXPORT, qw(CONFIG_HELP_OPTION);
use constant CONFIG_HELP_SECTION => 'section';
@@ -97,54 +90,6 @@ sub docConfigOptionDefault
push @EXPORT, qw(docConfigOptionDefault);
-####################################################################################################################################
-# Get the allowed setting range for the option if it exists
-####################################################################################################################################
-sub docConfigOptionRange
-{
- my $strOption = shift;
- my $strCommand = shift;
-
- # Get the command define
- my $oCommandDefine = docConfigCommandDefine($strOption, $strCommand);
-
- # Check for default in command
- if (defined($oCommandDefine) && defined($$oCommandDefine{&CFGDEF_ALLOW_RANGE}))
- {
- return $$oCommandDefine{&CFGDEF_ALLOW_RANGE}[0], $$oCommandDefine{&CFGDEF_ALLOW_RANGE}[1];
- }
-
- # If defined return, else try to grab the global default
- return $rhConfigDefine->{$strOption}{&CFGDEF_ALLOW_RANGE}[0], $rhConfigDefine->{$strOption}{&CFGDEF_ALLOW_RANGE}[1];
-}
-
-push @EXPORT, qw(docConfigOptionRange);
-
-####################################################################################################################################
-# Get the option type
-####################################################################################################################################
-sub docConfigOptionType
-{
- my $strOption = shift;
-
- return $rhConfigDefine->{$strOption}{&CFGDEF_TYPE};
-}
-
-push @EXPORT, qw(docConfigOptionType);
-
-####################################################################################################################################
-# Test the option type
-####################################################################################################################################
-sub docConfigOptionTypeTest
-{
- my $strOption = shift;
- my $strType = shift;
-
- return docConfigOptionType($strOption) eq $strType;
-}
-
-push @EXPORT, qw(docConfigOptionTypeTest);
-
####################################################################################################################################
# CONSTRUCTOR
####################################################################################################################################
@@ -317,10 +262,8 @@ sub process
$$oCommandOption{&CONFIG_HELP_SUMMARY} = $oOptionDoc->nodeGet('summary')->textGet();
$$oCommandOption{&CONFIG_HELP_DESCRIPTION} = $oOptionDoc->textGet();
- $$oCommandOption{&CONFIG_HELP_EXAMPLE} = $oOptionDoc->fieldGet('example');
$oCommandOption->{&CONFIG_HELP_INTERNAL} =
cfgDefineCommand()->{$strCommand}{&CFGDEF_INTERNAL} ? true : $oOptionDefine->{$strOption}{&CFGDEF_INTERNAL};
- $oCommandOption->{&CONFIG_HELP_BETA} = $oOptionDefine->{$strOption}{&CFGDEF_BETA};
# If internal is defined for the option/command it overrides everthing else
if (defined($oOptionDefine->{$strOption}{&CFGDEF_COMMAND}{$strCommand}{&CFGDEF_INTERNAL}))
@@ -329,31 +272,6 @@ sub process
$oOptionDefine->{$strOption}{&CFGDEF_COMMAND}{$strCommand}{&CFGDEF_INTERNAL};
}
- $$oCommandOption{&CONFIG_HELP_NAME} = $oOptionDoc->paramGet('name');
-
- # Generate a list of alternate names
- if (defined($rhConfigDefine->{$strOption}{&CFGDEF_DEPRECATE}))
- {
- my $rhNameAlt = {};
-
- foreach my $strNameAlt (sort(keys(%{$rhConfigDefine->{$strOption}{&CFGDEF_DEPRECATE}})))
- {
- $strNameAlt =~ s/\?//g;
-
- if ($strNameAlt ne $strOption)
- {
- $rhNameAlt->{$strNameAlt} = true;
- }
- }
-
- my @stryNameAlt = sort(keys(%{$rhNameAlt}));
-
- if (@stryNameAlt > 0)
- {
- $oCommandOption->{&CONFIG_HELP_NAME_ALT} = \@stryNameAlt;
- }
- }
-
# If the option did not come from the command also store in global option list. This prevents duplication of commonly
# used options.
if ($strOptionSource ne CONFIG_HELP_SOURCE_COMMAND)
@@ -367,12 +285,8 @@ sub process
$$oOption{&CONFIG_HELP_SECTION} = $strSection;
}
- $$oOption{&CONFIG_HELP_NAME} = $oOptionDoc->paramGet('name');
- $oOption->{&CONFIG_HELP_NAME_ALT} = $oCommandOption->{&CONFIG_HELP_NAME_ALT};
$$oOption{&CONFIG_HELP_DESCRIPTION} = $$oCommandOption{&CONFIG_HELP_DESCRIPTION};
- $$oOption{&CONFIG_HELP_EXAMPLE} = $oOptionDoc->fieldGet('example');
$oOption->{&CONFIG_HELP_INTERNAL} = $oOptionDefine->{$strOption}{&CFGDEF_INTERNAL};
- $oOption->{&CONFIG_HELP_BETA} = $oOptionDefine->{$strOption}{&CFGDEF_BETA};
}
}
}
@@ -603,313 +517,4 @@ sub manGetFormatText
return $strResult;
}
-####################################################################################################################################
-# helpConfigDocGet
-#
-# Get the xml for configuration help.
-####################################################################################################################################
-sub helpConfigDocGet
-{
- my $self = shift;
-
- # Assign function parameters, defaults, and log debug info
- my $strOperation = logDebugParam(__PACKAGE__ . '->helpConfigDocGet');
-
- # Build a hash of the sections
- my $oConfigHash = $self->{oConfigHash};
- my $oConfigDoc = $self->{oDoc}->nodeGet('config');
- my $oSectionHash = {};
-
- foreach my $strOption (sort(keys(%{$$oConfigHash{&CONFIG_HELP_OPTION}})))
- {
- my $oOption = $$oConfigHash{&CONFIG_HELP_OPTION}{$strOption};
-
- if (defined($$oOption{&CONFIG_HELP_SECTION}))
- {
- $$oSectionHash{$$oOption{&CONFIG_HELP_SECTION}}{$strOption} = true;
- }
- }
-
- my $oDoc = new pgBackRestDoc::Common::Doc();
- $oDoc->paramSet('title', $oConfigDoc->paramGet('title'));
-
- # set the description for use as a meta tag
- $oDoc->fieldSet('description', $oConfigDoc->fieldGet('description'));
-
- # Output the introduction
- my $oIntroSectionDoc = $oDoc->nodeAdd('section', undef, {id => 'introduction'});
- $oIntroSectionDoc->nodeAdd('title')->textSet('Introduction');
- $oIntroSectionDoc->textSet($oConfigDoc->textGet());
-
- foreach my $strSection (sort(keys(%{$oSectionHash})))
- {
- my $oSectionElement = $oDoc->nodeAdd('section', undef, {id => "section-${strSection}"});
-
- my $oSectionDoc = $oConfigDoc->nodeGet('config-section-list')->nodeGetById('config-section', $strSection);
-
- # Set the summary text for the section
- $oSectionElement->textSet($oSectionDoc->textGet());
-
- $oSectionElement->
- nodeAdd('title')->textSet(
- {name => 'text',
- children=> [$oSectionDoc->paramGet('name') . ' Options (', {name => 'id', value => $strSection}, ')']});
-
- foreach my $strOption (sort(keys(%{$$oSectionHash{$strSection}})))
- {
- # Skip internal options
- next if $oConfigHash->{&CONFIG_HELP_OPTION}{$strOption}{&CONFIG_HELP_INTERNAL};
-
- $self->helpOptionGet(undef, $strOption, $oSectionElement, $$oConfigHash{&CONFIG_HELP_OPTION}{$strOption});
- }
- }
-
- # Return from function and log return values if any
- return logDebugReturn
- (
- $strOperation,
- {name => 'oDoc', value => $oDoc}
- );
-}
-
-####################################################################################################################################
-# helpCommandDocGet
-#
-# Get the xml for command help.
-####################################################################################################################################
-sub helpCommandDocGet
-{
- my $self = shift;
-
- # Assign function parameters, defaults, and log debug info
- my $strOperation = logDebugParam(__PACKAGE__ . '->helpCommandDocGet');
-
- # Working variables
- my $oConfigHash = $self->{oConfigHash};
- my $oOperationDoc = $self->{oDoc}->nodeGet('operation');
- my $oOptionDefine = cfgDefine();
-
- my $oDoc = new pgBackRestDoc::Common::Doc();
- $oDoc->paramSet('title', $oOperationDoc->paramGet('title'));
-
- # set the description for use as a meta tag
- $oDoc->fieldSet('description', $oOperationDoc->fieldGet('description'));
-
- # Output the introduction
- my $oIntroSectionDoc = $oDoc->nodeAdd('section', undef, {id => 'introduction'});
- $oIntroSectionDoc->nodeAdd('title')->textSet('Introduction');
- $oIntroSectionDoc->textSet($oOperationDoc->textGet());
-
- foreach my $strCommand (sort(keys(%{$$oConfigHash{&CONFIG_HELP_COMMAND}})))
- {
- # Skip internal commands
- next if $oConfigHash->{&CONFIG_HELP_COMMAND}{$strCommand}{&CONFIG_HELP_INTERNAL};
-
- my $oCommandHash = $$oConfigHash{&CONFIG_HELP_COMMAND}{$strCommand};
- my $oSectionElement = $oDoc->nodeAdd('section', undef, {id => "command-${strCommand}"});
-
- my $oCommandDoc = $oOperationDoc->nodeGet('command-list')->nodeGetById('command', $strCommand);
-
- $oSectionElement->
- nodeAdd('title')->textSet(
- {name => 'text',
- children=> [$oCommandDoc->paramGet('name') . ' Command (', {name => 'id', value => $strCommand}, ')']});
-
- $oSectionElement->textSet($$oCommandHash{&CONFIG_HELP_DESCRIPTION});
-
- # use Data::doc;
- # confess Dumper($oDoc->{oDoc});
-
- if (defined($$oCommandHash{&CONFIG_HELP_OPTION}))
- {
- my $oCategory = {};
-
- foreach my $strOption (sort(keys(%{$$oCommandHash{&CONFIG_HELP_OPTION}})))
- {
- # Skip internal options
- next if $$oCommandHash{&CONFIG_HELP_OPTION}{$strOption}{&CONFIG_HELP_INTERNAL};
-
- # Skip secure options that can't be defined on the command line
- next if ($rhConfigDefine->{$strOption}{&CFGDEF_SECURE});
-
- my ($oOption, $strCategory) = helpCommandDocGetOptionFind($oConfigHash, $oOptionDefine, $strCommand, $strOption);
-
- $$oCategory{$strCategory}{$strOption} = $oOption;
- }
-
- # Iterate sections
- foreach my $strCategory (sort(keys(%{$oCategory})))
- {
- my $oOptionListElement = $oSectionElement->nodeAdd(
- 'section', undef, {id => "category-${strCategory}", toc => 'n'});
-
- $oOptionListElement->
- nodeAdd('title')->textSet(ucfirst($strCategory) . ' Options');
-
- # Iterate options
- foreach my $strOption (sort(keys(%{$$oCategory{$strCategory}})))
- {
- $self->helpOptionGet($strCommand, $strOption, $oOptionListElement,
- $$oCommandHash{&CONFIG_HELP_OPTION}{$strOption});
- }
- }
- }
- }
-
- # Return from function and log return values if any
- return logDebugReturn
- (
- $strOperation,
- {name => 'oDoc', value => $oDoc}
- );
-}
-
-# Helper function for helpCommandDocGet() to find options. The option may be stored with the command or in the option list depending
-# on whether it's generic or command-specific
-sub helpCommandDocGetOptionFind
-{
- my $oConfigHelpData = shift;
- my $oOptionDefine = shift;
- my $strCommand = shift;
- my $strOption = shift;
-
- # Get section from the option
- my $strSection = $oConfigHelpData->{&CONFIG_HELP_OPTION}{$strOption}{&CONFIG_HELP_SECTION};
-
- # Get option from the command to start
- my $oOption = $$oConfigHelpData{&CONFIG_HELP_COMMAND}{$strCommand}{&CONFIG_HELP_OPTION}{$strOption};
-
- # If the option has a section (i.e. not command-line only) then it comes from the standard option reference
- if ($$oOption{&CONFIG_HELP_SOURCE} eq CONFIG_HELP_SOURCE_SECTION)
- {
- $oOption = $$oConfigHelpData{&CONFIG_HELP_OPTION}{$strOption};
- }
-
- # Reduce the sections that are shown in the command help. This is the same logic as help.c.
- if (!defined($strSection) ||
- ($strSection ne 'general' && $strSection ne 'log' && $strSection ne 'repository' && $strSection ne 'stanza'))
- {
- $strSection = 'command';
- }
-
- return $oOption, $strSection;
-}
-
-####################################################################################################################################
-# helpOptionGet
-#
-# Get the xml for an option.
-####################################################################################################################################
-sub helpOptionGet
-{
- my $self = shift;
- my $strCommand = shift;
- my $strOption = shift;
- my $oParentElement = shift;
- my $oOptionHash = shift;
-
- # Create the option section
- my $oOptionElement = $oParentElement->nodeAdd(
- 'section', undef, {id => "option-${strOption}", toc => defined($strCommand) ? 'n' : 'y'});
-
- # Set the option section title
- $oOptionElement->
- nodeAdd('title')->textSet(
- {name => 'text',
- children=> [$$oOptionHash{&CONFIG_HELP_NAME} . ' Option (', {name => 'id', value => "--${strOption}"}, ')']});
-
- # Add the option summary and description
- $oOptionElement->
- nodeAdd('p')->textSet($$oOptionHash{&CONFIG_HELP_SUMMARY});
-
- # Add beta warning
- if ($$oOptionHash{&CONFIG_HELP_BETA})
- {
- $oOptionElement->nodeAdd('p')->textSet({name => 'text', children => ['FOR BETA TESTING ONLY. DO NOT USE IN PRODUCTION.']});
- }
-
- $oOptionElement->
- nodeAdd('p')->textSet($$oOptionHash{&CONFIG_HELP_DESCRIPTION});
-
- # Get the default value (or required=n if there is no default)
- my $strCodeBlock;
-
- if (defined(docConfigOptionDefault($strOption, $strCommand)))
- {
- my $strDefault;
-
- if ($strOption eq CFGOPT_REPO_HOST_CMD || $strOption eq CFGOPT_PG_HOST_CMD)
- {
- $strDefault = '[INSTALL-PATH]/' . PROJECT_EXE;
- }
- else
- {
- if (docConfigOptionTypeTest($strOption, CFGDEF_TYPE_BOOLEAN))
- {
- $strDefault = docConfigOptionDefault($strOption, $strCommand) ? 'y' : 'n';
- }
- else
- {
- $strDefault = docConfigOptionDefault($strOption, $strCommand);
- }
- }
-
- $strCodeBlock = "default: ${strDefault}";
- }
- # This won't work correctly until there is some notion of dependency
- # elsif (optionRequired($strOption, $strCommand))
- # {
- # $strCodeBlock = 'required: y';
- # }
-
- # Get the allowed range if it exists
- my ($strRangeMin, $strRangeMax) = docConfigOptionRange($strOption, $strCommand);
-
- if (defined($strRangeMin))
- {
- $strCodeBlock .= (defined($strCodeBlock) ? "\n" : '') . "allowed: ${strRangeMin}-${strRangeMax}";
- }
-
- # Get the example
- my $strExample = '';
-
- my $strOptionPrefix = $rhConfigDefine->{$strOption}{&CFGDEF_GROUP};
- my $strOptionIndex = defined($strOptionPrefix) ?
- "${strOptionPrefix}1-" . substr($strOption, length($strOptionPrefix) + 1) : $strOption;
-
- if (defined($strCommand) && docConfigOptionTypeTest($strOption, CFGDEF_TYPE_BOOLEAN))
- {
- if ($$oOptionHash{&CONFIG_HELP_EXAMPLE} ne 'n' && $$oOptionHash{&CONFIG_HELP_EXAMPLE} ne 'y')
- {
- confess &log(ERROR, "option ${strOption} example should be boolean but value is: " .
- $$oOptionHash{&CONFIG_HELP_EXAMPLE});
- }
-
- $strExample = '--' . ($$oOptionHash{&CONFIG_HELP_EXAMPLE} eq 'n' ? 'no-' : '') . $strOptionIndex;
- }
- else
- {
- if (defined($strCommand))
- {
- $strExample = '--';
- }
-
- $strExample .= "${strOptionIndex}=" . $$oOptionHash{&CONFIG_HELP_EXAMPLE};
- }
-
- $strCodeBlock .= (defined($strCodeBlock) ? "\n" : '') . "example: ${strExample}";
-
- $oOptionElement->
- nodeAdd('code-block')->valueSet($strCodeBlock);
-
- # Output deprecated names
- if (defined($oOptionHash->{&CONFIG_HELP_NAME_ALT}))
- {
- my $strCaption = 'Deprecated Name' . (@{$oOptionHash->{&CONFIG_HELP_NAME_ALT}} > 1 ? 's' : '');
-
- $oOptionElement->
- nodeAdd('p')->textSet("${strCaption}: " . join(', ', @{$oOptionHash->{&CONFIG_HELP_NAME_ALT}}));
- }
-}
-
1;
diff --git a/doc/lib/pgBackRestDoc/Common/DocRender.pm b/doc/lib/pgBackRestDoc/Common/DocRender.pm
index 1f928e265..6c0df2932 100644
--- a/doc/lib/pgBackRestDoc/Common/DocRender.pm
+++ b/doc/lib/pgBackRestDoc/Common/DocRender.pm
@@ -204,22 +204,7 @@ sub new
new pgBackRestDoc::Common::DocConfig(${$self->{oManifest}->sourceGet('help')}{doc}, $self);
}
- if (defined($$oRenderOut{source}) && $$oRenderOut{source} eq 'help' && $self->{oManifest}->isBackRest())
- {
- 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}");
- }
- }
- elsif (defined($$oRenderOut{source}) && $$oRenderOut{source} eq 'release' && $self->{oManifest}->isBackRest())
+ if (defined($$oRenderOut{source}) && $$oRenderOut{source} eq 'release' && $self->{oManifest}->isBackRest())
{
require pgBackRestDoc::Custom::DocCustomRelease;
pgBackRestDoc::Custom::DocCustomRelease->import();
diff --git a/doc/manifest.xml b/doc/manifest.xml
index 22886c3b6..659f32a5c 100644
--- a/doc/manifest.xml
+++ b/doc/manifest.xml
@@ -86,6 +86,8 @@
+
+
@@ -101,8 +103,8 @@
-
-
+
+
diff --git a/doc/src/build/config/config.yaml b/doc/src/build/config/config.yaml
new file mode 100644
index 000000000..e029b594d
--- /dev/null
+++ b/doc/src/build/config/config.yaml
@@ -0,0 +1,97 @@
+####################################################################################################################################
+# Configuration Definition
+####################################################################################################################################
+
+####################################################################################################################################
+# Commands
+####################################################################################################################################
+command:
+ help:
+ log-level-default: DEBUG
+ parameter-allowed: true
+
+ build:
+ parameter-allowed: true
+
+ noop:
+ internal: true
+
+ version:
+ log-level-default: DEBUG
+
+####################################################################################################################################
+# Option groups that are not used but must be present for modules to compile
+####################################################################################################################################
+optionGroup:
+ pg: {}
+ repo: {}
+
+####################################################################################################################################
+# Options
+####################################################################################################################################
+option:
+ # General options
+ #---------------------------------------------------------------------------------------------------------------------------------
+ buffer-size:
+ type: size
+ internal: true
+ default: 64KiB
+ allow-list:
+ - 16KiB
+ - 32KiB
+ - 64KiB
+ - 128KiB
+ - 256KiB
+ - 512KiB
+ - 1MiB
+
+ neutral-umask:
+ type: boolean
+ internal: true
+ default: true
+
+ repo-path:
+ type: string
+ default: pgbackrest
+ command:
+ build: {}
+
+ # Logging options
+ #---------------------------------------------------------------------------------------------------------------------------------
+ log-level:
+ type: string-id
+ default: info
+ allow-list:
+ - off
+ - error
+ - warn
+ - info
+ - detail
+ - debug
+ - trace
+
+ log-timestamp:
+ type: boolean
+ default: true
+ negate: true
+ command: log-level
+
+ # Options that are not used but must be present for modules to compile. All must have a default or not be required.
+ #---------------------------------------------------------------------------------------------------------------------------------
+ beta: {type: boolean, default: false, command: {noop: {}}}
+ compress-level-network: {type: string, required: false, command: {noop: {}}}
+ config: {
+ type: string, internal: true, default: CFGOPTDEF_CONFIG_PATH "/" PROJECT_CONFIG_FILE, default-literal: true, negate: true}
+ config-path: {type: string, required: false, command: {noop: {}}}
+ config-include-path: {
+ type: string, default: CFGOPTDEF_CONFIG_PATH "/" PROJECT_CONFIG_INCLUDE_PATH, default-literal: true, command: {noop: {}}}
+ job-retry: {type: string, required: false, deprecate: {job-retry-old: {}}, command: {noop: {}}}
+ job-retry-interval: {type: string, required: false, command: {noop: {}}}
+ log-level-file: {type: string, required: false, command: {noop: {}}}
+ log-level-stderr: {type: string, required: false, command: {noop: {}}}
+ pg: {type: string, required: false, command: {noop: {}}}
+ pg-path: {type: string, required: false, command: {noop: {}}}
+ repo-type: {type: string, required: false, command: {noop: {}}}
+ repo: {type: string, required: false, command: {noop: {}}}
+ spool-path: {type: string, required: false, command: {noop: {}}}
+ stanza: {type: string, required: false, command: {noop: {}}}
diff --git a/doc/src/build/help/help.xml b/doc/src/build/help/help.xml
new file mode 100644
index 000000000..7ff990d19
--- /dev/null
+++ b/doc/src/build/help/help.xml
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Get help.
+
+
+
Three levels of help are provided. If no command is specified then general help will be displayed. If a command is specified (e.g. pgbackrest help backup) then a full description of the command will be displayed along with a list of valid options. If an option is specified in addition to a command (e.g. pgbackrest help backup type) then a full description of the option as it applies to the command will be displayed.