Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(482)

Side by Side Diff: owners.py

Issue 9621012: Show a list of directories missing OWNER reviewers on upload, and show directories rather than file… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools/
Patch Set: Addressing Dirk's comments Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | presubmit_canned_checks.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | presubmit_canned_checks.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698