forked from lix-project/lix
parent
706f482216
commit
619cfa9fec
|
@ -1,4 +1,6 @@
|
||||||
#include "progress-bar.hh"
|
#include "progress-bar.hh"
|
||||||
|
#include "escape-string.hh"
|
||||||
|
#include "logging.hh"
|
||||||
#include "sync.hh"
|
#include "sync.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "names.hh"
|
#include "names.hh"
|
||||||
|
@ -39,48 +41,85 @@ static std::string_view storePathToName(std::string_view path)
|
||||||
// 100 years ought to be enough for anyone (yet sufficiently smaller than max() to not cause signed integer overflow).
|
// 100 years ought to be enough for anyone (yet sufficiently smaller than max() to not cause signed integer overflow).
|
||||||
constexpr const auto A_LONG_TIME = std::chrono::duration_cast<std::chrono::milliseconds>(100 * 365 * 86400s);
|
constexpr const auto A_LONG_TIME = std::chrono::duration_cast<std::chrono::milliseconds>(100 * 365 * 86400s);
|
||||||
|
|
||||||
|
|
||||||
|
struct ActInfo
|
||||||
|
{
|
||||||
|
using TimePoint = std::chrono::time_point<std::chrono::steady_clock>;
|
||||||
|
|
||||||
|
std::string s;
|
||||||
|
std::string lastLine;
|
||||||
|
std::string phase;
|
||||||
|
ActivityType type = actUnknown;
|
||||||
|
uint64_t done = 0;
|
||||||
|
uint64_t expected = 0;
|
||||||
|
uint64_t running = 0;
|
||||||
|
uint64_t failed = 0;
|
||||||
|
std::map<ActivityType, uint64_t> expectedByType;
|
||||||
|
bool visible = true;
|
||||||
|
ActivityId parent;
|
||||||
|
std::optional<std::string> name;
|
||||||
|
TimePoint startTime;
|
||||||
|
|
||||||
|
std::string to_string() const
|
||||||
|
{
|
||||||
|
EscapeStringOptions escapeOptions{
|
||||||
|
.escapeNonPrinting = true,
|
||||||
|
};
|
||||||
|
auto const escapedS = escapeString(s, escapeOptions);
|
||||||
|
auto const escapedLastLine = escapeString(lastLine, escapeOptions);
|
||||||
|
auto const escapedPhase = escapeString(phase, escapeOptions);
|
||||||
|
auto const typeS = activityTypeToString(type);
|
||||||
|
|
||||||
|
return fmt(
|
||||||
|
"ActInfo {\n s = %s,\n lastLine = %s,\n phase = %s,\n type = %s,\n done = %d\n expected = %d,\n running = %d,\n failed = %d,\n parent = %d,\n name = %s,\n}",
|
||||||
|
escapedS,
|
||||||
|
escapedLastLine,
|
||||||
|
escapedPhase,
|
||||||
|
typeS,
|
||||||
|
done,
|
||||||
|
expected,
|
||||||
|
running,
|
||||||
|
failed,
|
||||||
|
parent,
|
||||||
|
name.value_or("<nullopt>")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using ActInfoIterator = std::list<ActInfo>::iterator;
|
||||||
|
|
||||||
|
struct ActivitiesByType
|
||||||
|
{
|
||||||
|
std::map<ActivityId, ActInfoIterator> its;
|
||||||
|
uint64_t done = 0;
|
||||||
|
uint64_t expected = 0;
|
||||||
|
uint64_t failed = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BarState
|
||||||
|
{
|
||||||
|
std::list<ActInfo> activities;
|
||||||
|
std::map<ActivityId, ActInfoIterator> its;
|
||||||
|
|
||||||
|
std::map<ActivityType, ActivitiesByType> activitiesByType;
|
||||||
|
|
||||||
|
uint64_t filesLinked = 0;
|
||||||
|
uint64_t bytesLinked = 0;
|
||||||
|
uint64_t corruptedPaths = 0;
|
||||||
|
uint64_t untrustedPaths = 0;
|
||||||
|
|
||||||
|
bool active = true;
|
||||||
|
bool paused = false;
|
||||||
|
bool haveUpdate = true;
|
||||||
|
};
|
||||||
|
|
||||||
class ProgressBar : public Logger
|
class ProgressBar : public Logger
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
struct ActInfo
|
//using ActInfo = ActInfo;
|
||||||
{
|
using ActivitiesByType = ActivitiesByType;
|
||||||
std::string s, lastLine, phase;
|
using State = BarState;
|
||||||
ActivityType type = actUnknown;
|
|
||||||
uint64_t done = 0;
|
|
||||||
uint64_t expected = 0;
|
|
||||||
uint64_t running = 0;
|
|
||||||
uint64_t failed = 0;
|
|
||||||
std::map<ActivityType, uint64_t> expectedByType;
|
|
||||||
bool visible = true;
|
|
||||||
ActivityId parent;
|
|
||||||
std::optional<std::string> name;
|
|
||||||
std::chrono::time_point<std::chrono::steady_clock> startTime;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ActivitiesByType
|
|
||||||
{
|
|
||||||
std::map<ActivityId, std::list<ActInfo>::iterator> its;
|
|
||||||
uint64_t done = 0;
|
|
||||||
uint64_t expected = 0;
|
|
||||||
uint64_t failed = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct State
|
|
||||||
{
|
|
||||||
std::list<ActInfo> activities;
|
|
||||||
std::map<ActivityId, std::list<ActInfo>::iterator> its;
|
|
||||||
|
|
||||||
std::map<ActivityType, ActivitiesByType> activitiesByType;
|
|
||||||
|
|
||||||
uint64_t filesLinked = 0, bytesLinked = 0;
|
|
||||||
|
|
||||||
uint64_t corruptedPaths = 0, untrustedPaths = 0;
|
|
||||||
|
|
||||||
bool active = true;
|
|
||||||
bool paused = false;
|
|
||||||
bool haveUpdate = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
Sync<State> state_;
|
Sync<State> state_;
|
||||||
|
|
||||||
|
@ -415,6 +454,13 @@ public:
|
||||||
std::string getStatus(State & state)
|
std::string getStatus(State & state)
|
||||||
{
|
{
|
||||||
constexpr auto MiB = 1024.0 * 1024.0;
|
constexpr auto MiB = 1024.0 * 1024.0;
|
||||||
|
//this->cout("getStatus(): we have %d activities", state.activities.size());
|
||||||
|
//std::cerr << "\ngetStatus(): we have " << state.activities.size() << "\n";
|
||||||
|
|
||||||
|
if (!state.activities.empty()) {
|
||||||
|
ActInfo const & firstActivity = state.activities.front();
|
||||||
|
std::cerr << "\ngetStatus(): " << firstActivity.to_string() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
std::string res;
|
std::string res;
|
||||||
|
|
||||||
|
@ -433,21 +479,49 @@ public:
|
||||||
std::string s;
|
std::string s;
|
||||||
|
|
||||||
if (running || done || expected || failed) {
|
if (running || done || expected || failed) {
|
||||||
if (running)
|
if (running) {
|
||||||
if (expected != 0)
|
if (expected != 0) {
|
||||||
s = fmt(ANSI_BLUE + numberFmt + ANSI_NORMAL "/" ANSI_GREEN + numberFmt + ANSI_NORMAL "/" + numberFmt,
|
auto const runningPart = fmt(numberFmt, running / unit);
|
||||||
running / unit, done / unit, expected / unit);
|
auto const donePart = fmt(numberFmt, done / unit);
|
||||||
else
|
auto const expectedPart = fmt(numberFmt, expected / unit);
|
||||||
s = fmt(ANSI_BLUE + numberFmt + ANSI_NORMAL "/" ANSI_GREEN + numberFmt + ANSI_NORMAL,
|
s = fmt(
|
||||||
running / unit, done / unit);
|
ANSI_BLUE "%s" ANSI_NORMAL "/" ANSI_GREEN "%s" ANSI_NORMAL "/%s",
|
||||||
else if (expected != done)
|
runningPart,
|
||||||
if (expected != 0)
|
donePart,
|
||||||
s = fmt(ANSI_GREEN + numberFmt + ANSI_NORMAL "/" + numberFmt,
|
expectedPart
|
||||||
done / unit, expected / unit);
|
);
|
||||||
else
|
} else {
|
||||||
s = fmt(ANSI_GREEN + numberFmt + ANSI_NORMAL, done / unit);
|
auto const runningPart = fmt(numberFmt, running / unit);
|
||||||
else
|
auto const donePart = fmt(numberFmt, done / unit);
|
||||||
s = fmt(done ? ANSI_GREEN + numberFmt + ANSI_NORMAL : numberFmt, done / unit);
|
s = fmt(
|
||||||
|
ANSI_BLUE "%s" ANSI_NORMAL "/" ANSI_GREEN "%s" ANSI_NORMAL,
|
||||||
|
runningPart,
|
||||||
|
donePart
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (expected != done) {
|
||||||
|
if (expected != 0) {
|
||||||
|
auto const donePart = fmt(numberFmt, done / unit);
|
||||||
|
auto const expectedPart = fmt(numberFmt, expected / unit);
|
||||||
|
s = fmt(
|
||||||
|
ANSI_GREEN "%s" ANSI_NORMAL "/%s",
|
||||||
|
donePart,
|
||||||
|
expectedPart
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
auto const donePart = fmt(numberFmt, done / unit);
|
||||||
|
s = fmt(ANSI_GREEN "%s" ANSI_NORMAL, donePart);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto const donePart = fmt(numberFmt, done / unit);
|
||||||
|
|
||||||
|
// We only color if `done` is non-zero.
|
||||||
|
if (done) {
|
||||||
|
s = concatStrings(ANSI_GREEN, donePart, ANSI_NORMAL);
|
||||||
|
} else {
|
||||||
|
s = donePart;
|
||||||
|
}
|
||||||
|
}
|
||||||
s = fmt(itemFmt, s);
|
s = fmt(itemFmt, s);
|
||||||
|
|
||||||
if (failed)
|
if (failed)
|
||||||
|
@ -458,10 +532,10 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
auto showActivity = [&](ActivityType type, const std::string & itemFmt, const std::string & numberFmt = "%d", double unit = 1) {
|
auto showActivity = [&](ActivityType type, const std::string & itemFmt, const std::string & numberFmt = "%d", double unit = 1) {
|
||||||
auto s = renderActivity(type, itemFmt, numberFmt, unit);
|
auto rendered = renderActivity(type, itemFmt, numberFmt, unit);
|
||||||
if (s.empty()) return;
|
if (rendered.empty()) return;
|
||||||
if (!res.empty()) res += ", ";
|
if (!res.empty()) res += ", ";
|
||||||
res += s;
|
res += rendered;
|
||||||
};
|
};
|
||||||
|
|
||||||
showActivity(actBuilds, "%s built");
|
showActivity(actBuilds, "%s built");
|
||||||
|
|
|
@ -23,6 +23,38 @@ typedef enum {
|
||||||
actBuildWaiting = 111,
|
actBuildWaiting = 111,
|
||||||
} ActivityType;
|
} ActivityType;
|
||||||
|
|
||||||
|
constexpr std::string_view activityTypeToString(ActivityType const & actType)
|
||||||
|
{
|
||||||
|
switch (actType) {
|
||||||
|
case actUnknown:
|
||||||
|
return "Unknown";
|
||||||
|
case actCopyPath:
|
||||||
|
return "CopyPath";
|
||||||
|
case actFileTransfer:
|
||||||
|
return "FileTransfer";
|
||||||
|
case actRealise:
|
||||||
|
return "Realise";
|
||||||
|
case actCopyPaths:
|
||||||
|
return "CopyPaths";
|
||||||
|
case actBuilds:
|
||||||
|
return "Builds";
|
||||||
|
case actBuild:
|
||||||
|
return "Build";
|
||||||
|
case actOptimiseStore:
|
||||||
|
return "OptimiseStore";
|
||||||
|
case actVerifyPaths:
|
||||||
|
return "VerifyPaths";
|
||||||
|
case actSubstitute:
|
||||||
|
return "Substitute";
|
||||||
|
case actQueryPathInfo:
|
||||||
|
return "QueryPathInfo";
|
||||||
|
case actPostBuildHook:
|
||||||
|
return "PostBuildHook";
|
||||||
|
case actBuildWaiting:
|
||||||
|
return "BuildWaiting";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
resFileLinked = 100,
|
resFileLinked = 100,
|
||||||
resBuildLogLine = 101,
|
resBuildLogLine = 101,
|
||||||
|
|
Loading…
Reference in a new issue