OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 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. |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 only lowercase. | 52 only lowercase. |
53 """ | 53 """ |
54 | 54 |
55 import os | 55 import os |
56 import optparse | 56 import optparse |
57 import pipes | 57 import pipes |
58 import re | 58 import re |
59 import sys | 59 import sys |
60 import copy | 60 import copy |
61 | 61 |
62 # Variable name used in the DEPS file to specify module-level deps. | |
63 DEPS_VAR_NAME = "deps" | |
64 | |
65 # Variable name used in the DEPS file to add or subtract include files from | 62 # Variable name used in the DEPS file to add or subtract include files from |
66 # the module-level deps. | 63 # the module-level deps. |
67 INCLUDE_RULES_VAR_NAME = "include_rules" | 64 INCLUDE_RULES_VAR_NAME = "include_rules" |
68 | 65 |
69 # Optionally present in the DEPS file to list subdirectories which should not | 66 # 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. | 67 # be checked. This allows us to skip third party code, for example. |
71 SKIP_SUBDIRS_VAR_NAME = "skip_child_includes" | 68 SKIP_SUBDIRS_VAR_NAME = "skip_child_includes" |
72 | 69 |
73 # The maximum number of lines to check in each source file before giving up. | 70 # The maximum number of lines to check in each source file before giving up. |
74 MAX_LINES = 150 | 71 MAX_LINES = 150 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 for rule in self._rules: | 160 for rule in self._rules: |
164 if rule.ChildOrMatch(allowed_dir): | 161 if rule.ChildOrMatch(allowed_dir): |
165 # This rule applies. | 162 # This rule applies. |
166 if rule._allow: | 163 if rule._allow: |
167 return (True, "") | 164 return (True, "") |
168 return (False, rule.__str__()) | 165 return (False, rule.__str__()) |
169 # No rules apply, fail. | 166 # No rules apply, fail. |
170 return (False, "no rule applying") | 167 return (False, "no rule applying") |
171 | 168 |
172 | 169 |
173 def ApplyRules(existing_rules, deps, includes, cur_dir): | 170 def ApplyRules(existing_rules, includes, cur_dir): |
174 """Applies the given deps and include rules, returning the new rules. | 171 """Applies the given include rules, returning the new rules. |
175 | 172 |
176 Args: | 173 Args: |
177 existing_rules: A set of existing rules that will be combined. | 174 existing_rules: A set of existing rules that will be combined. |
178 deps: The list of imports from the "deps" section of the DEPS file. | |
179 include: The list of rules from the "include_rules" section of DEPS. | 175 include: The list of rules from the "include_rules" section of DEPS. |
180 cur_dir: The current directory. We will create an implicit rule that | 176 cur_dir: The current directory. We will create an implicit rule that |
181 allows inclusion from this directory. | 177 allows inclusion from this directory. |
182 | 178 |
183 Returns: A new set of rules combining the existing_rules with the other | 179 Returns: A new set of rules combining the existing_rules with the other |
184 arguments. | 180 arguments. |
185 """ | 181 """ |
186 rules = copy.copy(existing_rules) | 182 rules = copy.copy(existing_rules) |
187 | 183 |
188 # First apply the implicit "allow" rule for the current directory. | 184 # First apply the implicit "allow" rule for the current directory. |
189 if cur_dir.lower().startswith(BASE_DIRECTORY): | 185 if cur_dir.lower().startswith(BASE_DIRECTORY): |
190 relative_dir = cur_dir[len(BASE_DIRECTORY) + 1:] | 186 relative_dir = cur_dir[len(BASE_DIRECTORY) + 1:] |
191 # Normalize path separators to slashes. | 187 # Normalize path separators to slashes. |
192 relative_dir = relative_dir.replace("\\", "/") | 188 relative_dir = relative_dir.replace("\\", "/") |
193 source = relative_dir | 189 source = relative_dir |
194 if len(source) == 0: | 190 if len(source) == 0: |
195 source = "top level" # Make the help string a little more meaningful. | 191 source = "top level" # Make the help string a little more meaningful. |
196 rules.AddRule("+" + relative_dir, "Default rule for " + source) | 192 rules.AddRule("+" + relative_dir, "Default rule for " + source) |
197 else: | 193 else: |
198 raise Exception("Internal error: base directory is not at the beginning" + | 194 raise Exception("Internal error: base directory is not at the beginning" + |
199 " for\n %s and base dir\n %s" % | 195 " for\n %s and base dir\n %s" % |
200 (cur_dir, BASE_DIRECTORY)) | 196 (cur_dir, BASE_DIRECTORY)) |
201 | 197 |
202 # Next apply the DEPS additions, these are all allowed. Note that DEPS start | |
203 # out with "src/" which we want to trim. | |
204 for (index, key) in enumerate(deps): | |
205 if key.startswith("src/"): | |
206 key = key[4:] | |
207 rules.AddRule("+" + key, relative_dir + "'s deps for " + key) | |
208 | |
209 # Last, apply the additional explicit rules. | 198 # Last, apply the additional explicit rules. |
210 for (index, rule_str) in enumerate(includes): | 199 for (index, rule_str) in enumerate(includes): |
211 if not len(relative_dir): | 200 if not len(relative_dir): |
212 rule_description = "the top level include_rules" | 201 rule_description = "the top level include_rules" |
213 else: | 202 else: |
214 rule_description = relative_dir + "'s include_rules" | 203 rule_description = relative_dir + "'s include_rules" |
215 rules.AddRule(rule_str, rule_description) | 204 rules.AddRule(rule_str, rule_description) |
216 | 205 |
217 return rules | 206 return rules |
218 | 207 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 } | 257 } |
269 deps_file = os.path.join(dir_name, "DEPS") | 258 deps_file = os.path.join(dir_name, "DEPS") |
270 | 259 |
271 if os.path.isfile(deps_file): | 260 if os.path.isfile(deps_file): |
272 execfile(deps_file, global_scope, local_scope) | 261 execfile(deps_file, global_scope, local_scope) |
273 elif VERBOSE: | 262 elif VERBOSE: |
274 print " No deps file found in", dir_name | 263 print " No deps file found in", dir_name |
275 | 264 |
276 # Even if a DEPS file does not exist we still invoke ApplyRules | 265 # Even if a DEPS file does not exist we still invoke ApplyRules |
277 # to apply the implicit "allow" rule for the current directory | 266 # to apply the implicit "allow" rule for the current directory |
278 deps = local_scope.get(DEPS_VAR_NAME, {}) | |
279 include_rules = local_scope.get(INCLUDE_RULES_VAR_NAME, []) | 267 include_rules = local_scope.get(INCLUDE_RULES_VAR_NAME, []) |
280 skip_subdirs = local_scope.get(SKIP_SUBDIRS_VAR_NAME, []) | 268 skip_subdirs = local_scope.get(SKIP_SUBDIRS_VAR_NAME, []) |
281 | 269 |
282 return (ApplyRules(existing_rules, deps, include_rules, dir_name), | 270 return (ApplyRules(existing_rules, include_rules, dir_name), skip_subdirs) |
283 skip_subdirs) | |
284 | 271 |
285 | 272 |
286 def ShouldCheckFile(file_name): | 273 def ShouldCheckFile(file_name): |
287 """Returns True if the given file is a type we want to check.""" | 274 """Returns True if the given file is a type we want to check.""" |
288 checked_extensions = [ | 275 checked_extensions = [ |
289 '.h', | 276 '.h', |
290 '.cc', | 277 '.cc', |
291 '.m', | 278 '.m', |
292 '.mm', | 279 '.mm', |
293 ] | 280 ] |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
505 'to "../../.." relative to the script file, which ' | 492 'to "../../.." relative to the script file, which ' |
506 'will normally be the repository root.') | 493 'will normally be the repository root.') |
507 option_parser.add_option("-v", "--verbose", action="store_true", | 494 option_parser.add_option("-v", "--verbose", action="store_true", |
508 default=False, help="Print debug logging") | 495 default=False, help="Print debug logging") |
509 options, args = option_parser.parse_args() | 496 options, args = option_parser.parse_args() |
510 return checkdeps(options, args) | 497 return checkdeps(options, args) |
511 | 498 |
512 | 499 |
513 if '__main__' == __name__: | 500 if '__main__' == __name__: |
514 sys.exit(main()) | 501 sys.exit(main()) |
OLD | NEW |