import os import sys import shlex import shutil import argparse import platform import subprocess import uuid ROOTDIR = os.path.abspath(os.path.dirname(__file__)) if os.name == 'nt': import ctypes from ctypes import wintypes _GetShortPathNameW = ctypes.windll.kernel32.GetShortPathNameW _GetShortPathNameW.argtypes = [wintypes.LPCWSTR, wintypes.LPWSTR, wintypes.DWORD] _GetShortPathNameW.restype = wintypes.DWORD def win32_get_short_path_name(long_name): """ Gets the short path name of a given long path. http://stackoverflow.com/a/23598461/200291 """ output_buf_size = 0 while True: output_buf = ctypes.create_unicode_buffer(output_buf_size) needed = _GetShortPathNameW(long_name, output_buf, output_buf_size) if output_buf_size >= needed: return output_buf.value else: output_buf_size = needed def get_wine_shortpath(winecmd, wine_paths): seen = set() wine_paths += [p for p in wine_paths if not (p in seen or seen.add(p))] getShortPathScript = '%s.bat' % str(uuid.uuid4()).lower()[:5] with open(getShortPathScript, mode='w') as f: f.write("@ECHO OFF\nfor %%x in (%*) do (\n echo|set /p=;%~sx\n)\n") f.flush() try: with open(os.devnull, 'w') as stderr: wine_path = subprocess.check_output( winecmd + ['cmd', '/C', getShortPathScript] + wine_paths, stderr=stderr).decode('utf-8') except subprocess.CalledProcessError as e: print("Could not get short paths: %s" % e) wine_path = ';'.join(wine_paths) finally: os.remove(getShortPathScript) if len(wine_path) > 2048: raise AssertionError('WINEPATH size {} > 2048' ' this will cause random failure.'.format( len(wine_path))) return wine_path class Colors: HEADER = '\033[95m' OKBLUE = '\033[94m' OKGREEN = '\033[92m' WARNING = '\033[93m' FAIL = '\033[91m' ENDC = '\033[0m' 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 = '' cls.OKBLUE = '' cls.OKGREEN = '' cls.WARNING = '' cls.FAIL = '' cls.ENDC = '' @classmethod def enable(cls): if cls.force_disable: return cls.HEADER = '\033[95m' cls.OKBLUE = '\033[94m' cls.OKGREEN = '\033[92m' cls.WARNING = '\033[93m' cls.FAIL = '\033[91m' cls.ENDC = '\033[0m' def git(*args, repository_path='.', fatal=True): try: ret = subprocess.check_output(["git"] + list(args), cwd=repository_path, stdin=subprocess.DEVNULL, stderr=subprocess.STDOUT).decode() except subprocess.CalledProcessError as e: if fatal: raise e print("Non-fatal error running git {}:\n{}".format(' '.join(args), e)) return None return ret def accept_command(commands): """Search @commands and returns the first found absolute path.""" for command in commands: command = shutil.which(command) if command: return command return None def get_meson(): meson = os.path.join(ROOTDIR, 'meson', 'meson.py') if os.path.exists(meson): return [sys.executable, meson] mesonintrospect = os.environ.get('MESONINTROSPECT', '') for comp in shlex.split (mesonintrospect): # mesonintrospect might look like "/usr/bin/python /somewhere/meson introspect", # let's not get tricked if 'python' in os.path.basename (comp): continue if os.path.exists(comp): if comp.endswith('.py'): return [sys.executable, comp] else: return [comp] meson = accept_command(['meson.py']) if meson: return [sys.executable, meson] meson = accept_command(['meson']) if meson: return [meson] raise RuntimeError('Could not find Meson')