From a137506d46a2a1104e2019b9806b990e81aae7db Mon Sep 17 00:00:00 2001
From: "rnystrom@google.com" <rnystrom@google.com>
Date: Thu, 8 Jan 2015 23:58:32 +0000
Subject: [PATCH] Mute progress animation while Git is running so it doesn't
 overwrite credential prompts.

BUG=https://code.google.com/p/dart/issues/detail?id=21839
R=jacobr@google.com

Review URL: https://codereview.chromium.org//845543003

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge@42722 260f80e4-7a28-3924-810f-c04153c831b5
---
 lib/src/git.dart      |  4 ++++
 lib/src/log.dart      | 35 +++++++++++++++++++++++++++--------
 lib/src/progress.dart |  9 +++++----
 3 files changed, 36 insertions(+), 12 deletions(-)

diff --git a/lib/src/git.dart b/lib/src/git.dart
index 2c522eb0..53d69d89 100644
--- a/lib/src/git.dart
+++ b/lib/src/git.dart
@@ -50,10 +50,14 @@ Future<List<String>> run(List<String> args,
         "Please ensure Git is correctly installed.");
   }
 
+  log.muteProgress();
   return runProcess(_gitCommand, args, workingDir: workingDir,
       environment: environment).then((result) {
     if (!result.success) throw new GitException(args, result.stderr.join("\n"));
+
     return result.stdout;
+  }).whenComplete(() {
+    log.unmuteProgress();
   });
 }
 
diff --git a/lib/src/log.dart b/lib/src/log.dart
index 14627122..107970b4 100644
--- a/lib/src/log.dart
+++ b/lib/src/log.dart
@@ -42,9 +42,6 @@ const _MAX_TRANSCRIPT = 10000;
 /// [recordTranscript()] is called.
 Transcript<Entry> _transcript;
 
-/// All currently-running progress indicators.
-final _progresses = new Set<Progress>();
-
 /// The currently-animated progress indicator, if any.
 ///
 /// This will also be in [_progresses].
@@ -374,13 +371,10 @@ void dumpTranscript() {
 /// information will only be visible at [Level.FINE].
 Future progress(String message, Future callback(), {bool fine: false}) {
   _stopProgress();
+
   var progress = new Progress(message, fine: fine);
   _animatedProgress = progress;
-  _progresses.add(progress);
-  return callback().whenComplete(() {
-    progress.stop();
-    _progresses.remove(progress);
-  });
+  return callback().whenComplete(progress.stop);
 }
 
 /// Stops animating the running progress indicator, if currently running.
@@ -389,6 +383,31 @@ void _stopProgress() {
   _animatedProgress = null;
 }
 
+/// The number of outstanding calls to [muteProgress] that have not been unmuted
+/// yet.
+int _numMutes = 0;
+
+/// Whether progress animation should be muted or not.
+bool get isMuted => _numMutes > 0;
+
+/// Stops animating any ongoing progress.
+///
+/// This is called before spawning Git since Git sometimes writes directly to
+/// the terminal to ask for login credentials, which would then get overwritten
+/// by the progress animation.
+///
+/// Each call to this must be paired with a call to [unmuteProgress].
+void muteProgress() {
+  _numMutes++;
+}
+
+/// Resumes animating any ongoing progress once all calls to [muteProgress]
+/// have made their matching [unmuteProgress].
+void unmuteProgress() {
+  assert(_numMutes > 0);
+  _numMutes--;
+}
+
 /// Wraps [text] in the ANSI escape codes to make it bold when on a platform
 /// that supports that.
 ///
diff --git a/lib/src/progress.dart b/lib/src/progress.dart
index 6c0ffdcf..5029f61a 100644
--- a/lib/src/progress.dart
+++ b/lib/src/progress.dart
@@ -48,10 +48,11 @@ class Progress {
       return;
     }
 
-    _update();
     _timer = new Timer.periodic(new Duration(milliseconds: 100), (_) {
       _update();
     });
+
+    _update();
   }
 
   /// Stops the progress indicator.
@@ -88,11 +89,11 @@ class Progress {
 
   /// Refreshes the progress line.
   void _update() {
+    if (log.isMuted) return;
+
     stdout.write(log.format("\r$_message... "));
 
     // Show the time only once it gets noticeably long.
-    if (_stopwatch.elapsed.inSeconds > 0) {
-      stdout.write(log.gray(_time));
-    }
+    if (_stopwatch.elapsed.inSeconds > 0) stdout.write("${log.gray(_time)} ");
   }
 }
-- 
GitLab