OLD | NEW |
1 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """A database of OWNERS files.""" | 5 """A database of OWNERS files.""" |
6 | 6 |
7 class Assertion(AssertionError): | 7 class Assertion(AssertionError): |
8 pass | 8 pass |
9 | 9 |
| 10 |
| 11 class SyntaxErrorInOwnersFile(Exception): |
| 12 def __init__(self, path, line, msg): |
| 13 super(SyntaxErrorInOwnersFile, self).__init__((path, line, msg)) |
| 14 self.path = path |
| 15 self.line = line |
| 16 self.msg = msg |
| 17 |
| 18 def __str__(self): |
| 19 if self.msg: |
| 20 return "%s:%d syntax error: %s" % (self.path, self.line, self.msg) |
| 21 else: |
| 22 return "%s:%d syntax error" % (self.path, self.line) |
| 23 |
| 24 |
| 25 # Wildcard email-address in the OWNERS file. |
| 26 ANYONE = '*' |
| 27 |
| 28 |
10 class Database(object): | 29 class Database(object): |
| 30 """A database of OWNERS files for a repository. |
| 31 |
| 32 This class allows you to find a suggested set of reviewers for a list |
| 33 of changed files, and see if a list of changed files is covered by a |
| 34 list of reviewers.""" |
| 35 |
11 def __init__(self, root, fopen, os_path): | 36 def __init__(self, root, fopen, os_path): |
12 """Initializes the database of owners for a repository. | 37 """Args: |
13 | |
14 Args: | |
15 root: the path to the root of the Repository | 38 root: the path to the root of the Repository |
16 all_owners: the list of every owner in the system | 39 all_owners: the list of every owner in the system |
17 open: function callback to open a text file for reading | 40 open: function callback to open a text file for reading |
18 os_path: module/object callback with fields for 'exists', | 41 os_path: module/object callback with fields for 'exists', |
19 'dirname', and 'join' | 42 'dirname', and 'join' |
20 """ | 43 """ |
21 self.root = root | 44 self.root = root |
22 self.fopen = fopen | 45 self.fopen = fopen |
23 self.os_path = os_path | 46 self.os_path = os_path |
24 | 47 |
25 # Mapping of files to authorized owners. | 48 # Mapping of files to authorized owners. |
26 self.files_owned_by = {} | 49 self.files_owned_by = {} |
27 | 50 |
28 # Mapping of owners to the files they own. | 51 # Mapping of owners to the files they own. |
29 self.owners_for = {} | 52 self.owners_for = {} |
30 | 53 |
31 # In-memory cached map of files to their OWNERS files. | 54 # In-memory cached map of files to their OWNERS files. |
32 self.owners_file_for = {} | 55 self.owners_file_for = {} |
33 | 56 |
34 # In-memory cache of OWNERS files and their contents | 57 # In-memory cache of OWNERS files and their contents |
35 self.owners_files = {} | 58 self.owners_files = {} |
36 | 59 |
37 def OwnersFor(self, files): | 60 def ReviewersFor(self, files): |
38 """Returns a sets of reviewers that will cover the set of files. | 61 """Returns a suggested set of reviewers that will cover the set of files. |
39 | 62 |
40 The set of files are paths relative to (and under) self.root.""" | 63 The set of files are paths relative to (and under) self.root.""" |
41 self._LoadDataNeededFor(files) | 64 self._LoadDataNeededFor(files) |
42 return self._CoveringSetOfOwnersFor(files) | 65 return self._CoveringSetOfOwnersFor(files) |
43 | 66 |
44 def FilesAreCoveredBy(self, files, reviewers): | 67 def FilesAreCoveredBy(self, files, reviewers): |
45 return not self.FilesNotCoveredBy(files, reviewers) | 68 return not self.FilesNotCoveredBy(files, reviewers) |
46 | 69 |
47 def FilesNotCoveredBy(self, files, reviewers): | 70 def FilesNotCoveredBy(self, files, reviewers): |
48 covered_files = set() | 71 covered_files = set() |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 owners_for.add(owner) | 104 owners_for.add(owner) |
82 | 105 |
83 def _CoveringSetOfOwnersFor(self, files): | 106 def _CoveringSetOfOwnersFor(self, files): |
84 # TODO(dpranke): implement the greedy algorithm for covering sets, and | 107 # TODO(dpranke): implement the greedy algorithm for covering sets, and |
85 # consider returning multiple options in case there are several equally | 108 # consider returning multiple options in case there are several equally |
86 # short combinations of owners. | 109 # short combinations of owners. |
87 every_owner = set() | 110 every_owner = set() |
88 for f in files: | 111 for f in files: |
89 every_owner = every_owner.union(self.owners_for[f]) | 112 every_owner = every_owner.union(self.owners_for[f]) |
90 return every_owner | 113 return every_owner |
OLD | NEW |