about summary refs log tree commit diff
path: root/src/nix/progress-bar.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/nix/progress-bar.cc')
-rw-r--r--src/nix/progress-bar.cc50
1 files changed, 35 insertions, 15 deletions
diff --git a/src/nix/progress-bar.cc b/src/nix/progress-bar.cc
index fb9955190b40..252d12c5d37f 100644
--- a/src/nix/progress-bar.cc
+++ b/src/nix/progress-bar.cc
@@ -3,8 +3,9 @@
 #include "sync.hh"
 #include "store-api.hh"
 
-#include <map>
 #include <atomic>
+#include <map>
+#include <thread>
 
 namespace nix {
 
@@ -101,15 +102,28 @@ private:
 
     Sync<State> state_;
 
+    std::thread updateThread;
+
+    std::condition_variable quitCV, updateCV;
+
 public:
 
     ProgressBar()
     {
+        updateThread = std::thread([&]() {
+            auto state(state_.lock());
+            while (state->active) {
+                state.wait(updateCV);
+                draw(*state);
+                state.wait_for(quitCV, std::chrono::milliseconds(50));
+            }
+        });
     }
 
     ~ProgressBar()
     {
         stop();
+        updateThread.join();
     }
 
     void stop()
@@ -121,6 +135,8 @@ public:
         writeToStderr("\r\e[K");
         if (status != "")
             writeToStderr("[" + status + "]\n");
+        updateCV.notify_one();
+        quitCV.notify_one();
     }
 
     void log(Verbosity lvl, const FormatOrString & fs) override
@@ -132,7 +148,7 @@ public:
     void log(State & state, Verbosity lvl, const std::string & s)
     {
         writeToStderr("\r\e[K" + s + ANSI_NORMAL "\n");
-        update(state);
+        draw(state);
     }
 
     void startActivity(ActivityId act, Verbosity lvl, ActivityType type,
@@ -167,7 +183,12 @@ public:
 
         if (type == actSubstitute) {
             auto name = storePathToName(getS(fields, 0));
-            i->s = fmt("fetching " ANSI_BOLD "%s" ANSI_NORMAL " from %s", name, getS(fields, 1));
+            auto sub = getS(fields, 1);
+            i->s = fmt(
+                hasPrefix(sub, "local")
+                ? "copying " ANSI_BOLD "%s" ANSI_NORMAL " from %s"
+                : "fetching " ANSI_BOLD "%s" ANSI_NORMAL " from %s",
+                name, sub);
         }
 
         if (type == actQueryPathInfo) {
@@ -180,7 +201,7 @@ public:
             || (type == actCopyPath && hasAncestor(*state, actSubstitute, parent)))
             i->visible = false;
 
-        update(*state);
+        update();
     }
 
     /* Check whether an activity has an ancestore with the specified
@@ -215,7 +236,7 @@ public:
             state->its.erase(i);
         }
 
-        update(*state);
+        update();
     }
 
     void result(ActivityId act, ResultType type, const std::vector<Field> & fields) override
@@ -225,7 +246,7 @@ public:
         if (type == resFileLinked) {
             state->filesLinked++;
             state->bytesLinked += getI(fields, 0);
-            update(*state);
+            update();
         }
 
         else if (type == resBuildLogLine) {
@@ -238,25 +259,25 @@ public:
                 info.lastLine = lastLine;
                 state->activities.emplace_back(info);
                 i->second = std::prev(state->activities.end());
-                update(*state);
+                update();
             }
         }
 
         else if (type == resUntrustedPath) {
             state->untrustedPaths++;
-            update(*state);
+            update();
         }
 
         else if (type == resCorruptedPath) {
             state->corruptedPaths++;
-            update(*state);
+            update();
         }
 
         else if (type == resSetPhase) {
             auto i = state->its.find(act);
             assert(i != state->its.end());
             i->second->phase = getS(fields, 0);
-            update(*state);
+            update();
         }
 
         else if (type == resProgress) {
@@ -267,7 +288,7 @@ public:
             actInfo.expected = getI(fields, 1);
             actInfo.running = getI(fields, 2);
             actInfo.failed = getI(fields, 3);
-            update(*state);
+            update();
         }
 
         else if (type == resSetExpected) {
@@ -279,17 +300,16 @@ public:
             state->activitiesByType[type].expected -= j;
             j = getI(fields, 1);
             state->activitiesByType[type].expected += j;
-            update(*state);
+            update();
         }
     }
 
     void update()
     {
-        auto state(state_.lock());
-        update(*state);
+        updateCV.notify_one();
     }
 
-    void update(State & state)
+    void draw(State & state)
     {
         if (!state.active) return;