OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Wrapper script to help run clang tools across Chromium code. | 6 """Wrapper script to help run clang tools across Chromium code. |
7 | 7 |
8 How to use this tool: | 8 How to use this tool: |
9 If you want to run the tool across all Chromium code: | 9 If you want to run the tool across all Chromium code: |
10 run_tool.py <tool> <path/to/compiledb> | 10 run_tool.py <tool> <path/to/compiledb> |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
47 Edit = collections.namedtuple( | 47 Edit = collections.namedtuple( |
48 'Edit', ('edit_type', 'offset', 'length', 'replacement')) | 48 'Edit', ('edit_type', 'offset', 'length', 'replacement')) |
49 | 49 |
50 | 50 |
51 def _GetFilesFromGit(paths = None): | 51 def _GetFilesFromGit(paths = None): |
52 """Gets the list of files in the git repository. | 52 """Gets the list of files in the git repository. |
53 | 53 |
54 Args: | 54 Args: |
55 paths: Prefix filter for the returned paths. May contain multiple entries. | 55 paths: Prefix filter for the returned paths. May contain multiple entries. |
56 """ | 56 """ |
57 args = ['git', 'ls-files'] | 57 args = ['git.bat', 'ls-files'] |
dcheng
2014/11/11 23:36:07
Yay, Windows.
| |
58 if paths: | 58 if paths: |
59 args.extend(paths) | 59 args.extend(paths) |
60 command = subprocess.Popen(args, stdout=subprocess.PIPE) | 60 command = subprocess.Popen(args, stdout=subprocess.PIPE) |
61 output, _ = command.communicate() | 61 output, _ = command.communicate() |
62 return output.splitlines() | 62 return output.splitlines() |
63 | 63 |
64 | 64 |
65 def _ExtractEditsFromStdout(build_directory, stdout): | 65 def _ExtractEditsFromStdout(build_directory, stdout): |
66 """Extracts generated list of edits from the tool's stdout. | 66 """Extracts generated list of edits from the tool's stdout. |
67 | 67 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
133 Args: | 133 Args: |
134 toolname: Path to the tool to execute. | 134 toolname: Path to the tool to execute. |
135 build_directory: Directory that contains the compile database. | 135 build_directory: Directory that contains the compile database. |
136 filenames: The files to run the tool over. | 136 filenames: The files to run the tool over. |
137 """ | 137 """ |
138 self.__toolname = toolname | 138 self.__toolname = toolname |
139 self.__build_directory = build_directory | 139 self.__build_directory = build_directory |
140 self.__filenames = filenames | 140 self.__filenames = filenames |
141 self.__success_count = 0 | 141 self.__success_count = 0 |
142 self.__failed_count = 0 | 142 self.__failed_count = 0 |
143 self.__edit_count = 0 | |
dcheng
2014/11/11 23:36:07
I'll probably upstream this elsewhere--it's always
dcheng
2014/11/11 23:36:07
I'll probably upstream this elsewhere--it's always
| |
143 self.__edits = collections.defaultdict(list) | 144 self.__edits = collections.defaultdict(list) |
144 | 145 |
145 @property | 146 @property |
146 def edits(self): | 147 def edits(self): |
147 return self.__edits | 148 return self.__edits |
148 | 149 |
149 @property | 150 @property |
150 def failed_count(self): | 151 def failed_count(self): |
151 return self.__failed_count | 152 return self.__failed_count |
152 | 153 |
(...skipping 12 matching lines...) Expand all Loading... | |
165 def __ProcessResult(self, result): | 166 def __ProcessResult(self, result): |
166 """Handles result processing. | 167 """Handles result processing. |
167 | 168 |
168 Args: | 169 Args: |
169 result: The result dictionary returned by _ExecuteTool. | 170 result: The result dictionary returned by _ExecuteTool. |
170 """ | 171 """ |
171 if result['status']: | 172 if result['status']: |
172 self.__success_count += 1 | 173 self.__success_count += 1 |
173 for k, v in result['edits'].iteritems(): | 174 for k, v in result['edits'].iteritems(): |
174 self.__edits[k].extend(v) | 175 self.__edits[k].extend(v) |
176 self.__edit_count += len(v) | |
175 else: | 177 else: |
176 self.__failed_count += 1 | 178 self.__failed_count += 1 |
177 sys.stdout.write('\nFailed to process %s\n' % result['filename']) | 179 sys.stdout.write('\nFailed to process %s\n' % result['filename']) |
178 sys.stdout.write(result['stderr']) | 180 sys.stdout.write(result['stderr']) |
179 sys.stdout.write('\n') | 181 sys.stdout.write('\n') |
180 percentage = ( | 182 percentage = ( |
181 float(self.__success_count + self.__failed_count) / | 183 float(self.__success_count + self.__failed_count) / |
182 len(self.__filenames)) * 100 | 184 len(self.__filenames)) * 100 |
183 sys.stdout.write('Succeeded: %d, Failed: %d [%.2f%%]\r' % ( | 185 sys.stdout.write('Succeeded: %d, Failed: %d, Edits: %d [%.2f%%]\r' % ( |
184 self.__success_count, self.__failed_count, percentage)) | 186 self.__success_count, self.__failed_count, self.__edit_count, |
187 percentage)) | |
185 sys.stdout.flush() | 188 sys.stdout.flush() |
186 | 189 |
187 | 190 |
188 def _ApplyEdits(edits, clang_format_diff_path): | 191 def _ApplyEdits(edits, clang_format_diff_path): |
189 """Apply the generated edits. | 192 """Apply the generated edits. |
190 | 193 |
191 Args: | 194 Args: |
192 edits: A dict mapping filenames to Edit instances that apply to that file. | 195 edits: A dict mapping filenames to Edit instances that apply to that file. |
193 clang_format_diff_path: Path to the clang-format-diff.py helper to help | 196 clang_format_diff_path: Path to the clang-format-diff.py helper to help |
194 automatically reformat diffs to avoid style violations. Pass None if the | 197 automatically reformat diffs to avoid style violations. Pass None if the |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
278 print ' <path 1> <path2> ... can be used to filter what files are edited' | 281 print ' <path 1> <path2> ... can be used to filter what files are edited' |
279 return 1 | 282 return 1 |
280 | 283 |
281 clang_format_diff_path = os.path.join( | 284 clang_format_diff_path = os.path.join( |
282 os.path.dirname(os.path.realpath(__file__)), | 285 os.path.dirname(os.path.realpath(__file__)), |
283 '../../../third_party/llvm/tools/clang/tools/clang-format', | 286 '../../../third_party/llvm/tools/clang/tools/clang-format', |
284 'clang-format-diff.py') | 287 'clang-format-diff.py') |
285 # TODO(dcheng): Allow this to be controlled with a flag as well. | 288 # TODO(dcheng): Allow this to be controlled with a flag as well. |
286 if not os.path.isfile(clang_format_diff_path): | 289 if not os.path.isfile(clang_format_diff_path): |
287 clang_format_diff_path = None | 290 clang_format_diff_path = None |
291 clang_format_diff_path = None | |
288 | 292 |
289 filenames = frozenset(_GetFilesFromGit(argv[2:])) | 293 filenames = frozenset(_GetFilesFromGit(argv[2:])) |
290 # Filter out files that aren't C/C++/Obj-C/Obj-C++. | 294 # Filter out files that aren't C/C++/Obj-C/Obj-C++. |
291 extensions = frozenset(('.c', '.cc', '.m', '.mm')) | 295 extensions = frozenset(('.c', '.cc', '.m', '.mm')) |
292 dispatcher = _CompilerDispatcher(argv[0], argv[1], | 296 dispatcher = _CompilerDispatcher(argv[0], argv[1], |
293 [f for f in filenames | 297 [f for f in filenames |
294 if os.path.splitext(f)[1] in extensions]) | 298 if os.path.splitext(f)[1] in extensions]) |
295 dispatcher.Run() | 299 dispatcher.Run() |
296 # Filter out edits to files that aren't in the git repository, since it's not | 300 # Filter out edits to files that aren't in the git repository, since it's not |
297 # useful to modify files that aren't under source control--typically, these | 301 # useful to modify files that aren't under source control--typically, these |
298 # are generated files or files in a git submodule that's not part of Chromium. | 302 # are generated files or files in a git submodule that's not part of Chromium. |
299 _ApplyEdits({k : v for k, v in dispatcher.edits.iteritems() | 303 _ApplyEdits({k : v for k, v in dispatcher.edits.iteritems() |
300 if k in filenames}, | 304 if k in filenames}, |
301 clang_format_diff_path) | 305 clang_format_diff_path) |
302 if dispatcher.failed_count != 0: | 306 if dispatcher.failed_count != 0: |
303 return 2 | 307 return 2 |
304 return 0 | 308 return 0 |
305 | 309 |
306 | 310 |
307 if __name__ == '__main__': | 311 if __name__ == '__main__': |
308 sys.exit(main(sys.argv[1:])) | 312 sys.exit(main(sys.argv[1:])) |
OLD | NEW |