Bug 1691109 [wpt PR 27513] - Increase timeout duration for wpt/fetch/api/basic/keepal...
[gecko.git] / third_party / aom / tools / lint-hunks.py
blobd02bee16cebe9a13a2f2dac047bc914da93ad74b
1 #!/usr/bin/python
2 ##
3 ## Copyright (c) 2016, Alliance for Open Media. All rights reserved
4 ##
5 ## This source code is subject to the terms of the BSD 2 Clause License and
6 ## the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
7 ## was not distributed with this source code in the LICENSE file, you can
8 ## obtain it at www.aomedia.org/license/software. If the Alliance for Open
9 ## Media Patent License 1.0 was not distributed with this source code in the
10 ## PATENTS file, you can obtain it at www.aomedia.org/license/patent.
12 """Performs style checking on each diff hunk."""
13 import getopt
14 import os
15 import StringIO
16 import subprocess
17 import sys
19 import diff
22 SHORT_OPTIONS = "h"
23 LONG_OPTIONS = ["help"]
25 TOPLEVEL_CMD = ["git", "rev-parse", "--show-toplevel"]
26 DIFF_CMD = ["git", "diff"]
27 DIFF_INDEX_CMD = ["git", "diff-index", "-u", "HEAD", "--"]
28 SHOW_CMD = ["git", "show"]
29 CPPLINT_FILTERS = ["-readability/casting"]
32 class Usage(Exception):
33 pass
36 class SubprocessException(Exception):
37 def __init__(self, args):
38 msg = "Failed to execute '%s'"%(" ".join(args))
39 super(SubprocessException, self).__init__(msg)
42 class Subprocess(subprocess.Popen):
43 """Adds the notion of an expected returncode to Popen."""
45 def __init__(self, args, expected_returncode=0, **kwargs):
46 self._args = args
47 self._expected_returncode = expected_returncode
48 super(Subprocess, self).__init__(args, **kwargs)
50 def communicate(self, *args, **kwargs):
51 result = super(Subprocess, self).communicate(*args, **kwargs)
52 if self._expected_returncode is not None:
53 try:
54 ok = self.returncode in self._expected_returncode
55 except TypeError:
56 ok = self.returncode == self._expected_returncode
57 if not ok:
58 raise SubprocessException(self._args)
59 return result
62 def main(argv=None):
63 if argv is None:
64 argv = sys.argv
65 try:
66 try:
67 opts, args = getopt.getopt(argv[1:], SHORT_OPTIONS, LONG_OPTIONS)
68 except getopt.error, msg:
69 raise Usage(msg)
71 # process options
72 for o, _ in opts:
73 if o in ("-h", "--help"):
74 print __doc__
75 sys.exit(0)
77 if args and len(args) > 1:
78 print __doc__
79 sys.exit(0)
81 # Find the fully qualified path to the root of the tree
82 tl = Subprocess(TOPLEVEL_CMD, stdout=subprocess.PIPE)
83 tl = tl.communicate()[0].strip()
85 # See if we're working on the index or not.
86 if args:
87 diff_cmd = DIFF_CMD + [args[0] + "^!"]
88 else:
89 diff_cmd = DIFF_INDEX_CMD
91 # Build the command line to execute cpplint
92 cpplint_cmd = [os.path.join(tl, "tools", "cpplint.py"),
93 "--filter=" + ",".join(CPPLINT_FILTERS),
94 "-"]
96 # Get a list of all affected lines
97 file_affected_line_map = {}
98 p = Subprocess(diff_cmd, stdout=subprocess.PIPE)
99 stdout = p.communicate()[0]
100 for hunk in diff.ParseDiffHunks(StringIO.StringIO(stdout)):
101 filename = hunk.right.filename[2:]
102 if filename not in file_affected_line_map:
103 file_affected_line_map[filename] = set()
104 file_affected_line_map[filename].update(hunk.right.delta_line_nums)
106 # Run each affected file through cpplint
107 lint_failed = False
108 for filename, affected_lines in file_affected_line_map.iteritems():
109 if filename.split(".")[-1] not in ("c", "h", "cc"):
110 continue
112 if args:
113 # File contents come from git
114 show_cmd = SHOW_CMD + [args[0] + ":" + filename]
115 show = Subprocess(show_cmd, stdout=subprocess.PIPE)
116 lint = Subprocess(cpplint_cmd, expected_returncode=(0, 1),
117 stdin=show.stdout, stderr=subprocess.PIPE)
118 lint_out = lint.communicate()[1]
119 else:
120 # File contents come from the working tree
121 lint = Subprocess(cpplint_cmd, expected_returncode=(0, 1),
122 stdin=subprocess.PIPE, stderr=subprocess.PIPE)
123 stdin = open(os.path.join(tl, filename)).read()
124 lint_out = lint.communicate(stdin)[1]
126 for line in lint_out.split("\n"):
127 fields = line.split(":")
128 if fields[0] != "-":
129 continue
130 warning_line_num = int(fields[1])
131 if warning_line_num in affected_lines:
132 print "%s:%d:%s"%(filename, warning_line_num,
133 ":".join(fields[2:]))
134 lint_failed = True
136 # Set exit code if any relevant lint errors seen
137 if lint_failed:
138 return 1
140 except Usage, err:
141 print >>sys.stderr, err
142 print >>sys.stderr, "for help use --help"
143 return 2
145 if __name__ == "__main__":
146 sys.exit(main())