diff options
Diffstat (limited to 'src/zen/cmds/builds_cmd.h')
| -rw-r--r-- | src/zen/cmds/builds_cmd.h | 405 |
1 files changed, 253 insertions, 152 deletions
diff --git a/src/zen/cmds/builds_cmd.h b/src/zen/cmds/builds_cmd.h index 7ef71e176..338318757 100644 --- a/src/zen/cmds/builds_cmd.h +++ b/src/zen/cmds/builds_cmd.h @@ -2,65 +2,227 @@ #pragma once -#include "../authutils.h" -#include "../zen.h" - -#include <zenhttp/auth/authmgr.h> -#include <zenhttp/httpclientauth.h> +#include <zencore/scopeguard.h> #include <zenremotestore/builds/buildstoragecache.h> #include <zenremotestore/builds/buildstorageutil.h> #include <zenremotestore/partialblockrequestmode.h> -#include <filesystem> +#include <zenremotestore/transferthreadworkers.h> + +#include "authutils.h" +#include "consoleprogress.h" + +#include <optional> namespace zen { -class BuildsCommand; +class ProgressBase; +class AuthMgr; + +struct CreateBuildStorageOptions +{ + bool RequireNamespace = true; + bool RequireBucket = true; + bool BoostCacheBackgroundWorkers = false; +}; + +////////////////////////////////////////////////////////////////////////// -class BuildsListNamespacesSubCmd : public ZenSubCmdBase +struct BuildsConfiguration +{ + std::filesystem::path SystemRootDir; + bool UseSparseFiles = true; + + bool PlainProgress = false; + bool LogProgress = false; + bool Verbose = false; + bool Quiet = false; + ConsoleProgressMode ProgressMode = ConsoleProgressMode::Pretty; + bool BoostWorkerCount = false; + bool BoostWorkerMemory = false; + bool BoostWorkers = false; + + std::string OverrideHost; + std::string Host; + std::string Url; + bool AssumeHttp2 = false; + bool VerboseHttp = false; + bool AllowRedirect = false; + std::string Namespace; + std::string Bucket; + + std::filesystem::path StoragePath; + bool WriteMetadataAsJson = false; + + std::string ZenCacheHost; + + AuthCommandLineOptions AuthOptions; + + std::string IncludeWildcard; + std::string ExcludeWildcard; + std::string ExcludeFolders; + std::string ExcludeExtensions; + + std::filesystem::path ChunkingCachePath; + + bool AllowMultiparts = true; + std::string AllowPartialBlockRequests = "true"; + + bool AppendNewContent = false; + + std::filesystem::path ZenFolderPath; + + void AddSystemOptions(cxxopts::Options& Ops); + void AddCloudOptions(cxxopts::Options& Ops); + void AddFileOptions(cxxopts::Options& Ops); + void AddCacheOptions(cxxopts::Options& Ops); + void AddOutputOptions(cxxopts::Options& Ops); + void AddWorkerOptions(cxxopts::Options& Ops); + void AddZenFolderOptions(cxxopts::Options& Ops); + void AddChunkingCacheOptions(cxxopts::Options& Ops); + void AddWildcardOptions(cxxopts::Options& Ops); + void AddExcludeFolderOption(cxxopts::Options& Ops); + void AddExcludeExtensionsOption(cxxopts::Options& Ops); + void AddMultipartOptions(cxxopts::Options& Ops); + void AddPartialBlockRequestOptions(cxxopts::Options& Ops); + void AddAppendNewContentOptions(cxxopts::Options& Ops); +}; + +////////////////////////////////////////////////////////////////////////// + +class BuildsSubCmdBase : public ZenSubCmdBase { public: - explicit BuildsListNamespacesSubCmd(BuildsCommand& Parent); + BuildsSubCmdBase(BuildsConfiguration& Config, std::string_view Name, std::string_view Description) + : ZenSubCmdBase(Name, Description) + , m_Config(Config) + { + } + +protected: + const BuildsConfiguration& m_Config; + std::filesystem::path m_ResolvedZenFolderPath; + // Set by EnsureZenFolderExists: true if this command newly created the zen folder + // (so CleanZenFolder may remove the whole folder), false if it already existed + // (in which case only the temp subfolder is wiped, to preserve any pre-existing state). + bool m_CreatedZenFolder = false; + + struct ResolvedStorage + { + std::filesystem::path SystemRootDir; + std::string Host; + std::string Namespace; + std::string Bucket; + std::filesystem::path StoragePath; + }; + + void LogBanner(); + void LogWorkersInfo(const TransferThreadWorkers& Workers); + + // SystemRootDirOverride / StoragePathOverride: empty = fall back to m_Config. + ResolvedStorage ParseStorageOptions(std::string& BuildId, + const CreateBuildStorageOptions& Options, + cxxopts::Options& SubOpts, + const std::filesystem::path& SystemRootDirOverride = {}, + const std::filesystem::path& StoragePathOverride = {}); + + // Builds the storage instance using the supplied Resolved values. ZenFolder is the final zen folder + // path (caller resolves; pass GetZenFolderPath() after ResolveZenFolderPath). If ZenFolder is empty + // the storage runs without a temp directory and keeps all downloads in memory. + // Caller owns Stats/Auth lifetime. Stats must outlive the returned StorageInstance. + StorageInstance CreateBuildStorage(const std::filesystem::path& ZenFolder, + const CreateBuildStorageOptions& Options, + cxxopts::Options& SubOpts, + BuildStorageBase::Statistics& OutStorageStats, + BuildStorageCache::Statistics& OutCacheStats, + std::unique_ptr<AuthMgr>& OutAuth, + const ResolvedStorage& Resolved); + Oid ParseBuildId(const std::string& BuildIdStr, cxxopts::Options& SubOpts); + Oid ParseBuildPartId(const std::string& BuildPartIdStr, cxxopts::Options& SubOpts); + std::vector<Oid> ParseBuildPartIds(const std::vector<std::string>& BuildPartIdStrs, cxxopts::Options& SubOpts); + std::vector<std::string> ParseBuildPartNames(const std::vector<std::string>& BuildPartNameStrs, cxxopts::Options& SubOpts); + CbObject ParseBuildMetadata(bool CreateBuild, + std::filesystem::path& BuildMetadataPath, + const std::string& BuildMetadata, + cxxopts::Options& SubOpts); + void ParsePath(std::filesystem::path& Path, cxxopts::Options& SubOpts); + IoHash ParseBlobHash(const std::string& BlobHashStr, cxxopts::Options& SubOpts); + EPartialBlockRequestMode ParseAllowPartialBlockRequests(cxxopts::Options& SubOpts); + void ParseZenProcessId(int& ZenProcessId); + void ParseFileFilters(std::vector<std::string>& OutIncludeWildcards, std::vector<std::string>& OutExcludeWildcards); + void ParseExcludeFolderAndExtension(std::vector<std::string>& OutExcludeFolders, std::vector<std::string>& OutExcludeExtensions); + + // Resolves the zen folder using this chain: --zen-folder-path; else LocalPath/ZenFolderName + // if LocalPath is non-empty; else cwd/ZenFolderName. Read-only commands that do not need a + // zen folder should skip this and pass an empty path to CreateBuildStorage. + void ResolveZenFolderPath(const std::filesystem::path& LocalPath); + // Assigns the zen folder to --zen-folder-path if given, else to Fallback directly (no + // ZenFolderName appended). For commands that want a specific scratch location rather than + // the standard LocalPath/.zen chain. + void SetZenFolderPath(const std::filesystem::path& Fallback); + const std::filesystem::path& GetZenFolderPath() const { return m_ResolvedZenFolderPath; } + // Creates the resolved zen folder and records whether it had to be created. + // Use together with CleanZenFolder via MakeGuard. + void EnsureZenFolderExists(); + + std::atomic<bool>& AbortFlag() const; + std::atomic<bool>& PauseFlag() const; + std::unique_ptr<ProgressBase> CreateProgress() const; + + // Wipes temp state produced by the command. If EnsureZenFolderExists created the zen folder + // it is removed outright; otherwise only the temp subfolder is wiped so pre-existing state + // (e.g. current_state.cbo from a prior download in the same folder) is preserved. + void CleanZenFolder(); +}; + +////////////////////////////////////////////////////////////////////////// + +class BuildsListNamespacesSubCmd : public BuildsSubCmdBase +{ +public: + explicit BuildsListNamespacesSubCmd(BuildsConfiguration& Config); void Run(const ZenCliOptions& GlobalOptions) override; private: - BuildsCommand& m_Parent; bool m_Recursive = false; std::filesystem::path m_ResultPath; }; -class BuildsListSubCmd : public ZenSubCmdBase +////////////////////////////////////////////////////////////////////////// + +class BuildsListSubCmd : public BuildsSubCmdBase { public: - explicit BuildsListSubCmd(BuildsCommand& Parent); + explicit BuildsListSubCmd(BuildsConfiguration& Config); void Run(const ZenCliOptions& GlobalOptions) override; private: - BuildsCommand& m_Parent; std::filesystem::path m_QueryPath; std::filesystem::path m_ResultPath; }; -class BuildsListBlocksSubCmd : public ZenSubCmdBase +////////////////////////////////////////////////////////////////////////// + +class BuildsListBlocksSubCmd : public BuildsSubCmdBase { public: - explicit BuildsListBlocksSubCmd(BuildsCommand& Parent); + explicit BuildsListBlocksSubCmd(BuildsConfiguration& Config); void Run(const ZenCliOptions& GlobalOptions) override; private: - BuildsCommand& m_Parent; std::string m_BuildId; std::filesystem::path m_ResultPath; uint32_t m_MaxCount = 16; }; -class BuildsUploadSubCmd : public ZenSubCmdBase +////////////////////////////////////////////////////////////////////////// + +class BuildsUploadSubCmd : public BuildsSubCmdBase { public: - explicit BuildsUploadSubCmd(BuildsCommand& Parent); + explicit BuildsUploadSubCmd(BuildsConfiguration& Config); void Run(const ZenCliOptions& GlobalOptions) override; private: - BuildsCommand& m_Parent; std::filesystem::path m_Path; std::string m_BuildId; std::string m_BuildPartId; @@ -76,14 +238,15 @@ private: bool m_UploadToZenCache = true; }; -class BuildsDownloadSubCmd : public ZenSubCmdBase +////////////////////////////////////////////////////////////////////////// + +class BuildsDownloadSubCmd : public BuildsSubCmdBase { public: - explicit BuildsDownloadSubCmd(BuildsCommand& Parent); + explicit BuildsDownloadSubCmd(BuildsConfiguration& Config); void Run(const ZenCliOptions& GlobalOptions) override; private: - BuildsCommand& m_Parent; std::filesystem::path m_Path; std::string m_BuildId; std::vector<std::string> m_BuildPartIds; @@ -94,117 +257,129 @@ private: bool m_EnableScavenging = true; std::filesystem::path m_DownloadSpecPath; bool m_UploadToZenCache = true; - bool m_PrimeCacheOnly = false; bool m_AllowFileClone = true; }; -class BuildsLsSubCmd : public ZenSubCmdBase +////////////////////////////////////////////////////////////////////////// + +class BuildsLsSubCmd : public BuildsSubCmdBase { public: - explicit BuildsLsSubCmd(BuildsCommand& Parent); + explicit BuildsLsSubCmd(BuildsConfiguration& Config); void Run(const ZenCliOptions& GlobalOptions) override; private: - BuildsCommand& m_Parent; std::string m_BuildId; std::vector<std::string> m_BuildPartIds; std::vector<std::string> m_BuildPartNames; std::filesystem::path m_ResultPath; }; -class BuildsDiffSubCmd : public ZenSubCmdBase +////////////////////////////////////////////////////////////////////////// + +class BuildsDiffSubCmd : public BuildsSubCmdBase { public: - explicit BuildsDiffSubCmd(BuildsCommand& Parent); + explicit BuildsDiffSubCmd(BuildsConfiguration& Config); void Run(const ZenCliOptions& GlobalOptions) override; private: - BuildsCommand& m_Parent; std::filesystem::path m_Path; std::filesystem::path m_DiffPath; bool m_OnlyChunked = false; }; -class BuildsFetchBlobSubCmd : public ZenSubCmdBase +////////////////////////////////////////////////////////////////////////// + +class BuildsFetchBlobSubCmd : public BuildsSubCmdBase { public: - explicit BuildsFetchBlobSubCmd(BuildsCommand& Parent); + explicit BuildsFetchBlobSubCmd(BuildsConfiguration& Config); void Run(const ZenCliOptions& GlobalOptions) override; private: - BuildsCommand& m_Parent; - std::string m_BuildId; - std::string m_BlobHash; + std::string m_BuildId; + std::string m_BlobHash; }; -class BuildsPrimeCacheSubCmd : public ZenSubCmdBase +////////////////////////////////////////////////////////////////////////// + +class BuildsPrimeCacheSubCmd : public BuildsSubCmdBase { public: - explicit BuildsPrimeCacheSubCmd(BuildsCommand& Parent); + explicit BuildsPrimeCacheSubCmd(BuildsConfiguration& Config); void Run(const ZenCliOptions& GlobalOptions) override; private: - BuildsCommand& m_Parent; std::string m_BuildId; std::vector<std::string> m_BuildPartIds; std::vector<std::string> m_BuildPartNames; bool m_Force = false; }; -class BuildsPauseSubCmd : public ZenSubCmdBase +////////////////////////////////////////////////////////////////////////// + +class BuildsPauseSubCmd : public BuildsSubCmdBase { public: - explicit BuildsPauseSubCmd(BuildsCommand& Parent); + explicit BuildsPauseSubCmd(BuildsConfiguration& Config); void Run(const ZenCliOptions& GlobalOptions) override; private: - BuildsCommand& m_Parent; - int m_ZenProcessId = -1; + int m_ZenProcessId = -1; }; -class BuildsResumeSubCmd : public ZenSubCmdBase +////////////////////////////////////////////////////////////////////////// + +class BuildsResumeSubCmd : public BuildsSubCmdBase { public: - explicit BuildsResumeSubCmd(BuildsCommand& Parent); + explicit BuildsResumeSubCmd(BuildsConfiguration& Config); void Run(const ZenCliOptions& GlobalOptions) override; private: - BuildsCommand& m_Parent; - int m_ZenProcessId = -1; + int m_ZenProcessId = -1; }; -class BuildsAbortSubCmd : public ZenSubCmdBase +////////////////////////////////////////////////////////////////////////// + +class BuildsAbortSubCmd : public BuildsSubCmdBase { public: - explicit BuildsAbortSubCmd(BuildsCommand& Parent); + explicit BuildsAbortSubCmd(BuildsConfiguration& Config); void Run(const ZenCliOptions& GlobalOptions) override; private: - BuildsCommand& m_Parent; - int m_ZenProcessId = -1; + int m_ZenProcessId = -1; }; -class BuildsValidatePartSubCmd : public ZenSubCmdBase +////////////////////////////////////////////////////////////////////////// + +class BuildsValidatePartSubCmd : public BuildsSubCmdBase { public: - explicit BuildsValidatePartSubCmd(BuildsCommand& Parent); + explicit BuildsValidatePartSubCmd(BuildsConfiguration& Config); void Run(const ZenCliOptions& GlobalOptions) override; private: - BuildsCommand& m_Parent; - std::string m_BuildId; - std::string m_BuildPartId; - std::string m_BuildPartName; + std::string m_BuildId; + std::string m_BuildPartId; + std::string m_BuildPartName; }; -class BuildsTestSubCmd : public ZenSubCmdBase +////////////////////////////////////////////////////////////////////////// + +class BuildsTestSubCmd : public BuildsSubCmdBase { public: - explicit BuildsTestSubCmd(BuildsCommand& Parent); + explicit BuildsTestSubCmd(BuildsConfiguration& Config); void Run(const ZenCliOptions& GlobalOptions) override; private: - BuildsCommand& m_Parent; + // Fixture-only overrides of SystemRootDir/StoragePath; passed to ParseStorageOptions explicitly. + std::filesystem::path m_TestSystemRootDir; + std::filesystem::path m_TestStoragePath; + std::filesystem::path m_Path; std::string m_BuildPartName; std::string m_BuildId; @@ -217,21 +392,27 @@ private: bool m_AllowFileClone = true; }; -class BuildsMultiTestDownloadSubCmd : public ZenSubCmdBase +////////////////////////////////////////////////////////////////////////// + +class BuildsMultiTestDownloadSubCmd : public BuildsSubCmdBase { public: - explicit BuildsMultiTestDownloadSubCmd(BuildsCommand& Parent); + explicit BuildsMultiTestDownloadSubCmd(BuildsConfiguration& Config); void Run(const ZenCliOptions& GlobalOptions) override; private: - BuildsCommand& m_Parent; + // Fixture-only override of SystemRootDir; passed to CreateStorage explicitly. + std::filesystem::path m_TestSystemRootDir; + std::filesystem::path m_Path; std::vector<std::string> m_BuildIds; bool m_EnableScavenging = true; bool m_AllowFileClone = true; }; -class BuildsCommand : public CacheStoreCmdWithSubCommands +////////////////////////////////////////////////////////////////////////// + +class BuildsCommand : public ZenCmdWithSubCommands { public: static constexpr char Name[] = "builds"; @@ -243,99 +424,14 @@ public: cxxopts::Options& Options() override { return m_Options; } - // Option-adding helpers (called by subcommand constructors) - void AddSystemOptions(cxxopts::Options& Ops); - void AddCloudOptions(cxxopts::Options& Ops); - void AddFileOptions(cxxopts::Options& Ops); - void AddCacheOptions(cxxopts::Options& Ops); - void AddOutputOptions(cxxopts::Options& Ops); - void AddWorkerOptions(cxxopts::Options& Ops); - void AddZenFolderOptions(cxxopts::Options& Ops); - void AddChunkingCacheOptions(cxxopts::Options& Ops); - void AddWildcardOptions(cxxopts::Options& Ops); - void AddExcludeFolderOption(cxxopts::Options& Ops); - void AddExcludeExtensionsOption(cxxopts::Options& Ops); - void AddMultipartOptions(cxxopts::Options& Ops); - void AddPartialBlockRequestOptions(cxxopts::Options& Ops); - void AddAppendNewContentOptions(cxxopts::Options& Ops); - - // Shared parsing/factory methods used by subcommand Run() implementations - void ParseStorageOptions(std::string& BuildId, bool RequireNamespace, bool RequireBucket, cxxopts::Options& SubOpts); - StorageInstance CreateBuildStorage(BuildStorageBase::Statistics& StorageStats, - BuildStorageCache::Statistics& StorageCacheStats, - const std::filesystem::path& TempPath, - std::string& BuildId, - bool RequireNamespace, - bool RequireBucket, - bool BoostCacheBackgroundWorkerPool, - std::unique_ptr<AuthMgr>& Auth, - cxxopts::Options& SubOpts); - Oid ParseBuildId(const std::string& BuildIdStr, cxxopts::Options& SubOpts); - Oid ParseBuildPartId(const std::string& BuildPartIdStr, cxxopts::Options& SubOpts); - std::vector<Oid> ParseBuildPartIds(const std::vector<std::string>& BuildPartIdStrs, cxxopts::Options& SubOpts); - std::vector<std::string> ParseBuildPartNames(const std::vector<std::string>& BuildPartNameStrs, cxxopts::Options& SubOpts); - CbObject ParseBuildMetadata(bool CreateBuild, - std::filesystem::path& BuildMetadataPath, - const std::string& BuildMetadata, - cxxopts::Options& SubOpts); - void ParsePath(std::filesystem::path& Path, cxxopts::Options& SubOpts); - IoHash ParseBlobHash(const std::string& BlobHashStr, cxxopts::Options& SubOpts); - EPartialBlockRequestMode ParseAllowPartialBlockRequests(bool PrimeCacheOnly, cxxopts::Options& SubOpts); - void ParseZenProcessId(int& ZenProcessId); - void ParseFileFilters(std::vector<std::string>& OutIncludeWildcards, std::vector<std::string>& OutExcludeWildcards); - void ParseExcludeFolderAndExtension(std::vector<std::string>& OutExcludeFolders, std::vector<std::string>& OutExcludeExtensions); - - void ResolveZenFolderPath(const std::filesystem::path& DefaultPath); - const std::filesystem::path& GetZenFolderPath() const { return m_ZenFolderPath; } - - cxxopts::Options m_Options{Name, Description}; - std::string m_SubCommand; - - // Shared state populated by AddXxxOptions helpers (bound via cxxopts::value references) - std::filesystem::path m_SystemRootDir; - bool m_UseSparseFiles = true; - - bool m_PlainProgress = false; - bool m_LogProgress = false; - bool m_Verbose = false; - bool m_Quiet = false; - bool m_BoostWorkerCount = false; - bool m_BoostWorkerMemory = false; - bool m_BoostWorkers = false; - - // cloud builds - std::string m_OverrideHost; - std::string m_Host; - std::string m_Url; - bool m_AssumeHttp2 = false; - bool m_VerboseHttp = false; - bool m_AllowRedirect = false; - std::string m_Namespace; - std::string m_Bucket; - - std::filesystem::path m_StoragePath; - bool m_WriteMetadataAsJson = false; - - std::string m_ZenCacheHost; - - AuthCommandLineOptions m_AuthOptions; - - std::string m_IncludeWildcard; - std::string m_ExcludeWildcard; - std::string m_ExcludeFolders; - std::string m_ExcludeExtensions; - - std::filesystem::path m_ChunkingCachePath; - - bool m_AllowMultiparts = true; - std::string m_AllowPartialBlockRequests = "true"; - - bool m_AppendNewContent = false; + BuildsConfiguration& GetConfiguration() { return m_Configuration; } + const BuildsConfiguration& GetConfiguration() const { return m_Configuration; } private: - std::filesystem::path m_ZenFolderPath; + cxxopts::Options m_Options{Name, Description}; + std::string m_SubCommand; + BuildsConfiguration m_Configuration; -protected: BuildsListNamespacesSubCmd m_ListNamespacesSubCmd; BuildsListSubCmd m_ListSubCmd; BuildsListBlocksSubCmd m_ListBlocksSubCmd; @@ -352,6 +448,11 @@ protected: BuildsTestSubCmd m_TestSubCmd; BuildsMultiTestDownloadSubCmd m_MultiTestDownloadSubCmd; + std::optional<ScopedSignalHandler> m_SigIntGuard; +#if ZEN_PLATFORM_WINDOWS + std::optional<ScopedSignalHandler> m_SigBreakGuard; +#endif + bool OnParentOptionsParsed(const ZenCliOptions& GlobalOptions) override; }; |