diff options
| author | Zousar Shaker <[email protected]> | 2025-04-24 08:26:29 -0600 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2025-04-24 08:26:29 -0600 |
| commit | 787449efb4de24fd12f3af3c4e466a9629203108 (patch) | |
| tree | cb4a0e84a0381e9b4a087401037ba5837e8e65d7 /src/zen/cmds/builds_cmd.cpp | |
| parent | Changelog update terminology (diff) | |
| parent | 5.6.6-pre1 (diff) | |
| download | archived-zen-787449efb4de24fd12f3af3c4e466a9629203108.tar.xz archived-zen-787449efb4de24fd12f3af3c4e466a9629203108.zip | |
Merge branch 'main' into zs/zencli-list-namespaces-buckets
Diffstat (limited to 'src/zen/cmds/builds_cmd.cpp')
| -rw-r--r-- | src/zen/cmds/builds_cmd.cpp | 760 |
1 files changed, 355 insertions, 405 deletions
diff --git a/src/zen/cmds/builds_cmd.cpp b/src/zen/cmds/builds_cmd.cpp index 624bb2270..15c635594 100644 --- a/src/zen/cmds/builds_cmd.cpp +++ b/src/zen/cmds/builds_cmd.cpp @@ -164,24 +164,6 @@ namespace { ); - std::filesystem::path MakeSafeAbsolutePath(std::filesystem::path Path) - { - std::filesystem::path AbsolutePath = std::filesystem::absolute(Path).make_preferred(); -#if ZEN_PLATFORM_WINDOWS && 1 - const std::string_view Prefix = "\\\\?\\"; - const std::u8string PrefixU8(Prefix.begin(), Prefix.end()); - std::u8string PathString = AbsolutePath.u8string(); - if (!PathString.empty() && !PathString.starts_with(PrefixU8)) - { - PathString.insert(0, PrefixU8); - return std::filesystem::path(PathString); - } -#endif - return AbsolutePath; - } - - std::filesystem::path MakeSafeAbsolutePath(const std::string PathString) { return MakeSafeAbsolutePath(StringToPath(PathString)); } - bool IsFileWithRetry(const std::filesystem::path& Path) { std::error_code Ec; @@ -690,75 +672,6 @@ namespace { return CacheFolderPath / RawHash.ToHexString(); } - ChunkedFolderContent ScanAndChunkFolder( - GetFolderContentStatistics& GetFolderContentStats, - ChunkingStatistics& ChunkingStats, - const std::filesystem::path& Path, - std::function<bool(const std::string_view& RelativePath)>&& IsAcceptedFolder, - std::function<bool(std::string_view RelativePath, uint64_t Size, uint32_t Attributes)>&& IsAcceptedFile, - ChunkingController& ChunkController) - { - ZEN_TRACE_CPU("ScanAndChunkFolder"); - - FolderContent Content = GetFolderContent( - GetFolderContentStats, - Path, - std::move(IsAcceptedFolder), - std::move(IsAcceptedFile), - GetIOWorkerPool(), - UsePlainProgress ? 5000 : 200, - [](bool, std::ptrdiff_t) {}, - AbortFlag); - if (AbortFlag) - { - return {}; - } - - ProgressBar ProgressBar(UsePlainProgress); - FilteredRate FilteredBytesHashed; - FilteredBytesHashed.Start(); - ChunkedFolderContent FolderContent = ChunkFolderContent( - ChunkingStats, - GetIOWorkerPool(), - Path, - Content, - ChunkController, - UsePlainProgress ? 5000 : 200, - [&](bool, std::ptrdiff_t) { - FilteredBytesHashed.Update(ChunkingStats.BytesHashed.load()); - std::string Details = fmt::format("{}/{} ({}/{}, {}B/s) scanned, {} ({}) chunks found", - ChunkingStats.FilesProcessed.load(), - GetFolderContentStats.AcceptedFileCount.load(), - NiceBytes(ChunkingStats.BytesHashed.load()), - NiceBytes(GetFolderContentStats.FoundFileByteCount), - NiceNum(FilteredBytesHashed.GetCurrent()), - ChunkingStats.UniqueChunksFound.load(), - NiceBytes(ChunkingStats.UniqueBytesFound.load())); - ProgressBar.UpdateState({.Task = "Scanning files ", - .Details = Details, - .TotalCount = GetFolderContentStats.AcceptedFileByteCount, - .RemainingCount = GetFolderContentStats.AcceptedFileByteCount - ChunkingStats.BytesHashed.load()}, - false); - }, - AbortFlag); - if (AbortFlag) - { - return {}; - } - FilteredBytesHashed.Stop(); - ProgressBar.Finish(); - - ZEN_CONSOLE("Found {} ({}) files divided into {} ({}) unique chunks in '{}' in {}. Average hash rate {}B/sec", - ChunkingStats.FilesProcessed.load(), - NiceBytes(ChunkingStats.BytesHashed.load()), - ChunkingStats.UniqueChunksFound.load(), - NiceBytes(ChunkingStats.UniqueBytesFound.load()), - Path, - NiceTimeSpanMs((GetFolderContentStats.ElapsedWallTimeUS + ChunkingStats.ElapsedWallTimeUS) / 1000), - NiceNum(GetBytesPerSecond(ChunkingStats.ElapsedWallTimeUS, ChunkingStats.BytesHashed))); - return FolderContent; - }; - struct DiskStatistics { std::atomic<uint64_t> OpenReadCount = 0; @@ -2562,7 +2475,7 @@ namespace { BlockIndexes.push_back(It->second); TotalBlocksSize += NewBlocks.BlockSizes[It->second]; } - if (auto ChunkIndexIt = Lookup.ChunkHashToChunkIndex.find(RawHash); ChunkIndexIt != Lookup.ChunkHashToChunkIndex.end()) + else if (auto ChunkIndexIt = Lookup.ChunkHashToChunkIndex.find(RawHash); ChunkIndexIt != Lookup.ChunkHashToChunkIndex.end()) { const uint32_t ChunkIndex = ChunkIndexIt->second; if (auto LooseOrderIndexIt = ChunkIndexToLooseChunkOrderIndex.find(ChunkIndex); @@ -2572,6 +2485,11 @@ namespace { TotalLooseChunksSize += Content.ChunkedContent.ChunkRawSizes[ChunkIndex]; } } + else + { + throw std::runtime_error( + fmt::format("Can not upload requested build blob {} as it was not generated by this upload", RawHash)); + } } uint64_t TotalRawSize = TotalLooseChunksSize + TotalBlocksSize; @@ -3169,8 +3087,9 @@ namespace { auto ParseManifest = [](const std::filesystem::path& Path, const std::filesystem::path& ManifestPath) -> std::vector<std::filesystem::path> { std::vector<std::filesystem::path> AssetPaths; - std::filesystem::path AbsoluteManifestPath = ManifestPath.is_absolute() ? ManifestPath : Path / ManifestPath; - IoBuffer ManifestContent = ReadFile(AbsoluteManifestPath).Flatten(); + std::filesystem::path AbsoluteManifestPath = + MakeSafeAbsolutePath(ManifestPath.is_absolute() ? ManifestPath : Path / ManifestPath); + IoBuffer ManifestContent = ReadFile(AbsoluteManifestPath).Flatten(); std::string_view ManifestString((const char*)ManifestContent.GetView().GetData(), ManifestContent.GetSize()); std::string_view::size_type Offset = 0; while (Offset < ManifestContent.GetSize()) @@ -3730,7 +3649,8 @@ namespace { UploadAttachments(PutBuildPartResult.second); } - while (!AbortFlag) + uint32_t FinalizeBuildPartRetryCount = 5; + while (!AbortFlag && (FinalizeBuildPartRetryCount--) > 0) { Stopwatch FinalizeBuildPartTimer; std::vector<IoHash> Needs = Storage.BuildStorage->FinalizeBuildPart(BuildId, BuildPartId, PartHash); @@ -8175,13 +8095,13 @@ namespace { return RemoteContent; } - ChunkedFolderContent GetLocalContent(GetFolderContentStatistics& LocalFolderScanStats, - ChunkingStatistics& ChunkingStats, - const std::filesystem::path& Path, - const std::filesystem::path& StateFilePath, - ChunkingController& ChunkController, - const ChunkedFolderContent& ReferenceContent, - FolderContent& OutLocalFolderContent) + ChunkedFolderContent GetLocalContent(GetFolderContentStatistics& LocalFolderScanStats, + ChunkingStatistics& ChunkingStats, + const std::filesystem::path& Path, + const std::filesystem::path& StateFilePath, + ChunkingController& ChunkController, + std::span<const std::filesystem::path> ReferencePaths, + FolderContent& OutLocalFolderContent) { FolderContent LocalFolderState; ChunkedFolderContent LocalContent; @@ -8193,7 +8113,7 @@ namespace { ZEN_CONSOLE("Read local state file {} in {}", StateFilePath, NiceTimeSpanMs(ReadStateTimer.GetElapsedTimeMs())); } { - const uint32_t LocalPathCount = gsl::narrow<uint32_t>(ReferenceContent.Paths.size()); + const uint32_t LocalPathCount = gsl::narrow<uint32_t>(ReferencePaths.size()); const uint32_t RemotePathCount = gsl::narrow<uint32_t>(LocalFolderState.Paths.size()); std::vector<std::filesystem::path> PathsToCheck; @@ -8208,7 +8128,7 @@ namespace { PathsToCheck.push_back(LocalPath); } - for (const std::filesystem::path& RemotePath : ReferenceContent.Paths) + for (const std::filesystem::path& RemotePath : ReferencePaths) { if (FileSet.insert(RemotePath.generic_string()).second) { @@ -8351,6 +8271,56 @@ namespace { return LocalContent; } + ChunkedFolderContent ScanAndChunkFolder( + GetFolderContentStatistics& GetFolderContentStats, + ChunkingStatistics& ChunkingStats, + const std::filesystem::path& Path, + std::function<bool(const std::string_view& RelativePath)>&& IsAcceptedFolder, + std::function<bool(std::string_view RelativePath, uint64_t Size, uint32_t Attributes)>&& IsAcceptedFile, + ChunkingController& ChunkController) + { + Stopwatch Timer; + + ZEN_TRACE_CPU("ScanAndChunkFolder"); + + FolderContent Content = GetFolderContent( + GetFolderContentStats, + Path, + std::move(IsAcceptedFolder), + std::move(IsAcceptedFile), + GetIOWorkerPool(), + UsePlainProgress ? 5000 : 200, + [](bool, std::ptrdiff_t) {}, + AbortFlag); + if (AbortFlag) + { + return {}; + } + + FolderContent _; + ChunkedFolderContent Result = GetLocalContent(GetFolderContentStats, + ChunkingStats, + Path, + ZenStateFilePath(Path / ZenFolderName), + ChunkController, + Content.Paths, + _); + + const uint64_t TotalRawSize = std::accumulate(Result.RawSizes.begin(), Result.RawSizes.end(), std::uint64_t(0)); + const uint64_t ChunkedRawSize = + std::accumulate(Result.ChunkedContent.ChunkRawSizes.begin(), Result.ChunkedContent.ChunkRawSizes.end(), std::uint64_t(0)); + + ZEN_CONSOLE("Found {} ({}) files divided into {} ({}) unique chunks in '{}' in {}. Average hash rate {}B/sec", + Result.Paths.size(), + NiceBytes(TotalRawSize), + Result.ChunkedContent.ChunkHashes.size(), + NiceBytes(ChunkedRawSize), + Path, + NiceTimeSpanMs(Timer.GetElapsedTimeMs()), + NiceNum(GetBytesPerSecond(ChunkingStats.ElapsedWallTimeUS, ChunkingStats.BytesHashed))); + return Result; + }; + void DownloadFolder(StorageInstance& Storage, const Oid& BuildId, const std::vector<Oid>& BuildPartIds, @@ -8415,7 +8385,7 @@ namespace { Path, ZenStateFilePath(ZenFolderPath), *ChunkController, - RemoteContent, + RemoteContent.Paths, LocalFolderContent); } } @@ -8712,7 +8682,7 @@ namespace { double KeptPercent = BaseTotalRawSize > 0 ? (100.0 * (BaseTotalRawSize - RemovedSize)) / BaseTotalRawSize : 0; - ZEN_CONSOLE("{} ({}) files removed, {} ({}) files added, {} ({} {:.1f}%) files kept", + ZEN_CONSOLE("File diff : {} ({}) removed, {} ({}) added, {} ({} {:.1f}%) kept", RemovedHashes.size(), NiceBytes(RemovedSize), AddedHashes.size(), @@ -8747,7 +8717,7 @@ namespace { double FoundPercent = CompareTotalRawSize > 0 ? (100.0 * FoundChunkSize) / CompareTotalRawSize : 0; double NewPercent = CompareTotalRawSize > 0 ? (100.0 * NewChunkSize) / CompareTotalRawSize : 0; - ZEN_CONSOLE("Found {} ({} {:.1f}%) out of {} ({}) chunks in {} ({}) base chunks. Added {} ({} {:.1f}%) chunks.", + ZEN_CONSOLE("Chunk diff: {} ({} {:.1f}%) out of {} ({}) chunks in {} ({}) base chunks. Added {} ({} {:.1f}%) chunks.", FoundChunkCount, NiceBytes(FoundChunkSize), FoundPercent, @@ -8769,7 +8739,7 @@ BuildsCommand::BuildsCommand() m_Options.add_options()("h,help", "Print help"); auto AddSystemOptions = [this](cxxopts::Options& Ops) { - Ops.add_option("", "", "system-dir", "Specify system root", cxxopts::value<std::string>(m_SystemRootDir), "<systemdir>"); + Ops.add_option("", "", "system-dir", "Specify system root", cxxopts::value(m_SystemRootDir), "<systemdir>"); }; auto AddAuthOptions = [this](cxxopts::Options& Ops) { @@ -8890,7 +8860,7 @@ BuildsCommand::BuildsCommand() Ops.add_option("", "", "boost-workers", - "Increase the number of worker threads - may cause computer to less responsive", + "Increase the number of worker threads - may cause computer to be less responsive", cxxopts::value(m_BoostWorkerThreads), "<boostworkers>"); }; @@ -9218,8 +9188,13 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) std::filesystem::path SystemRootDir; auto ParseSystemOptions = [&]() { - SystemRootDir = m_SystemRootDir.empty() ? PickDefaultSystemRootDirectory() : MakeSafeAbsolutePath(m_SystemRootDir); + if (m_SystemRootDir.empty()) + { + m_SystemRootDir = PickDefaultSystemRootDirectory(); + } + MakeSafeAbsolutePathÍnPlace(m_SystemRootDir); }; + ParseSystemOptions(); auto ParseStorageOptions = [&]() { if (!m_OverrideHost.empty() || !m_Host.empty()) @@ -9238,6 +9213,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { throw zen::OptionParseException(fmt::format("At least one storage option is required\n{}", m_UploadOptions.help())); } + MakeSafeAbsolutePathÍnPlace(m_StoragePath); }; std::unique_ptr<AuthMgr> Auth; @@ -9247,7 +9223,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) .RetryCount = 2}; auto CreateAuthMgr = [&]() { - ZEN_ASSERT(!SystemRootDir.empty()); + ZEN_ASSERT(!m_SystemRootDir.empty()); if (!Auth) { if (m_EncryptionKey.empty()) @@ -9262,7 +9238,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) ZEN_CONSOLE("Warning: Using default encryption initialization vector"); } - AuthConfig AuthMgrConfig = {.RootDirectory = SystemRootDir / "auth", + AuthConfig AuthMgrConfig = {.RootDirectory = m_SystemRootDir / "auth", .EncryptionKey = AesKey256Bit::FromString(m_EncryptionKey), .EncryptionIV = AesIV128Bit::FromString(m_EncryptionIV)}; if (!AuthMgrConfig.EncryptionKey.IsValid()) @@ -9278,7 +9254,6 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) }; auto ParseAuthOptions = [&]() { - ParseSystemOptions(); if (!m_OpenIdProviderUrl.empty() && !m_OpenIdClientId.empty()) { CreateAuthMgr(); @@ -9325,7 +9300,8 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) } else if (!m_AccessTokenPath.empty()) { - std::string ResolvedAccessToken = ReadAccessTokenFromFile(MakeSafeAbsolutePath(m_AccessTokenPath)); + MakeSafeAbsolutePathÍnPlace(m_AccessTokenPath); + std::string ResolvedAccessToken = ReadAccessTokenFromFile(m_AccessTokenPath); if (!ResolvedAccessToken.empty()) { ClientSettings.AccessTokenProvider = httpclientauth::CreateFromStaticToken(ResolvedAccessToken); @@ -9567,10 +9543,9 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) } else if (!m_StoragePath.empty()) { - std::filesystem::path StoragePath = MakeSafeAbsolutePath(m_StoragePath); - StorageDescription = fmt::format("folder {}", StoragePath); - Result.BuildStorage = CreateFileBuildStorage(StoragePath, StorageStats, false, DefaultLatency, DefaultDelayPerKBSec); - Result.StorageName = fmt::format("Disk {}", StoragePath.stem()); + StorageDescription = fmt::format("folder {}", m_StoragePath); + Result.BuildStorage = CreateFileBuildStorage(m_StoragePath, StorageStats, false, DefaultLatency, DefaultDelayPerKBSec); + Result.StorageName = fmt::format("Disk {}", m_StoragePath.stem()); } else { @@ -9614,6 +9589,137 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) return Result; }; + auto ParsePath = [&]() { + if (m_Path.empty()) + { + throw zen::OptionParseException(fmt::format("local-path is required\n{}", m_UploadOptions.help())); + } + MakeSafeAbsolutePathÍnPlace(m_Path); + }; + + auto ParseDiffPath = [&]() { + if (m_DiffPath.empty()) + { + throw zen::OptionParseException(fmt::format("compare-path is required\n{}", m_DownloadOptions.help())); + } + MakeSafeAbsolutePathÍnPlace(m_DiffPath); + }; + + auto ParseBlobHash = [&]() -> IoHash { + if (m_BlobHash.empty()) + { + throw zen::OptionParseException(fmt::format("Blob hash string is missing\n{}", m_UploadOptions.help())); + } + + IoHash BlobHash; + if (!IoHash::TryParse(m_BlobHash, BlobHash)) + { + throw zen::OptionParseException(fmt::format("Blob hash string is invalid\n{}", m_UploadOptions.help())); + } + + return BlobHash; + }; + + auto ParseBuildId = [&]() -> Oid { + if (m_BuildId.length() != Oid::StringLength) + { + throw zen::OptionParseException(fmt::format("Invalid build id\n{}", m_UploadOptions.help())); + } + else if (Oid BuildId = Oid::FromHexString(m_BuildId); BuildId == Oid::Zero) + { + throw zen::OptionParseException(fmt::format("Invalid build id\n{}", m_UploadOptions.help())); + } + else + { + return BuildId; + } + }; + + auto ParseBuildPartId = [&]() -> Oid { + if (m_BuildPartId.length() != Oid::StringLength) + { + throw zen::OptionParseException(fmt::format("Invalid build part id\n{}", m_UploadOptions.help())); + } + else if (Oid BuildPartId = Oid::FromHexString(m_BuildPartId); BuildPartId == Oid::Zero) + { + throw zen::OptionParseException(fmt::format("Invalid build part id\n{}", m_UploadOptions.help())); + } + else + { + return BuildPartId; + } + }; + + auto ParseBuildPartIds = [&]() -> std::vector<Oid> { + std::vector<Oid> BuildPartIds; + for (const std::string& BuildPartId : m_BuildPartIds) + { + BuildPartIds.push_back(Oid::TryFromHexString(BuildPartId)); + if (BuildPartIds.back() == Oid::Zero) + { + throw zen::OptionParseException(fmt::format("build-part-id '{}' is invalid\n{}", BuildPartId, m_DownloadOptions.help())); + } + } + return BuildPartIds; + }; + + auto ParseBuildMetadata = [&]() -> CbObject { + if (m_CreateBuild) + { + if (m_BuildMetadataPath.empty() && m_BuildMetadata.empty()) + { + throw zen::OptionParseException(fmt::format("Options for builds target are missing\n{}", m_UploadOptions.help())); + } + if (!m_BuildMetadataPath.empty() && !m_BuildMetadata.empty()) + { + throw zen::OptionParseException(fmt::format("Conflicting options for builds target\n{}", m_UploadOptions.help())); + } + + if (!m_BuildMetadataPath.empty()) + { + MakeSafeAbsolutePathÍnPlace(m_BuildMetadataPath); + IoBuffer MetaDataJson = ReadFile(m_BuildMetadataPath).Flatten(); + std::string_view Json(reinterpret_cast<const char*>(MetaDataJson.GetData()), MetaDataJson.GetSize()); + std::string JsonError; + CbObject MetaData = LoadCompactBinaryFromJson(Json, JsonError).AsObject(); + if (!JsonError.empty()) + { + throw std::runtime_error( + fmt::format("build metadata file '{}' is malformed. Reason: '{}'", m_BuildMetadataPath, JsonError)); + } + return MetaData; + } + if (!m_BuildMetadata.empty()) + { + CbObjectWriter MetaDataWriter(1024); + ForEachStrTok(m_BuildMetadata, ';', [&](std::string_view Pair) { + size_t SplitPos = Pair.find('='); + if (SplitPos == std::string::npos || SplitPos == 0) + { + throw std::runtime_error(fmt::format("build metadata key-value pair '{}' is malformed", Pair)); + } + MetaDataWriter.AddString(Pair.substr(0, SplitPos), Pair.substr(SplitPos + 1)); + return true; + }); + return MetaDataWriter.Save(); + } + } + else + { + if (!m_BuildMetadataPath.empty()) + { + throw zen::OptionParseException( + fmt::format("metadata-path option is only valid if creating a build\n{}", m_UploadOptions.help())); + } + if (!m_BuildMetadata.empty()) + { + throw zen::OptionParseException( + fmt::format("metadata option is only valid if creating a build\n{}", m_UploadOptions.help())); + } + } + return {}; + }; + BoostWorkerThreads = m_BoostWorkerThreads; try @@ -9671,6 +9777,9 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) if (SubOption == &m_ListOptions) { + MakeSafeAbsolutePathÍnPlace(m_ListQueryPath); + MakeSafeAbsolutePathÍnPlace(m_ListResultPath); + if (!m_ListResultPath.empty()) { ZEN_CONSOLE("Running {}: {}", GetRunningExecutablePath(), ZEN_CFG_VERSION_BUILD_STRING_FULL); @@ -9685,14 +9794,13 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) } else { - std::filesystem::path ListQueryPath = MakeSafeAbsolutePath(m_ListQueryPath); - if (ToLower(ListQueryPath.extension().string()) == ".cbo") + if (ToLower(m_ListQueryPath.extension().string()) == ".cbo") { - QueryObject = LoadCompactBinaryObject(IoBufferBuilder::MakeFromFile(ListQueryPath)); + QueryObject = LoadCompactBinaryObject(IoBufferBuilder::MakeFromFile(m_ListQueryPath)); } else { - IoBuffer MetaDataJson = ReadFile(ListQueryPath).Flatten(); + IoBuffer MetaDataJson = ReadFile(m_ListQueryPath).Flatten(); std::string_view Json(reinterpret_cast<const char*>(MetaDataJson.GetData()), MetaDataJson.GetSize()); std::string JsonError; QueryObject = LoadCompactBinaryFromJson(Json, JsonError).AsObject(); @@ -9707,19 +9815,22 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) BuildStorage::Statistics StorageStats; BuildStorageCache::Statistics StorageCacheStats; - const std::filesystem::path ZenFolderPath = m_ZenFolderPath.empty() - ? MakeSafeAbsolutePath(std::filesystem::current_path()) / ZenFolderName - : MakeSafeAbsolutePath(m_ZenFolderPath); - CreateDirectories(ZenFolderPath); - auto _ = MakeGuard([ZenFolderPath]() { - if (CleanDirectory(ZenFolderPath, {})) + if (m_ZenFolderPath.empty()) + { + m_ZenFolderPath = std::filesystem::current_path() / ZenFolderName; + } + MakeSafeAbsolutePathÍnPlace(m_ZenFolderPath); + + CreateDirectories(m_ZenFolderPath); + auto _ = MakeGuard([this]() { + if (CleanDirectory(m_ZenFolderPath, {})) { std::error_code DummyEc; - RemoveDir(ZenFolderPath, DummyEc); + RemoveDir(m_ZenFolderPath, DummyEc); } }); - StorageInstance Storage = CreateBuildStorage(StorageStats, StorageCacheStats, ZenTempFolderPath(ZenFolderPath)); + StorageInstance Storage = CreateBuildStorage(StorageStats, StorageCacheStats, ZenTempFolderPath(m_ZenFolderPath)); CbObject Response = Storage.BuildStorage->ListBuilds(QueryObject); ZEN_ASSERT(ValidateCompactBinary(Response.GetView(), CbValidateMode::All) == CbValidateError::None); @@ -9731,17 +9842,16 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) } else { - std::filesystem::path ListResultPath = MakeSafeAbsolutePath(m_ListResultPath); - if (ToLower(ListResultPath.extension().string()) == ".cbo") + if (ToLower(m_ListResultPath.extension().string()) == ".cbo") { MemoryView ResponseView = Response.GetView(); - WriteFile(ListResultPath, IoBuffer(IoBuffer::Wrap, ResponseView.GetData(), ResponseView.GetSize())); + WriteFile(m_ListResultPath, IoBuffer(IoBuffer::Wrap, ResponseView.GetData(), ResponseView.GetSize())); } else { ExtendableStringBuilder<1024> SB; CompactBinaryToJson(Response.GetView(), SB); - WriteFile(ListResultPath, IoBuffer(IoBuffer::Wrap, SB.Data(), SB.Size())); + WriteFile(m_ListResultPath, IoBuffer(IoBuffer::Wrap, SB.Data(), SB.Size())); } } @@ -9752,130 +9862,53 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { ZEN_CONSOLE("Running {}: {}", GetRunningExecutablePath(), ZEN_CFG_VERSION_BUILD_STRING_FULL); - if (m_Path.empty()) - { - throw zen::OptionParseException(fmt::format("local-path is required\n{}", m_UploadOptions.help())); - } - - if (m_CreateBuild) - { - if (m_BuildMetadataPath.empty() && m_BuildMetadata.empty()) - { - throw zen::OptionParseException(fmt::format("Options for builds target are missing\n{}", m_UploadOptions.help())); - } - if (!m_BuildMetadataPath.empty() && !m_BuildMetadata.empty()) - { - throw zen::OptionParseException(fmt::format("Conflicting options for builds target\n{}", m_UploadOptions.help())); - } - } - else - { - if (!m_BuildMetadataPath.empty()) - { - throw zen::OptionParseException( - fmt::format("metadata-path option is only valid if creating a build\n{}", m_UploadOptions.help())); - } - if (!m_BuildMetadata.empty()) - { - throw zen::OptionParseException( - fmt::format("metadata option is only valid if creating a build\n{}", m_UploadOptions.help())); - } - } - - std::filesystem::path Path = MakeSafeAbsolutePath(m_Path); + ParsePath(); if (m_BuildPartName.empty()) { - m_BuildPartName = Path.filename().string(); - } - - const bool GeneratedBuildId = m_BuildId.empty(); - if (GeneratedBuildId) - { - m_BuildId = Oid::NewOid().ToString(); - } - else if (m_BuildId.length() != Oid::StringLength) - { - throw zen::OptionParseException(fmt::format("Invalid build id\n{}", m_UploadOptions.help())); - } - else if (Oid::FromHexString(m_BuildId) == Oid::Zero) - { - throw zen::OptionParseException(fmt::format("Invalid build id\n{}", m_UploadOptions.help())); + m_BuildPartName = m_Path.filename().string(); } - const bool GeneratedBuildPartId = m_BuildPartId.empty(); - if (GeneratedBuildPartId) - { - m_BuildPartId = Oid::NewOid().ToString(); - } - else if (m_BuildPartId.length() != Oid::StringLength) + const Oid BuildId = m_BuildId.empty() ? Oid::NewOid() : ParseBuildId(); + if (m_BuildId.empty()) { - throw zen::OptionParseException(fmt::format("Invalid build id\n{}", m_UploadOptions.help())); + m_BuildId = BuildId.ToString(); } - else if (Oid::FromHexString(m_BuildPartId) == Oid::Zero) + const Oid BuildPartId = m_BuildPartId.empty() ? Oid::NewOid() : ParseBuildPartId(); + if (m_BuildPartId.empty()) { - throw zen::OptionParseException(fmt::format("Invalid build part id\n{}", m_UploadOptions.help())); + m_BuildPartId = BuildPartId.ToString(); } - const Oid BuildId = Oid::FromHexString(m_BuildId); - const Oid BuildPartId = Oid::FromHexString(m_BuildPartId); - BuildStorage::Statistics StorageStats; BuildStorageCache::Statistics StorageCacheStats; - const std::filesystem::path ZenFolderPath = m_ZenFolderPath.empty() - ? MakeSafeAbsolutePath(std::filesystem::current_path()) / ZenFolderName - : MakeSafeAbsolutePath(m_ZenFolderPath); - CreateDirectories(ZenFolderPath); - auto _ = MakeGuard([ZenFolderPath]() { - if (CleanDirectory(ZenFolderPath, {})) + if (m_ZenFolderPath.empty()) + { + m_ZenFolderPath = std::filesystem::current_path() / ZenFolderName; + } + MakeSafeAbsolutePathÍnPlace(m_ZenFolderPath); + + CreateDirectories(m_ZenFolderPath); + auto _ = MakeGuard([this]() { + if (CleanDirectory(m_ZenFolderPath, {})) { std::error_code DummyEc; - RemoveDir(ZenFolderPath, DummyEc); + RemoveDir(m_ZenFolderPath, DummyEc); } }); - StorageInstance Storage = CreateBuildStorage(StorageStats, StorageCacheStats, ZenTempFolderPath(ZenFolderPath)); + StorageInstance Storage = CreateBuildStorage(StorageStats, StorageCacheStats, ZenTempFolderPath(m_ZenFolderPath)); - CbObject MetaData; - if (m_CreateBuild) - { - if (!m_BuildMetadataPath.empty()) - { - std::filesystem::path MetadataPath = MakeSafeAbsolutePath(m_BuildMetadataPath); - IoBuffer MetaDataJson = ReadFile(MetadataPath).Flatten(); - std::string_view Json(reinterpret_cast<const char*>(MetaDataJson.GetData()), MetaDataJson.GetSize()); - std::string JsonError; - MetaData = LoadCompactBinaryFromJson(Json, JsonError).AsObject(); - if (!JsonError.empty()) - { - throw std::runtime_error( - fmt::format("build metadata file '{}' is malformed. Reason: '{}'", m_BuildMetadataPath, JsonError)); - } - } - if (!m_BuildMetadata.empty()) - { - CbObjectWriter MetaDataWriter(1024); - ForEachStrTok(m_BuildMetadata, ';', [&](std::string_view Pair) { - size_t SplitPos = Pair.find('='); - if (SplitPos == std::string::npos || SplitPos == 0) - { - throw std::runtime_error(fmt::format("build metadata key-value pair '{}' is malformed", Pair)); - } - MetaDataWriter.AddString(Pair.substr(0, SplitPos), Pair.substr(SplitPos + 1)); - return true; - }); - MetaData = MetaDataWriter.Save(); - } - } + CbObject MetaData = ParseBuildMetadata(); UploadFolder(Storage, BuildId, BuildPartId, m_BuildPartName, - Path, - ZenFolderPath, - m_ManifestPath.empty() ? std::filesystem::path{} : MakeSafeAbsolutePath(m_ManifestPath), + m_Path, + m_ZenFolderPath, + m_ManifestPath, m_FindBlockMaxCount, m_BlockReuseMinPercentLimit, m_AllowMultiparts, @@ -9911,26 +9944,9 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { ZEN_CONSOLE("Running {}: {}", GetRunningExecutablePath(), ZEN_CFG_VERSION_BUILD_STRING_FULL); - ParseSystemOptions(); - - if (m_Path.empty()) - { - throw zen::OptionParseException(fmt::format("local-path is required\n{}", m_DownloadOptions.help())); - } - if (m_BuildId.empty()) - { - throw zen::OptionParseException(fmt::format("build-id is required\n{}", m_DownloadOptions.help())); - } - Oid BuildId = Oid::TryFromHexString(m_BuildId); - if (BuildId == Oid::Zero) - { - throw zen::OptionParseException(fmt::format("build-id is invalid\n{}", m_DownloadOptions.help())); - } + ParsePath(); - if (!m_BuildPartName.empty() && !m_BuildPartId.empty()) - { - throw zen::OptionParseException(fmt::format("build-part-id conflicts with build-part-name\n{}", m_DownloadOptions.help())); - } + const Oid BuildId = ParseBuildId(); if (m_PostDownloadVerify && m_PrimeCacheOnly) { @@ -9948,34 +9964,26 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) ZEN_WARN("ignoring 'allow-partial-block-requests' option when 'cache-prime-only' is enabled"); } - std::vector<Oid> BuildPartIds; - for (const std::string& BuildPartId : m_BuildPartIds) + std::vector<Oid> BuildPartIds = ParseBuildPartIds(); + + if (m_ZenFolderPath.empty()) { - BuildPartIds.push_back(Oid::TryFromHexString(BuildPartId)); - if (BuildPartIds.back() == Oid::Zero) - { - throw zen::OptionParseException( - fmt::format("build-part-id '{}' is invalid\n{}", BuildPartId, m_DownloadOptions.help())); - } + m_ZenFolderPath = m_Path / ZenFolderName; } - - std::filesystem::path Path = MakeSafeAbsolutePath(m_Path); + MakeSafeAbsolutePathÍnPlace(m_ZenFolderPath); BuildStorage::Statistics StorageStats; BuildStorageCache::Statistics StorageCacheStats; - const std::filesystem::path ZenFolderPath = - m_ZenFolderPath.empty() ? Path / ZenFolderName : MakeSafeAbsolutePath(m_ZenFolderPath); - - StorageInstance Storage = CreateBuildStorage(StorageStats, StorageCacheStats, ZenTempFolderPath(ZenFolderPath)); + StorageInstance Storage = CreateBuildStorage(StorageStats, StorageCacheStats, ZenTempFolderPath(m_ZenFolderPath)); DownloadFolder(Storage, BuildId, BuildPartIds, m_BuildPartNames, - Path, - ZenFolderPath, - SystemRootDir, + m_Path, + m_ZenFolderPath, + m_SystemRootDir, m_AllowMultiparts, m_AllowPartialBlockRequests && !m_PrimeCacheOnly, m_Clean, @@ -9983,79 +9991,43 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) m_PrimeCacheOnly, m_EnableScavenging); - if (false) - { - ZEN_CONSOLE( - "{}:\n" - "Read: {}\n" - "Write: {}\n" - "Requests: {}\n" - "Avg Request Time: {}\n" - "Avg I/O Time: {}", - Storage.StorageName, - NiceBytes(StorageStats.TotalBytesRead.load()), - NiceBytes(StorageStats.TotalBytesWritten.load()), - StorageStats.TotalRequestCount.load(), - StorageStats.TotalExecutionTimeUs.load() > 0 - ? NiceTimeSpanMs(StorageStats.TotalExecutionTimeUs.load() / 1000 / StorageStats.TotalRequestCount.load()) - : 0, - StorageStats.TotalRequestCount.load() > 0 - ? NiceTimeSpanMs(StorageStats.TotalRequestTimeUs.load() / 1000 / StorageStats.TotalRequestCount.load()) - : 0); - } - return AbortFlag ? 11 : 0; } if (SubOption == &m_DiffOptions) { - if (m_Path.empty()) - { - throw zen::OptionParseException(fmt::format("local-path is required\n{}", m_DownloadOptions.help())); - } - if (m_DiffPath.empty()) - { - throw zen::OptionParseException(fmt::format("compare-path is required\n{}", m_DownloadOptions.help())); - } - std::filesystem::path Path = MakeSafeAbsolutePath(m_Path); - std::filesystem::path DiffPath = MakeSafeAbsolutePath(m_DiffPath); - DiffFolders(Path, DiffPath, m_OnlyChunked); + ParsePath(); + ParseDiffPath(); + + DiffFolders(m_Path, m_DiffPath, m_OnlyChunked); return AbortFlag ? 11 : 0; } if (SubOption == &m_FetchBlobOptions) { ZEN_CONSOLE("Running {}: {}", GetRunningExecutablePath(), ZEN_CFG_VERSION_BUILD_STRING_FULL); - if (m_BlobHash.empty()) - { - throw zen::OptionParseException(fmt::format("Blob hash string is missing\n{}", m_UploadOptions.help())); - } - - IoHash BlobHash; - if (!IoHash::TryParse(m_BlobHash, BlobHash)) - { - throw zen::OptionParseException(fmt::format("Blob hash string is invalid\n{}", m_UploadOptions.help())); - } + IoHash BlobHash = ParseBlobHash(); const Oid BuildId = Oid::FromHexString(m_BuildId); - std::filesystem::path Path = MakeSafeAbsolutePath(m_Path); - BuildStorage::Statistics StorageStats; BuildStorageCache::Statistics StorageCacheStats; - const std::filesystem::path ZenFolderPath = m_ZenFolderPath.empty() - ? MakeSafeAbsolutePath(std::filesystem::current_path()) / ZenFolderName - : MakeSafeAbsolutePath(m_ZenFolderPath); - CreateDirectories(ZenFolderPath); - auto _ = MakeGuard([ZenFolderPath]() { - if (CleanDirectory(ZenFolderPath, {})) + if (m_ZenFolderPath.empty()) + { + m_ZenFolderPath = std::filesystem::current_path() / ZenFolderName; + } + MakeSafeAbsolutePathÍnPlace(m_ZenFolderPath); + + CreateDirectories(m_ZenFolderPath); + auto _ = MakeGuard([this]() { + if (CleanDirectory(m_ZenFolderPath, {})) { std::error_code DummyEc; - RemoveDir(ZenFolderPath, DummyEc); + RemoveDir(m_ZenFolderPath, DummyEc); } }); - StorageInstance Storage = CreateBuildStorage(StorageStats, StorageCacheStats, ZenTempFolderPath(ZenFolderPath)); + StorageInstance Storage = CreateBuildStorage(StorageStats, StorageCacheStats, ZenTempFolderPath(m_ZenFolderPath)); uint64_t CompressedSize; uint64_t DecompressedSize; @@ -10075,41 +10047,34 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { ZEN_CONSOLE("Running {}: {}", GetRunningExecutablePath(), ZEN_CFG_VERSION_BUILD_STRING_FULL); - if (m_BuildId.empty()) - { - throw zen::OptionParseException(fmt::format("build-id is required\n{}", m_DownloadOptions.help())); - } - Oid BuildId = Oid::TryFromHexString(m_BuildId); - if (BuildId == Oid::Zero) - { - throw zen::OptionParseException(fmt::format("build-id is invalid\n{}", m_DownloadOptions.help())); - } + Oid BuildId = ParseBuildId(); if (!m_BuildPartName.empty() && !m_BuildPartId.empty()) { throw zen::OptionParseException(fmt::format("build-part-id conflicts with build-part-name\n{}", m_DownloadOptions.help())); } - std::filesystem::path Path = MakeSafeAbsolutePath(m_Path); - BuildStorage::Statistics StorageStats; BuildStorageCache::Statistics StorageCacheStats; - const std::filesystem::path ZenFolderPath = m_ZenFolderPath.empty() - ? MakeSafeAbsolutePath(std::filesystem::current_path()) / ZenFolderName - : MakeSafeAbsolutePath(m_ZenFolderPath); - CreateDirectories(ZenFolderPath); - auto _ = MakeGuard([ZenFolderPath]() { - if (CleanDirectory(ZenFolderPath, {})) + if (m_ZenFolderPath.empty()) + { + m_ZenFolderPath = std::filesystem::current_path() / ZenFolderName; + } + MakeSafeAbsolutePathÍnPlace(m_ZenFolderPath); + + CreateDirectories(m_ZenFolderPath); + auto _ = MakeGuard([this]() { + if (CleanDirectory(m_ZenFolderPath, {})) { std::error_code DummyEc; - RemoveDir(ZenFolderPath, DummyEc); + RemoveDir(m_ZenFolderPath, DummyEc); } }); - StorageInstance Storage = CreateBuildStorage(StorageStats, StorageCacheStats, ZenTempFolderPath(ZenFolderPath)); + StorageInstance Storage = CreateBuildStorage(StorageStats, StorageCacheStats, ZenTempFolderPath(m_ZenFolderPath)); - Oid BuildPartId = Oid::TryFromHexString(m_BuildPartId); + const Oid BuildPartId = m_BuildPartName.empty() ? Oid::Zero : ParseBuildPartId(); ValidateStatistics ValidateStats; DownloadStatistics DownloadStats; @@ -10120,35 +10085,23 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) if (SubOption == &m_MultiTestDownloadOptions) { - SystemRootDir = (GetRunningExecutablePath().parent_path() / ".tmpzensystem").make_preferred(); - CreateDirectories(SystemRootDir); - CleanDirectory(SystemRootDir, {}); - auto _ = MakeGuard([&]() { DeleteDirectories(SystemRootDir); }); + m_SystemRootDir = (GetRunningExecutablePath().parent_path() / ".tmpzensystem").make_preferred(); + CreateDirectories(m_SystemRootDir); + CleanDirectory(m_SystemRootDir, {}); + auto _ = MakeGuard([&]() { DeleteDirectories(m_SystemRootDir); }); + + ParsePath(); - if (m_Path.empty()) + if (m_ZenFolderPath.empty()) { - throw zen::OptionParseException(fmt::format("local-path is required\n{}", m_DownloadOptions.help())); + m_ZenFolderPath = m_Path / ZenFolderName; } - - // m_StoragePath = "D:\\buildstorage"; - // m_Path = "F:\\Saved\\DownloadedBuilds\\++Fortnite+Main-CL-XXXXXXXX\\WindowsClient"; - // std::vector<std::string> BuildIdStrings{"07d3942f0e7f4ca1b13b0587", - // "07d394eed89d769f2254e75d", - // "07d3953f22fa3f8000fa6f0a", - // "07d3959df47ed1f42ddbe44c", - // "07d395fa7803d50804f14417", - // "07d3964f919d577a321a1fdd", - // "07d396a6ce875004e16b9528"}; - - std::filesystem::path Path = MakeSafeAbsolutePath(m_Path); + MakeSafeAbsolutePathÍnPlace(m_ZenFolderPath); BuildStorage::Statistics StorageStats; BuildStorageCache::Statistics StorageCacheStats; - const std::filesystem::path ZenFolderPath = - m_ZenFolderPath.empty() ? Path / ZenFolderName : MakeSafeAbsolutePath(m_ZenFolderPath); - - StorageInstance Storage = CreateBuildStorage(StorageStats, StorageCacheStats, ZenTempFolderPath(ZenFolderPath)); + StorageInstance Storage = CreateBuildStorage(StorageStats, StorageCacheStats, ZenTempFolderPath(m_ZenFolderPath)); Stopwatch Timer; for (const std::string& BuildIdString : m_BuildIds) @@ -10162,9 +10115,9 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) BuildId, {}, {}, - Path, - ZenFolderPath, - SystemRootDir, + m_Path, + m_ZenFolderPath, + m_SystemRootDir, m_AllowMultiparts, m_AllowPartialBlockRequests, BuildIdString == m_BuildIds.front(), @@ -10184,47 +10137,41 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) if (SubOption == &m_TestOptions) { - SystemRootDir = (GetRunningExecutablePath().parent_path() / ".tmpzensystem").make_preferred(); - CreateDirectories(SystemRootDir); - CleanDirectory(SystemRootDir, {}); - auto _ = MakeGuard([&]() { DeleteDirectories(SystemRootDir); }); - - if (m_Path.empty()) - { - throw zen::OptionParseException(fmt::format("local-path is required\n{}", m_DownloadOptions.help())); - } + m_SystemRootDir = (GetRunningExecutablePath().parent_path() / ".tmpzensystem").make_preferred(); + CreateDirectories(m_SystemRootDir); + CleanDirectory(m_SystemRootDir, {}); + auto _ = MakeGuard([&]() { DeleteDirectories(m_SystemRootDir); }); - std::filesystem::path Path = MakeSafeAbsolutePath(m_Path); + ParsePath(); m_BuildId = Oid::NewOid().ToString(); - m_BuildPartName = Path.filename().string(); + m_BuildPartName = m_Path.filename().string(); m_BuildPartId = Oid::NewOid().ToString(); m_CreateBuild = true; const Oid BuildId = Oid::FromHexString(m_BuildId); const Oid BuildPartId = Oid::FromHexString(m_BuildPartId); - std::filesystem::path StoragePath = MakeSafeAbsolutePath(m_StoragePath); - - if (m_OverrideHost.empty() && StoragePath.empty()) + if (m_OverrideHost.empty() && m_StoragePath.empty()) { - StoragePath = (GetRunningExecutablePath().parent_path() / ".tmpstore").make_preferred(); - CreateDirectories(StoragePath); - CleanDirectory(StoragePath, {}); - m_StoragePath = StoragePath.generic_string(); + m_StoragePath = (GetRunningExecutablePath().parent_path() / ".tmpstore").make_preferred(); + CreateDirectories(m_StoragePath); + CleanDirectory(m_StoragePath, {}); + m_StoragePath = m_StoragePath.generic_string(); } + auto __ = MakeGuard([&]() { - if (m_OverrideHost.empty() && StoragePath.empty()) + if (m_OverrideHost.empty() && m_StoragePath.empty()) { - DeleteDirectories(StoragePath); + DeleteDirectories(m_StoragePath); } }); BuildStorage::Statistics StorageStats; BuildStorageCache::Statistics StorageCacheStats; - const std::filesystem::path DownloadPath = Path.parent_path() / (m_BuildPartName + "_test"); - const std::filesystem::path DownloadPath2 = Path.parent_path() / (m_BuildPartName + "_test2"); + const std::filesystem::path DownloadPath = m_Path.parent_path() / (m_BuildPartName + "_test"); + const std::filesystem::path DownloadPath2 = m_Path.parent_path() / (m_BuildPartName + "_test2"); auto ___ = MakeGuard([DownloadPath, DownloadPath2]() { CleanDirectory(DownloadPath, true); @@ -10233,10 +10180,13 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) DeleteDirectories(DownloadPath2); }); - const std::filesystem::path ZenFolderPath = - m_ZenFolderPath.empty() ? DownloadPath / ZenFolderName : MakeSafeAbsolutePath(m_ZenFolderPath); + if (m_ZenFolderPath.empty()) + { + m_ZenFolderPath = m_Path / ZenFolderName; + } + MakeSafeAbsolutePathÍnPlace(m_ZenFolderPath); - StorageInstance Storage = CreateBuildStorage(StorageStats, StorageCacheStats, ZenTempFolderPath(ZenFolderPath)); + StorageInstance Storage = CreateBuildStorage(StorageStats, StorageCacheStats, ZenTempFolderPath(m_ZenFolderPath)); auto MakeMetaData = [](const Oid& BuildId) -> CbObject { CbObjectWriter BuildMetaDataWriter; @@ -10263,8 +10213,8 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) BuildId, BuildPartId, m_BuildPartName, - Path, - ZenFolderPath, + m_Path, + m_ZenFolderPath, {}, m_FindBlockMaxCount, m_BlockReuseMinPercentLimit, @@ -10285,8 +10235,8 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) {BuildPartId}, {}, DownloadPath, - ZenFolderPath, - SystemRootDir, + DownloadPath / ZenFolderName, + m_SystemRootDir, m_AllowMultiparts, m_AllowPartialBlockRequests, true, @@ -10309,8 +10259,8 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) {BuildPartId}, {}, DownloadPath, - ZenFolderPath, - SystemRootDir, + DownloadPath / ZenFolderName, + m_SystemRootDir, m_AllowMultiparts, m_AllowPartialBlockRequests, false, @@ -10428,8 +10378,8 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) {BuildPartId}, {}, DownloadPath, - ZenFolderPath, - SystemRootDir, + DownloadPath / ZenFolderName, + m_SystemRootDir, m_AllowMultiparts, m_AllowPartialBlockRequests, false, @@ -10459,7 +10409,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) BuildPartId2, m_BuildPartName, DownloadPath, - ZenFolderPath, + m_ZenFolderPath, {}, m_FindBlockMaxCount, m_BlockReuseMinPercentLimit, @@ -10480,8 +10430,8 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) {BuildPartId}, {}, DownloadPath, - ZenFolderPath, - SystemRootDir, + DownloadPath / ZenFolderName, + m_SystemRootDir, m_AllowMultiparts, m_AllowPartialBlockRequests, false, @@ -10500,8 +10450,8 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) {BuildPartId2}, {}, DownloadPath, - ZenFolderPath, - SystemRootDir, + DownloadPath / ZenFolderName, + m_SystemRootDir, m_AllowMultiparts, m_AllowPartialBlockRequests, false, @@ -10520,8 +10470,8 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) {BuildPartId2}, {}, DownloadPath, - ZenFolderPath, - SystemRootDir, + DownloadPath / ZenFolderName, + m_SystemRootDir, m_AllowMultiparts, m_AllowPartialBlockRequests, false, @@ -10540,8 +10490,8 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) {BuildPartId}, {}, DownloadPath2, - ZenFolderPath, - SystemRootDir, + DownloadPath2 / ZenFolderName, + m_SystemRootDir, m_AllowMultiparts, m_AllowPartialBlockRequests, false, |