1e5c31af7Sopenharmony_ci#!/usr/bin/env python
2e5c31af7Sopenharmony_ci# -*- coding: utf-8 -*-
3e5c31af7Sopenharmony_ci
4e5c31af7Sopenharmony_ci#-------------------------------------------------------------------------
5e5c31af7Sopenharmony_ci# drawElements Quality Program utilities
6e5c31af7Sopenharmony_ci# --------------------------------------
7e5c31af7Sopenharmony_ci#
8e5c31af7Sopenharmony_ci# Copyright 2015 The Android Open Source Project
9e5c31af7Sopenharmony_ci#
10e5c31af7Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
11e5c31af7Sopenharmony_ci# you may not use this file except in compliance with the License.
12e5c31af7Sopenharmony_ci# You may obtain a copy of the License at
13e5c31af7Sopenharmony_ci#
14e5c31af7Sopenharmony_ci#      http://www.apache.org/licenses/LICENSE-2.0
15e5c31af7Sopenharmony_ci#
16e5c31af7Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software
17e5c31af7Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
18e5c31af7Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19e5c31af7Sopenharmony_ci# See the License for the specific language governing permissions and
20e5c31af7Sopenharmony_ci# limitations under the License.
21e5c31af7Sopenharmony_ci#
22e5c31af7Sopenharmony_ci#-------------------------------------------------------------------------
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci# Check that the input file has no external include guards.
25e5c31af7Sopenharmony_ci# Returns with 0 exit code on success, 1 otherwise.
26e5c31af7Sopenharmony_ci
27e5c31af7Sopenharmony_ciimport re
28e5c31af7Sopenharmony_ciimport sys
29e5c31af7Sopenharmony_ciimport subprocess
30e5c31af7Sopenharmony_ci
31e5c31af7Sopenharmony_cidef git(*args, **kwargs):
32e5c31af7Sopenharmony_ci    return subprocess.check_output(['git'] + list(args), **kwargs)
33e5c31af7Sopenharmony_ci
34e5c31af7Sopenharmony_cidef get_changed_paths(filter):
35e5c31af7Sopenharmony_ci    output = git('diff', '--cached', '--name-only', '-z', '--diff-filter='+filter)
36e5c31af7Sopenharmony_ci    return output.split('\0')[:-1] # remove trailing ''
37e5c31af7Sopenharmony_ci
38e5c31af7Sopenharmony_cidef get_against():
39e5c31af7Sopenharmony_ci    try:
40e5c31af7Sopenharmony_ci        head = git('rev-parse', '--verify', 'HEAD', stderr=None)
41e5c31af7Sopenharmony_ci    except subprocess.CalledProcessError:
42e5c31af7Sopenharmony_ci        # Initial commit: diff against an empty tree object
43e5c31af7Sopenharmony_ci        return '4b825dc642cb6eb9a060e54bf8d69288fbee4904'
44e5c31af7Sopenharmony_ci    else:
45e5c31af7Sopenharmony_ci        return 'HEAD'
46e5c31af7Sopenharmony_ci
47e5c31af7Sopenharmony_ciagainst = get_against()
48e5c31af7Sopenharmony_ci
49e5c31af7Sopenharmony_cisuccess = True
50e5c31af7Sopenharmony_ci
51e5c31af7Sopenharmony_cidef croak(path, line, msg, *args):
52e5c31af7Sopenharmony_ci    global success
53e5c31af7Sopenharmony_ci    success = False
54e5c31af7Sopenharmony_ci    if path is not None:
55e5c31af7Sopenharmony_ci        sys.stderr.write("%s:%d: " % (path, line or 0))
56e5c31af7Sopenharmony_ci    sys.stderr.write(msg % args if args else msg)
57e5c31af7Sopenharmony_ci    if msg[-1] != '\n':
58e5c31af7Sopenharmony_ci        sys.stderr.write('\n')
59e5c31af7Sopenharmony_ci
60e5c31af7Sopenharmony_cidef check_filenames():
61e5c31af7Sopenharmony_ci    try:
62e5c31af7Sopenharmony_ci        allownonascii = git('config', '--get', '--bool', 'hooks.allownonascii')
63e5c31af7Sopenharmony_ci    except subprocess.CalledProcessError:
64e5c31af7Sopenharmony_ci        pass
65e5c31af7Sopenharmony_ci    else:
66e5c31af7Sopenharmony_ci        if allownonascii == 'true':
67e5c31af7Sopenharmony_ci            return
68e5c31af7Sopenharmony_ci
69e5c31af7Sopenharmony_ci    for path in get_changed_paths('ACR'):
70e5c31af7Sopenharmony_ci        try:
71e5c31af7Sopenharmony_ci            path.decode('ascii')
72e5c31af7Sopenharmony_ci        except UnicodeDecodeError:
73e5c31af7Sopenharmony_ci            croak(path, 0, "Non-ASCII file name")
74e5c31af7Sopenharmony_ci
75e5c31af7Sopenharmony_cidef check_whitespace():
76e5c31af7Sopenharmony_ci    try:
77e5c31af7Sopenharmony_ci        git('diff-index', '--check', '--cached', against, stderr=None)
78e5c31af7Sopenharmony_ci    except subprocess.CalledProcessError as e:
79e5c31af7Sopenharmony_ci        sys.stderr.write(e.output)
80e5c31af7Sopenharmony_ci        global success
81e5c31af7Sopenharmony_ci        success = False
82e5c31af7Sopenharmony_ci
83e5c31af7Sopenharmony_ciguard_re = re.compile('^[ \t]*#\s*ifndef\s+_.*?_H(PP)?\n'
84e5c31af7Sopenharmony_ci                      '\s*#\s*include\s+(".*?")\s*\n'
85e5c31af7Sopenharmony_ci                      '\s*#\s*endif.*?$',
86e5c31af7Sopenharmony_ci                      re.MULTILINE)
87e5c31af7Sopenharmony_ci
88e5c31af7Sopenharmony_cidef check_external_guards (infile):
89e5c31af7Sopenharmony_ci    contents = infile.read()
90e5c31af7Sopenharmony_ci    for m in guard_re.finditer(contents):
91e5c31af7Sopenharmony_ci        lineno = 1 + contents[:m.start()].count('\n')
92e5c31af7Sopenharmony_ci        croak(infile.name, lineno, "External include guard")
93e5c31af7Sopenharmony_ci        croak(None, None, m.group(0))
94e5c31af7Sopenharmony_ci
95e5c31af7Sopenharmony_cidef check_changed_files():
96e5c31af7Sopenharmony_ci    for path in get_changed_paths('AM'):
97e5c31af7Sopenharmony_ci        check_external_guards(open(path))
98e5c31af7Sopenharmony_ci
99e5c31af7Sopenharmony_cidef main():
100e5c31af7Sopenharmony_ci    check_filenames()
101e5c31af7Sopenharmony_ci    check_changed_files()
102e5c31af7Sopenharmony_ci    check_whitespace()
103e5c31af7Sopenharmony_ci    if not success:
104e5c31af7Sopenharmony_ci        exit(1)
105e5c31af7Sopenharmony_ci
106e5c31af7Sopenharmony_ciif __name__ == '__main__':
107e5c31af7Sopenharmony_ci    main()
108