aboutsummaryrefslogtreecommitdiff
path: root/src/zen/cmds/projectstore_cmd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/zen/cmds/projectstore_cmd.cpp')
-rw-r--r--src/zen/cmds/projectstore_cmd.cpp301
1 files changed, 162 insertions, 139 deletions
diff --git a/src/zen/cmds/projectstore_cmd.cpp b/src/zen/cmds/projectstore_cmd.cpp
index d31c34fd0..c6a3434f8 100644
--- a/src/zen/cmds/projectstore_cmd.cpp
+++ b/src/zen/cmds/projectstore_cmd.cpp
@@ -2,16 +2,21 @@
#include "projectstore_cmd.h"
+#include "zenserviceclient.h"
+
#include <zencore/basicfile.h>
#include <zencore/compactbinarybuilder.h>
#include <zencore/compactbinaryutil.h>
#include <zencore/compress.h>
+#include <zencore/except_fmt.h>
#include <zencore/filesystem.h>
#include <zencore/fmtutils.h>
#include <zencore/logging.h>
+#include <zencore/logging/broadcastsink.h>
#include <zencore/parallelwork.h>
#include <zencore/process.h>
#include <zencore/scopeguard.h>
+#include <zencore/session.h>
#include <zencore/stream.h>
#include <zencore/timer.h>
#include <zencore/workthreadpool.h>
@@ -21,16 +26,20 @@
#include <zenhttp/httpclientauth.h>
#include <zenhttp/httpcommon.h>
#include <zenremotestore/builds/buildstoragecache.h>
+#include <zenremotestore/builds/buildstorageresolve.h>
#include <zenremotestore/builds/buildstorageutil.h>
#include <zenremotestore/builds/jupiterbuildstorage.h>
#include <zenremotestore/jupiter/jupiterhost.h>
-#include <zenremotestore/operationlogoutput.h>
#include <zenremotestore/projectstore/projectstoreoperations.h>
#include <zenremotestore/projectstore/remoteprojectstore.h>
#include <zenremotestore/transferthreadworkers.h>
+#include <zenutil/authutils.h>
+#include <zenutil/logging.h>
+#include <zenutil/progress.h>
+#include <zenutil/sessionsclient.h>
#include <zenutil/workerpools.h>
-#include "../progressbar.h"
+#include "consoleprogress.h"
ZEN_THIRD_PARTY_INCLUDES_START
#include <json11.hpp>
@@ -112,6 +121,26 @@ namespace projectstore_impl {
}
}
+ // `OplogMirrorCommand::Run` uses a latching boolean flag rather than the
+ // SignalCounter above, because it drives a worker pool that aborts on any
+ // interrupt. Kept separate from SignalCallbackHandler so neither interferes
+ // with the other when both are installed in the same process.
+ static std::atomic<bool> MirrorAbortFlag{false};
+
+ static void MirrorSignalCallbackHandler(int SigNum)
+ {
+ if (SigNum == SIGINT)
+ {
+ MirrorAbortFlag.store(true);
+ }
+#if ZEN_PLATFORM_WINDOWS
+ if (SigNum == SIGBREAK)
+ {
+ MirrorAbortFlag.store(true);
+ }
+#endif
+ }
+
void ExecuteAsyncOperation(HttpClient& Http, std::string_view Url, IoBuffer&& Payload, bool PlainProgress)
{
signal(SIGINT, SignalCallbackHandler);
@@ -131,13 +160,16 @@ namespace projectstore_impl {
throw std::runtime_error(fmt::format("invalid job id returned, received '{}'", JobIdText));
}
- ProgressBar ProgressBar(PlainProgress ? ProgressBar::Mode::Plain : ProgressBar::Mode::Pretty, ""sv);
+ std::unique_ptr<ProgressBase> ProgressOwner(
+ CreateConsoleProgress(PlainProgress ? ConsoleProgressMode::Plain : ConsoleProgressMode::Pretty));
+ std::unique_ptr<ProgressBase::ProgressBar> Bar = ProgressOwner->CreateProgressBar(""sv);
+ std::string ActiveTask;
- auto OuputMessages = [&](CbObjectView StatusObject) {
+ auto OutputMessages = [&](CbObjectView StatusObject) {
CbArrayView Messages = StatusObject["Messages"sv].AsArrayView();
if (Messages.Num() > 0)
{
- ProgressBar.ForceLinebreak();
+ Bar->ForceLinebreak();
for (auto M : Messages)
{
std::string_view Message = M.AsString();
@@ -169,33 +201,36 @@ namespace projectstore_impl {
uint64_t RemainingCount = StatusObject["RemainingCount"sv].AsUInt64();
uint64_t ProgressElapsedTimeMs = StatusObject["ProgressElapsedTimeMs"sv].AsUInt64((uint64_t)-1);
- if (!ProgressBar.IsSameTask(CurrentOp))
+ if (ActiveTask != CurrentOp)
{
- ProgressBar.Finish();
+ Bar->Finish();
+ ActiveTask = "";
}
- if (!ProgressBar.HasActiveTask())
+ if (ActiveTask.empty())
{
- OuputMessages(StatusObject);
+ OutputMessages(StatusObject);
MessagesDone = true;
+ ActiveTask = std::string(CurrentOp);
}
- ProgressBar.UpdateState({.Task = std::string(CurrentOp),
- .Details = std::string(CurrentOpDetails),
- .TotalCount = TotalCount,
- .RemainingCount = RemainingCount,
- .OptionalElapsedTime = ProgressElapsedTimeMs},
- false);
+ Bar->UpdateState({.Task = std::string(CurrentOp),
+ .Details = std::string(CurrentOpDetails),
+ .TotalCount = TotalCount,
+ .RemainingCount = RemainingCount,
+ .OptionalElapsedTime = ProgressElapsedTimeMs},
+ false);
}
if ((Status == "Complete") || (Status == "Aborted"))
{
- ProgressBar.Finish();
+ Bar->Finish();
+ ActiveTask = "";
}
if (!MessagesDone)
{
- OuputMessages(StatusObject);
+ OutputMessages(StatusObject);
}
if (Status == "Complete")
@@ -246,13 +281,13 @@ namespace projectstore_impl {
#endif // ZEN_PLATFORM_WINDOWS
if (HttpClient::Response DeleteResult = Http.Delete(fmt::format("/admin/jobs/{}", JobId)))
{
- ProgressBar.ForceLinebreak();
+ Bar->ForceLinebreak();
ZEN_CONSOLE("Requested cancel...");
Cancelled = true;
}
else
{
- ProgressBar.ForceLinebreak();
+ Bar->ForceLinebreak();
ZEN_CONSOLE("Failed cancelling job {}", DeleteResult);
}
continue;
@@ -530,14 +565,8 @@ DropProjectCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
return;
}
- m_HostName = ResolveTargetHostSpec(m_HostName);
-
- if (m_HostName.empty())
- {
- throw OptionParseException("Unable to resolve server specification", m_Options.help());
- }
-
- HttpClient Http = CreateHttpClient(m_HostName);
+ ZenServiceClient Service({.HostSpec = m_HostName, .CommandName = Name});
+ HttpClient& Http = Service.Http();
m_ProjectName = ResolveProject(Http, m_ProjectName);
if (m_ProjectName.empty())
@@ -569,7 +598,7 @@ DropProjectCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
m_OplogName = ResolveOplog(Http, m_ProjectName, m_OplogName);
if (m_OplogName.empty())
{
- throw std::runtime_error(fmt::format("Can't find oplog in project '{}'", m_OplogName, m_ProjectName));
+ throw zen::runtime_error("Can't find oplog '{}' in project '{}'", m_OplogName, m_ProjectName);
}
if (m_DryRun)
{
@@ -620,19 +649,13 @@ ProjectInfoCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
return;
}
- m_HostName = ResolveTargetHostSpec(m_HostName);
-
- if (m_HostName.empty())
- {
- throw OptionParseException("Unable to resolve server specification", m_Options.help());
- }
-
if (!m_OplogName.empty() && m_ProjectName.empty())
{
throw OptionParseException("'--project' is required", m_Options.help());
}
- HttpClient Http = CreateHttpClient(m_HostName);
+ ZenServiceClient Service({.HostSpec = m_HostName, .CommandName = Name});
+ HttpClient& Http = Service.Http();
std::string Url;
if (m_ProjectName.empty())
@@ -709,19 +732,13 @@ CreateProjectCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** a
return;
}
- m_HostName = ResolveTargetHostSpec(m_HostName);
-
- if (m_HostName.empty())
- {
- throw OptionParseException("Unable to resolve server specification", m_Options.help());
- }
-
if (m_ProjectId.empty())
{
throw OptionParseException("'--project' is required", m_Options.help());
}
- HttpClient Http = CreateHttpClient(m_HostName);
+ ZenServiceClient Service({.HostSpec = m_HostName, .CommandName = Name});
+ HttpClient& Http = Service.Http();
std::string Url = fmt::format("/prj/{}", m_ProjectId);
@@ -779,20 +796,14 @@ CreateOplogCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
return;
}
- m_HostName = ResolveTargetHostSpec(m_HostName);
-
- if (m_HostName.empty())
- {
- throw OptionParseException("Unable to resolve server specification", m_Options.help());
- }
-
if (m_ProjectId.empty())
{
throw OptionParseException("'--project' is required", m_Options.help());
}
- HttpClient Http = CreateHttpClient(m_HostName);
- m_ProjectId = ResolveProject(Http, m_ProjectId);
+ ZenServiceClient Service({.HostSpec = m_HostName, .CommandName = Name});
+ HttpClient& Http = Service.Http();
+ m_ProjectId = ResolveProject(Http, m_ProjectId);
if (m_ProjectId.empty())
{
throw std::runtime_error("Project can not be found");
@@ -1010,20 +1021,14 @@ ExportOplogCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
m_BoostWorkerMemory = true;
}
- m_HostName = ResolveTargetHostSpec(m_HostName);
-
- if (m_HostName.empty())
- {
- throw OptionParseException("Unable to resolve server specification", m_Options.help());
- }
-
if (m_ProjectName.empty())
{
throw OptionParseException("'--project' is required", m_Options.help());
}
- HttpClient Http = CreateHttpClient(m_HostName);
- m_ProjectName = ResolveProject(Http, m_ProjectName);
+ ZenServiceClient Service({.HostSpec = m_HostName, .CommandName = Name});
+ HttpClient& Http = Service.Http();
+ m_ProjectName = ResolveProject(Http, m_ProjectName);
if (m_ProjectName.empty())
{
throw std::runtime_error("Project can not be found");
@@ -1114,7 +1119,7 @@ ExportOplogCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
std::string TargetUrlBase = m_ZenUrl;
if (TargetUrlBase.find("://") == std::string::npos)
{
- // Assume https URL
+ // Assume http URL
TargetUrlBase = fmt::format("http://{}", TargetUrlBase);
}
@@ -1303,7 +1308,14 @@ ExportOplogCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
std::filesystem::path MetadataPath(m_BuildsMetadataPath);
IoBuffer MetaDataJson = ReadFile(MetadataPath).Flatten();
std::string_view Json(reinterpret_cast<const char*>(MetaDataJson.GetData()), MetaDataJson.GetSize());
- CbFieldIterator MetaData = LoadCompactBinaryFromJson(Json);
+ std::string JsonError;
+ CbFieldIterator MetaData = LoadCompactBinaryFromJson(Json, JsonError);
+ if (!JsonError.empty())
+ {
+ throw zen::runtime_error("builds metadata file '{}' is malformed. Reason: '{}'",
+ MetadataPath.string(),
+ JsonError);
+ }
Writer.AddBinary("metadata"sv, MetaData.GetBuffer());
}
if (!m_BuildsMetadata.empty())
@@ -1313,7 +1325,7 @@ ExportOplogCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
size_t SplitPos = Pair.find('=');
if (SplitPos == std::string::npos || SplitPos == 0)
{
- throw std::runtime_error(fmt::format("builds metadata key-value pair '{}' is malformed", Pair));
+ throw zen::runtime_error("builds metadata key-value pair '{}' is malformed", Pair);
}
MetaDataWriter.AddString(Pair.substr(0, SplitPos), Pair.substr(SplitPos + 1));
return true;
@@ -1323,7 +1335,7 @@ ExportOplogCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
}
}
Writer.EndObject(); // "builds"
- TargetDescription = fmt::format("[builds] {}/{}/{}/{}", m_CloudUrl, m_JupiterNamespace, m_JupiterBucket, m_BuildsId);
+ TargetDescription = fmt::format("[builds] {}/{}/{}/{}", m_BuildsUrl, m_JupiterNamespace, m_JupiterBucket, m_BuildsId);
}
if (!m_ZenUrl.empty())
{
@@ -1517,13 +1529,6 @@ ImportOplogCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
m_BoostWorkerMemory = true;
}
- m_HostName = ResolveTargetHostSpec(m_HostName);
-
- if (m_HostName.empty())
- {
- throw OptionParseException("Unable to resolve server specification", m_Options.help());
- }
-
if (m_ProjectName.empty())
{
throw OptionParseException("'--project' is required", m_Options.help());
@@ -1541,8 +1546,9 @@ ImportOplogCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
m_Options.help());
}
- HttpClient Http = CreateHttpClient(m_HostName);
- m_ProjectName = ResolveProject(Http, m_ProjectName);
+ ZenServiceClient Service({.HostSpec = m_HostName, .CommandName = Name});
+ HttpClient& Http = Service.Http();
+ m_ProjectName = ResolveProject(Http, m_ProjectName);
if (m_ProjectName.empty())
{
throw std::runtime_error("Project can not be found");
@@ -1738,7 +1744,11 @@ ImportOplogCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
}
}
Writer.EndObject(); // "builds"
- SourceDescription = fmt::format("[builds] {}/{}/{}/{}", m_CloudUrl, m_JupiterNamespace, m_JupiterBucket, m_BuildsId);
+ SourceDescription = fmt::format("[builds] {}/{}/{}/{}",
+ m_BuildsHost.empty() ? m_BuildsOverrideHost : m_BuildsHost,
+ m_JupiterNamespace,
+ m_JupiterBucket,
+ m_BuildsId);
}
if (!m_ZenUrl.empty())
{
@@ -1806,14 +1816,8 @@ SnapshotOplogCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** a
return;
}
- m_HostName = ResolveTargetHostSpec(m_HostName);
-
- if (m_HostName.empty())
- {
- throw OptionParseException("Unable to resolve server specification", m_Options.help());
- }
-
- HttpClient Http = CreateHttpClient(m_HostName);
+ ZenServiceClient Service({.HostSpec = m_HostName, .CommandName = Name});
+ HttpClient& Http = Service.Http();
if (m_ProjectName.empty())
{
@@ -1869,14 +1873,8 @@ ProjectStatsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** ar
return;
}
- m_HostName = ResolveTargetHostSpec(m_HostName);
-
- if (m_HostName.empty())
- {
- throw OptionParseException("Unable to resolve server specification", m_Options.help());
- }
-
- HttpClient Http = CreateHttpClient(m_HostName);
+ ZenServiceClient Service({.HostSpec = m_HostName, .CommandName = Name});
+ HttpClient& Http = Service.Http();
if (HttpClient::Response Result = Http.Get("/stats/prj", HttpClient::Accept(ZenContentType::kJSON)))
{
ZEN_CONSOLE("{}", Result.ToText());
@@ -1922,14 +1920,8 @@ ProjectOpDetailsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char*
return;
}
- m_HostName = ResolveTargetHostSpec(m_HostName);
-
- if (m_HostName.empty())
- {
- throw OptionParseException("Unable to resolve server specification", m_Options.help());
- }
-
- HttpClient Http = CreateHttpClient(m_HostName);
+ ZenServiceClient Service({.HostSpec = m_HostName, .CommandName = Name});
+ HttpClient& Http = Service.Http();
m_ProjectName = ResolveProject(Http, m_ProjectName);
if (m_ProjectName.empty())
@@ -2038,14 +2030,8 @@ OplogMirrorCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
return;
}
- m_HostName = ResolveTargetHostSpec(m_HostName);
-
- if (m_HostName.empty())
- {
- throw OptionParseException("Unable to resolve server specification", m_Options.help());
- }
-
- HttpClient Http = CreateHttpClient(m_HostName);
+ ZenServiceClient Service({.HostSpec = m_HostName, .CommandName = Name});
+ HttpClient& Http = Service.Http();
m_ProjectName = ResolveProject(Http, m_ProjectName);
if (m_ProjectName.empty())
@@ -2108,16 +2094,59 @@ OplogMirrorCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
std::unordered_set<std::u8string> FileNames;
std::atomic<uint64_t> WrittenByteCount = 0;
- std::atomic<bool> AbortFlag(false);
+ // Install Ctrl-C handler so SIGINT aborts the worker pool rather than killing
+ // the process. Without this the local AbortFlag would shadow whatever global
+ // handler is installed elsewhere and interrupts would be dropped. RAII so
+ // the previous handler is restored when the function returns or throws.
+ MirrorAbortFlag.store(false);
+ ScopedSignalHandler SigIntGuard(SIGINT, MirrorSignalCallbackHandler);
+#if ZEN_PLATFORM_WINDOWS
+ ScopedSignalHandler SigBreakGuard(SIGBREAK, MirrorSignalCallbackHandler);
+#endif
+ std::atomic<bool>& AbortFlag = MirrorAbortFlag;
Stopwatch WriteStopWatch;
+ // Filenames come from the remote oplog, which may be compromised or untrusted.
+ // Reject anything that could escape the mirror root via an absolute path, drive
+ // letter / UNC / device path prefix, or '..' component before it is joined to
+ // RootPath. Returns nullptr when the filename is safe.
+ auto UnsafeFileNameReason = [](const std::filesystem::path& FileName) -> const char* {
+ if (FileName.empty())
+ {
+ return "filename is empty";
+ }
+ if (FileName.has_root_name())
+ {
+ return "filename has a root name (drive letter, UNC share, or device path)";
+ }
+ if (FileName.has_root_directory())
+ {
+ return "filename is absolute";
+ }
+ for (const std::filesystem::path& Component : FileName)
+ {
+ const std::u8string C = Component.u8string();
+ if (C.empty() || C == u8"..")
+ {
+ return "filename contains a '..' or empty component";
+ }
+ }
+ return nullptr;
+ };
+
auto EmitFilesForDataArray = [&](CbArrayView DataArray) {
for (auto DataIter : DataArray)
{
if (CbObjectView Data = DataIter.AsObjectView())
{
std::filesystem::path FileName(Data["filename"sv].AsU8String());
+ if (const char* Reason = UnsafeFileNameReason(FileName))
+ {
+ ZEN_CONSOLE_ERROR("Rejecting unsafe filename '{}' from remote oplog: {}", FileName.string(), Reason);
+ AbortFlag.store(true);
+ break;
+ }
if (!m_FilenameFilter.empty())
{
std::string FileNameLowerCase = ToLower(FileName.string());
@@ -2162,7 +2191,7 @@ OplogMirrorCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
IoBuffer ChunkData =
m_Decompress ? TryDecompress(ChunkResponse.ResponsePayload) : ChunkResponse.ResponsePayload;
- if (!MoveToFile(TargetPath, ChunkData))
+ if (std::error_code MoveEc = MoveToFile(TargetPath, ChunkData); MoveEc)
{
WriteFile(TargetPath, ChunkData);
}
@@ -2196,17 +2225,18 @@ OplogMirrorCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
ZEN_CONSOLE("Fetched oplog in {}", NiceTimeSpanMs(uint64_t(Response.ElapsedSeconds * 1000.0)));
if (CbObject ResponseObject = Response.AsObject())
{
- std::unique_ptr<ProgressBar> EmitProgressBar;
+ std::unique_ptr<ProgressBase> ProgressOwner2(CreateConsoleProgress(ConsoleProgressMode::Pretty));
+ std::unique_ptr<ProgressBase::ProgressBar> EmitProgressBar;
{
- ProgressBar ParseProgressBar(ProgressBar::Mode::Pretty, "");
- CbArrayView Entries = ResponseObject["entries"sv].AsArrayView();
- uint64_t Remaining = Entries.Num();
+ std::unique_ptr<ProgressBase::ProgressBar> ParseProgressBar = ProgressOwner2->CreateProgressBar("");
+ CbArrayView Entries = ResponseObject["entries"sv].AsArrayView();
+ uint64_t Remaining = Entries.Num();
for (auto EntryIter : Entries)
{
if (!AbortFlag)
{
CbObjectView Entry = EntryIter.AsObjectView();
- ParseProgressBar.UpdateState(
+ ParseProgressBar->UpdateState(
{.Task = "Parsing oplog", .Details = "", .TotalCount = Entries.Num(), .RemainingCount = Remaining},
false);
Remaining--;
@@ -2219,7 +2249,7 @@ OplogMirrorCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
}
if (!EmitProgressBar)
{
- EmitProgressBar = std::make_unique<ProgressBar>(ProgressBar::Mode::Pretty, ""sv);
+ EmitProgressBar = ProgressOwner2->CreateProgressBar(""sv);
WriteStopWatch.Reset();
}
@@ -2229,7 +2259,7 @@ OplogMirrorCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
++OplogEntryCount;
}
}
- ParseProgressBar.Finish();
+ ParseProgressBar->Finish();
}
WorkRemaining.CountDown();
@@ -2262,7 +2292,7 @@ OplogMirrorCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg
if (AbortFlag)
{
- throw std::runtime_error("Failed top mirror oplog");
+ throw std::runtime_error("Failed to mirror oplog");
}
}
else
@@ -2306,14 +2336,8 @@ OplogValidateCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** a
return;
}
- m_HostName = ResolveTargetHostSpec(m_HostName);
-
- if (m_HostName.empty())
- {
- throw OptionParseException("Unable to resolve server specification", m_Options.help());
- }
-
- HttpClient Http = CreateHttpClient(m_HostName);
+ ZenServiceClient Service({.HostSpec = m_HostName, .CommandName = Name});
+ HttpClient& Http = Service.Http();
m_ProjectName = ResolveProject(Http, m_ProjectName);
if (m_ProjectName.empty())
@@ -2472,7 +2496,7 @@ OplogDownloadCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** a
};
ParseSystemOptions();
- ProgressBar::Mode ProgressMode = ProgressBar::Mode::Pretty;
+ ConsoleProgressMode ProgressMode = ConsoleProgressMode::Pretty;
auto ParseOutputOptions = [&]() {
if (m_Verbose && m_Quiet)
@@ -2494,23 +2518,19 @@ OplogDownloadCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** a
if (m_LogProgress)
{
- ProgressMode = ProgressBar::Mode::Log;
+ ProgressMode = ConsoleProgressMode::Log;
}
else if (m_PlainProgress)
{
- ProgressMode = ProgressBar::Mode::Plain;
- }
- else if (m_Verbose)
- {
- ProgressMode = ProgressBar::Mode::Plain;
+ ProgressMode = ConsoleProgressMode::Plain;
}
else if (m_Quiet)
{
- ProgressMode = ProgressBar::Mode::Quiet;
+ ProgressMode = ConsoleProgressMode::Quiet;
}
else
{
- ProgressMode = ProgressBar::Mode::Pretty;
+ ProgressMode = ConsoleProgressMode::Pretty;
}
};
ParseOutputOptions();
@@ -2565,7 +2585,7 @@ OplogDownloadCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** a
m_BoostWorkerMemory = true;
}
- std::unique_ptr<OperationLogOutput> OperationLogOutput(CreateConsoleLogOutput(ProgressMode));
+ std::unique_ptr<ProgressBase> Progress(CreateConsoleProgress(ProgressMode));
TransferThreadWorkers Workers(m_BoostWorkerCount, /*SingleThreaded*/ false);
if (!m_Quiet)
@@ -2594,7 +2614,7 @@ OplogDownloadCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** a
/*Hidden*/ false,
m_Verbose);
- BuildStorageResolveResult ResolveRes = ResolveBuildStorage(*OperationLogOutput,
+ BuildStorageResolveResult ResolveRes = ResolveBuildStorage(ConsoleLog(),
ClientSettings,
m_Host,
m_OverrideHost,
@@ -2629,6 +2649,8 @@ OplogDownloadCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** a
.MaximumInMemoryDownloadSize = m_BoostWorkerMemory ? RemoteStoreOptions::DefaultMaxBlockSize : 1024u * 1024u},
[&AbortFlag]() { return AbortFlag.load(); });
Storage.CacheHost = ResolveRes.Cache;
+
+ Storage.SetupCacheSession(ResolveRes.Cache.Address, Name, GetSessionId());
}
if (!m_Quiet)
@@ -2677,7 +2699,7 @@ OplogDownloadCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** a
}
ProjectStoreOperationOplogState State(
- *OperationLogOutput,
+ ConsoleLog(),
Storage,
BuildId,
{.IsQuiet = m_Quiet, .IsVerbose = m_Verbose, .ForceDownload = m_ForceDownload, .TempFolderPath = StorageTempPath});
@@ -2704,7 +2726,8 @@ OplogDownloadCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** a
}
std::atomic<bool> PauseFlag;
- ProjectStoreOperationDownloadAttachments Op(*OperationLogOutput,
+ ProjectStoreOperationDownloadAttachments Op(ConsoleLog(),
+ *Progress,
Storage,
AbortFlag,
PauseFlag,