OLD | NEW |
(Empty) | |
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 """Base classes to represent dependency rules, used by checkdeps.py""" |
| 6 |
| 7 |
| 8 class Rule(object): |
| 9 """Specifies a single rule for an include, which can be one of |
| 10 ALLOW, DISALLOW and TEMP_ALLOW. |
| 11 """ |
| 12 |
| 13 # These are the prefixes used to indicate each type of rule. These |
| 14 # are also used as values for self.allow to indicate which type of |
| 15 # rule this is. |
| 16 ALLOW = "+" |
| 17 DISALLOW = "-" |
| 18 TEMP_ALLOW = "!" |
| 19 |
| 20 def __init__(self, allow, directory, source): |
| 21 self.allow = allow |
| 22 self._dir = directory |
| 23 self._source = source |
| 24 |
| 25 def __str__(self): |
| 26 return '"%s%s" from %s.' % (self.allow, self._dir, self._source) |
| 27 |
| 28 def ParentOrMatch(self, other): |
| 29 """Returns true if the input string is an exact match or is a parent |
| 30 of the current rule. For example, the input "foo" would match "foo/bar".""" |
| 31 return self._dir == other or self._dir.startswith(other + "/") |
| 32 |
| 33 def ChildOrMatch(self, other): |
| 34 """Returns true if the input string would be covered by this rule. For |
| 35 example, the input "foo/bar" would match the rule "foo".""" |
| 36 return self._dir == other or other.startswith(self._dir + "/") |
| 37 |
| 38 |
| 39 def ParseRuleString(rule_string, source): |
| 40 """Returns a tuple of a boolean indicating whether the directory is an allow |
| 41 rule, and a string holding the directory name. |
| 42 """ |
| 43 if not rule_string: |
| 44 raise Exception('The rule string "%s" is empty\nin %s' % |
| 45 (rule_string, source)) |
| 46 |
| 47 if not rule_string[0] in [Rule.ALLOW, Rule.DISALLOW, Rule.TEMP_ALLOW]: |
| 48 raise Exception( |
| 49 'The rule string "%s" does not begin with a "+", "-" or "!".' % |
| 50 rule_string) |
| 51 |
| 52 return (rule_string[0], rule_string[1:]) |
| 53 |
| 54 |
| 55 class Rules(object): |
| 56 def __init__(self): |
| 57 """Initializes the current rules with an empty rule list.""" |
| 58 self._rules = [] |
| 59 |
| 60 def __str__(self): |
| 61 return 'Rules = [\n%s]' % '\n'.join(' %s' % x for x in self._rules) |
| 62 |
| 63 def AddRule(self, rule_string, source): |
| 64 """Adds a rule for the given rule string. |
| 65 |
| 66 Args: |
| 67 rule_string: The include_rule string read from the DEPS file to apply. |
| 68 source: A string representing the location of that string (filename, etc.) |
| 69 so that we can give meaningful errors. |
| 70 """ |
| 71 (add_rule, rule_dir) = ParseRuleString(rule_string, source) |
| 72 # Remove any existing rules or sub-rules that apply. For example, if we're |
| 73 # passed "foo", we should remove "foo", "foo/bar", but not "foobar". |
| 74 self._rules = [x for x in self._rules if not x.ParentOrMatch(rule_dir)] |
| 75 self._rules.insert(0, Rule(add_rule, rule_dir, source)) |
| 76 |
| 77 def DirAllowed(self, allowed_dir): |
| 78 """Returns a tuple (success, message), where success indicates if the given |
| 79 directory is allowed given the current set of rules, and the message tells |
| 80 why if the comparison failed.""" |
| 81 for rule in self._rules: |
| 82 if rule.ChildOrMatch(allowed_dir): |
| 83 # This rule applies. |
| 84 why_failed = "" |
| 85 if rule.allow != Rule.ALLOW: |
| 86 why_failed = str(rule) |
| 87 return (rule.allow, why_failed) |
| 88 # No rules apply, fail. |
| 89 return (Rule.DISALLOW, "no rule applying") |
OLD | NEW |