aboutsummaryrefslogtreecommitdiff
path: root/src/zen/cmds/builds_cmd.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/zen/cmds/builds_cmd.h')
-rw-r--r--src/zen/cmds/builds_cmd.h405
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;
};