| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 | #!/usr/bin/env python3import collectionsimport jsonimport pathlibimport subprocessimport sysDEFAULT_REF = 'origin/master'THE_BIG_LIST_OF_NAUGHTY_FILES = list(map(pathlib.Path, [    #    # Problems with files listed here get lighter treatment: they are blocking    # only when they are a part of the current pull request.    #    # for pylint    'Documentation/conf.py',    'LibOS/shim/test/apps/ltp/contrib/conf_lint.py',    'LibOS/shim/test/apps/ltp/contrib/conf_merge.py',    'LibOS/shim/test/apps/ltp/contrib/conf_missing.py',    'LibOS/shim/test/apps/ltp/contrib/conf_remove_must_pass.py',    'LibOS/shim/test/apps/ltp/contrib/has_own_main.py',    'LibOS/shim/test/apps/ltp/contrib/report.py',    'LibOS/shim/test/apps/ltp/runltp_xml.py',    'LibOS/shim/test/apps/python-scipy-insecure/scripts/test-numpy.py',    'LibOS/shim/test/apps/python-scipy-insecure/scripts/test-scipy.py',    'LibOS/shim/test/apps/python-simple/scripts/benchrun.py',    'LibOS/shim/test/apps/python-simple/scripts/dummy-web-server.py',    'LibOS/shim/test/apps/python-simple/scripts/fibonacci.py',    'LibOS/shim/test/apps/python-simple/scripts/helloworld.py',    'LibOS/shim/test/apps/python-simple/scripts/test-http.py',    'LibOS/shim/test/fs/test_fs.py',    'LibOS/shim/test/regression/test_libos.py',    'Pal/regression/test_pal.py',    'Pal/src/host/Linux-SGX/sgx-driver/link-intel-driver.py',    'Pal/src/host/Linux/pal-gdb.py',    'Scripts/regression.py',    'Tools',    # for shellcheck    'LibOS/shim/test/apps/bash/scripts/bash_test.sh',    'LibOS/shim/test/apps/common_tools/benchmark-http.sh',    'LibOS/shim/test/apps/python-simple/run-tests.sh',    'LibOS/shim/test/native',    'Pal/src/host/Linux-SGX/debugger/gdb',    'Pal/src/host/Linux-SGX/sgx-driver/load.sh',    'Runtime/pal_loader',    'Scripts/clean-check',    'Scripts/clean-check-prepare',    'Scripts/clean-check-test-copy',    'Scripts/list-all-graphene.sh',    'Scripts/memusg',    '.ci/run-pylint',    '.ci/run-shellcheck',]))def get_diff_ranges(ref=DEFAULT_REF):    '''Get chunks affected by a merge request    Args:        ref (str): a reference to diff the HEAD against (default: origin/master)    Returns:        dict: a dict with filenames in keys and list of `(start, end)` ranges in            values (start is inclusive, end is not, wrt :py:func:`range`)    '''    files = collections.defaultdict(list)    data = subprocess.check_output(['git', 'diff', '-U0', ref, 'HEAD']).decode()    path = None    for line in data.split('\n'):        if line.startswith('+++ '):            path = (None if line == '+++ /dev/null'                else line.split('/', maxsplit=1)[-1])            continue        if line.startswith('@@ '):            # @@ -8,0 +9 @@ [class name or previous line or whatever]            if path is None: # /dev/null                continue            _, _, plus, *_ = line.split()            start, length, *_ = *(int(i) for i in plus[1:].split(',')), 1            if not length:                # remove-only chunk                continue            files[path].append((start, start + length))    return filesclass Diff:    '''A quick and dirty diff evaluator    >>> diff = Diff()    >>> (message['file'], message['line']) in diff    True # or False    >>> diff.message_is_important(message)    True # or False    The default diff is to the ``origin/master`` ref.    '''    # pylint: disable=too-few-public-methods    def __init__(self, ref=DEFAULT_REF):        self._files = get_diff_ranges(ref)    def __contains__(self, pathline):        path, line = pathline        try:            return any(start <= line < end for start, end in self._files[path])        except KeyError:            return False    def message_is_important(self, message):        path = pathlib.Path(message['path'])        for i in THE_BIG_LIST_OF_NAUGHTY_FILES:            try:                path.relative_to(i)                break            except ValueError:                # path is not .relative_to() the path from WHITELIST                pass        else:            # not on whitelist: always complain            return True        if (message['path'], message['line']) in self:            # on whitelist, but in diff: do complain            return True        # on whitelist and outside diff: don't complain        return Falsedef main():    diff = Diff()    with sys.stdin:        pylint = json.load(sys.stdin)    ret = 0    for message in pylint:        # shellcheck        if 'path' not in message:            message['path'] = message['file']        if 'symbol' not in message:            message['symbol'] = message['code']        if diff.message_is_important(message):            if not ret:                print('MESSAGES AFFECTING THIS PR:')            print('{path} +{line}:{column}: {symbol}: {message}'.format(                **message))            ret += 1    return min(ret, 255)if __name__ == '__main__':    sys.exit(main())
 |