Add env var flag to override stdout.hasTerminal for output animations (#3658)

diff --git a/lib/src/progress.dart b/lib/src/progress.dart
index b9c6931..d29a9fb 100644
--- a/lib/src/progress.dart
+++ b/lib/src/progress.dart
@@ -39,9 +39,8 @@
     // The animation is only shown when it would be meaningful to a human.
     // That means we're writing a visible message to a TTY at normal log levels
     // with non-JSON output.
-    if (stdioType(stdout) != StdioType.terminal ||
+    if (!canAnimateOutput ||
         !log.verbosity.isLevelVisible(level) ||
-        log.json.enabled ||
         fine ||
         log.verbosity.isLevelVisible(log.Level.fine)) {
       // Not animating, so just log the start and wait until the task is
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 0719bbb..82655f1 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -426,6 +426,26 @@
 /// Gets an ANSI escape if those are supported by stdout (or nothing).
 String getAnsi(String ansiCode) => canUseAnsiCodes ? ansiCode : '';
 
+/// Whether an environment variable overriding the [stdout.hasTerminal] check
+/// was passed.
+bool get forceTerminalOutput =>
+    Platform.environment.containsKey('_PUB_FORCE_TERMINAL_OUTPUT');
+
+/// Whether it makes sense to do stdout animation.
+///
+/// Checks if pub is in JSON output mode or if stdout has no terminal attached.
+/// The flutter tool sets an environment variable when running "pub get" that
+/// overrides the terminal check. See [forceTerminalOutput].
+bool get canAnimateOutput {
+  if (log.json.enabled) {
+    return false;
+  }
+  if (!stdout.hasTerminal && !forceTerminalOutput) {
+    return false;
+  }
+  return true;
+}
+
 /// Gets a emoji special character as unicode, or the [alternative] if unicode
 /// charactors are not supported by stdout.
 String emoji(String unicode, String alternative) =>