about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2017-08-21T10·01+0200
committerEelco Dolstra <edolstra@gmail.com>2017-08-21T10·18+0200
commit4af2611bd105f365e568069463b1700d141dd0a8 (patch)
treeb222a94aba0780ebf34f65c0417488457e104f31 /src
parent4c6a26539c8c5d1163c1a6a6d22caf818376b36a (diff)
Allow builders to create activities
Actually, currently they can only create download activities. Thus,
downloads by builtins.fetchurl show up in the progress bar.
Diffstat (limited to 'src')
-rw-r--r--src/libstore/build.cc78
1 files changed, 72 insertions, 6 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index fc039a8e52b5..3663c33b012b 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -55,6 +55,8 @@
 #include <sys/statvfs.h>
 #endif
 
+#include <nlohmann/json.hpp>
+
 
 namespace nix {
 
@@ -839,6 +841,8 @@ private:
 
     std::unique_ptr<Activity> act;
 
+    std::map<ActivityId, Activity> builderActivities;
+
 public:
     DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs,
         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()
 {
     /* 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. */
         if (drv->isBuiltin()) {
             try {
+                logger = new BuilderLogger(*logger);
                 if (drv->builder == "builtin:fetchurl")
                     builtinFetchurl(*drv, netrcData);
                 else
@@ -3250,14 +3283,47 @@ void DerivationGoal::handleEOF(int fd)
 
 void DerivationGoal::flushLine()
 {
-    if (settings.verboseBuild &&
-        (settings.printRepeatedBuilds || curRound == 1))
-        printError(filterANSIEscapes(currentLogLine, true));
+    if (hasPrefix(currentLogLine, "@nix ")) {
+
+        try {
+            auto json = nlohmann::json::parse(std::string(currentLogLine, 5));
+
+            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());
+        }
+    }
+
     else {
-        logTail.push_back(currentLogLine);
-        if (logTail.size() > settings.logLines) logTail.pop_front();
+        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);
     }
-    act->result(resBuildLogLine, currentLogLine);
+
     currentLogLine = "";
     currentLogLinePos = 0;
 }