Allow builders to create activities

Actually, currently they can only create download activities. Thus,
downloads by builtins.fetchurl show up in the progress bar.
This commit is contained in:
Eelco Dolstra 2017-08-21 12:01:21 +02:00
parent 4c6a26539c
commit 4af2611bd1
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
4 changed files with 77 additions and 8 deletions

View file

@ -3,7 +3,7 @@ ifeq ($(MAKECMDGOALS), dist)
dist-files += $(shell git --git-dir=.git ls-files || find * -type f) dist-files += $(shell git --git-dir=.git ls-files || find * -type f)
endif endif
dist-files += configure config.h.in nix.spec perl/configure dist-files += configure config.h.in nix.spec perl/configure src/nlohmann/json.hpp
clean-files += Makefile.config clean-files += Makefile.config

View file

@ -43,6 +43,8 @@ let
(cd perl ; autoreconf --install --force --verbose) (cd perl ; autoreconf --install --force --verbose)
# TeX needs a writable font cache. # TeX needs a writable font cache.
export VARTEXFONTS=$TMPDIR/texfonts export VARTEXFONTS=$TMPDIR/texfonts
cp -rv ${nlohmann_json}/include/nlohmann src/nlohmann
''; '';
distPhase = distPhase =

View file

@ -18,6 +18,7 @@ with import ./release-common.nix { inherit pkgs; };
customMemoryManagement = false; customMemoryManagement = false;
}) })
autoreconfHook autoreconfHook
nlohmann_json
# For nix-perl # For nix-perl
perl perl

View file

@ -55,6 +55,8 @@
#include <sys/statvfs.h> #include <sys/statvfs.h>
#endif #endif
#include <nlohmann/json.hpp>
namespace nix { namespace nix {
@ -839,6 +841,8 @@ private:
std::unique_ptr<Activity> act; std::unique_ptr<Activity> act;
std::map<ActivityId, Activity> builderActivities;
public: public:
DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs, DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs,
Worker & worker, BuildMode buildMode = bmNormal); Worker & worker, BuildMode buildMode = bmNormal);
@ -2390,6 +2394,34 @@ void setupSeccomp()
} }
struct BuilderLogger : Logger
{
Logger & prevLogger;
BuilderLogger(Logger & prevLogger) : prevLogger(prevLogger) { }
void log(Verbosity lvl, const FormatOrString & fs) override
{
prevLogger.log(lvl, fs);
}
void startActivity(ActivityId act, ActivityType type, const std::string & s) override
{
log(lvlError, fmt("@nix {\"action\": \"start\", \"id\": %d, \"type\": %d, \"text\": \"%s\"}", act, type, s));
}
void stopActivity(ActivityId act) override
{
log(lvlError, fmt("@nix {\"action\": \"stop\", \"id\": %d}", act));
}
void progress(ActivityId act, uint64_t done = 0, uint64_t expected = 0, uint64_t running = 0, uint64_t failed = 0) override
{
log(lvlError, fmt("@nix {\"action\": \"progress\", \"id\": %d, \"done\": %d, \"expected\": %d, \"running\": %d, \"failed\": %d}", act, done, expected, running, failed));
}
};
void DerivationGoal::runChild() void DerivationGoal::runChild()
{ {
/* Warning: in the child we should absolutely not make any SQLite /* Warning: in the child we should absolutely not make any SQLite
@ -2796,6 +2828,7 @@ void DerivationGoal::runChild()
/* Execute the program. This should not return. */ /* Execute the program. This should not return. */
if (drv->isBuiltin()) { if (drv->isBuiltin()) {
try { try {
logger = new BuilderLogger(*logger);
if (drv->builder == "builtin:fetchurl") if (drv->builder == "builtin:fetchurl")
builtinFetchurl(*drv, netrcData); builtinFetchurl(*drv, netrcData);
else else
@ -3250,14 +3283,47 @@ void DerivationGoal::handleEOF(int fd)
void DerivationGoal::flushLine() void DerivationGoal::flushLine()
{ {
if (settings.verboseBuild && if (hasPrefix(currentLogLine, "@nix ")) {
(settings.printRepeatedBuilds || curRound == 1))
printError(filterANSIEscapes(currentLogLine, true)); try {
else { auto json = nlohmann::json::parse(std::string(currentLogLine, 5));
logTail.push_back(currentLogLine);
if (logTail.size() > settings.logLines) logTail.pop_front(); std::string action = json["action"];
if (action == "start") {
auto type = (ActivityType) json["type"];
if (type == actDownload)
builderActivities.emplace(std::piecewise_construct,
std::forward_as_tuple(json["id"]),
std::forward_as_tuple(*logger, type, json["text"]));
}
else if (action == "stop")
builderActivities.erase((ActivityId) json["id"]);
else if (action == "progress") {
auto i = builderActivities.find((ActivityId) json["id"]);
if (i != builderActivities.end())
i->second.progress(json.value("done", 0), json.value("expected", 0), json.value("running", 0), json.value("failed", 0));
}
} catch (std::exception & e) {
printError("bad log message from builder: %s", e.what());
}
} }
act->result(resBuildLogLine, currentLogLine);
else {
if (settings.verboseBuild &&
(settings.printRepeatedBuilds || curRound == 1))
printError(filterANSIEscapes(currentLogLine, true));
else {
logTail.push_back(currentLogLine);
if (logTail.size() > settings.logLines) logTail.pop_front();
}
act->result(resBuildLogLine, currentLogLine);
}
currentLogLine = ""; currentLogLine = "";
currentLogLinePos = 0; currentLogLinePos = 0;
} }