Laszlo Nagy | bc68758 | 2016-01-12 22:38:41 +0000 | [diff] [blame] | 1 | # -*- coding: utf-8 -*- |
| 2 | # The LLVM Compiler Infrastructure |
| 3 | # |
| 4 | # This file is distributed under the University of Illinois Open Source |
| 5 | # License. See LICENSE.TXT for details. |
Laszlo Nagy | 46fc18a | 2017-01-28 22:48:26 +0000 | [diff] [blame] | 6 | """ This module is a collection of methods commonly used in this project. """ |
| 7 | import functools |
| 8 | import logging |
| 9 | import os |
| 10 | import os.path |
| 11 | import subprocess |
| 12 | import sys |
Laszlo Nagy | bc68758 | 2016-01-12 22:38:41 +0000 | [diff] [blame] | 13 | |
| 14 | |
| 15 | def duplicate_check(method): |
| 16 | """ Predicate to detect duplicated entries. |
| 17 | |
| 18 | Unique hash method can be use to detect duplicates. Entries are |
| 19 | represented as dictionaries, which has no default hash method. |
| 20 | This implementation uses a set datatype to store the unique hash values. |
| 21 | |
| 22 | This method returns a method which can detect the duplicate values. """ |
| 23 | |
| 24 | def predicate(entry): |
| 25 | entry_hash = predicate.unique(entry) |
| 26 | if entry_hash not in predicate.state: |
| 27 | predicate.state.add(entry_hash) |
| 28 | return False |
| 29 | return True |
| 30 | |
| 31 | predicate.unique = method |
| 32 | predicate.state = set() |
| 33 | return predicate |
| 34 | |
| 35 | |
| 36 | def tempdir(): |
| 37 | """ Return the default temorary directory. """ |
| 38 | |
Laszlo Nagy | 46fc18a | 2017-01-28 22:48:26 +0000 | [diff] [blame] | 39 | return os.getenv('TMPDIR', os.getenv('TEMP', os.getenv('TMP', '/tmp'))) |
| 40 | |
| 41 | |
Laszlo Nagy | 52c1d7e | 2017-02-14 10:30:50 +0000 | [diff] [blame^] | 42 | def run_build(command, *args, **kwargs): |
| 43 | """ Run and report build command execution |
| 44 | |
| 45 | :param command: array of tokens |
| 46 | :return: exit code of the process |
| 47 | """ |
| 48 | environment = kwargs.get('env', os.environ) |
| 49 | logging.debug('run build %s, in environment: %s', command, environment) |
| 50 | exit_code = subprocess.call(command, *args, **kwargs) |
| 51 | logging.debug('build finished with exit code: %d', exit_code) |
| 52 | return exit_code |
| 53 | |
| 54 | |
Laszlo Nagy | 46fc18a | 2017-01-28 22:48:26 +0000 | [diff] [blame] | 55 | def run_command(command, cwd=None): |
| 56 | """ Run a given command and report the execution. |
| 57 | |
| 58 | :param command: array of tokens |
| 59 | :param cwd: the working directory where the command will be executed |
| 60 | :return: output of the command |
| 61 | """ |
| 62 | def decode_when_needed(result): |
| 63 | """ check_output returns bytes or string depend on python version """ |
| 64 | return result.decode('utf-8') if isinstance(result, bytes) else result |
| 65 | |
| 66 | try: |
| 67 | directory = os.path.abspath(cwd) if cwd else os.getcwd() |
| 68 | logging.debug('exec command %s in %s', command, directory) |
| 69 | output = subprocess.check_output(command, |
| 70 | cwd=directory, |
| 71 | stderr=subprocess.STDOUT) |
| 72 | return decode_when_needed(output).splitlines() |
| 73 | except subprocess.CalledProcessError as ex: |
| 74 | ex.output = decode_when_needed(ex.output).splitlines() |
| 75 | raise ex |
Laszlo Nagy | bc68758 | 2016-01-12 22:38:41 +0000 | [diff] [blame] | 76 | |
| 77 | |
| 78 | def initialize_logging(verbose_level): |
| 79 | """ Output content controlled by the verbosity level. """ |
| 80 | |
Laszlo Nagy | bc68758 | 2016-01-12 22:38:41 +0000 | [diff] [blame] | 81 | level = logging.WARNING - min(logging.WARNING, (10 * verbose_level)) |
| 82 | |
| 83 | if verbose_level <= 3: |
| 84 | fmt_string = '{0}: %(levelname)s: %(message)s' |
| 85 | else: |
| 86 | fmt_string = '{0}: %(levelname)s: %(funcName)s: %(message)s' |
| 87 | |
| 88 | program = os.path.basename(sys.argv[0]) |
| 89 | logging.basicConfig(format=fmt_string.format(program), level=level) |
| 90 | |
| 91 | |
| 92 | def command_entry_point(function): |
| 93 | """ Decorator for command entry points. """ |
| 94 | |
Laszlo Nagy | bc68758 | 2016-01-12 22:38:41 +0000 | [diff] [blame] | 95 | @functools.wraps(function) |
| 96 | def wrapper(*args, **kwargs): |
| 97 | |
| 98 | exit_code = 127 |
| 99 | try: |
| 100 | exit_code = function(*args, **kwargs) |
| 101 | except KeyboardInterrupt: |
| 102 | logging.warning('Keyboard interupt') |
| 103 | except Exception: |
| 104 | logging.exception('Internal error.') |
| 105 | if logging.getLogger().isEnabledFor(logging.DEBUG): |
| 106 | logging.error("Please report this bug and attach the output " |
| 107 | "to the bug report") |
| 108 | else: |
| 109 | logging.error("Please run this command again and turn on " |
| 110 | "verbose mode (add '-vvv' as argument).") |
| 111 | finally: |
| 112 | return exit_code |
| 113 | |
| 114 | return wrapper |