OLD | NEW |
---|---|
(Empty) | |
1 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | |
M-A Ruel
2011/02/24 16:25:57
2011
| |
2 # Use of this source code is governed by a BSD-style license that can be | |
3 # found in the LICENSE file. | |
4 | |
5 """A database of OWNERS files.""" | |
6 | |
7 import os | |
8 import pdb | |
M-A Ruel
2011/02/24 16:25:57
remove
| |
9 | |
10 | |
11 class Assertion(AssertionError): | |
12 pass | |
13 | |
14 class Database(object): | |
15 def __init__(self, root, all_owners=None, | |
M-A Ruel
2011/02/24 16:25:57
Either all align one per line or all packed at 80
| |
16 open=file, | |
17 os_path=os.path): | |
18 """Initialize the database of owners for a repository. | |
M-A Ruel
2011/02/24 16:25:57
Initializes
| |
19 | |
20 Args: | |
21 root: the path to the root of the Repository | |
22 all_owners: the list of every owner in the system | |
23 open: function callback to open a text file for reading | |
24 os_path: module/object callback with fields for 'exists', | |
25 'dirname', and 'join' | |
26 """ | |
27 self.root = root | |
28 self.all_owners = all_owners or set() | |
29 self.open = open | |
30 self.os_path = os_path | |
31 | |
32 # Mapping of files to authorized owners. | |
33 self.files_owned_by = {} | |
34 | |
35 # Mapping of owners to the files they own. | |
36 self.owners_for = {} | |
37 | |
38 # In-memory cached map of files to their OWNERS files. | |
39 self.owners_file_for = {} | |
40 | |
41 # In-memory cache of OWNERS files and their contents | |
42 self.owners_files = {} | |
43 | |
44 def OwnersFor(self, files): | |
45 """Returns a list of sets of reviewers that will cover the set of files. | |
46 | |
47 The set of files are paths relative to (and under) self.root.""" | |
48 self._LoadDataNeededFor(files) | |
49 return self._FindCoveringSets(files) | |
50 | |
51 def AreCovered(self, files, reviewers): | |
52 return len(self.not_covered(files, reviewers)) == 0 | |
M-A Ruel
2011/02/24 16:25:57
return not self.not_covered(files, reviewers)
| |
53 | |
54 def FilesNotCoveredBy(self, files, reviewers): | |
55 covered_files = set() | |
56 for reviewer in reviewers: | |
57 covered_files = covered_files.union(self.files_owned_by(reviewer)) | |
58 return files.difference(covered_files) | |
59 | |
60 def _LoadDataNeededFor(self, files): | |
61 for f in files: | |
62 self._LoadOwnersFor(f) | |
63 | |
64 def _LoadOwnersFor(self, f): | |
65 if f not in self.owners_for: | |
66 owner_file = self._FindOwnersFileFor(f) | |
67 self.owners_file_for[f] = owner_file | |
68 self._ReadOwnersFile(owner_file, f) | |
69 | |
70 def _FindOwnersFileFor(self, f): | |
71 # This is really a "do ... until dirname = ''" | |
72 dirname = self.os_path.dirname(f) | |
73 while dirname: | |
74 owner_path = self.os_path.join(dirname, 'OWNERS') | |
75 if self.os_path.exists(owner_path): | |
76 return owner_path | |
77 dirname = self.os_path.dirname(dirname) | |
78 owner_path = self.os_path.join(dirname, 'OWNERS') | |
79 if self.os_path.exists(owner_path): | |
80 return owner_path | |
81 | |
82 raise Assertion('No OWNERS file found for %s' % f) | |
M-A Ruel
2011/02/24 16:25:57
Is this really an exceptional event? I think it sh
| |
83 | |
84 def _ReadOwnersFile(self, owner_file, affected_file): | |
85 owners_for = self.owners_for.setdefault(affected_file, set()) | |
86 for owner in self.open(owner_file).readlines(): | |
M-A Ruel
2011/02/24 16:25:57
.readlines() is implied.
| |
87 owner = owner.strip() | |
88 self.files_owned_by.setdefault(owner, set()).add(affected_file) | |
89 owners_for.add(owner) | |
90 | |
91 def _FindCoveringSets(self, files): | |
92 # TODO(dpranke): implement the greedy algorithm for covering sets. | |
93 # For now we return the list of every owner that touches at least | |
94 # one file in the set. | |
95 all_owners = set() | |
96 for f in files: | |
97 all_owners = all_owners.union(self.owners_for[f]) | |
98 return [all_owners] | |
M-A Ruel
2011/02/24 16:25:57
Did you mean:
return list(all_owners)
?
| |
OLD | NEW |