about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2019-05-15T15·33+0200
committerEelco Dolstra <edolstra@gmail.com>2019-05-15T15·33+0200
commit66b8a62101cb1dfe2e368346cf99efd32e9328ae (patch)
tree4ef5a346b159b93a6b1ce6839b30bac5fb23a3c4
parent83f2b110cecf50877ce1585c698dbed6dd225562 (diff)
nix: Add --print-build-logs flag
This causes 'nix' to print build log output to stderr rather than
showing the last log line in the progress bar. Log lines are prefixed
by the name of the derivation (minus the version string), e.g.

  binutils> make[1]: Leaving directory '/build/binutils-2.31.1'
  binutils-wrapper> unpacking sources
  binutils-wrapper> patching sources
  ...
  binutils-wrapper> Using dynamic linker: '/nix/store/kr51dlsj9v5cr4n8700jliyz8v5b2q7q-bootstrap-stage0-glibc/lib/ld-linux-x86-64.so.2'
  bootstrap-stage2-gcc-wrapper> unpacking sources
  ...
  linux-headers> unpacking sources
  linux-headers> unpacking source archive /nix/store/8javli69jhj3bkql2c35gsj5vl91p382-linux-4.19.16.tar.xz
-rw-r--r--src/libutil/util.hh1
-rw-r--r--src/nix/main.cc10
-rw-r--r--src/nix/progress-bar.cc39
-rw-r--r--src/nix/progress-bar.hh2
4 files changed, 39 insertions, 13 deletions
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 9f239bff371a..23360de2e8d4 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -401,6 +401,7 @@ void ignoreException();
 /* Some ANSI escape sequences. */
 #define ANSI_NORMAL "\e[0m"
 #define ANSI_BOLD "\e[1m"
+#define ANSI_FAINT "\e[2m"
 #define ANSI_RED "\e[31;1m"
 #define ANSI_GREEN "\e[32;1m"
 #define ANSI_BLUE "\e[34;1m"
diff --git a/src/nix/main.cc b/src/nix/main.cc
index 64c1dc35787c..4f87ad72b65c 100644
--- a/src/nix/main.cc
+++ b/src/nix/main.cc
@@ -20,6 +20,8 @@ std::string programPath;
 
 struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
 {
+    bool printBuildLogs = false;
+
     NixArgs() : MultiCommand(*RegisterCommand::commands), MixCommonArgs("nix")
     {
         mkFlag()
@@ -42,6 +44,11 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
             });
 
         mkFlag()
+            .longName("print-build-logs")
+            .description("print full build logs on stderr")
+            .set(&printBuildLogs, true);
+
+        mkFlag()
             .longName("version")
             .description("show version information")
             .handler([&]() { printVersion(programName); });
@@ -98,8 +105,7 @@ void mainWrapped(int argc, char * * argv)
 
     Finally f([]() { stopProgressBar(); });
 
-    if (isatty(STDERR_FILENO))
-        startProgressBar();
+    startProgressBar(args.printBuildLogs);
 
     args.command->prepare();
     args.command->run();
diff --git a/src/nix/progress-bar.cc b/src/nix/progress-bar.cc
index 40b905ba3243..304f918cc5f5 100644
--- a/src/nix/progress-bar.cc
+++ b/src/nix/progress-bar.cc
@@ -2,6 +2,7 @@
 #include "util.hh"
 #include "sync.hh"
 #include "store-api.hh"
+#include "names.hh"
 
 #include <atomic>
 #include <map>
@@ -38,6 +39,7 @@ private:
         std::map<ActivityType, uint64_t> expectedByType;
         bool visible = true;
         ActivityId parent;
+        std::optional<std::string> name;
     };
 
     struct ActivitiesByType
@@ -68,10 +70,16 @@ private:
 
     std::condition_variable quitCV, updateCV;
 
+    bool printBuildLogs;
+    bool isTTY;
+
 public:
 
-    ProgressBar()
+    ProgressBar(bool printBuildLogs, bool isTTY)
+        : printBuildLogs(printBuildLogs)
+        , isTTY(isTTY)
     {
+        state_.lock()->active = isTTY;
         updateThread = std::thread([&]() {
             auto state(state_.lock());
             while (state->active) {
@@ -109,8 +117,14 @@ public:
 
     void log(State & state, Verbosity lvl, const std::string & s)
     {
-        writeToStderr("\r\e[K" + s + ANSI_NORMAL "\n");
-        draw(state);
+        if (state.active) {
+            writeToStderr("\r\e[K" + s + ANSI_NORMAL "\n");
+            draw(state);
+        } else {
+            auto s2 = s + ANSI_NORMAL "\n";
+            if (!isTTY) s2 = filterANSIEscapes(s2, true);
+            writeToStderr(s2);
+        }
     }
 
     void startActivity(ActivityId act, Verbosity lvl, ActivityType type,
@@ -141,6 +155,7 @@ public:
             auto nrRounds = getI(fields, 3);
             if (nrRounds != 1)
                 i->s += fmt(" (round %d/%d)", curRound, nrRounds);
+            i->name = DrvName(name).name;
         }
 
         if (type == actSubstitute) {
@@ -217,11 +232,15 @@ public:
                 auto i = state->its.find(act);
                 assert(i != state->its.end());
                 ActInfo info = *i->second;
-                state->activities.erase(i->second);
-                info.lastLine = lastLine;
-                state->activities.emplace_back(info);
-                i->second = std::prev(state->activities.end());
-                update();
+                if (printBuildLogs) {
+                    log(*state, lvlInfo, ANSI_FAINT + info.name.value_or("unnamed") + "> " + ANSI_NORMAL + lastLine);
+                } else {
+                    state->activities.erase(i->second);
+                    info.lastLine = lastLine;
+                    state->activities.emplace_back(info);
+                    i->second = std::prev(state->activities.end());
+                    update();
+                }
             }
         }
 
@@ -395,9 +414,9 @@ public:
     }
 };
 
-void startProgressBar()
+void startProgressBar(bool printBuildLogs)
 {
-    logger = new ProgressBar();
+    logger = new ProgressBar(printBuildLogs, isatty(STDERR_FILENO));
 }
 
 void stopProgressBar()
diff --git a/src/nix/progress-bar.hh b/src/nix/progress-bar.hh
index af8eda5a84fd..4d61175c24e4 100644
--- a/src/nix/progress-bar.hh
+++ b/src/nix/progress-bar.hh
@@ -4,7 +4,7 @@
 
 namespace nix {
 
-void startProgressBar();
+void startProgressBar(bool printBuildLogs = false);
 
 void stopProgressBar();