diff --git a/src/Makefile.in b/src/Makefile.in index 83d8798cdb..a2d3376c15 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -83,6 +83,7 @@ SRCS = \ command/repo/common.c \ command/repo/get.c \ command/repo/ls.c \ + command/repo/push.c \ command/repo/put.c \ command/repo/rm.c \ command/restore/blockChecksum.c \ diff --git a/src/build/config/config.yaml b/src/build/config/config.yaml index 07c7b2948b..1636c2ccd1 100644 --- a/src/build/config/config.yaml +++ b/src/build/config/config.yaml @@ -107,6 +107,16 @@ command: log-level-default: DEBUG parameter-allowed: true + repo-push: + command-role: + async: {} + local: {} + remote: {} + internal: true + log-file: false + log-level-default: DEBUG + parameter-allowed: true + repo-put: command-role: remote: {} @@ -328,6 +338,7 @@ option: backup: {} check: {} expire: {} + repo-push: {} restore: {} stanza-create: {} stanza-upgrade: {} @@ -392,6 +403,8 @@ option: manifest: default: latest required: true + repo-push: + required: true restore: default: latest required: true @@ -425,6 +438,8 @@ option: required: false repo-ls: required: false + repo-push: + required: true repo-put: required: false repo-rm: @@ -572,6 +587,7 @@ option: manifest: {} repo-get: {} repo-ls: {} + repo-push: {} repo-put: {} repo-rm: {} restore: {} @@ -614,6 +630,7 @@ option: manifest: {} repo-get: {} repo-ls: {} + repo-push: {} repo-put: {} repo-rm: {} restore: {} @@ -785,6 +802,7 @@ option: command: archive-push: {} backup: {} + repo-push: {} command-role: main: {} @@ -812,6 +830,7 @@ option: manifest: {} repo-get: {} repo-ls: {} + repo-push: {} repo-put: {} restore: {} stanza-create: {} @@ -1731,6 +1750,9 @@ option: command-role: main: {} remote: {} + repo-push: + command-role: + main: {} repo-put: command-role: main: {} @@ -1851,6 +1873,10 @@ option: command-role: main: {} remote: {} + repo-push: + command-role: + main: {} + remote: {} repo-put: command-role: main: {} diff --git a/src/build/help/help.xml b/src/build/help/help.xml index a55b64e06a..bb312d7238 100644 --- a/src/build/help/help.xml +++ b/src/build/help/help.xml @@ -2414,6 +2414,27 @@ + + Upload a metadata file to the repository. + + +

Upload a metadata file to the repository. The metadata file is stored in the same storage as the restore point and inherits the compression settings defined in the pgBackRest configuration.

+
+ + + + + +
+ Put a file in the repository. diff --git a/src/command/repo/push.c b/src/command/repo/push.c new file mode 100644 index 0000000000..720b8e6871 --- /dev/null +++ b/src/command/repo/push.c @@ -0,0 +1,208 @@ +/*********************************************************************************************************************************** +Repository Put Command +***********************************************************************************************************************************/ +#include "build.auto.h" + +#include + +#include "command/repo/common.h" +#include "common/compress/helper.h" +#include "common/debug.h" +#include "common/io/fdRead.h" +#include "common/io/filter/size.h" +#include "common/io/io.h" +#include "common/log.h" +#include "common/memContext.h" +#include "common/type/string.h" +#include "config/config.h" +#include "info/manifest.h" +#include "storage/helper.h" + +static String * +composeDestinationPath(const String *backupLabel, const String *fileName) +{ + FUNCTION_LOG_BEGIN(logLevelDebug); + FUNCTION_LOG_PARAM(STRING, backupLabel); + FUNCTION_LOG_PARAM(STRING, fileName); + FUNCTION_LOG_END(); + + String *const result = strNewFmt(STORAGE_REPO_BACKUP "/%s/%s", strZ(backupLabel), strZ(fileName)); + + FUNCTION_LOG_RETURN(STRING, result); +} + +/*********************************************************************************************************************************** +Write source IO to destination file +***********************************************************************************************************************************/ +static void +storagePushProcess(const String *file, CompressType compressType, int compressLevel) +{ + FUNCTION_LOG_BEGIN(logLevelDebug); + FUNCTION_LOG_PARAM(STRING, file); + FUNCTION_LOG_PARAM(ENUM, compressType); + FUNCTION_LOG_PARAM(INT, compressLevel); + FUNCTION_LOG_END(); + + // Ensure that the file exists and readable + MEM_CONTEXT_TEMP_BEGIN() + { + // Normalize source file path + // Get current working dir + char currentWorkDir[1024]; + THROW_ON_SYS_ERROR(getcwd(currentWorkDir, sizeof(currentWorkDir)) == NULL, FormatError, "unable to get cwd"); + + String *sourcePath = strPathAbsolute(file, strNewZ(currentWorkDir)); + + // Repository Path Formation + + const String *backupLabel = cfgOptionStr(cfgOptSet); + + String *destFilename = strCat(strNew(), strFileName(file)); + compressExtCat(destFilename, compressType); + + String *destPath = composeDestinationPath(backupLabel, destFilename); + + // Is path valid for repo? + destPath = repoPathIsValid(destPath); + + bool repoChecksum = false; + const Storage *storage = storageRepoWrite(); + const StorageWrite *const destination = storageNewWriteP(storage, destPath); + + IoRead *const sourceIo = storageReadIo(storageNewReadP(storageLocal(), sourcePath)); + IoWrite *const destinationIo = storageWriteIo(destination); + + IoFilterGroup *const readFilterGroup = ioReadFilterGroup(sourceIo); + IoFilterGroup *const writeFilterGroup = ioWriteFilterGroup(destinationIo); + + const String *manifestFileName = strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strZ(backupLabel)); + Manifest *manifest = manifestLoadFile( + storage, manifestFileName, + cipherTypeNone, NULL); + + // Add SHA1 filter + ioFilterGroupAdd(writeFilterGroup, cryptoHashNew(hashTypeSha1)); + + // Add compression + if (compressType != compressTypeNone) + { + ioFilterGroupAdd( + writeFilterGroup, + compressFilterP(compressType, compressLevel)); + + repoChecksum = true; + } + + // Capture checksum of file stored in the repo if filters that modify the output have been applied + if (repoChecksum) + ioFilterGroupAdd(writeFilterGroup, cryptoHashNew(hashTypeSha1)); + + // Add size filter last to calculate repo size + ioFilterGroupAdd(writeFilterGroup, ioSizeNew()); + + // Add size filter last to calculate source file size + ioFilterGroupAdd(readFilterGroup, ioSizeNew()); + + // Open source and destination + ioReadOpen(sourceIo); + ioWriteOpen(destinationIo); + + // Copy data from source to destination + ioCopyP(sourceIo, destinationIo); + + // Close the source and destination + ioReadClose(sourceIo); + ioWriteClose(destinationIo); + + // Use base path to set ownership and mode + const ManifestPath *const basePath = manifestPathFind(manifest, MANIFEST_TARGET_PGDATA_STR); + + // Add to manifest + uint64_t rsize = pckReadU64P(ioFilterGroupResultP(readFilterGroup, SIZE_FILTER_TYPE)); + uint64_t wsize = pckReadU64P(ioFilterGroupResultP(writeFilterGroup, SIZE_FILTER_TYPE)); + ManifestFile customFile = + { + .name = destFilename, + .mode = basePath->mode & (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), + .size = wsize, + .sizeOriginal = rsize, + .sizeRepo = wsize, + .timestamp = time(NULL), + .checksumSha1 = bufPtr(pckReadBinP(ioFilterGroupResultP(writeFilterGroup, CRYPTO_HASH_FILTER_TYPE, .idx = 0))), + }; + + if (repoChecksum) + { + PackRead *packRead = ioFilterGroupResultP(writeFilterGroup, CRYPTO_HASH_FILTER_TYPE, .idx = 1); + ASSERT(packRead != NULL); + customFile.checksumRepoSha1 = bufPtr(pckReadBinP(packRead)); + } + + bool found = false; + + for (unsigned int fileIdx = 0; fileIdx < manifestCustomFileTotal(manifest); fileIdx++) + { + ManifestFile manifestFile = manifestCustomFile(manifest, fileIdx); + + if (strCmp(manifestFile.name, destFilename) == 0){ + manifestFile.mode = customFile.mode; + manifestFile.size = customFile.size; + manifestFile.sizeOriginal = customFile.sizeOriginal; + manifestFile.sizeRepo = customFile.sizeRepo; + manifestFile.timestamp = customFile.timestamp; + manifestFile.checksumSha1 = customFile.checksumSha1; + + manifestCustomFileUpdate(manifest, &manifestFile); + found = true; + break; + } + } + + if (!found) + manifestCustomFileAdd(manifest, &customFile); + + // Save manifest + IoWrite *const manifestWrite = storageWriteIo( + storageNewWriteP( + storageRepoWrite(), + manifestFileName + )); + + manifestSave(manifest, manifestWrite); + } + MEM_CONTEXT_TEMP_END(); + + FUNCTION_LOG_RETURN_VOID(); +} + +/**********************************************************************************************************************************/ +FN_EXTERN void +cmdStoragePush(void) +{ + FUNCTION_LOG_VOID(logLevelDebug); + + MEM_CONTEXT_TEMP_BEGIN() + { + const StringList *params = cfgCommandParam(); + + if (strLstSize(params) != 1) + THROW(ParamInvalidError, "exactly one parameter is required"); + + String *filename = strLstGet(params, 0); + + // Check that the filename does not end with a slash + if (strEndsWith(filename, FSLASH_STR)) + THROW(ParamInvalidError, "file parameter should not end with a slash"); + + LOG_INFO_FMT( + "push file %s to the archive.", + strZ(filename)); + + storagePushProcess(filename, + compressTypeEnum(cfgOptionStrId(cfgOptCompressType)), + cfgOptionInt(cfgOptCompressLevel)); + } + MEM_CONTEXT_TEMP_END(); + + FUNCTION_LOG_RETURN_VOID(); +} diff --git a/src/command/repo/push.h b/src/command/repo/push.h new file mode 100644 index 0000000000..1afb2dc683 --- /dev/null +++ b/src/command/repo/push.h @@ -0,0 +1,13 @@ +/*********************************************************************************************************************************** +Repository Push Command +***********************************************************************************************************************************/ +#ifndef COMMAND_STORAGE_PUSH_H +#define COMMAND_STORAGE_PUSH_H + +/*********************************************************************************************************************************** +Functions +***********************************************************************************************************************************/ +// Push a metadata file into the repository +FN_EXTERN void cmdStoragePush(void); + +#endif diff --git a/src/common/type/string.c b/src/common/type/string.c index da7ea27d8d..8a0b82588a 100644 --- a/src/common/type/string.c +++ b/src/common/type/string.c @@ -796,6 +796,27 @@ strPath(const String *const this) end - this->pub.buffer <= 1 ? (size_t)(end - this->pub.buffer) : (size_t)(end - this->pub.buffer - 1))); } +/**********************************************************************************************************************************/ +FN_EXTERN String * +strFileName(const String *const this) +{ + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(STRING, this); + FUNCTION_TEST_END(); + + ASSERT(this != NULL); + + const char *end = this->pub.buffer + strSize(this); + const char *ptr = end; + + while (ptr > this->pub.buffer && *(ptr - 1) != '/') + ptr--; + + FUNCTION_TEST_RETURN( + STRING, + strNewZN(ptr, (size_t)(end - ptr))); +} + /**********************************************************************************************************************************/ FN_EXTERN String * strPathAbsolute(const String *const this, const String *const base) diff --git a/src/common/type/string.h b/src/common/type/string.h index 50f89ae892..5413890e57 100644 --- a/src/common/type/string.h +++ b/src/common/type/string.h @@ -197,6 +197,9 @@ FN_EXTERN String *strLower(String *this); // Return the path part of a string (i.e. everything before the last / or "" if there is no /) FN_EXTERN String *strPath(const String *this); +// Return the file name part of a string (i.e. everything after the last / or "" if there is no /) +FN_EXTERN String *strFileName(const String *const this); + // Combine with a base path to get an absolute path FN_EXTERN String *strPathAbsolute(const String *this, const String *base); diff --git a/src/config/config.auto.h b/src/config/config.auto.h index 72067a3876..b36e2d4e88 100644 --- a/src/config/config.auto.h +++ b/src/config/config.auto.h @@ -20,6 +20,7 @@ Command constants #define CFGCMD_MANIFEST "manifest" #define CFGCMD_REPO_GET "repo-get" #define CFGCMD_REPO_LS "repo-ls" +#define CFGCMD_REPO_PUSH "repo-push" #define CFGCMD_REPO_PUT "repo-put" #define CFGCMD_REPO_RM "repo-rm" #define CFGCMD_RESTORE "restore" @@ -33,7 +34,7 @@ Command constants #define CFGCMD_VERIFY "verify" #define CFGCMD_VERSION "version" -#define CFG_COMMAND_TOTAL 23 +#define CFG_COMMAND_TOTAL 24 /*********************************************************************************************************************************** Option group constants @@ -371,6 +372,7 @@ typedef enum cfgCmdManifest, cfgCmdRepoGet, cfgCmdRepoLs, + cfgCmdRepoPush, cfgCmdRepoPut, cfgCmdRepoRm, cfgCmdRestore, diff --git a/src/config/parse.auto.c.inc b/src/config/parse.auto.c.inc index edddfc6f70..3b8150d349 100644 --- a/src/config/parse.auto.c.inc +++ b/src/config/parse.auto.c.inc @@ -822,6 +822,22 @@ static const ParseRuleCommand parseRuleCommand[CFG_COMMAND_TOTAL] = ), // cmd/repo-ls ), // cmd/repo-ls // ----------------------------------------------------------------------------------------------------------------------------- + PARSE_RULE_COMMAND // cmd/repo-push + ( // cmd/repo-push + PARSE_RULE_COMMAND_NAME("repo-push"), // cmd/repo-push + PARSE_RULE_COMMAND_LOCK_TYPE(None), // cmd/repo-push + PARSE_RULE_COMMAND_LOG_LEVEL_DEFAULT(Debug), // cmd/repo-push + PARSE_RULE_COMMAND_PARAMETER_ALLOWED(true), // cmd/repo-push + // cmd/repo-push + PARSE_RULE_COMMAND_ROLE_VALID_LIST // cmd/repo-push + ( // cmd/repo-push + PARSE_RULE_COMMAND_ROLE(Async) // cmd/repo-push + PARSE_RULE_COMMAND_ROLE(Local) // cmd/repo-push + PARSE_RULE_COMMAND_ROLE(Main) // cmd/repo-push + PARSE_RULE_COMMAND_ROLE(Remote) // cmd/repo-push + ), // cmd/repo-push + ), // cmd/repo-push + // ----------------------------------------------------------------------------------------------------------------------------- PARSE_RULE_COMMAND // cmd/repo-put ( // cmd/repo-put PARSE_RULE_COMMAND_NAME("repo-put"), // cmd/repo-put @@ -1476,6 +1492,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/beta PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/beta PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/beta + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/beta PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/beta PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/beta PARSE_RULE_OPTION_COMMAND(Restore) // opt/beta @@ -1493,6 +1510,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ( // opt/beta PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/beta PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/beta + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/beta ), // opt/beta // opt/beta PARSE_RULE_OPTION_COMMAND_ROLE_LOCAL_VALID_LIST // opt/beta @@ -1500,6 +1518,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/beta PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/beta PARSE_RULE_OPTION_COMMAND(Backup) // opt/beta + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/beta PARSE_RULE_OPTION_COMMAND(Restore) // opt/beta PARSE_RULE_OPTION_COMMAND(Verify) // opt/beta ), // opt/beta @@ -1515,6 +1534,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/beta PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/beta PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/beta + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/beta PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/beta PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/beta PARSE_RULE_OPTION_COMMAND(Restore) // opt/beta @@ -1768,6 +1788,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ( // opt/compress PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/compress PARSE_RULE_OPTION_COMMAND(Backup) // opt/compress + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/compress ), // opt/compress // opt/compress PARSE_RULE_OPTIONAL // opt/compress @@ -1794,11 +1815,13 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ( // opt/compress-level PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/compress-level PARSE_RULE_OPTION_COMMAND(Backup) // opt/compress-level + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/compress-level ), // opt/compress-level // opt/compress-level PARSE_RULE_OPTION_COMMAND_ROLE_ASYNC_VALID_LIST // opt/compress-level ( // opt/compress-level PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/compress-level + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/compress-level ), // opt/compress-level ), // opt/compress-level // ----------------------------------------------------------------------------------------------------------------------------- @@ -1821,6 +1844,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/compress-level-network PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/compress-level-network PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/compress-level-network + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/compress-level-network PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/compress-level-network PARSE_RULE_OPTION_COMMAND(Restore) // opt/compress-level-network PARSE_RULE_OPTION_COMMAND(StanzaCreate) // opt/compress-level-network @@ -1833,6 +1857,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ( // opt/compress-level-network PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/compress-level-network PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/compress-level-network + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/compress-level-network ), // opt/compress-level-network // opt/compress-level-network PARSE_RULE_OPTION_COMMAND_ROLE_LOCAL_VALID_LIST // opt/compress-level-network @@ -1840,6 +1865,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/compress-level-network PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/compress-level-network PARSE_RULE_OPTION_COMMAND(Backup) // opt/compress-level-network + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/compress-level-network PARSE_RULE_OPTION_COMMAND(Restore) // opt/compress-level-network PARSE_RULE_OPTION_COMMAND(Verify) // opt/compress-level-network ), // opt/compress-level-network @@ -1874,11 +1900,13 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ( // opt/compress-type PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/compress-type PARSE_RULE_OPTION_COMMAND(Backup) // opt/compress-type + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/compress-type ), // opt/compress-type // opt/compress-type PARSE_RULE_OPTION_COMMAND_ROLE_ASYNC_VALID_LIST // opt/compress-type ( // opt/compress-type PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/compress-type + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/compress-type ), // opt/compress-type // opt/compress-type PARSE_RULE_OPTIONAL // opt/compress-type @@ -1928,6 +1956,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/config PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/config PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/config + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/config PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/config PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/config PARSE_RULE_OPTION_COMMAND(Restore) // opt/config @@ -1945,6 +1974,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ( // opt/config PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/config PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/config + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/config ), // opt/config // opt/config PARSE_RULE_OPTION_COMMAND_ROLE_LOCAL_VALID_LIST // opt/config @@ -1952,6 +1982,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/config PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/config PARSE_RULE_OPTION_COMMAND(Backup) // opt/config + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/config PARSE_RULE_OPTION_COMMAND(Restore) // opt/config PARSE_RULE_OPTION_COMMAND(Verify) // opt/config ), // opt/config @@ -1967,6 +1998,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/config PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/config PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/config + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/config PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/config PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/config PARSE_RULE_OPTION_COMMAND(Restore) // opt/config @@ -2007,6 +2039,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/config-include-path PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/config-include-path PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/config-include-path + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/config-include-path PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/config-include-path PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/config-include-path PARSE_RULE_OPTION_COMMAND(Restore) // opt/config-include-path @@ -2024,6 +2057,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ( // opt/config-include-path PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/config-include-path PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/config-include-path + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/config-include-path ), // opt/config-include-path // opt/config-include-path PARSE_RULE_OPTION_COMMAND_ROLE_LOCAL_VALID_LIST // opt/config-include-path @@ -2031,6 +2065,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/config-include-path PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/config-include-path PARSE_RULE_OPTION_COMMAND(Backup) // opt/config-include-path + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/config-include-path PARSE_RULE_OPTION_COMMAND(Restore) // opt/config-include-path PARSE_RULE_OPTION_COMMAND(Verify) // opt/config-include-path ), // opt/config-include-path @@ -2046,6 +2081,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/config-include-path PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/config-include-path PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/config-include-path + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/config-include-path PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/config-include-path PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/config-include-path PARSE_RULE_OPTION_COMMAND(Restore) // opt/config-include-path @@ -2086,6 +2122,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/config-path PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/config-path PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/config-path + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/config-path PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/config-path PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/config-path PARSE_RULE_OPTION_COMMAND(Restore) // opt/config-path @@ -2103,6 +2140,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ( // opt/config-path PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/config-path PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/config-path + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/config-path ), // opt/config-path // opt/config-path PARSE_RULE_OPTION_COMMAND_ROLE_LOCAL_VALID_LIST // opt/config-path @@ -2110,6 +2148,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/config-path PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/config-path PARSE_RULE_OPTION_COMMAND(Backup) // opt/config-path + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/config-path PARSE_RULE_OPTION_COMMAND(Restore) // opt/config-path PARSE_RULE_OPTION_COMMAND(Verify) // opt/config-path ), // opt/config-path @@ -2125,6 +2164,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/config-path PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/config-path PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/config-path + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/config-path PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/config-path PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/config-path PARSE_RULE_OPTION_COMMAND(Restore) // opt/config-path @@ -2330,6 +2370,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/exec-id PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/exec-id PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/exec-id + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/exec-id PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/exec-id PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/exec-id PARSE_RULE_OPTION_COMMAND(Restore) // opt/exec-id @@ -2347,6 +2388,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ( // opt/exec-id PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/exec-id PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/exec-id + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/exec-id ), // opt/exec-id // opt/exec-id PARSE_RULE_OPTION_COMMAND_ROLE_LOCAL_VALID_LIST // opt/exec-id @@ -2354,6 +2396,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/exec-id PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/exec-id PARSE_RULE_OPTION_COMMAND(Backup) // opt/exec-id + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/exec-id PARSE_RULE_OPTION_COMMAND(Restore) // opt/exec-id PARSE_RULE_OPTION_COMMAND(Verify) // opt/exec-id ), // opt/exec-id @@ -2369,6 +2412,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/exec-id PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/exec-id PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/exec-id + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/exec-id PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/exec-id PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/exec-id PARSE_RULE_OPTION_COMMAND(Restore) // opt/exec-id @@ -2495,6 +2539,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Backup) // opt/fork PARSE_RULE_OPTION_COMMAND(Check) // opt/fork PARSE_RULE_OPTION_COMMAND(Expire) // opt/fork + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/fork PARSE_RULE_OPTION_COMMAND(Restore) // opt/fork PARSE_RULE_OPTION_COMMAND(StanzaCreate) // opt/fork PARSE_RULE_OPTION_COMMAND(StanzaUpgrade) // opt/fork @@ -2505,6 +2550,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ( // opt/fork PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/fork PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/fork + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/fork ), // opt/fork // opt/fork PARSE_RULE_OPTION_COMMAND_ROLE_LOCAL_VALID_LIST // opt/fork @@ -2512,6 +2558,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/fork PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/fork PARSE_RULE_OPTION_COMMAND(Backup) // opt/fork + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/fork PARSE_RULE_OPTION_COMMAND(Restore) // opt/fork PARSE_RULE_OPTION_COMMAND(Verify) // opt/fork ), // opt/fork @@ -2523,6 +2570,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/fork PARSE_RULE_OPTION_COMMAND(Backup) // opt/fork PARSE_RULE_OPTION_COMMAND(Check) // opt/fork + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/fork PARSE_RULE_OPTION_COMMAND(Restore) // opt/fork PARSE_RULE_OPTION_COMMAND(StanzaCreate) // opt/fork PARSE_RULE_OPTION_COMMAND(StanzaUpgrade) // opt/fork @@ -2942,6 +2990,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/log-level-console PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/log-level-console PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/log-level-console + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-level-console PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/log-level-console PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/log-level-console PARSE_RULE_OPTION_COMMAND(Restore) // opt/log-level-console @@ -2959,6 +3008,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ( // opt/log-level-console PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/log-level-console PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/log-level-console + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-level-console ), // opt/log-level-console // opt/log-level-console PARSE_RULE_OPTION_COMMAND_ROLE_LOCAL_VALID_LIST // opt/log-level-console @@ -2966,6 +3016,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/log-level-console PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/log-level-console PARSE_RULE_OPTION_COMMAND(Backup) // opt/log-level-console + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-level-console PARSE_RULE_OPTION_COMMAND(Restore) // opt/log-level-console PARSE_RULE_OPTION_COMMAND(Verify) // opt/log-level-console ), // opt/log-level-console @@ -2981,6 +3032,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/log-level-console PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/log-level-console PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/log-level-console + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-level-console PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/log-level-console PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/log-level-console PARSE_RULE_OPTION_COMMAND(Restore) // opt/log-level-console @@ -3033,6 +3085,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/log-level-file PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/log-level-file PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/log-level-file + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-level-file PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/log-level-file PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/log-level-file PARSE_RULE_OPTION_COMMAND(Restore) // opt/log-level-file @@ -3050,6 +3103,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ( // opt/log-level-file PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/log-level-file PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/log-level-file + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-level-file ), // opt/log-level-file // opt/log-level-file PARSE_RULE_OPTION_COMMAND_ROLE_LOCAL_VALID_LIST // opt/log-level-file @@ -3057,6 +3111,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/log-level-file PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/log-level-file PARSE_RULE_OPTION_COMMAND(Backup) // opt/log-level-file + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-level-file PARSE_RULE_OPTION_COMMAND(Restore) // opt/log-level-file PARSE_RULE_OPTION_COMMAND(Verify) // opt/log-level-file ), // opt/log-level-file @@ -3072,6 +3127,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/log-level-file PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/log-level-file PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/log-level-file + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-level-file PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/log-level-file PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/log-level-file PARSE_RULE_OPTION_COMMAND(Restore) // opt/log-level-file @@ -3124,6 +3180,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/log-level-stderr PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/log-level-stderr PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/log-level-stderr + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-level-stderr PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/log-level-stderr PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/log-level-stderr PARSE_RULE_OPTION_COMMAND(Restore) // opt/log-level-stderr @@ -3141,6 +3198,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ( // opt/log-level-stderr PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/log-level-stderr PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/log-level-stderr + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-level-stderr ), // opt/log-level-stderr // opt/log-level-stderr PARSE_RULE_OPTION_COMMAND_ROLE_LOCAL_VALID_LIST // opt/log-level-stderr @@ -3148,6 +3206,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/log-level-stderr PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/log-level-stderr PARSE_RULE_OPTION_COMMAND(Backup) // opt/log-level-stderr + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-level-stderr PARSE_RULE_OPTION_COMMAND(Restore) // opt/log-level-stderr PARSE_RULE_OPTION_COMMAND(Verify) // opt/log-level-stderr ), // opt/log-level-stderr @@ -3163,6 +3222,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/log-level-stderr PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/log-level-stderr PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/log-level-stderr + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-level-stderr PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/log-level-stderr PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/log-level-stderr PARSE_RULE_OPTION_COMMAND(Restore) // opt/log-level-stderr @@ -3215,6 +3275,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/log-path PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/log-path PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/log-path + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-path PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/log-path PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/log-path PARSE_RULE_OPTION_COMMAND(Restore) // opt/log-path @@ -3232,6 +3293,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ( // opt/log-path PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/log-path PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/log-path + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-path ), // opt/log-path // opt/log-path PARSE_RULE_OPTION_COMMAND_ROLE_LOCAL_VALID_LIST // opt/log-path @@ -3239,6 +3301,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/log-path PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/log-path PARSE_RULE_OPTION_COMMAND(Backup) // opt/log-path + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-path PARSE_RULE_OPTION_COMMAND(Restore) // opt/log-path PARSE_RULE_OPTION_COMMAND(Verify) // opt/log-path ), // opt/log-path @@ -3254,6 +3317,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/log-path PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/log-path PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/log-path + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-path PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/log-path PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/log-path PARSE_RULE_OPTION_COMMAND(Restore) // opt/log-path @@ -3372,6 +3436,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/log-timestamp PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/log-timestamp PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/log-timestamp + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-timestamp PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/log-timestamp PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/log-timestamp PARSE_RULE_OPTION_COMMAND(Restore) // opt/log-timestamp @@ -3389,6 +3454,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ( // opt/log-timestamp PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/log-timestamp PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/log-timestamp + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-timestamp ), // opt/log-timestamp // opt/log-timestamp PARSE_RULE_OPTION_COMMAND_ROLE_LOCAL_VALID_LIST // opt/log-timestamp @@ -3396,6 +3462,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/log-timestamp PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/log-timestamp PARSE_RULE_OPTION_COMMAND(Backup) // opt/log-timestamp + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-timestamp PARSE_RULE_OPTION_COMMAND(Restore) // opt/log-timestamp PARSE_RULE_OPTION_COMMAND(Verify) // opt/log-timestamp ), // opt/log-timestamp @@ -3411,6 +3478,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/log-timestamp PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/log-timestamp PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/log-timestamp + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/log-timestamp PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/log-timestamp PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/log-timestamp PARSE_RULE_OPTION_COMMAND(Restore) // opt/log-timestamp @@ -4603,6 +4671,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/process PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/process PARSE_RULE_OPTION_COMMAND(Backup) // opt/process + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/process PARSE_RULE_OPTION_COMMAND(Restore) // opt/process PARSE_RULE_OPTION_COMMAND(Verify) // opt/process ), // opt/process @@ -4618,6 +4687,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/process PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/process PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/process + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/process PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/process PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/process PARSE_RULE_OPTION_COMMAND(Restore) // opt/process @@ -4797,6 +4867,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND_ROLE_MAIN_VALID_LIST // opt/raw ( // opt/raw PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/raw + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/raw PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/raw ), // opt/raw // opt/raw @@ -4895,6 +4966,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/remote-type PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/remote-type PARSE_RULE_OPTION_COMMAND(Backup) // opt/remote-type + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/remote-type PARSE_RULE_OPTION_COMMAND(Restore) // opt/remote-type PARSE_RULE_OPTION_COMMAND(Verify) // opt/remote-type ), // opt/remote-type @@ -4910,6 +4982,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/remote-type PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/remote-type PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/remote-type + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/remote-type PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/remote-type PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/remote-type PARSE_RULE_OPTION_COMMAND(Restore) // opt/remote-type @@ -4949,6 +5022,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo @@ -5023,6 +5097,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-azure-account PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-azure-account PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-azure-account + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-azure-account PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-azure-account PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-azure-account PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-azure-account @@ -5057,6 +5132,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-azure-account PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-azure-account PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-azure-account + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-azure-account PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-azure-account PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-azure-account PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-azure-account @@ -5100,6 +5176,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-azure-container PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-azure-container PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-azure-container + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-azure-container PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-azure-container PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-azure-container PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-azure-container @@ -5134,6 +5211,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-azure-container PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-azure-container PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-azure-container + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-azure-container PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-azure-container PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-azure-container PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-azure-container @@ -5178,6 +5256,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-azure-endpoint PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-azure-endpoint PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-azure-endpoint + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-azure-endpoint PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-azure-endpoint PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-azure-endpoint PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-azure-endpoint @@ -5212,6 +5291,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-azure-endpoint PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-azure-endpoint PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-azure-endpoint + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-azure-endpoint PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-azure-endpoint PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-azure-endpoint PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-azure-endpoint @@ -5261,6 +5341,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-azure-key PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-azure-key PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-azure-key + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-azure-key PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-azure-key PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-azure-key PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-azure-key @@ -5295,6 +5376,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-azure-key PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-azure-key PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-azure-key + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-azure-key PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-azure-key PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-azure-key PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-azure-key @@ -5338,6 +5420,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-azure-key-type PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-azure-key-type PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-azure-key-type + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-azure-key-type PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-azure-key-type PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-azure-key-type PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-azure-key-type @@ -5372,6 +5455,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-azure-key-type PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-azure-key-type PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-azure-key-type + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-azure-key-type PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-azure-key-type PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-azure-key-type PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-azure-key-type @@ -5426,6 +5510,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-azure-uri-style PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-azure-uri-style PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-azure-uri-style + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-azure-uri-style PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-azure-uri-style PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-azure-uri-style PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-azure-uri-style @@ -5460,6 +5545,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-azure-uri-style PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-azure-uri-style PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-azure-uri-style + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-azure-uri-style PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-azure-uri-style PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-azure-uri-style PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-azure-uri-style @@ -5813,6 +5899,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-cipher-pass PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-cipher-pass PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-cipher-pass + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-cipher-pass PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-cipher-pass PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-cipher-pass PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-cipher-pass @@ -5847,6 +5934,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-cipher-pass PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-cipher-pass PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-cipher-pass + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-cipher-pass PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-cipher-pass PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-cipher-pass PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-cipher-pass @@ -5891,6 +5979,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-cipher-type PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-cipher-type PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-cipher-type + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-cipher-type PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-cipher-type PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-cipher-type PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-cipher-type @@ -5925,6 +6014,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-cipher-type PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-cipher-type PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-cipher-type + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-cipher-type PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-cipher-type PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-cipher-type PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-cipher-type @@ -5973,6 +6063,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-gcs-bucket PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-gcs-bucket PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-gcs-bucket + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-gcs-bucket PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-gcs-bucket PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-gcs-bucket PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-gcs-bucket @@ -6007,6 +6098,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-gcs-bucket PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-gcs-bucket PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-gcs-bucket + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-gcs-bucket PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-gcs-bucket PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-gcs-bucket PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-gcs-bucket @@ -6049,6 +6141,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-gcs-endpoint PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-gcs-endpoint PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-gcs-endpoint + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-gcs-endpoint PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-gcs-endpoint PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-gcs-endpoint PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-gcs-endpoint @@ -6083,6 +6176,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-gcs-endpoint PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-gcs-endpoint PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-gcs-endpoint + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-gcs-endpoint PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-gcs-endpoint PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-gcs-endpoint PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-gcs-endpoint @@ -6131,6 +6225,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-gcs-key PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-gcs-key PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-gcs-key + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-gcs-key PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-gcs-key PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-gcs-key PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-gcs-key @@ -6165,6 +6260,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-gcs-key PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-gcs-key PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-gcs-key + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-gcs-key PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-gcs-key PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-gcs-key PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-gcs-key @@ -6209,6 +6305,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-gcs-key-type PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-gcs-key-type PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-gcs-key-type + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-gcs-key-type PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-gcs-key-type PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-gcs-key-type PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-gcs-key-type @@ -6243,6 +6340,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-gcs-key-type PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-gcs-key-type PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-gcs-key-type + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-gcs-key-type PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-gcs-key-type PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-gcs-key-type PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-gcs-key-type @@ -7100,6 +7198,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-path PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-path PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-path + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-path PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-path PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-path PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-path @@ -7134,6 +7233,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-path PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-path PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-path + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-path PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-path PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-path PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-path @@ -7356,6 +7456,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-bucket PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-bucket PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-bucket + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-bucket PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-bucket PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-bucket PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-bucket @@ -7390,6 +7491,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-bucket PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-bucket PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-bucket + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-bucket PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-bucket PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-bucket PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-bucket @@ -7434,6 +7536,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-endpoint PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-endpoint PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-endpoint + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-endpoint PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-endpoint PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-endpoint PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-endpoint @@ -7468,6 +7571,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-endpoint PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-endpoint PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-endpoint + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-endpoint PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-endpoint PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-endpoint PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-endpoint @@ -7513,6 +7617,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-key PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-key PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-key + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-key PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-key PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-key PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-key @@ -7547,6 +7652,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-key PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-key PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-key + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-key PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-key PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-key PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-key @@ -7592,6 +7698,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-key-secret PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-key-secret PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-key-secret + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-key-secret PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-key-secret PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-key-secret PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-key-secret @@ -7626,6 +7733,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-key-secret PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-key-secret PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-key-secret + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-key-secret PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-key-secret PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-key-secret PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-key-secret @@ -7669,6 +7777,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-key-type PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-key-type PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-key-type + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-key-type PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-key-type PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-key-type PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-key-type @@ -7703,6 +7812,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-key-type PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-key-type PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-key-type + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-key-type PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-key-type PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-key-type PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-key-type @@ -7758,6 +7868,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-kms-key-id PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-kms-key-id PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-kms-key-id + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-kms-key-id PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-kms-key-id PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-kms-key-id PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-kms-key-id @@ -7792,6 +7903,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-kms-key-id PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-kms-key-id PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-kms-key-id + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-kms-key-id PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-kms-key-id PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-kms-key-id PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-kms-key-id @@ -7836,6 +7948,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-region PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-region PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-region + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-region PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-region PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-region PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-region @@ -7870,6 +7983,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-region PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-region PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-region + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-region PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-region PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-region PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-region @@ -7913,6 +8027,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-role PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-role PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-role + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-role PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-role PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-role PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-role @@ -7947,6 +8062,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-role PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-role PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-role + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-role PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-role PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-role PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-role @@ -7991,6 +8107,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-sse-customer-key PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-sse-customer-key PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-sse-customer-key + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-sse-customer-key PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-sse-customer-key PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-sse-customer-key PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-sse-customer-key @@ -8025,6 +8142,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-sse-customer-key PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-sse-customer-key PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-sse-customer-key + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-sse-customer-key PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-sse-customer-key PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-sse-customer-key PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-sse-customer-key @@ -8069,6 +8187,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-token PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-token PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-token + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-token PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-token PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-token PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-token @@ -8103,6 +8222,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-token PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-token PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-token + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-token PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-token PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-token PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-token @@ -8146,6 +8266,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-uri-style PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-uri-style PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-uri-style + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-uri-style PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-uri-style PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-uri-style PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-uri-style @@ -8180,6 +8301,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-s3-uri-style PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-s3-uri-style PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-s3-uri-style + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-s3-uri-style PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-s3-uri-style PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-s3-uri-style PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-s3-uri-style @@ -8234,6 +8356,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-host PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-host PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-host + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-host PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-host PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-host PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-host @@ -8268,6 +8391,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-host PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-host PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-host + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-host PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-host PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-host PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-host @@ -8311,6 +8435,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-host-fingerprint PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-host-fingerprint PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-host-fingerprint + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-host-fingerprint PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-host-fingerprint PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-host-fingerprint PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-host-fingerprint @@ -8345,6 +8470,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-host-fingerprint PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-host-fingerprint PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-host-fingerprint + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-host-fingerprint PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-host-fingerprint PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-host-fingerprint PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-host-fingerprint @@ -8389,6 +8515,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-host-key-check-type PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-host-key-check-type PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-host-key-check-type + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-host-key-check-type PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-host-key-check-type PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-host-key-check-type PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-host-key-check-type @@ -8423,6 +8550,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-host-key-check-type PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-host-key-check-type PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-host-key-check-type + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-host-key-check-type PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-host-key-check-type PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-host-key-check-type PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-host-key-check-type @@ -8479,6 +8607,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-host-key-hash-type PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-host-key-hash-type PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-host-key-hash-type + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-host-key-hash-type PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-host-key-hash-type PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-host-key-hash-type PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-host-key-hash-type @@ -8513,6 +8642,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-host-key-hash-type PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-host-key-hash-type PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-host-key-hash-type + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-host-key-hash-type PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-host-key-hash-type PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-host-key-hash-type PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-host-key-hash-type @@ -8563,6 +8693,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-host-port PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-host-port PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-host-port + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-host-port PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-host-port PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-host-port PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-host-port @@ -8597,6 +8728,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-host-port PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-host-port PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-host-port + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-host-port PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-host-port PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-host-port PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-host-port @@ -8651,6 +8783,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-host-user PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-host-user PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-host-user + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-host-user PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-host-user PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-host-user PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-host-user @@ -8685,6 +8818,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-host-user PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-host-user PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-host-user + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-host-user PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-host-user PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-host-user PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-host-user @@ -8729,6 +8863,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-known-host PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-known-host PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-known-host + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-known-host PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-known-host PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-known-host PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-known-host @@ -8763,6 +8898,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-known-host PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-known-host PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-known-host + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-known-host PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-known-host PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-known-host PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-known-host @@ -8807,6 +8943,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-private-key-file PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-private-key-file PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-private-key-file + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-private-key-file PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-private-key-file PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-private-key-file PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-private-key-file @@ -8841,6 +8978,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-private-key-file PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-private-key-file PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-private-key-file + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-private-key-file PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-private-key-file PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-private-key-file PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-private-key-file @@ -8885,6 +9023,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-private-key-passphrase PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-private-key-passphrase PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-private-key-passphrase + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-private-key-passphrase PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-private-key-passphrase PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-private-key-passphrase PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-private-key-passphrase @@ -8919,6 +9058,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-private-key-passphrase PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-private-key-passphrase PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-private-key-passphrase + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-private-key-passphrase PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-private-key-passphrase PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-private-key-passphrase PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-private-key-passphrase @@ -8962,6 +9102,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-public-key-file PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-public-key-file PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-public-key-file + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-public-key-file PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-public-key-file PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-public-key-file PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-public-key-file @@ -8996,6 +9137,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-sftp-public-key-file PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-sftp-public-key-file PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-sftp-public-key-file + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-sftp-public-key-file PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-sftp-public-key-file PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-sftp-public-key-file PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-sftp-public-key-file @@ -9039,6 +9181,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-storage-ca-file PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-storage-ca-file PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-storage-ca-file + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-storage-ca-file PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-storage-ca-file PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-storage-ca-file PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-storage-ca-file @@ -9073,6 +9216,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-storage-ca-file PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-storage-ca-file PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-storage-ca-file + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-storage-ca-file PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-storage-ca-file PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-storage-ca-file PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-storage-ca-file @@ -9118,6 +9262,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-storage-ca-path PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-storage-ca-path PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-storage-ca-path + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-storage-ca-path PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-storage-ca-path PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-storage-ca-path PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-storage-ca-path @@ -9152,6 +9297,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-storage-ca-path PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-storage-ca-path PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-storage-ca-path + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-storage-ca-path PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-storage-ca-path PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-storage-ca-path PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-storage-ca-path @@ -9197,6 +9343,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-storage-host PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-storage-host PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-storage-host + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-storage-host PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-storage-host PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-storage-host PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-storage-host @@ -9231,6 +9378,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-storage-host PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-storage-host PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-storage-host + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-storage-host PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-storage-host PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-storage-host PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-storage-host @@ -9275,6 +9423,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-storage-port PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-storage-port PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-storage-port + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-storage-port PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-storage-port PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-storage-port PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-storage-port @@ -9309,6 +9458,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-storage-port PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-storage-port PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-storage-port + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-storage-port PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-storage-port PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-storage-port PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-storage-port @@ -9365,6 +9515,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-storage-tag PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-storage-tag PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-storage-tag + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-storage-tag PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-storage-tag PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-storage-tag PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-storage-tag @@ -9399,6 +9550,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-storage-tag PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-storage-tag PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-storage-tag + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-storage-tag PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-storage-tag PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-storage-tag PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-storage-tag @@ -9444,6 +9596,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-storage-upload-chunk-size PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-storage-upload-chunk-size PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-storage-upload-chunk-size + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-storage-upload-chunk-size PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-storage-upload-chunk-size PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-storage-upload-chunk-size PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-storage-upload-chunk-size @@ -9478,6 +9631,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-storage-upload-chunk-size PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-storage-upload-chunk-size PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-storage-upload-chunk-size + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-storage-upload-chunk-size PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-storage-upload-chunk-size PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-storage-upload-chunk-size PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-storage-upload-chunk-size @@ -9530,6 +9684,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-storage-verify-tls PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-storage-verify-tls PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-storage-verify-tls + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-storage-verify-tls PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-storage-verify-tls PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-storage-verify-tls PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-storage-verify-tls @@ -9564,6 +9719,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-storage-verify-tls PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-storage-verify-tls PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-storage-verify-tls + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-storage-verify-tls PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-storage-verify-tls PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-storage-verify-tls PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-storage-verify-tls @@ -9647,6 +9803,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-type PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-type PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-type + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-type PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-type PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-type PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-type @@ -9681,6 +9838,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/repo-type PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/repo-type PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/repo-type + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/repo-type PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/repo-type PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/repo-type PARSE_RULE_OPTION_COMMAND(Restore) // opt/repo-type @@ -9936,6 +10094,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Expire) // opt/set PARSE_RULE_OPTION_COMMAND(Info) // opt/set PARSE_RULE_OPTION_COMMAND(Manifest) // opt/set + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/set PARSE_RULE_OPTION_COMMAND(Restore) // opt/set PARSE_RULE_OPTION_COMMAND(Verify) // opt/set ), // opt/set @@ -9947,6 +10106,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_FILTER_CMD // opt/set ( // opt/set PARSE_RULE_VAL_CMD(Annotate), // opt/set + PARSE_RULE_VAL_CMD(RepoPush), // opt/set ), // opt/set // opt/set PARSE_RULE_OPTIONAL_REQUIRED(), // opt/set @@ -10093,6 +10253,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/stanza PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/stanza PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/stanza + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/stanza PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/stanza PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/stanza PARSE_RULE_OPTION_COMMAND(Restore) // opt/stanza @@ -10108,6 +10269,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ( // opt/stanza PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/stanza PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/stanza + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/stanza ), // opt/stanza // opt/stanza PARSE_RULE_OPTION_COMMAND_ROLE_LOCAL_VALID_LIST // opt/stanza @@ -10115,6 +10277,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(ArchiveGet) // opt/stanza PARSE_RULE_OPTION_COMMAND(ArchivePush) // opt/stanza PARSE_RULE_OPTION_COMMAND(Backup) // opt/stanza + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/stanza PARSE_RULE_OPTION_COMMAND(Restore) // opt/stanza PARSE_RULE_OPTION_COMMAND(Verify) // opt/stanza ), // opt/stanza @@ -10130,6 +10293,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION_COMMAND(Manifest) // opt/stanza PARSE_RULE_OPTION_COMMAND(RepoGet) // opt/stanza PARSE_RULE_OPTION_COMMAND(RepoLs) // opt/stanza + PARSE_RULE_OPTION_COMMAND(RepoPush) // opt/stanza PARSE_RULE_OPTION_COMMAND(RepoPut) // opt/stanza PARSE_RULE_OPTION_COMMAND(RepoRm) // opt/stanza PARSE_RULE_OPTION_COMMAND(Restore) // opt/stanza diff --git a/src/info/manifest.c b/src/info/manifest.c index a11ffdecae..9759d7c3d8 100644 --- a/src/info/manifest.c +++ b/src/info/manifest.c @@ -419,6 +419,30 @@ manifestFileAdd(Manifest *const this, ManifestFile *const file) FUNCTION_TEST_RETURN_VOID(); } +FN_EXTERN void +manifestCustomFileAdd(Manifest *const this, ManifestFile *const file) +{ + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(MANIFEST, this); + FUNCTION_TEST_PARAM(MANIFEST_FILE, file); + FUNCTION_TEST_END(); + + ASSERT(this != NULL); + ASSERT(file->name != NULL); + + file->user = manifestOwnerCache(this, file->user); + file->group = manifestOwnerCache(this, file->group); + + MEM_CONTEXT_BEGIN(lstMemContext(this->pub.customFileList)) + { + const ManifestFilePack *const filePack = manifestFilePack(this, file); + lstAdd(this->pub.customFileList, &filePack); + } + MEM_CONTEXT_END(); + + FUNCTION_TEST_RETURN_VOID(); +} + // Update file pack by creating a new one and then freeing the old one static void manifestFilePackUpdate(Manifest *const this, ManifestFilePack **const filePack, const ManifestFile *const file) @@ -444,6 +468,31 @@ manifestFilePackUpdate(Manifest *const this, ManifestFilePack **const filePack, FUNCTION_TEST_RETURN_VOID(); } +// Update custom file pack by creating a new one and then freeing the old one +static void +manifestCustomFilePackUpdate(Manifest *const this, ManifestFilePack **const filePack, const ManifestFile *const file) +{ + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(MANIFEST, this); + FUNCTION_TEST_PARAM_P(VOID, filePack); + FUNCTION_TEST_PARAM(MANIFEST_FILE, file); + FUNCTION_TEST_END(); + + ASSERT(this != NULL); + ASSERT(filePack != NULL); + ASSERT(file != NULL); + + MEM_CONTEXT_BEGIN(lstMemContext(this->pub.customFileList)) + { + ManifestFilePack *const filePackOld = *filePack; + *filePack = manifestFilePack(this, file); + memFree(filePackOld); + } + MEM_CONTEXT_END(); + + FUNCTION_TEST_RETURN_VOID(); +} + FN_EXTERN void manifestLinkAdd(Manifest *const this, const ManifestLink *const link) { @@ -557,6 +606,7 @@ manifestNewInternal(void) .linkList = lstNewP(sizeof(ManifestLink), .comparator = lstComparatorStr), .pathList = lstNewP(sizeof(ManifestPath), .comparator = lstComparatorStr), .targetList = lstNewP(sizeof(ManifestTarget), .comparator = lstComparatorStr), + .customFileList = lstNewP(sizeof(ManifestFilePack *), .comparator = lstComparatorStr), .referenceList = strLstNew(), }, .ownerList = strLstNew(), @@ -1867,6 +1917,8 @@ manifestBuildComplete( #define MANIFEST_SECTION_TARGET_PATH "target:path" #define MANIFEST_SECTION_TARGET_PATH_DEFAULT "target:path:default" +#define MANIFEST_SECTION_CUSTOM_FILE "custom:file" + #define MANIFEST_KEY_ANNOTATION "annotation" #define MANIFEST_KEY_BACKUP_ARCHIVE_START "backup-archive-start" #define MANIFEST_KEY_BACKUP_ARCHIVE_STOP "backup-archive-stop" @@ -1994,141 +2046,156 @@ manifestOwnerDefaultGet(const Variant *const ownerDefault) } static void -manifestLoadCallback(void *const callbackData, const String *const section, const String *const key, const String *const value) +manifestLoadFileEntry(Manifest *const manifest, ManifestLoadData *const loadData, const String *const key, const String *const value, ManifestFile *file) { - FUNCTION_TEST_BEGIN(); - FUNCTION_TEST_PARAM_P(VOID, callbackData); - FUNCTION_TEST_PARAM(STRING, section); - FUNCTION_TEST_PARAM(STRING, key); - FUNCTION_TEST_PARAM(STRING, value); - FUNCTION_TEST_END(); + JsonRead *const json = jsonReadNew(value); + jsonReadObjectBegin(json); - FUNCTION_AUDIT_CALLBACK(); + // Block incremental info + if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_BLOCK_INCR)) + { + file->blockIncrSize = (size_t)jsonReadUInt64(json) * BLOCK_INCR_SIZE_FACTOR; - ASSERT(callbackData != NULL); - ASSERT(section != NULL); - ASSERT(key != NULL); + if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_BLOCK_INCR_CHECKSUM)) + file->blockIncrChecksumSize = (size_t)jsonReadUInt64(json); + else + file->blockIncrChecksumSize = BLOCK_INCR_CHECKSUM_SIZE_MIN; - ManifestLoadData *const loadData = (ManifestLoadData *)callbackData; - Manifest *const manifest = loadData->manifest; + if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_BLOCK_INCR_MAP)) + file->blockIncrMapSize = jsonReadUInt64(json); + } - // ----------------------------------------------------------------------------------------------------------------------------- - if (strEqZ(section, MANIFEST_SECTION_TARGET_FILE)) + // Bundle info + if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_BUNDLE_ID)) { - ManifestFile file = {.name = key}; + file->bundleId = jsonReadUInt64(json); - JsonRead *const json = jsonReadNew(value); - jsonReadObjectBegin(json); + if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_BUNDLE_OFFSET)) + file->bundleOffset = jsonReadUInt64(json); + } - // Block incremental info - if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_BLOCK_INCR)) - { - file.blockIncrSize = (size_t)jsonReadUInt64(json) * BLOCK_INCR_SIZE_FACTOR; + // The checksum might not exist if this is a partial save that was done during the backup to preserve checksums for already + // backed up files + if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_CHECKSUM)) + file->checksumSha1 = bufPtr(bufNewDecode(encodingHex, jsonReadStr(json))); - if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_BLOCK_INCR_CHECKSUM)) - file.blockIncrChecksumSize = (size_t)jsonReadUInt64(json); - else - file.blockIncrChecksumSize = BLOCK_INCR_CHECKSUM_SIZE_MIN; + // Page checksum errors + if (jsonReadKeyExpectZ(json, MANIFEST_KEY_CHECKSUM_PAGE)) + { + file->checksumPage = true; + file->checksumPageError = !jsonReadBool(json); - if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_BLOCK_INCR_MAP)) - file.blockIncrMapSize = jsonReadUInt64(json); - } + if (jsonReadKeyExpectZ(json, MANIFEST_KEY_CHECKSUM_PAGE_ERROR)) + file->checksumPageErrorList = jsonFromVar(jsonReadVar(json)); + } - // Bundle info - if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_BUNDLE_ID)) - { - file.bundleId = jsonReadUInt64(json); + // Group + if (jsonReadKeyExpectZ(json, MANIFEST_KEY_GROUP)) + file->group = manifestOwnerGet(jsonReadVar(json)); + else + file->group = manifest->fileGroupDefault; - if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_BUNDLE_OFFSET)) - file.bundleOffset = jsonReadUInt64(json); - } + // Mode + if (jsonReadKeyExpectZ(json, MANIFEST_KEY_MODE)) + file->mode = cvtZToMode(strZ(jsonReadStr(json))); + else + file->mode = manifest->fileModeDefault; - // The checksum might not exist if this is a partial save that was done during the backup to preserve checksums for already - // backed up files - if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_CHECKSUM)) - file.checksumSha1 = bufPtr(bufNewDecode(encodingHex, jsonReadStr(json))); + // The repo checksum might not exist if this is a partial save that was done during the backup to preserve checksums for + // already backed up files or if this is an older manifest + if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_CHECKSUM_REPO)) + file->checksumRepoSha1 = bufPtr(bufNewDecode(encodingHex, jsonReadStr(json))); - // Page checksum errors - if (jsonReadKeyExpectZ(json, MANIFEST_KEY_CHECKSUM_PAGE)) - { - file.checksumPage = true; - file.checksumPageError = !jsonReadBool(json); + // Reference + if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_REFERENCE)) + { + file->reference = jsonReadStr(json); - if (jsonReadKeyExpectZ(json, MANIFEST_KEY_CHECKSUM_PAGE_ERROR)) - file.checksumPageErrorList = jsonFromVar(jsonReadVar(json)); - } + if (!loadData->referenceListFound) + file->reference = strLstAddIfMissing(manifest->pub.referenceList, file->reference); + } - // Group - if (jsonReadKeyExpectZ(json, MANIFEST_KEY_GROUP)) - file.group = manifestOwnerGet(jsonReadVar(json)); - else - file.group = manifest->fileGroupDefault; + // If "repo-size" is not present in the manifest file, then it is the same as size (i.e. uncompressed) - to save space, + // the repo-size is only stored in the manifest file if it is different than size. + const bool sizeRepoExists = jsonReadKeyExpectStrId(json, MANIFEST_KEY_SIZE_REPO); - // Mode - if (jsonReadKeyExpectZ(json, MANIFEST_KEY_MODE)) - file.mode = cvtZToMode(strZ(jsonReadStr(json))); - else - file.mode = manifest->fileModeDefault; + if (sizeRepoExists) + file->sizeRepo = jsonReadUInt64(json); - // The repo checksum might not exist if this is a partial save that was done during the backup to preserve checksums for - // already backed up files or if this is an older manifest - if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_CHECKSUM_REPO)) - file.checksumRepoSha1 = bufPtr(bufNewDecode(encodingHex, jsonReadStr(json))); + // Size is required so error if it is not present. Older versions removed the size before the backup to ensure that the + // manifest was updated during the backup, so size can be missing in partial manifests. This error will prevent older + // partials from being resumed. + if (!jsonReadKeyExpectStrId(json, MANIFEST_KEY_SIZE)) + THROW_FMT(FormatError, "missing size for file '%s'", strZ(key)); - // Reference - if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_REFERENCE)) - { - file.reference = jsonReadStr(json); + file->size = jsonReadUInt64(json); - if (!loadData->referenceListFound) - file.reference = strLstAddIfMissing(manifest->pub.referenceList, file.reference); - } + // If repo size did not exist then + if (!sizeRepoExists) + file->sizeRepo = file->size; + + // If file size is zero then assign the static zero hash + if (file->size == 0) + file->checksumSha1 = bufPtrConst(HASH_TYPE_SHA1_ZERO_BUF); - // If "repo-size" is not present in the manifest file, then it is the same as size (i.e. uncompressed) - to save space, - // the repo-size is only stored in the manifest file if it is different than size. - const bool sizeRepoExists = jsonReadKeyExpectStrId(json, MANIFEST_KEY_SIZE_REPO); + // If original is not present in the manifest file then it is the same as size (i.e. the file did not change size during + // copy) -- to save space the original size is only stored in the manifest file if it is different than size. + if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_SIZE_ORIGINAL)) + file->sizeOriginal = jsonReadUInt64(json); + else + file->sizeOriginal = file->size; - if (sizeRepoExists) - file.sizeRepo = jsonReadUInt64(json); + // Timestamp is required so error if it is not present + if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_TIMESTAMP)) + file->timestamp = (time_t)jsonReadInt64(json); + else + THROW_FMT(FormatError, "missing timestamp for file '%s'", strZ(key)); - // Size is required so error if it is not present. Older versions removed the size before the backup to ensure that the - // manifest was updated during the backup, so size can be missing in partial manifests. This error will prevent older - // partials from being resumed. - if (!jsonReadKeyExpectStrId(json, MANIFEST_KEY_SIZE)) - THROW_FMT(FormatError, "missing size for file '%s'", strZ(key)); + // User + if (jsonReadKeyExpectZ(json, MANIFEST_KEY_USER)) + file->user = manifestOwnerGet(jsonReadVar(json)); + else + file->user = manifest->fileUserDefault; +} - file.size = jsonReadUInt64(json); +static void +manifestLoadCallback(void *const callbackData, const String *const section, const String *const key, const String *const value) +{ + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM_P(VOID, callbackData); + FUNCTION_TEST_PARAM(STRING, section); + FUNCTION_TEST_PARAM(STRING, key); + FUNCTION_TEST_PARAM(STRING, value); + FUNCTION_TEST_END(); - // If repo size did not exist then - if (!sizeRepoExists) - file.sizeRepo = file.size; + FUNCTION_AUDIT_CALLBACK(); - // If file size is zero then assign the static zero hash - if (file.size == 0) - file.checksumSha1 = bufPtrConst(HASH_TYPE_SHA1_ZERO_BUF); + ASSERT(callbackData != NULL); + ASSERT(section != NULL); + ASSERT(key != NULL); - // If original is not present in the manifest file then it is the same as size (i.e. the file did not change size during - // copy) -- to save space the original size is only stored in the manifest file if it is different than size. - if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_SIZE_ORIGINAL)) - file.sizeOriginal = jsonReadUInt64(json); - else - file.sizeOriginal = file.size; + ManifestLoadData *const loadData = (ManifestLoadData *)callbackData; + Manifest *const manifest = loadData->manifest; - // Timestamp is required so error if it is not present - if (jsonReadKeyExpectStrId(json, MANIFEST_KEY_TIMESTAMP)) - file.timestamp = (time_t)jsonReadInt64(json); - else - THROW_FMT(FormatError, "missing timestamp for file '%s'", strZ(key)); + // ----------------------------------------------------------------------------------------------------------------------------- + if (strEqZ(section, MANIFEST_SECTION_TARGET_FILE)) + { + ManifestFile file = {.name = key}; - // User - if (jsonReadKeyExpectZ(json, MANIFEST_KEY_USER)) - file.user = manifestOwnerGet(jsonReadVar(json)); - else - file.user = manifest->fileUserDefault; + manifestLoadFileEntry(manifest, loadData, key, value, &file); manifestFileAdd(manifest, &file); } // ----------------------------------------------------------------------------------------------------------------------------- + else if (strEqZ(section, MANIFEST_SECTION_CUSTOM_FILE)) + { + ManifestFile file = {.name = key}; + + manifestLoadFileEntry(manifest, loadData, key, value, &file); + + manifestCustomFileAdd(manifest, &file); + } + // ----------------------------------------------------------------------------------------------------------------------------- else if (strEqZ(section, MANIFEST_SECTION_TARGET_PATH)) { ManifestPath path = {.name = key}; @@ -2500,6 +2567,84 @@ manifestOwnerVar(const String *const ownerDefault) FUNCTION_TEST_RETURN_CONST(VARIANT, ownerDefault == NULL ? BOOL_FALSE_VAR : varNewStr(ownerDefault)); } +static void +manifestSaveFileEntry(const ManifestFile *file, ManifestSaveData *const saveData, const char *section, InfoSave *const infoSaveData) +{ + JsonWrite *const json = jsonWriteObjectBegin(jsonWriteNewP()); + + // Block incremental info + if (file->blockIncrSize != 0) + { + jsonWriteUInt64(jsonWriteKeyStrId(json, MANIFEST_KEY_BLOCK_INCR), file->blockIncrSize / BLOCK_INCR_SIZE_FACTOR); + + if (file->blockIncrChecksumSize != BLOCK_INCR_CHECKSUM_SIZE_MIN) + jsonWriteUInt64(jsonWriteKeyStrId(json, MANIFEST_KEY_BLOCK_INCR_CHECKSUM), file->blockIncrChecksumSize); + + if (file->blockIncrMapSize != 0) + jsonWriteUInt64(jsonWriteKeyStrId(json, MANIFEST_KEY_BLOCK_INCR_MAP), file->blockIncrMapSize); + } + + // Bundle info + if (file->bundleId != 0) + { + jsonWriteUInt64(jsonWriteKeyStrId(json, MANIFEST_KEY_BUNDLE_ID), file->bundleId); + + if (file->bundleOffset != 0) + jsonWriteUInt64(jsonWriteKeyStrId(json, MANIFEST_KEY_BUNDLE_OFFSET), file->bundleOffset); + } + + // Save if the file size is not zero and the checksum exists. The checksum might not exist if this is a partial save + // performed during a backup. + if (file->size != 0 && file->checksumSha1 != NULL) + { + jsonWriteStr( + jsonWriteKeyStrId(json, MANIFEST_KEY_CHECKSUM), + strNewEncode(encodingHex, BUF(file->checksumSha1, HASH_TYPE_SHA1_SIZE))); + } + + if (file->checksumPage) + { + jsonWriteBool(jsonWriteKeyZ(json, MANIFEST_KEY_CHECKSUM_PAGE), !file->checksumPageError); + + if (file->checksumPageErrorList != NULL) + jsonWriteJson(jsonWriteKeyZ(json, MANIFEST_KEY_CHECKSUM_PAGE_ERROR), file->checksumPageErrorList); + } + + if (!varEq(manifestOwnerVar(file->group), saveData->groupDefault)) + jsonWriteVar(jsonWriteKeyZ(json, MANIFEST_KEY_GROUP), manifestOwnerVar(file->group)); + + if (file->mode != saveData->fileModeDefault) + jsonWriteStrFmt(jsonWriteKeyZ(json, MANIFEST_KEY_MODE), "%04o", file->mode); + + // Save if the repo checksum is not null. The repo checksum for zero-length files may vary depending on compression + // and encryption applied. + if (file->checksumRepoSha1 != NULL) + { + jsonWriteStr( + jsonWriteKeyStrId(json, MANIFEST_KEY_CHECKSUM_REPO), + strNewEncode(encodingHex, BUF(file->checksumRepoSha1, HASH_TYPE_SHA1_SIZE))); + } + + if (file->reference != NULL) + jsonWriteStr(jsonWriteKeyStrId(json, MANIFEST_KEY_REFERENCE), file->reference); + + if (file->sizeRepo != file->size) + jsonWriteUInt64(jsonWriteKeyStrId(json, MANIFEST_KEY_SIZE_REPO), file->sizeRepo); + + jsonWriteUInt64(jsonWriteKeyStrId(json, MANIFEST_KEY_SIZE), file->size); + + if (file->sizeOriginal != file->size) + jsonWriteUInt64(jsonWriteKeyStrId(json, MANIFEST_KEY_SIZE_ORIGINAL), file->sizeOriginal); + + jsonWriteUInt64(jsonWriteKeyStrId(json, MANIFEST_KEY_TIMESTAMP), (uint64_t)file->timestamp); + + if (!varEq(manifestOwnerVar(file->user), saveData->userDefault)) + jsonWriteVar(jsonWriteKeyZ(json, MANIFEST_KEY_USER), manifestOwnerVar(file->user)); + + infoSaveValue( + infoSaveData, section, strZ(file->name), jsonWriteResult(jsonWriteObjectEnd(json))); +} + static void manifestSaveCallback(void *const callbackData, const String *const sectionNext, InfoSave *const infoSaveData) { @@ -2725,6 +2870,23 @@ manifestSaveCallback(void *const callbackData, const String *const sectionNext, MEM_CONTEXT_TEMP_END(); } + // ----------------------------------------------------------------------------------------------------------------------------- + if (infoSaveSection(infoSaveData, MANIFEST_SECTION_CUSTOM_FILE, sectionNext)) + { + MEM_CONTEXT_TEMP_RESET_BEGIN() + { + for (unsigned int fileIdx = 0; fileIdx < manifestCustomFileTotal(manifest); fileIdx++) + { + const ManifestFile file = manifestCustomFile(manifest, fileIdx); + + manifestSaveFileEntry(&file, saveData, MANIFEST_SECTION_CUSTOM_FILE, infoSaveData); + + MEM_CONTEXT_TEMP_RESET(1000); + } + } + MEM_CONTEXT_TEMP_END(); + } + // ----------------------------------------------------------------------------------------------------------------------------- if (infoSaveSection(infoSaveData, MANIFEST_SECTION_DB, sectionNext)) { @@ -2765,79 +2927,8 @@ manifestSaveCallback(void *const callbackData, const String *const sectionNext, for (unsigned int fileIdx = 0; fileIdx < manifestFileTotal(manifest); fileIdx++) { const ManifestFile file = manifestFile(manifest, fileIdx); - JsonWrite *const json = jsonWriteObjectBegin(jsonWriteNewP()); - - // Block incremental info - if (file.blockIncrSize != 0) - { - jsonWriteUInt64(jsonWriteKeyStrId(json, MANIFEST_KEY_BLOCK_INCR), file.blockIncrSize / BLOCK_INCR_SIZE_FACTOR); - if (file.blockIncrChecksumSize != BLOCK_INCR_CHECKSUM_SIZE_MIN) - jsonWriteUInt64(jsonWriteKeyStrId(json, MANIFEST_KEY_BLOCK_INCR_CHECKSUM), file.blockIncrChecksumSize); - - if (file.blockIncrMapSize != 0) - jsonWriteUInt64(jsonWriteKeyStrId(json, MANIFEST_KEY_BLOCK_INCR_MAP), file.blockIncrMapSize); - } - - // Bundle info - if (file.bundleId != 0) - { - jsonWriteUInt64(jsonWriteKeyStrId(json, MANIFEST_KEY_BUNDLE_ID), file.bundleId); - - if (file.bundleOffset != 0) - jsonWriteUInt64(jsonWriteKeyStrId(json, MANIFEST_KEY_BUNDLE_OFFSET), file.bundleOffset); - } - - // Save if the file size is not zero and the checksum exists. The checksum might not exist if this is a partial save - // performed during a backup. - if (file.size != 0 && file.checksumSha1 != NULL) - { - jsonWriteStr( - jsonWriteKeyStrId(json, MANIFEST_KEY_CHECKSUM), - strNewEncode(encodingHex, BUF(file.checksumSha1, HASH_TYPE_SHA1_SIZE))); - } - - if (file.checksumPage) - { - jsonWriteBool(jsonWriteKeyZ(json, MANIFEST_KEY_CHECKSUM_PAGE), !file.checksumPageError); - - if (file.checksumPageErrorList != NULL) - jsonWriteJson(jsonWriteKeyZ(json, MANIFEST_KEY_CHECKSUM_PAGE_ERROR), file.checksumPageErrorList); - } - - if (!varEq(manifestOwnerVar(file.group), saveData->groupDefault)) - jsonWriteVar(jsonWriteKeyZ(json, MANIFEST_KEY_GROUP), manifestOwnerVar(file.group)); - - if (file.mode != saveData->fileModeDefault) - jsonWriteStrFmt(jsonWriteKeyZ(json, MANIFEST_KEY_MODE), "%04o", file.mode); - - // Save if the repo checksum is not null. The repo checksum for zero-length files may vary depending on compression - // and encryption applied. - if (file.checksumRepoSha1 != NULL) - { - jsonWriteStr( - jsonWriteKeyStrId(json, MANIFEST_KEY_CHECKSUM_REPO), - strNewEncode(encodingHex, BUF(file.checksumRepoSha1, HASH_TYPE_SHA1_SIZE))); - } - - if (file.reference != NULL) - jsonWriteStr(jsonWriteKeyStrId(json, MANIFEST_KEY_REFERENCE), file.reference); - - if (file.sizeRepo != file.size) - jsonWriteUInt64(jsonWriteKeyStrId(json, MANIFEST_KEY_SIZE_REPO), file.sizeRepo); - - jsonWriteUInt64(jsonWriteKeyStrId(json, MANIFEST_KEY_SIZE), file.size); - - if (file.sizeOriginal != file.size) - jsonWriteUInt64(jsonWriteKeyStrId(json, MANIFEST_KEY_SIZE_ORIGINAL), file.sizeOriginal); - - jsonWriteUInt64(jsonWriteKeyStrId(json, MANIFEST_KEY_TIMESTAMP), (uint64_t)file.timestamp); - - if (!varEq(manifestOwnerVar(file.user), saveData->userDefault)) - jsonWriteVar(jsonWriteKeyZ(json, MANIFEST_KEY_USER), manifestOwnerVar(file.user)); - - infoSaveValue( - infoSaveData, MANIFEST_SECTION_TARGET_FILE, strZ(file.name), jsonWriteResult(jsonWriteObjectEnd(json))); + manifestSaveFileEntry(&file, saveData, MANIFEST_SECTION_TARGET_FILE, infoSaveData); MEM_CONTEXT_TEMP_RESET(1000); } @@ -3043,6 +3134,25 @@ manifestFilePackFindInternal(const Manifest *const this, const String *const nam FUNCTION_TEST_RETURN_TYPE_PP(ManifestFilePack, filePack); } +static ManifestFilePack ** +manifestCustomFilePackFindInternal(const Manifest *const this, const String *const name) +{ + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(MANIFEST, this); + FUNCTION_TEST_PARAM(STRING, name); + FUNCTION_TEST_END(); + + ASSERT(this != NULL); + ASSERT(name != NULL); + + ManifestFilePack **const filePack = lstFind(this->pub.customFileList, &name); + + if (filePack == NULL) + THROW_FMT(AssertError, "unable to find '%s' in manifest file list", strZ(name)); + + FUNCTION_TEST_RETURN_TYPE_PP(ManifestFilePack, filePack); +} + const ManifestFilePack * manifestFilePackFind(const Manifest *const this, const String *const name) { @@ -3096,6 +3206,28 @@ manifestFileUpdate(Manifest *const this, const ManifestFile *const file) FUNCTION_TEST_RETURN_VOID(); } +FN_EXTERN void +manifestCustomFileUpdate(Manifest *const this, const ManifestFile *file) +{ + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(MANIFEST, this); + FUNCTION_TEST_PARAM(MANIFEST_FILE, file); + FUNCTION_TEST_END(); + + ASSERT(this != NULL); + ASSERT(file != NULL); + ASSERT( + (!file->checksumPage && !file->checksumPageError && file->checksumPageErrorList == NULL) || + (file->checksumPage && !file->checksumPageError && file->checksumPageErrorList == NULL) || + (file->checksumPage && file->checksumPageError)); + ASSERT(file->size != 0 || (file->bundleId == 0 && file->bundleOffset == 0)); + + ManifestFilePack **const filePack = manifestCustomFilePackFindInternal(this, file->name); + manifestCustomFilePackUpdate(this, filePack, file); + + FUNCTION_TEST_RETURN_VOID(); +} + /*********************************************************************************************************************************** Link functions and getters/setters ***********************************************************************************************************************************/ diff --git a/src/info/manifest.h b/src/info/manifest.h index 0bf04148a2..56e99aa008 100644 --- a/src/info/manifest.h +++ b/src/info/manifest.h @@ -236,6 +236,7 @@ typedef struct ManifestPub List *linkList; // List of links List *pathList; // List of paths List *targetList; // List of targets + List *customFileList; // List of custom files StringList *referenceList; // List of file references } ManifestPub; @@ -342,6 +343,13 @@ manifestFilePackGet(const Manifest *const this, const unsigned int fileIdx) return *(ManifestFilePack **)lstGet(THIS_PUB(Manifest)->fileList, fileIdx); } +// Get custom file in pack format by index +FN_INLINE_ALWAYS const ManifestFilePack * +manifestCustomFilePackGet(const Manifest *const this, const unsigned int fileIdx) +{ + return *(ManifestFilePack **)lstGet(THIS_PUB(Manifest)->customFileList, fileIdx); +} + // Get file name FN_INLINE_ALWAYS const String * manifestFileNameGet(const Manifest *const this, const unsigned int fileIdx) @@ -356,9 +364,19 @@ manifestFile(const Manifest *const this, const unsigned int fileIdx) return manifestFileUnpack(this, manifestFilePackGet(this, fileIdx)); } +// Get custom file by index +FN_INLINE_ALWAYS ManifestFile +manifestCustomFile(const Manifest *const this, const unsigned int fileIdx) +{ + return manifestFileUnpack(this, manifestCustomFilePackGet(this, fileIdx)); +} + // Add a file FN_EXTERN void manifestFileAdd(Manifest *this, ManifestFile *file); +// Add a file to the custom file list +FN_EXTERN void manifestCustomFileAdd(Manifest *this, ManifestFile *file); + // Find file in pack format by name FN_EXTERN const ManifestFilePack *manifestFilePackFind(const Manifest *this, const String *name); @@ -386,9 +404,18 @@ manifestFileTotal(const Manifest *const this) return lstSize(THIS_PUB(Manifest)->fileList); } +FN_INLINE_ALWAYS unsigned int +manifestCustomFileTotal(const Manifest *const this) +{ + return lstSize(THIS_PUB(Manifest)->customFileList); +} + // Update a file with new data FN_EXTERN void manifestFileUpdate(Manifest *const this, const ManifestFile *file); +// Update a custom file with new data +FN_EXTERN void manifestCustomFileUpdate(Manifest *const this, const ManifestFile *file); + /*********************************************************************************************************************************** Link functions and getters/setters ***********************************************************************************************************************************/ diff --git a/src/main.c b/src/main.c index 1c1b4d54b7..a61613432c 100644 --- a/src/main.c +++ b/src/main.c @@ -25,6 +25,7 @@ Main #include "command/remote/remote.h" #include "command/repo/get.h" #include "command/repo/ls.h" +#include "command/repo/push.h" #include "command/repo/put.h" #include "command/repo/rm.h" #include "command/restore/restore.h" @@ -199,6 +200,12 @@ main(int argListSize, const char *argList[]) cmdStorageList(); break; + // Repository push metadata file command + // ----------------------------------------------------------------------------------------------------------------- + case cfgCmdRepoPush: + cmdStoragePush(); + break; + // Repository put file command // ----------------------------------------------------------------------------------------------------------------- case cfgCmdRepoPut: diff --git a/src/meson.build b/src/meson.build index 8d2863af70..f4ac9beb32 100644 --- a/src/meson.build +++ b/src/meson.build @@ -151,6 +151,7 @@ src_pgbackrest = [ 'command/repo/common.c', 'command/repo/get.c', 'command/repo/ls.c', + 'command/repo/push.c', 'command/repo/put.c', 'command/repo/rm.c', 'command/restore/blockChecksum.c', diff --git a/test/code-count/file-type.yaml b/test/code-count/file-type.yaml index 538dfdc83e..eac6bc271a 100644 --- a/test/code-count/file-type.yaml +++ b/test/code-count/file-type.yaml @@ -1127,6 +1127,14 @@ src/command/repo/ls.h: class: core type: c/h +src/command/repo/push.c: + class: core + type: c + +src/command/repo/push.h: + class: core + type: c/h + src/command/repo/put.c: class: core type: c diff --git a/test/define.yaml b/test/define.yaml index d2fe3861ad..fbcab5fbbb 100644 --- a/test/define.yaml +++ b/test/define.yaml @@ -811,7 +811,7 @@ unit: # ---------------------------------------------------------------------------------------------------------------------------- - name: manifest - total: 6 + total: 7 harness: name: manifest shim: @@ -1023,12 +1023,13 @@ unit: # ---------------------------------------------------------------------------------------------------------------------------- - name: repo - total: 3 + total: 4 coverage: - command/repo/common - command/repo/get - command/repo/ls + - command/repo/push - command/repo/put - command/repo/rm diff --git a/test/src/module/command/repoTest.c b/test/src/module/command/repoTest.c index 44d3cbe295..b1a8a2e6e6 100644 --- a/test/src/module/command/repoTest.c +++ b/test/src/module/command/repoTest.c @@ -1,17 +1,46 @@ /*********************************************************************************************************************************** Test Repo Commands ***********************************************************************************************************************************/ +#include "common/compress/helper.h" #include "common/io/bufferRead.h" #include "common/io/bufferWrite.h" +#include "common/memContext.h" +#include "common/type/string.h" +#include "storage/helper.h" #include "storage/posix/storage.h" #include "common/harnessConfig.h" #include "common/harnessInfo.h" +#include "common/harnessPostgres.h" #include "common/harnessStorageHelper.h" #include "info/infoArchive.h" #include "info/infoBackup.h" +static String * +testManifestCustomFilesValidate(Manifest *manifest) +{ + FUNCTION_HARNESS_BEGIN(); + FUNCTION_HARNESS_END(); + + String *const result = strNew(); + + MEM_CONTEXT_TEMP_BEGIN() + { + // Build list of files in the manifest + + for (unsigned int fileIdx = 0; fileIdx < manifestCustomFileTotal(manifest); fileIdx++) + { + const ManifestFile file = manifestFileUnpack(manifest, manifestCustomFilePackGet(manifest, fileIdx)); + + strCatFmt(result, "%s %" PRIu64 "\n", strZ(file.name), file.sizeOriginal); + } + } + MEM_CONTEXT_TEMP_END(); + + FUNCTION_HARNESS_RETURN(STRING, result); +} + /*********************************************************************************************************************************** Test Run ***********************************************************************************************************************************/ @@ -881,5 +910,271 @@ testRun(void) TEST_STORAGE_LIST(storageRepo(), NULL, "path/\n", .comment = "check path exists and file removed"); } + #define TEST_BACKUP_LABEL_FULL "20260201-173010F" + #define TEST_STANZA "testStanza01" + + #define TEST_DATA \ + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, " \ + "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. " \ + "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris " \ + "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in " \ + "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla " \ + "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in " \ + "culpa qui officia deserunt mollit anim id est laborum." + + #define TEST_MANIFEST_HEADER \ + "[backup]\n" \ + "backup-label=null\n" \ + "backup-timestamp-copy-start=0\n" \ + "backup-timestamp-start=0\n" \ + "backup-timestamp-stop=0\n" \ + "backup-type=\"full\"\n" + + #define TEST_MANIFEST_OPTION_ALL \ + "\n" \ + "[backup:option]\n" \ + "option-archive-check=false\n" \ + "option-archive-copy=false\n" \ + "option-checksum-page=false\n" \ + "option-compress=false\n" \ + "option-compress-type=\"none\"\n" \ + "option-hardlink=false\n" \ + "option-online=false\n" + + #define TEST_MANIFEST_TARGET \ + "\n" \ + "[backup:target]\n" \ + "pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n" + + #define TEST_MANIFEST_DB \ + "\n" \ + "[db]\n" \ + "postgres={\"db-id\":12173,\"db-last-system-id\":12168}\n" + #define TEST_MANIFEST_FILE \ + "\n" \ + "[target:file]\n" \ + "pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"size\":4,\"timestamp\":1565282114}\n" + + #define TEST_MANIFEST_FILE_DEFAULT \ + "\n" \ + "[target:file:default]\n" \ + "group=\"group1\"\n" \ + "mode=\"0600\"\n" \ + "user=\"user1\"\n" + + #define TEST_MANIFEST_LINK \ + "\n" \ + "[target:link]\n" \ + "pg_data/pg_stat={\"destination\":\"../pg_stat\"}\n" + + #define TEST_MANIFEST_LINK_DEFAULT \ + "\n" \ + "[target:link:default]\n" \ + "group=\"group1\"\n" \ + "user=false\n" + + #define TEST_MANIFEST_PATH \ + "\n" \ + "[target:path]\n" \ + "pg_data={\"user\":\"user1\"}\n" \ + + #define TEST_MANIFEST_PATH_DEFAULT \ + "\n" \ + "[target:path:default]\n" \ + "group=false\n" \ + "mode=\"0700\"\n" \ + "user=\"user1\"\n" + + // ***************************************************************************************************************************** + if (testBegin("cmdStoragePush()")) + { + HRN_STORAGE_PATH_CREATE(storageRepoWrite(), "path"); + + Storage *storageTest = storagePosixNewP(TEST_PATH_STR, .write = true); + + HRN_STORAGE_PUT_Z(storageTest, "path/aaa.txt", "TESTDATA", .timeModified = 1578671569); + + HRN_INFO_PUT( + storageRepoWrite(), STORAGE_REPO_BACKUP "/" TEST_STANZA "/" TEST_BACKUP_LABEL_FULL "/" BACKUP_MANIFEST_FILE, + TEST_MANIFEST_HEADER + "\n" + "[backup:db]\n" + "db-catalog-version=201608131\n" + "db-control-version=960\n" + "db-id=1\n" + "db-system-id=" HRN_PG_SYSTEMID_94_Z "\n" // 9.4 system id is used so version will trigger error + "db-version=\"9.6\"\n" + TEST_MANIFEST_OPTION_ALL + TEST_MANIFEST_TARGET + TEST_MANIFEST_DB + TEST_MANIFEST_FILE + TEST_MANIFEST_FILE_DEFAULT + TEST_MANIFEST_LINK + TEST_MANIFEST_LINK_DEFAULT + TEST_MANIFEST_PATH + TEST_MANIFEST_PATH_DEFAULT, + .comment = "manifest db section mismatch"); + + TEST_TITLE("missing file argument"); + StringList *argList = strLstNew(); + hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 1, TEST_PATH "/bogus"); + hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 2, TEST_PATH "/repo"); + hrnCfgArgRawZ(argList, cfgOptStanza, TEST_STANZA); + hrnCfgArgRawZ(argList, cfgOptSet, TEST_BACKUP_LABEL_FULL); + hrnCfgArgRawZ(argList, cfgOptRepo, "2"); + + HRN_CFG_LOAD(cfgCmdRepoPush, argList); + + TEST_ERROR( + cmdStoragePush(), ParamInvalidError, + "exactly one parameter is required"); + + TEST_TITLE("invalid file"); + + argList = strLstNew(); + hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 1, TEST_PATH "/bogus"); + hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 2, TEST_PATH "/repo"); + hrnCfgArgRawZ(argList, cfgOptCompressType, "none"); + hrnCfgArgRawZ(argList, cfgOptStanza, TEST_STANZA); + hrnCfgArgRawZ(argList, cfgOptSet, TEST_BACKUP_LABEL_FULL); + hrnCfgArgRawZ(argList, cfgOptRepo, "2"); + strLstAddZ(argList, "path/aaa.txt/"); + + HRN_CFG_LOAD(cfgCmdRepoPush, argList); + + TEST_ERROR( + cmdStoragePush(), ParamInvalidError, + "file parameter should not end with a slash"); + + TEST_TITLE("non-existent file"); + + argList = strLstNew(); + hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 1, TEST_PATH "/bogus"); + hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 2, TEST_PATH "/repo"); + hrnCfgArgRawZ(argList, cfgOptCompressType, "none"); + hrnCfgArgRawZ(argList, cfgOptStanza, TEST_STANZA); + hrnCfgArgRawZ(argList, cfgOptSet, TEST_BACKUP_LABEL_FULL); + hrnCfgArgRawZ(argList, cfgOptRepo, "2"); + strLstAddZ(argList, "path/non-existent.txt"); + + HRN_CFG_LOAD(cfgCmdRepoPush, argList); + + TEST_ERROR( + cmdStoragePush(), FileMissingError, + "unable to open missing file '" TEST_PATH "/path/non-existent.txt' for read"); + + TEST_RESULT_LOG("P00 INFO: push file path/non-existent.txt to the archive."); + + TEST_TITLE("push uncompressed file"); + + argList = strLstNew(); + hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 1, TEST_PATH "/bogus"); + hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 2, TEST_PATH "/repo"); + hrnCfgArgRawZ(argList, cfgOptCompressType, "none"); + hrnCfgArgRawZ(argList, cfgOptStanza, TEST_STANZA); + hrnCfgArgRawZ(argList, cfgOptSet, TEST_BACKUP_LABEL_FULL); + hrnCfgArgRawZ(argList, cfgOptRepo, "2"); + strLstAddZ(argList, "path/aaa.txt"); + + HRN_CFG_LOAD(cfgCmdRepoPush, argList); + + TEST_RESULT_VOID(cmdStoragePush(), "push file"); + TEST_RESULT_LOG("P00 INFO: push file path/aaa.txt to the archive."); + TEST_STORAGE_LIST(storageRepo(), STORAGE_PATH_BACKUP "/" TEST_STANZA "/" TEST_BACKUP_LABEL_FULL, "aaa.txt\nbackup.manifest\n", .comment = "check path exists and file added"); + + TEST_STORAGE_GET(storageRepo(), STORAGE_PATH_BACKUP "/" TEST_STANZA "/" TEST_BACKUP_LABEL_FULL "/aaa.txt", "TESTDATA"); + + Manifest *manifest = manifestLoadFile( + storageRepo(), STR(STORAGE_REPO_BACKUP "/" TEST_BACKUP_LABEL_FULL "/" BACKUP_MANIFEST_FILE), cipherTypeNone, NULL); + + /* Check manifest record */ + TEST_RESULT_STR_Z( + testManifestCustomFilesValidate(manifest), + "aaa.txt 8\n", + "compare file list"); + + TEST_TITLE("push uncompressed file, replace existing"); + + HRN_STORAGE_PUT_Z(storageTest, "path/aaa.txt", TEST_DATA, .timeModified = 1578671569); + + TEST_RESULT_VOID(cmdStoragePush(), "push file"); + TEST_RESULT_LOG("P00 INFO: push file path/aaa.txt to the archive."); + TEST_STORAGE_LIST(storageRepo(), STORAGE_PATH_BACKUP "/" TEST_STANZA "/" TEST_BACKUP_LABEL_FULL, "aaa.txt\nbackup.manifest\n", .comment = "check path exists and file added"); + + TEST_STORAGE_GET(storageRepo(), STORAGE_PATH_BACKUP "/" TEST_STANZA "/" TEST_BACKUP_LABEL_FULL "/aaa.txt", TEST_DATA); + + manifest = manifestLoadFile( + storageRepo(), STR(STORAGE_REPO_BACKUP "/" TEST_BACKUP_LABEL_FULL "/" BACKUP_MANIFEST_FILE), cipherTypeNone, NULL); + + /* Check manifest record */ + TEST_RESULT_STR_Z( + testManifestCustomFilesValidate(manifest), + "aaa.txt 445\n", + "compare file list"); + + TEST_TITLE("push compressed file"); + argList = strLstNew(); + hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 1, TEST_PATH "/bogus"); + hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 2, TEST_PATH "/repo"); + hrnCfgArgRawZ(argList, cfgOptStanza, TEST_STANZA); + hrnCfgArgRawZ(argList, cfgOptSet, TEST_BACKUP_LABEL_FULL); + hrnCfgArgRawZ(argList, cfgOptRepo, "2"); + hrnCfgArgRawZ(argList, cfgOptCompressType, "gz"); + hrnCfgArgRawZ(argList, cfgOptCompressLevel, "3"); + strLstAddZ(argList, "path/aaa.txt"); + + HRN_INFO_PUT( + storageRepoWrite(), STORAGE_REPO_BACKUP "/" TEST_STANZA "/" TEST_BACKUP_LABEL_FULL "/" BACKUP_MANIFEST_FILE, + TEST_MANIFEST_HEADER + "\n" + "[backup:db]\n" + "db-catalog-version=201608131\n" + "db-control-version=960\n" + "db-id=1\n" + "db-system-id=" HRN_PG_SYSTEMID_94_Z "\n" // 9.4 system id is used so version will trigger error + "db-version=\"9.6\"\n" + TEST_MANIFEST_OPTION_ALL + TEST_MANIFEST_TARGET + TEST_MANIFEST_DB + TEST_MANIFEST_FILE + TEST_MANIFEST_FILE_DEFAULT + TEST_MANIFEST_LINK + TEST_MANIFEST_LINK_DEFAULT + TEST_MANIFEST_PATH + TEST_MANIFEST_PATH_DEFAULT, + .comment = "manifest db section mismatch"); + + HRN_CFG_LOAD(cfgCmdRepoPush, argList); + + TEST_RESULT_VOID(cmdStoragePush(), "push file"); + TEST_RESULT_LOG("P00 INFO: push file path/aaa.txt to the archive."); + TEST_STORAGE_LIST(storageRepo(), STORAGE_PATH_BACKUP "/" TEST_STANZA "/" TEST_BACKUP_LABEL_FULL, "aaa.txt\naaa.txt.gz\nbackup.manifest\n", .comment = "check path exists and file added"); + + TEST_STORAGE_GET(storageRepo(), STORAGE_PATH_BACKUP "/" TEST_STANZA "/" TEST_BACKUP_LABEL_FULL "/aaa.txt", TEST_DATA, .compressType = compressTypeGz); + + manifest = manifestLoadFile( + storageRepo(), STR(STORAGE_REPO_BACKUP "/" TEST_BACKUP_LABEL_FULL "/" BACKUP_MANIFEST_FILE), cipherTypeNone, NULL); + + /* Check manifest record */ + TEST_RESULT_STR_Z( + testManifestCustomFilesValidate(manifest), + "aaa.txt 445\naaa.txt.gz 445\n", + "compare file list"); + + TEST_TITLE("push encrypted file not supported"); + argList = strLstNew(); + hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 1, TEST_PATH "/bogus"); + hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 2, TEST_PATH "/repo"); + hrnCfgArgRawZ(argList, cfgOptStanza, TEST_STANZA); + hrnCfgArgRawZ(argList, cfgOptSet, TEST_BACKUP_LABEL_FULL); + hrnCfgArgRawZ(argList, cfgOptRepo, "2"); + hrnCfgArgRawZ(argList, cfgOptCipherPass, "unimportant"); + strLstAddZ(argList, "path/aaa.txt"); + + TEST_ERROR( + HRN_CFG_LOAD(cfgCmdRepoPush, argList), OptionInvalidError, + "option 'cipher-pass' not valid for command 'repo-push'"); + } + FUNCTION_HARNESS_RETURN_VOID(); } diff --git a/test/src/module/common/typeStringTest.c b/test/src/module/common/typeStringTest.c index 927feada00..588c4faf29 100644 --- a/test/src/module/common/typeStringTest.c +++ b/test/src/module/common/typeStringTest.c @@ -120,7 +120,7 @@ testRun(void) } // ***************************************************************************************************************************** - if (testBegin("strBase(), strPath(), and strPathAbsolute()")) + if (testBegin("strBase(), strPath(), strPathAbsolute() and strFileName()")) { TEST_RESULT_STR_Z(strBase(STRDEF("")), "", "empty string"); TEST_RESULT_STR_Z(strBase(STRDEF("/")), "", "/ only"); @@ -143,6 +143,11 @@ testRun(void) TEST_RESULT_STR_Z(strPathAbsolute(STRDEF("../"), STRDEF("/path1")), "/", "simple relative path with trailing /"); TEST_RESULT_STR_Z( strPathAbsolute(STRDEF("../path2/.././path3"), STRDEF("/base1/base2")), "/base1/path3", "complex relative path"); + + TEST_RESULT_STR_Z(strFileName(STRDEF("/path/to/file")), "file", "filename"); + TEST_RESULT_STR_Z(strFileName(STRDEF("/path/to/file.ext")), "file.ext", "filename with extension"); + TEST_RESULT_STR_Z(strFileName(STRDEF("/path/to/file.ext/")), "", "empty filename if trailing /"); + TEST_RESULT_STR_Z(strFileName(STRDEF("")), "", "empty string"); } // ***************************************************************************************************************************** diff --git a/test/src/module/info/manifestTest.c b/test/src/module/info/manifestTest.c index e798082192..926bd4181d 100644 --- a/test/src/module/info/manifestTest.c +++ b/test/src/module/info/manifestTest.c @@ -2047,4 +2047,84 @@ testRun(void) TEST_RESULT_VOID(manifestFree(manifest), "free manifest"); TEST_RESULT_VOID(manifestFree(NULL), "free null manifest"); } + + // ***************************************************************************************************************************** + if (testBegin("manifestCustomFileAdd(), manifestCustomFileUpdate() and manifestSave()/manifestNewLoad()")) + { + Manifest *manifest = NULL; + + HRN_STORAGE_PATH_CREATE(storageTest, "pg", .mode = 0700); + Storage *storagePg = storagePosixNewP(STRDEF(TEST_PATH "/pg")); + + // Add a tablespace to tablespaceList that does exist + PackWrite *tablespaceList = pckWriteNewP(); + + pckWriteArrayBeginP(tablespaceList); + pckWriteU32P(tablespaceList, 2); + pckWriteStrP(tablespaceList, STRDEF("tblspc2")); + pckWriteArrayEndP(tablespaceList); + pckWriteArrayBeginP(tablespaceList); + pckWriteU32P(tablespaceList, 1); + pckWriteStrP(tablespaceList, STRDEF("tblspc1")); + pckWriteArrayEndP(tablespaceList); + pckWriteEndP(tablespaceList); + + TEST_ASSIGN( + manifest, + manifestNewBuild( + storagePg, PG_VERSION_94, hrnPgCatalogVersion(PG_VERSION_94), 0, false, false, false, false, NULL, NULL, + pckWriteResult(tablespaceList)), + "build manifest"); + + #define TEST_CUSTOM_FILE_NAME STRDEF("somefile.txt") + + ManifestFile customFile = + { + .name = TEST_CUSTOM_FILE_NAME, + .mode = 0600, + .size = 42, + .sizeOriginal = 43, + .sizeRepo = 44, + .timestamp = time(NULL), + .checksumSha1 = bufPtr(bufNewDecode(encodingHex, STR("deadbeef5e6b4b0d3255bfef95601890afd80709"))), + }; + + TEST_RESULT_VOID(manifestCustomFileAdd(manifest, &customFile), "manifestCustomFileAdd"); + TEST_RESULT_UINT(manifestCustomFileTotal(manifest), 1, "manifestCustomFileTotal"); + + ManifestFilePack **const filePack = manifestCustomFilePackFindInternal(manifest, TEST_CUSTOM_FILE_NAME); + TEST_RESULT_PTR_NE(filePack, NULL, "file in the manifest"); + + ManifestFile file = manifestFileUnpack(manifest, *filePack); + + TEST_RESULT_UINT(file.size, 42, "size"); + + ManifestFile manifestFile = manifestCustomFile(manifest, 0); + + manifestFile.size = 45; + TEST_RESULT_VOID(manifestCustomFileUpdate(manifest, &manifestFile), "update"); + TEST_RESULT_UINT(manifestCustomFileTotal(manifest), 1, "manifestCustomFileTotal"); + + ManifestFile manifestFile2 = manifestCustomFile(manifest, 0); + TEST_RESULT_UINT(manifestFile2.size, 45, "size"); + + Buffer *contentSave = bufNew(0); + TEST_RESULT_VOID(manifestSave(manifest, ioBufferWriteNew(contentSave)), "save manifest"); + + Manifest *manifest2 = NULL; + + TEST_ASSIGN( + manifest2, + manifestNewLoad(ioBufferReadNew(contentSave)), + "load manifest" + ); + TEST_RESULT_PTR_NE(manifest2, NULL, "manifest loaded"); + TEST_RESULT_UINT(manifestCustomFileTotal(manifest2), 1, "manifestCustomFileTotal"); + manifestFile2 = manifestCustomFile(manifest2, 0); + TEST_RESULT_UINT(manifestFile2.size, 45, "size"); + + // Try to find non-existent file + TEST_ERROR(manifestCustomFilePackFindInternal(manifest2, STRDEF("badbadfile.txt")), + AssertError, "unable to find 'badbadfile.txt' in manifest file list"); + } }