Chromium Code Reviews| 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 import collections | 7 import collections |
| 8 import re | 8 import re |
| 9 | 9 |
| 10 | 10 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 68 self.stop_looking = set(['']) | 68 self.stop_looking = set(['']) |
| 69 | 69 |
| 70 def reviewers_for(self, files): | 70 def reviewers_for(self, files): |
| 71 """Returns a suggested set of reviewers that will cover the files. | 71 """Returns a suggested set of reviewers that will cover the files. |
| 72 | 72 |
| 73 files is a sequence of paths relative to (and under) self.root.""" | 73 files is a sequence of paths relative to (and under) self.root.""" |
| 74 self._check_paths(files) | 74 self._check_paths(files) |
| 75 self._load_data_needed_for(files) | 75 self._load_data_needed_for(files) |
| 76 return self._covering_set_of_owners_for(files) | 76 return self._covering_set_of_owners_for(files) |
| 77 | 77 |
| 78 def files_are_covered_by(self, files, reviewers): | 78 def files_are_covered_by(self, files, reviewers): |
|
Dirk Pranke
2012/03/08 07:19:48
I meant that I don't think anyone calls this routi
| |
| 79 """Returns whether every file is owned by at least one reviewer.""" | 79 """Returns whether every file is owned by at least one reviewer. |
| 80 return not self.files_not_covered_by(files, reviewers) | |
| 81 | 80 |
| 82 def files_not_covered_by(self, files, reviewers): | 81 If reviewers is empty, returns False if there are any files at all. |
| 83 """Returns the set of files that are not owned by at least one reviewer. | 82 """ |
| 83 if files and not reviewers: | |
| 84 return False | |
| 85 return not self.directories_not_covered_by(files, reviewers) | |
| 86 | |
| 87 def directories_not_covered_by(self, files, reviewers): | |
| 88 """Returns the set of directories that are not owned by a reviewer. | |
| 89 | |
| 90 Determines which of the given files are not owned by at least one of the | |
| 91 reviewers, then returns a set containing the applicable enclosing | |
| 92 directories, i.e. the ones upward from the files that have OWNERS files. | |
| 84 | 93 |
| 85 Args: | 94 Args: |
| 86 files is a sequence of paths relative to (and under) self.root. | 95 files is a sequence of paths relative to (and under) self.root. |
| 87 reviewers is a sequence of strings matching self.email_regexp.""" | 96 reviewers is a sequence of strings matching self.email_regexp. |
| 97 """ | |
| 88 self._check_paths(files) | 98 self._check_paths(files) |
| 89 self._check_reviewers(reviewers) | 99 self._check_reviewers(reviewers) |
| 90 if not reviewers: | |
| 91 return files | |
| 92 | 100 |
| 93 self._load_data_needed_for(files) | 101 self._load_data_needed_for(files) |
| 94 files_by_dir = self._files_by_dir(files) | 102 files_by_dir = self._files_by_dir(files) |
|
Dirk Pranke
2012/03/08 07:19:48
You no longer need the files, just the dirs, so yo
Pam (message me for reviews)
2012/03/08 09:11:54
Thanks, I should have seen that. No more coding at
| |
| 95 covered_dirs = self._dirs_covered_by(reviewers) | 103 covered_dirs = self._dirs_covered_by(reviewers) |
| 96 uncovered_files = [] | 104 uncovered_dirs = [] |
| 97 for d, files_in_d in files_by_dir.iteritems(): | 105 for d, files_in_d in files_by_dir.iteritems(): |
| 98 if not self._is_dir_covered_by(d, covered_dirs): | 106 if not self._is_dir_covered_by(d, covered_dirs): |
| 99 uncovered_files.extend(files_in_d) | 107 uncovered_dirs.append(self._enclosing_dir_with_owners(d)) |
| 100 return set(uncovered_files) | 108 return set(uncovered_dirs) |
| 101 | 109 |
| 102 def _check_paths(self, files): | 110 def _check_paths(self, files): |
| 103 def _is_under(f, pfx): | 111 def _is_under(f, pfx): |
| 104 return self.os_path.abspath(self.os_path.join(pfx, f)).startswith(pfx) | 112 return self.os_path.abspath(self.os_path.join(pfx, f)).startswith(pfx) |
| 105 _assert_is_collection(files) | 113 _assert_is_collection(files) |
| 106 assert all(_is_under(f, self.os_path.abspath(self.root)) for f in files) | 114 assert all(_is_under(f, self.os_path.abspath(self.root)) for f in files) |
| 107 | 115 |
| 108 def _check_reviewers(self, reviewers): | 116 def _check_reviewers(self, reviewers): |
| 109 _assert_is_collection(reviewers) | 117 _assert_is_collection(reviewers) |
| 110 assert all(self.email_regexp.match(r) for r in reviewers) | 118 assert all(self.email_regexp.match(r) for r in reviewers) |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 122 return dirs | 130 return dirs |
| 123 | 131 |
| 124 def _stop_looking(self, dirname): | 132 def _stop_looking(self, dirname): |
| 125 return dirname in self.stop_looking | 133 return dirname in self.stop_looking |
| 126 | 134 |
| 127 def _is_dir_covered_by(self, dirname, covered_dirs): | 135 def _is_dir_covered_by(self, dirname, covered_dirs): |
| 128 while not dirname in covered_dirs and not self._stop_looking(dirname): | 136 while not dirname in covered_dirs and not self._stop_looking(dirname): |
| 129 dirname = self.os_path.dirname(dirname) | 137 dirname = self.os_path.dirname(dirname) |
| 130 return dirname in covered_dirs | 138 return dirname in covered_dirs |
| 131 | 139 |
| 140 def _enclosing_dir_with_owners(self, directory): | |
| 141 """Returns the innermost enclosing directory that has an OWNERS file.""" | |
| 142 dirpath = directory | |
| 143 while not dirpath in self.owners_for: | |
| 144 if self._stop_looking(dirpath): | |
| 145 break | |
| 146 dirpath = self.os_path.dirname(dirpath) | |
| 147 return dirpath | |
| 148 | |
| 132 def _load_data_needed_for(self, files): | 149 def _load_data_needed_for(self, files): |
| 133 for f in files: | 150 for f in files: |
| 134 dirpath = self.os_path.dirname(f) | 151 dirpath = self.os_path.dirname(f) |
| 135 while not dirpath in self.owners_for: | 152 while not dirpath in self.owners_for: |
| 136 self._read_owners_in_dir(dirpath) | 153 self._read_owners_in_dir(dirpath) |
| 137 if self._stop_looking(dirpath): | 154 if self._stop_looking(dirpath): |
| 138 break | 155 break |
| 139 dirpath = self.os_path.dirname(dirpath) | 156 dirpath = self.os_path.dirname(dirpath) |
| 140 | 157 |
| 141 def _read_owners_in_dir(self, dirpath): | 158 def _read_owners_in_dir(self, dirpath): |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 169 # short combinations of owners. | 186 # short combinations of owners. |
| 170 every_owner = set() | 187 every_owner = set() |
| 171 for f in files: | 188 for f in files: |
| 172 dirname = self.os_path.dirname(f) | 189 dirname = self.os_path.dirname(f) |
| 173 while dirname in self.owners_for: | 190 while dirname in self.owners_for: |
| 174 every_owner |= self.owners_for[dirname] | 191 every_owner |= self.owners_for[dirname] |
| 175 if self._stop_looking(dirname): | 192 if self._stop_looking(dirname): |
| 176 break | 193 break |
| 177 dirname = self.os_path.dirname(dirname) | 194 dirname = self.os_path.dirname(dirname) |
| 178 return every_owner | 195 return every_owner |
| OLD | NEW |