scripts: Auto-detect whether we can enable colors
authorNirbheek Chauhan <nirbheek@centricular.com>
Tue, 5 Feb 2019 11:53:49 +0000 (17:23 +0530)
committerNirbheek Chauhan <nirbheek@centricular.com>
Tue, 5 Feb 2019 11:53:49 +0000 (17:23 +0530)
Also do the setup necessary on Windows to enable ANSI colours on the
console (if available). That code is copied from Meson and is Apache2
licensed.

checkout-branch-worktree
common.py
git-update

index 3b29e73..7f2dbd5 100755 (executable)
@@ -73,7 +73,7 @@ if __name__ == "__main__":
                         help="The meson build directory")
     options = parser.parse_args()
 
-    if options.no_color:
+    if options.no_color or not Colors.can_enable():
         Colors.disable()
 
     if not os.path.exists(options.builddir):
index 7f16391..a9eca33 100644 (file)
--- a/common.py
+++ b/common.py
@@ -1,9 +1,10 @@
-import argparse
 import os
 import sys
+import shlex
 import shutil
+import argparse
+import platform
 import subprocess
-import shlex
 
 
 ROOTDIR = os.path.abspath(os.path.dirname(__file__))
@@ -19,6 +20,27 @@ class Colors:
 
     force_disable = False
 
+    def _windows_ansi():
+        from ctypes import windll, byref
+        from ctypes.wintypes import DWORD
+
+        kernel = windll.kernel32
+        stdout = kernel.GetStdHandle(-11)
+        mode = DWORD()
+        if not kernel.GetConsoleMode(stdout, byref(mode)):
+            return False
+        # Try setting ENABLE_VIRTUAL_TERMINAL_PROCESSING (0x4)
+        # If that fails (returns 0), we disable colors
+        return kernel.SetConsoleMode(stdout, mode.value | 0x4) or os.environ.get('ANSICON')
+
+    @classmethod
+    def can_enable(cls):
+        if not os.isatty(sys.stdout.fileno()):
+            return False
+        if platform.system().lower() == 'windows':
+            return cls._windows_ansi()
+        return os.environ.get('TERM') != 'dumb'
+
     @classmethod
     def disable(cls):
         cls.HEADER = ''
@@ -44,7 +66,8 @@ class Colors:
 
 def git(*args, repository_path='.'):
     return subprocess.check_output(["git"] + list(args), cwd=repository_path,
-                                   ).decode()
+                                   stdin=subprocess.DEVNULL,
+                                   stderr=subprocess.STDOUT).decode()
 
 def accept_command(commands):
     """Search @commands and returns the first found absolute path."""
index ce1a109..71c6d03 100755 (executable)
@@ -136,7 +136,7 @@ if __name__ == "__main__":
                         help="Use a android repo manifest to sync repositories"
                         " Note that it will let all repositories in detached state")
     options = parser.parse_args()
-    if options.no_color:
+    if options.no_color or not Colors.can_enable():
         Colors.disable()
 
     if options.no_interaction: