Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(754)

Side by Side Diff: tools/checkdeps/checkdeps.py

Issue 10805042: Implement ability to specify temporarily-allowed dependencies in DEPS (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove unneeded import. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 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 """Makes sure that files include headers from allowed directories. 6 """Makes sure that files include headers from allowed directories.
7 7
8 Checks DEPS files in the source tree for rules, and applies those rules to 8 Checks DEPS files in the source tree for rules, and applies those rules to
9 "#include" commands in source files. Any source file including something not 9 "#include" commands in source files. Any source file including something not
10 permitted by the DEPS files will fail. 10 permitted by the DEPS files will fail.
11 11
12 The format of the deps file: 12 The format of the deps file:
13 13
14 First you have the normal module-level deps. These are the ones used by 14 First you have the normal module-level deps. These are the ones used by
15 gclient. An example would be: 15 gclient. An example would be:
16 16
17 deps = { 17 deps = {
18 "base":"http://foo.bar/trunk/base" 18 "base":"http://foo.bar/trunk/base"
19 } 19 }
20 20
21 DEPS files not in the top-level of a module won't need this. Then you have 21 DEPS files not in the top-level of a module won't need this. Then you
22 any additional include rules. You can add (using "+") or subtract (using "-") 22 have any additional include rules. You can add (using "+") or subtract
23 from the previously specified rules (including module-level deps). 23 (using "-") from the previously specified rules (including
24 module-level deps). You can also specify a path that is allowed for
25 now but that we intend to remove, using "!"; this is treated the same
26 as "+" when check_deps is run by our bots, but a presubmit step will
27 show a warning if you add a new include of a file that is only allowed
28 by "!".
29
30 Note that for .java files, there is currently no difference between
31 "+" and "!", even in the presubmit step.
24 32
25 include_rules = { 33 include_rules = {
26 # Code should be able to use base (it's specified in the module-level 34 # Code should be able to use base (it's specified in the module-level
27 # deps above), but nothing in "base/evil" because it's evil. 35 # deps above), but nothing in "base/evil" because it's evil.
28 "-base/evil", 36 "-base/evil",
29 37
30 # But this one subdirectory of evil is OK. 38 # But this one subdirectory of evil is OK.
31 "+base/evil/not", 39 "+base/evil/not",
32 40
33 # And it can include files from this other directory even though there is 41 # And it can include files from this other directory even though there is
34 # no deps rule for it. 42 # no deps rule for it.
35 "+tools/crime_fighter" 43 "+tools/crime_fighter",
44
45 # This dependency is allowed for now but work is ongoing to remove it,
46 # so you shouldn't add further dependencies on it.
47 "!base/evil/ok_for_now.h",
36 } 48 }
37 49
38 DEPS files may be placed anywhere in the tree. Each one applies to all 50 DEPS files may be placed anywhere in the tree. Each one applies to all
39 subdirectories, where there may be more DEPS files that provide additions or 51 subdirectories, where there may be more DEPS files that provide additions or
40 subtractions for their own sub-trees. 52 subtractions for their own sub-trees.
41 53
42 There is an implicit rule for the current directory (where the DEPS file lives) 54 There is an implicit rule for the current directory (where the DEPS file lives)
43 and all of its subdirectories. This prevents you from having to explicitly 55 and all of its subdirectories. This prevents you from having to explicitly
44 allow the current directory everywhere. This implicit rule is applied first, 56 allow the current directory everywhere. This implicit rule is applied first,
45 so you can modify or remove it using the normal include rules. 57 so you can modify or remove it using the normal include rules.
46 58
47 The rules are processed in order. This means you can explicitly allow a higher 59 The rules are processed in order. This means you can explicitly allow a higher
48 directory and then take away permissions from sub-parts, or the reverse. 60 directory and then take away permissions from sub-parts, or the reverse.
49 61
50 Note that all directory separators must be slashes (Unix-style) and not 62 Note that all directory separators must be slashes (Unix-style) and not
51 backslashes. All directories should be relative to the source root and use 63 backslashes. All directories should be relative to the source root and use
52 only lowercase. 64 only lowercase.
53 """ 65 """
54 66
55 import os 67 import os
56 import optparse 68 import optparse
57 import pipes 69 import subprocess
58 import sys 70 import sys
59 import copy 71 import copy
60 72
61 import cpp_checker 73 import cpp_checker
62 import java_checker 74 import java_checker
75 from rules import Rule, Rules
63 76
64 77
65 # Variable name used in the DEPS file to add or subtract include files from 78 # Variable name used in the DEPS file to add or subtract include files from
66 # the module-level deps. 79 # the module-level deps.
67 INCLUDE_RULES_VAR_NAME = "include_rules" 80 INCLUDE_RULES_VAR_NAME = "include_rules"
68 81
69 # Optionally present in the DEPS file to list subdirectories which should not 82 # Optionally present in the DEPS file to list subdirectories which should not
70 # be checked. This allows us to skip third party code, for example. 83 # be checked. This allows us to skip third party code, for example.
71 SKIP_SUBDIRS_VAR_NAME = "skip_child_includes" 84 SKIP_SUBDIRS_VAR_NAME = "skip_child_includes"
72 85
73 # Set to true for more output. This is set by the command line options. 86 # Set to true for more output. This is set by the command line options.
74 VERBOSE = False 87 VERBOSE = False
75 88
76 # In lowercase, using forward slashes as directory separators, ending in a 89 # OS-compatible path for base directory (e.g. C:\chrome\src). Set
77 # forward slash. Set by the command line options. 90 # implicitly or by command-line option.
78 BASE_DIRECTORY = "" 91 BASE_DIRECTORY = ""
79 92
80 # The directories which contain the sources managed by git. 93 # The directories which contain the sources managed by git.
81 GIT_SOURCE_DIRECTORY = set() 94 GIT_SOURCE_DIRECTORY = set()
82 95
83 96
84 # Specifies a single rule for an include, which can be either allow or disallow.
85 class Rule(object):
86 def __init__(self, allow, directory, source):
87 self.allow = allow
88 self._dir = directory
89 self._source = source
90
91 def __str__(self):
92 if (self.allow):
93 return '"+%s" from %s.' % (self._dir, self._source)
94 return '"-%s" from %s.' % (self._dir, self._source)
95
96 def ParentOrMatch(self, other):
97 """Returns true if the input string is an exact match or is a parent
98 of the current rule. For example, the input "foo" would match "foo/bar"."""
99 return self._dir == other or self._dir.startswith(other + "/")
100
101 def ChildOrMatch(self, other):
102 """Returns true if the input string would be covered by this rule. For
103 example, the input "foo/bar" would match the rule "foo"."""
104 return self._dir == other or other.startswith(self._dir + "/")
105
106
107 def ParseRuleString(rule_string, source):
108 """Returns a tuple of a boolean indicating whether the directory is an allow
109 rule, and a string holding the directory name.
110 """
111 if len(rule_string) < 1:
112 raise Exception('The rule string "%s" is too short\nin %s' %
113 (rule_string, source))
114
115 if rule_string[0] == "+":
116 return (True, rule_string[1:])
117 if rule_string[0] == "-":
118 return (False, rule_string[1:])
119 raise Exception('The rule string "%s" does not begin with a "+" or a "-"' %
120 rule_string)
121
122
123 class Rules:
124 def __init__(self):
125 """Initializes the current rules with an empty rule list."""
126 self._rules = []
127
128 def __str__(self):
129 ret = "Rules = [\n"
130 ret += "\n".join([" %s" % x for x in self._rules])
131 ret += "]\n"
132 return ret
133
134 def AddRule(self, rule_string, source):
135 """Adds a rule for the given rule string.
136
137 Args:
138 rule_string: The include_rule string read from the DEPS file to apply.
139 source: A string representing the location of that string (filename, etc.)
140 so that we can give meaningful errors.
141 """
142 (add_rule, rule_dir) = ParseRuleString(rule_string, source)
143 # Remove any existing rules or sub-rules that apply. For example, if we're
144 # passed "foo", we should remove "foo", "foo/bar", but not "foobar".
145 self._rules = [x for x in self._rules if not x.ParentOrMatch(rule_dir)]
146 self._rules.insert(0, Rule(add_rule, rule_dir, source))
147
148 def DirAllowed(self, allowed_dir):
149 """Returns a tuple (success, message), where success indicates if the given
150 directory is allowed given the current set of rules, and the message tells
151 why if the comparison failed."""
152 for rule in self._rules:
153 if rule.ChildOrMatch(allowed_dir):
154 # This rule applies.
155 if rule.allow:
156 return (True, "")
157 return (False, rule.__str__())
158 # No rules apply, fail.
159 return (False, "no rule applying")
160
161
162 def ApplyRules(existing_rules, includes, cur_dir): 97 def ApplyRules(existing_rules, includes, cur_dir):
163 """Applies the given include rules, returning the new rules. 98 """Applies the given include rules, returning the new rules.
164 99
165 Args: 100 Args:
166 existing_rules: A set of existing rules that will be combined. 101 existing_rules: A set of existing rules that will be combined.
167 include: The list of rules from the "include_rules" section of DEPS. 102 include: The list of rules from the "include_rules" section of DEPS.
168 cur_dir: The current directory. We will create an implicit rule that 103 cur_dir: The current directory. We will create an implicit rule that
169 allows inclusion from this directory. 104 allows inclusion from this directory.
170 105
171 Returns: A new set of rules combining the existing_rules with the other 106 Returns: A new set of rules combining the existing_rules with the other
172 arguments. 107 arguments.
173 """ 108 """
174 rules = copy.copy(existing_rules) 109 rules = copy.copy(existing_rules)
175 110
176 # First apply the implicit "allow" rule for the current directory. 111 # First apply the implicit "allow" rule for the current directory.
177 if cur_dir.lower().startswith(BASE_DIRECTORY): 112 if os.path.normcase(os.path.normpath(cur_dir)).startswith(
M-A Ruel 2012/07/26 13:06:03 normcase is totally useless: http://docs.python.or
Jói 2012/07/26 13:32:13 Done.
113 os.path.normcase(os.path.normpath(BASE_DIRECTORY))):
178 relative_dir = cur_dir[len(BASE_DIRECTORY) + 1:] 114 relative_dir = cur_dir[len(BASE_DIRECTORY) + 1:]
179 # Normalize path separators to slashes.
180 relative_dir = relative_dir.replace("\\", "/")
181 source = relative_dir 115 source = relative_dir
182 if len(source) == 0: 116 if len(source) == 0:
183 source = "top level" # Make the help string a little more meaningful. 117 source = "top level" # Make the help string a little more meaningful.
184 rules.AddRule("+" + relative_dir, "Default rule for " + source) 118 rules.AddRule("+" + relative_dir, "Default rule for " + source)
185 else: 119 else:
186 raise Exception("Internal error: base directory is not at the beginning" + 120 raise Exception("Internal error: base directory is not at the beginning" +
187 " for\n %s and base dir\n %s" % 121 " for\n %s and base dir\n %s" %
188 (cur_dir, BASE_DIRECTORY)) 122 (cur_dir, BASE_DIRECTORY))
189 123
190 # Last, apply the additional explicit rules. 124 # Last, apply the additional explicit rules.
(...skipping 21 matching lines...) Expand all
212 This will also be used to generate the implicit rules. 146 This will also be used to generate the implicit rules.
213 147
214 Returns: A tuple containing: (1) the combined set of rules to apply to the 148 Returns: A tuple containing: (1) the combined set of rules to apply to the
215 sub-tree, and (2) a list of all subdirectories that should NOT be 149 sub-tree, and (2) a list of all subdirectories that should NOT be
216 checked, as specified in the DEPS file (if any). 150 checked, as specified in the DEPS file (if any).
217 """ 151 """
218 # Check for a .svn directory in this directory or check this directory is 152 # Check for a .svn directory in this directory or check this directory is
219 # contained in git source direcotries. This will tell us if it's a source 153 # contained in git source direcotries. This will tell us if it's a source
220 # directory and should be checked. 154 # directory and should be checked.
221 if not (os.path.exists(os.path.join(dir_name, ".svn")) or 155 if not (os.path.exists(os.path.join(dir_name, ".svn")) or
222 (dir_name.lower() in GIT_SOURCE_DIRECTORY)): 156 (dir_name in GIT_SOURCE_DIRECTORY)):
M-A Ruel 2012/07/26 13:06:03 Same here: any(dir_name.lower() == i.lower() for i
Jói 2012/07/26 13:32:13 Done, by making the paths lower-case when adding t
223 return (None, []) 157 return (None, [])
224 158
225 # Check the DEPS file in this directory. 159 # Check the DEPS file in this directory.
226 if VERBOSE: 160 if VERBOSE:
227 print "Applying rules from", dir_name 161 print "Applying rules from", dir_name
228 def FromImpl(_unused, _unused2): 162 def FromImpl(_unused, _unused2):
229 pass # NOP function so "From" doesn't fail. 163 pass # NOP function so "From" doesn't fail.
230 164
231 def FileImpl(_unused): 165 def FileImpl(_unused):
232 pass # NOP function so "File" doesn't fail. 166 pass # NOP function so "File" doesn't fail.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 success = False 224 success = False
291 225
292 # Next recurse into the subdirectories. 226 # Next recurse into the subdirectories.
293 for cur in dirs_to_check: 227 for cur in dirs_to_check:
294 if not CheckDirectory(rules, checkers, cur): 228 if not CheckDirectory(rules, checkers, cur):
295 success = False 229 success = False
296 230
297 return success 231 return success
298 232
299 233
234 def CheckAddedIncludes(added_includes):
235 """This is used from PRESUBMIT.py to check new #include statements added in
236 the change being presubmit checked.
237
238 Args:
239 added_includes: ((file_path, (include_line, include_line, ...), ...)
240
241 Return:
242 A list of tuples, (bad_file_path, rule_type, rule_description)
243 where rule_type is one of Rule.DISALLOW or Rule.TEMP_ALLOW and
244 rule_description is human-readable. Empty if no problems.
245 """
246 CommonSetup()
247
248 # Map of directory paths to rules to use for those directories, or
249 # None for directories that should be skipped.
250 directory_rules = {}
251
252 def ApplyDirectoryRulesAndSkipSubdirs(parent_rules, dir_path):
253 rules_tuple = ApplyDirectoryRules(parent_rules, dir_path)
254 directory_rules[dir_path] = rules_tuple[0]
255 for subdir in rules_tuple[1]:
256 directory_rules[os.path.join(dir_path, subdir)] = None
257
258 ApplyDirectoryRulesAndSkipSubdirs(Rules(), BASE_DIRECTORY)
259
260 def GetDirectoryRules(dir_path):
261 """Returns a Rules object to use for the given directory, or None
262 if the given directory should be skipped.
263 """
264 if not dir_path.startswith(BASE_DIRECTORY):
265 dir_path = os.path.join(BASE_DIRECTORY, dir_path)
266
267 parent_dir = os.path.dirname(dir_path)
268 parent_rules = None
269 if not dir_path in directory_rules:
270 parent_rules = GetDirectoryRules(parent_dir)
271
272 # We need to check for an entry for our dir_path again, in case we
273 # are at a path e.g. A/B/C where A/B/DEPS specifies the C
274 # subdirectory to be skipped; in this case, the invocation to
275 # GetDirectoryRules(parent_dir) has already filled in an entry for
276 # A/B/C.
277 if not dir_path in directory_rules:
278 if not parent_rules:
279 # If the parent directory should be skipped, then the current
280 # directory should also be skipped.
281 directory_rules[dir_path] = None
282 else:
283 ApplyDirectoryRulesAndSkipSubdirs(parent_rules, dir_path)
284 return directory_rules[dir_path]
285
286 cpp = cpp_checker.CppChecker(VERBOSE)
287
288 problems = []
289 for file_path, include_lines in added_includes:
290 # TODO(joi): Make this cover Java as well.
291 if not os.path.splitext(file_path)[1] in cpp.EXTENSIONS:
292 pass
293 rules_for_file = GetDirectoryRules(os.path.dirname(file_path))
294 if rules_for_file:
295 for line in include_lines:
296 is_include, line_status, rule_type = cpp.CheckLine(
297 rules_for_file, line, True)
298 if rule_type != Rule.ALLOW:
299 problems.append((file_path, rule_type, line_status))
300 return problems
301
302
303 def TestCheckAddedIncludes():
M-A Ruel 2012/07/26 13:06:03 This function should be in a checkdeps_test.py and
Jói 2012/07/26 13:32:13 Made it a separate checkdeps_manualtest.py file (m
304 """Run this by giving the argument 'manualtest' to checkdeps."""
M-A Ruel 2012/07/26 13:06:03 Runs this What is "this" ?
Jói 2012/07/26 13:32:13 Removed this comment, it is meaningless in the new
305 # Note that these tests depend on the rules currently in DEPS files
306 # checked into the tree, which may change. Therefore the test is
307 # only run manually and may need to be updated from time to time.
308 problems = CheckAddedIncludes(
309 # The first of these should fail as a DISALLOW, the second should
310 # fail as a TEMP_ALLOW, because of rules in chrome/browser/DEPS.
311 [['chrome/browser/bingo.cc',
312 ['#include "chrome/browser/ui/views/boondog.h"',
313 '#include "chrome/browser/ui/views/ash/panel_view_aura.h"']],
314 # This should fail because of no rule applying.
315 ['chrome/browser/lifetime/bongo.cc', ['#include "fantastic/food.h"']],
316 # The following two shouldn't fail as they are under a directory
317 # that is skipped for checking, in src/DEPS.
318 ['breakpad/fooblat.cc', ['#include "fantastic/food.h"']],
319 ['breakpad/bingo/bongo/fooblat.cc', ['#include "fantastic/food.h"']],
320 ])
321
322 for problem in problems:
323 print problem[0]
324 print problem[1]
325 print problem[2]
326 print
327 print
328
329
300 def GetGitSourceDirectory(root): 330 def GetGitSourceDirectory(root):
301 """Returns a set of the directories to be checked. 331 """Returns a set of the directories to be checked.
302 332
303 Args: 333 Args:
304 root: The repository root where .git directory exists. 334 root: The repository root where .git directory exists.
305 335
306 Returns: 336 Returns:
307 A set of directories which contain sources managed by git. 337 A set of directories which contain sources managed by git.
308 """ 338 """
309 git_source_directory = set() 339 git_source_directory = set()
310 popen_out = os.popen("cd %s && git ls-files --full-name ." % 340 popen_out = os.popen("cd %s && git ls-files --full-name ." %
311 pipes.quote(root)) 341 subprocess.list2cmdline([root]))
312 for line in popen_out.readlines(): 342 for line in popen_out.readlines():
313 dir_name = os.path.join(root, os.path.dirname(line)) 343 dir_name = os.path.join(root, os.path.dirname(line))
314 # Add the directory as well as all the parent directories. 344 # Add the directory as well as all the parent directories.
315 while dir_name != root: 345 while dir_name != root:
316 git_source_directory.add(dir_name) 346 git_source_directory.add(dir_name)
317 dir_name = os.path.dirname(dir_name) 347 dir_name = os.path.dirname(dir_name)
318 git_source_directory.add(root) 348 git_source_directory.add(root)
319 return git_source_directory 349 return git_source_directory
320 350
321 351
352 def CommonSetup(base_dir=None):
353 """Setup that is in common between the main() entrypoint to this
354 script and the CheckAddedIncludes (presubmit check) entrypoint.
355 """
356 global BASE_DIRECTORY
357 global GIT_SOURCE_DIRECTORY
358
359 if base_dir:
360 BASE_DIRECTORY = base_dir
361 else:
362 BASE_DIRECTORY = os.path.abspath(
363 os.path.join(os.path.abspath(os.path.dirname(__file__)), "../.."))
364
365 if os.path.exists(os.path.join(BASE_DIRECTORY, ".git")):
366 GIT_SOURCE_DIRECTORY = GetGitSourceDirectory(BASE_DIRECTORY)
367
368
322 def PrintUsage(): 369 def PrintUsage():
323 print """Usage: python checkdeps.py [--root <root>] [tocheck] 370 print """Usage: python checkdeps.py [--root <root>] [tocheck]
324 --root Specifies the repository root. This defaults to "../../.." relative 371 --root Specifies the repository root. This defaults to "../../.." relative
325 to the script file. This will be correct given the normal location 372 to the script file. This will be correct given the normal location
326 of the script in "<root>/tools/checkdeps". 373 of the script in "<root>/tools/checkdeps".
327 374
328 tocheck Specifies the directory, relative to root, to check. This defaults 375 tocheck Specifies the directory, relative to root, to check. This defaults
329 to "." so it checks everything. Only one level deep is currently 376 to "." so it checks everything. Only one level deep is currently
330 supported, so you can say "chrome" but not "chrome/browser". 377 supported, so you can say "chrome" but not "chrome/browser".
331 378
332 Examples: 379 Examples:
333 python checkdeps.py 380 python checkdeps.py
334 python checkdeps.py --root c:\\source chrome""" 381 python checkdeps.py --root c:\\source chrome"""
335 382
336 383
337 def checkdeps(options, args): 384 def checkdeps(options, args):
385 global BASE_DIRECTORY
M-A Ruel 2012/07/26 13:06:03 It'd be simpler if it was not a global. Same for G
Jói 2012/07/26 13:32:13 I'm not sure I follow, I get that it's harder to u
M-A Ruel 2012/07/26 13:50:51 global as in module global, since this is python.
Jói 2012/07/26 17:05:52 Done, I made these members of a checkdeps.DepsChec
338 global VERBOSE 386 global VERBOSE
339 if options.verbose: 387 if options.verbose:
340 VERBOSE = True 388 VERBOSE = True
341 389
342 # Optional base directory of the repository. 390 # Optional base directory of the repository.
343 global BASE_DIRECTORY
344 if not options.base_directory: 391 if not options.base_directory:
345 BASE_DIRECTORY = os.path.abspath( 392 CommonSetup()
346 os.path.join(os.path.abspath(os.path.dirname(__file__)), "../.."))
347 else: 393 else:
348 BASE_DIRECTORY = os.path.abspath(options.base_directory) 394 CommonSetup(os.path.abspath(options.base_directory))
349 395
350 # Figure out which directory we have to check. 396 # Figure out which directory we have to check.
351 if len(args) == 0: 397 if len(args) == 0:
352 # No directory to check specified, use the repository root. 398 # No directory to check specified, use the repository root.
353 start_dir = BASE_DIRECTORY 399 start_dir = BASE_DIRECTORY
354 elif len(args) == 1: 400 elif len(args) == 1:
355 # Directory specified. Start here. It's supposed to be relative to the 401 # Directory specified. Start here. It's supposed to be relative to the
356 # base directory. 402 # base directory.
357 start_dir = os.path.abspath(os.path.join(BASE_DIRECTORY, args[0])) 403 start_dir = os.path.abspath(os.path.join(BASE_DIRECTORY, args[0]))
358 else: 404 else:
359 # More than one argument, we don't handle this. 405 # More than one argument, we don't handle this.
360 PrintUsage() 406 PrintUsage()
361 return 1 407 return 1
362 408
363 print "Using base directory:", BASE_DIRECTORY 409 print "Using base directory:", BASE_DIRECTORY
364 print "Checking:", start_dir 410 print "Checking:", start_dir
365 411
366 base_rules = Rules() 412 base_rules = Rules()
367
368 # The base directory should be lower case from here on since it will be used
369 # for substring matching on the includes, and we compile on case-insensitive
370 # systems. Plus, we always use slashes here since the include parsing code
371 # will also normalize to slashes.
372 BASE_DIRECTORY = BASE_DIRECTORY.lower()
373 BASE_DIRECTORY = BASE_DIRECTORY.replace("\\", "/")
374 start_dir = start_dir.replace("\\", "/")
375
376 if os.path.exists(os.path.join(BASE_DIRECTORY, ".git")):
377 global GIT_SOURCE_DIRECTORY
378 GIT_SOURCE_DIRECTORY = GetGitSourceDirectory(BASE_DIRECTORY)
379
380 java = java_checker.JavaChecker(BASE_DIRECTORY, VERBOSE) 413 java = java_checker.JavaChecker(BASE_DIRECTORY, VERBOSE)
381 cpp = cpp_checker.CppChecker(VERBOSE) 414 cpp = cpp_checker.CppChecker(VERBOSE)
382 checkers = dict( 415 checkers = dict(
383 (extension, checker) 416 (extension, checker)
384 for checker in [java, cpp] for extension in checker.EXTENSIONS) 417 for checker in [java, cpp] for extension in checker.EXTENSIONS)
385 success = CheckDirectory(base_rules, checkers, start_dir) 418 success = CheckDirectory(base_rules, checkers, start_dir)
386 if not success: 419 if not success:
387 print "\nFAILED\n" 420 print "\nFAILED\n"
388 return 1 421 return 1
389 print "\nSUCCESS\n" 422 print "\nSUCCESS\n"
390 return 0 423 return 0
391 424
392 425
393 def main(): 426 def main():
394 option_parser = optparse.OptionParser() 427 option_parser = optparse.OptionParser()
395 option_parser.add_option("", "--root", default="", dest="base_directory", 428 option_parser.add_option("", "--root", default="", dest="base_directory",
396 help='Specifies the repository root. This defaults ' 429 help='Specifies the repository root. This defaults '
397 'to "../../.." relative to the script file, which ' 430 'to "../../.." relative to the script file, which '
398 'will normally be the repository root.') 431 'will normally be the repository root.')
399 option_parser.add_option("-v", "--verbose", action="store_true", 432 option_parser.add_option("-v", "--verbose", action="store_true",
400 default=False, help="Print debug logging") 433 default=False, help="Print debug logging")
401 options, args = option_parser.parse_args() 434 options, args = option_parser.parse_args()
402 return checkdeps(options, args) 435 if args and args[0] == "manualtest":
436 return TestCheckAddedIncludes()
437 else:
438 return checkdeps(options, args)
403 439
404 440
405 if '__main__' == __name__: 441 if '__main__' == __name__:
406 sys.exit(main()) 442 sys.exit(main())
OLDNEW
« no previous file with comments | « chrome/test/DEPS ('k') | tools/checkdeps/cpp_checker.py » ('j') | tools/checkdeps/rules.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698