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

Unified Diff: owners.py

Issue 1085993004: Implement support for file: includes in OWNERS files. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: add a noparent tset Created 5 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | testing_support/filesystem_mock.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: owners.py
diff --git a/owners.py b/owners.py
index 30646ffa24dd203754a08abf5bba6d60f0f938cf..d830f6793579a4f966a553dfa032431955b9cca7 100644
--- a/owners.py
+++ b/owners.py
@@ -18,6 +18,7 @@ line := directive
| comment
directive := "set noparent"
+ | "file:" glob
| email_address
| "*"
@@ -45,6 +46,10 @@ If "per-file glob=set noparent" is used, then global directives are ignored
for the glob, and only the "per-file" owners are used for files matching that
glob.
+If the "file:" directive is used, the referred to OWNERS file will be parsed and
+considered when determining the valid set of OWNERS. If the filename starts with
+"//" it is considered to be an absolute path, otherwise a relative path.
Dirk Pranke 2015/04/15 19:42:37 "absolute path" might be confusing. I might call t
Peter Beverloo 2015/04/15 20:04:31 Ah yes, thanks. I'll adopt your comment with s/top
Peter Beverloo 2015/04/16 09:54:05 Done.
+
Examples for all of these combinations can be found in tests/owners_unittest.py.
"""
@@ -52,6 +57,9 @@ import collections
import random
import re
+# Name of the file in a directory containing the OWNERS contents.
+OWNERS_FILE = 'OWNERS'
+
# If this is present by itself on a line, this means that everyone can review.
EVERYONE = '*'
@@ -118,6 +126,9 @@ class Database(object):
# (This is implicitly true for the root directory).
self.stop_looking = set([''])
+ # Set of files which have already been read.
+ self.read_files = set()
+
def reviewers_for(self, files, author):
"""Returns a suggested set of reviewers that will cover the files.
@@ -189,15 +200,21 @@ class Database(object):
for f in files:
dirpath = self.os_path.dirname(f)
while not dirpath in self.owners_for:
- self._read_owners_in_dir(dirpath)
+ self._read_owners_in_dir(dirpath, OWNERS_FILE)
if self._stop_looking(dirpath):
break
dirpath = self.os_path.dirname(dirpath)
- def _read_owners_in_dir(self, dirpath):
- owners_path = self.os_path.join(self.root, dirpath, 'OWNERS')
+ def _read_owners_in_dir(self, dirpath, owners_file):
+ owners_path = self.os_path.join(self.root, dirpath, owners_file)
if not self.os_path.exists(owners_path):
return
+
+ if owners_path in self.read_files:
+ return
Dirk Pranke 2015/04/15 19:42:37 Since read_files is a set, calling add() multiple
Peter Beverloo 2015/04/15 20:04:31 I may be misunderstanding you, but both the set an
Dirk Pranke 2015/04/15 20:52:03 Oh, I was misreading the code, and thought the fun
+
+ self.read_files.add(owners_path)
+
comment = []
in_comment = False
lineno = 0
@@ -244,6 +261,21 @@ class Database(object):
line_type, owners_path, lineno, comment):
if directive == 'set noparent':
self.stop_looking.add(path)
+ elif directive.startswith('file:'):
+ dirpath, owners_file = self._resolve_include(directive[5:], owners_path)
+ if not dirpath:
+ raise SyntaxErrorInOwnersFile(owners_path, lineno,
+ ('%s does not refer to an existing file.' % directive[5:]))
+
+ self._read_owners_in_dir(dirpath, owners_file)
+ for key in self.owned_by:
+ if not dirpath in self.owned_by[key]:
+ continue
+ self.owned_by[key].add(path)
+
+ if dirpath in self.owners_for:
+ self.owners_for.setdefault(path, set()).update(self.owners_for[dirpath])
+
elif self.email_regexp.match(directive) or directive == EVERYONE:
self.comments.setdefault(directive, {})
self.comments[directive][path] = comment
@@ -251,9 +283,25 @@ class Database(object):
self.owners_for.setdefault(path, set()).add(directive)
else:
raise SyntaxErrorInOwnersFile(owners_path, lineno,
- ('%s is not a "set" directive, "*", '
+ ('%s is not a "set" directive, include, "*", '
'or an email address: "%s"' % (line_type, directive)))
+ def _resolve_include(self, include_path, base_path):
+ if include_path.startswith('//'):
+ dirpath = self.os_path.dirname(include_path[2:])
+ else:
+ assert base_path.startswith(self.root)
+ base_path = self.os_path.dirname(base_path[len(self.root):])
+ dirpath = self.os_path.join(base_path, self.os_path.dirname(include_path))
+
+ owners_file = self.os_path.basename(include_path)
+
+ owners_path = self.os_path.join(self.root, dirpath, owners_file)
+ if not self.os_path.exists(owners_path):
+ return None, None
+
+ return dirpath, owners_path
Dirk Pranke 2015/04/15 19:42:37 see comment above; it's not clear to me that retur
Peter Beverloo 2015/04/15 20:04:31 I named them to be consistent with the arguments o
Dirk Pranke 2015/04/15 20:52:03 I'm not fully sure I understood your comments, but
Peter Beverloo 2015/04/15 20:57:09 Yes, it does. Thanks! I'll apply the changes tomor
Peter Beverloo 2015/04/16 09:54:06 Done.
+
def _covering_set_of_owners_for(self, files, author):
dirs_remaining = set(self._enclosing_dir_with_owners(f) for f in files)
all_possible_owners = self.all_possible_owners(dirs_remaining, author)
« no previous file with comments | « no previous file | testing_support/filesystem_mock.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698