about summary refs log tree commit diff
path: root/src/libstore
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore')
-rw-r--r--src/libstore/build.cc54
-rw-r--r--src/libstore/globals.cc1
-rw-r--r--src/libstore/globals.hh8
-rw-r--r--src/libstore/remote-store.cc2
4 files changed, 52 insertions, 13 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index f680b3737895..3830d7a671e8 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -747,6 +747,11 @@ private:
     /* Number of bytes received from the builder's stdout/stderr. */
     unsigned long logSize;
 
+    /* The most recent log lines. */
+    std::list<std::string> logTail;
+
+    std::string currentLogLine;
+
     /* Pipe for the builder's standard output/error. */
     Pipe builderOut;
 
@@ -872,6 +877,7 @@ private:
     /* Callback used by the worker to write to the log. */
     void handleChildOutput(int fd, const string & data) override;
     void handleEOF(int fd) override;
+    void flushLine();
 
     /* Return the set of (in)valid paths. */
     PathSet checkPathValidity(bool returnValid, bool checkHash);
@@ -1462,11 +1468,19 @@ void DerivationGoal::buildDone()
                     if (pathExists(chrootRootDir + i))
                         rename((chrootRootDir + i).c_str(), i.c_str());
 
+            std::string msg = (format("builder for ‘%1%’ %2%")
+                % drvPath % statusToString(status)).str();
+
+            if (!settings.verboseBuild && !logTail.empty()) {
+                msg += (format("; last %d log lines:") % logTail.size()).str();
+                for (auto & line : logTail)
+                    msg += "\n  " + line;
+            }
+
             if (diskFull)
-                printMsg(lvlError, "note: build failure may have been caused by lack of free disk space");
+                msg += "\nnote: build failure may have been caused by lack of free disk space";
 
-            throw BuildError(format("builder for ‘%1%’ %2%")
-                % drvPath % statusToString(status));
+            throw BuildError(msg);
         }
 
         /* Compute the FS closure of the outputs and register them as
@@ -2920,8 +2934,20 @@ void DerivationGoal::handleChildOutput(int fd, const string & data)
             done(BuildResult::LogLimitExceeded);
             return;
         }
-        if (verbosity >= settings.buildVerbosity)
-            printMsg(lvlError, filterANSIEscapes(data, true)); // FIXME
+
+        for (size_t pos = 0; true; ) {
+            auto newline = data.find('\n', pos);
+
+            if (newline == std::string::npos) {
+                currentLogLine.append(data, pos, std::string::npos);
+                break;
+            }
+
+            currentLogLine.append(data, pos, newline - pos);
+            flushLine();
+            pos = newline + 1;
+        }
+
         if (bzLogFile) {
             int err;
             BZ2_bzWrite(&err, bzLogFile, (unsigned char *) data.data(), data.size());
@@ -2937,10 +2963,23 @@ void DerivationGoal::handleChildOutput(int fd, const string & data)
 
 void DerivationGoal::handleEOF(int fd)
 {
+    flushLine();
     worker.wakeUp(shared_from_this());
 }
 
 
+void DerivationGoal::flushLine()
+{
+    if (settings.verboseBuild)
+        printMsg(lvlInfo, filterANSIEscapes(currentLogLine, true));
+    else {
+        logTail.push_back(currentLogLine);
+        if (logTail.size() > settings.logLines) logTail.pop_front();
+    }
+    currentLogLine = "";
+}
+
+
 PathSet DerivationGoal::checkPathValidity(bool returnValid, bool checkHash)
 {
     PathSet result;
@@ -3341,10 +3380,7 @@ void SubstitutionGoal::finished()
 void SubstitutionGoal::handleChildOutput(int fd, const string & data)
 {
     assert(fd == logPipe.readSide);
-    if (verbosity >= settings.buildVerbosity)
-        printMsg(lvlError, data); // FIXME
-    /* Don't write substitution output to a log file for now.  We
-       probably should, though. */
+    printMsg(lvlError, data); // FIXME
 }
 
 
diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc
index f4c41d715f35..90539ea85420 100644
--- a/src/libstore/globals.cc
+++ b/src/libstore/globals.cc
@@ -28,7 +28,6 @@ Settings::Settings()
     keepFailed = false;
     keepGoing = false;
     tryFallback = false;
-    buildVerbosity = lvlError;
     maxBuildJobs = 1;
     buildCores = 1;
 #ifdef _SC_NPROCESSORS_ONLN
diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh
index 8fa49e2dc120..60251ef421bf 100644
--- a/src/libstore/globals.hh
+++ b/src/libstore/globals.hh
@@ -78,8 +78,12 @@ struct Settings {
        instead. */
     bool tryFallback;
 
-    /* Verbosity level for build output. */
-    Verbosity buildVerbosity;
+    /* Whether to show build log output in real time. */
+    bool verboseBuild = true;
+
+    /* If verboseBuild is false, the number of lines of the tail of
+       the log to show if a build fails. */
+    size_t logLines = 10;
 
     /* Maximum number of parallel build jobs.  0 means unlimited. */
     unsigned int maxBuildJobs;
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index 831f4a83e029..4663291b9171 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -120,7 +120,7 @@ void RemoteStore::setOptions(ref<Connection> conn)
     if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 2)
         conn->to << settings.useBuildHook;
     if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 4)
-        conn->to << settings.buildVerbosity
+        conn->to << (settings.verboseBuild ? lvlError : lvlVomit)
                  << 0 // obsolete log type
                  << 0 /* obsolete print build trace */;
     if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 6)