Add watchlists to 'gcl upload'

Watchlists provides an opportunity for someone interested in a particular
code section to make comments before commit. One can subscribe to watchlists
depending on filepath (regular expressions) and she'll automatically get
cc-ed to changes when the watchlist is triggered.

Additional examples of watchlist_rules in diff repo:
http://codereview.chromium.org/118431
http://codereview.chromium.org/119356
Review URL: http://codereview.chromium.org/118432

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@18209 0039d316-1c4b-4281-b951-d872f2087c98
parent 899410c9
# Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Watchlist Rules
# Refer: http://dev.chromium.org/developers/contributing-code/watchlists
{
'WATCHLIST_DEFINITIONS': {
'this_file': {
'filepath': '^WATCHLISTS$',
},
'depot_tools': {
'filepath': '.+',
},
},
'WATCHLISTS': {
'this_file': ['nirnimesh@chromium.org'],
'depot_tools': ['maruel@chromium.org'],
},
}
...@@ -615,6 +615,7 @@ Basic commands: ...@@ -615,6 +615,7 @@ Basic commands:
gcl upload change_name [-r reviewer1@gmail.com,reviewer2@gmail.com,...] gcl upload change_name [-r reviewer1@gmail.com,reviewer2@gmail.com,...]
[--send_mail] [--no_try] [--no_presubmit] [--send_mail] [--no_try] [--no_presubmit]
[--no_watchlists]
Uploads the changelist to the server for review. Uploads the changelist to the server for review.
gcl commit change_name [--no_presubmit] gcl commit change_name [--no_presubmit]
...@@ -738,6 +739,8 @@ def UploadCL(change_info, args): ...@@ -738,6 +739,8 @@ def UploadCL(change_info, args):
if not OptionallyDoPresubmitChecks(change_info, False, args): if not OptionallyDoPresubmitChecks(change_info, False, args):
return return
no_try = FilterFlag(args, "--no_try") or FilterFlag(args, "--no-try") no_try = FilterFlag(args, "--no_try") or FilterFlag(args, "--no-try")
no_watchlists = FilterFlag(args, "--no_watchlists") or \
FilterFlag(args, "--no-watchlists")
# Map --send-mail to --send_mail # Map --send-mail to --send_mail
if FilterFlag(args, "--send-mail"): if FilterFlag(args, "--send-mail"):
...@@ -775,7 +778,17 @@ def UploadCL(change_info, args): ...@@ -775,7 +778,17 @@ def UploadCL(change_info, args):
os.write(handle, change_info.description) os.write(handle, change_info.description)
os.close(handle) os.close(handle)
# Watchlist processing -- CC people interested in this changeset
# http://dev.chromium.org/developers/contributing-code/watchlists
if not no_watchlists:
import watchlists
watchlist = watchlists.Watchlists(GetRepositoryRoot())
watchers = watchlist.GetWatchersForPaths(change_info.FileList())
cc_list = GetCodeReviewSetting("CC_LIST") cc_list = GetCodeReviewSetting("CC_LIST")
if not no_watchlists and watchers:
# Filter out all empty elements and join by ','
cc_list = ','.join(filter(None, [cc_list] + watchers))
if cc_list: if cc_list:
upload_arg.append("--cc=" + cc_list) upload_arg.append("--cc=" + cc_list)
upload_arg.append("--description_file=" + desc_file + "") upload_arg.append("--description_file=" + desc_file + "")
......
#!/usr/bin/python
# Copyright (c) 2009 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Watchlists
Watchlists is a mechanism that allow a developer (a "watcher") to watch over
portions of code that he is interested in. A "watcher" will be cc-ed to
changes that modify that portion of code, thereby giving him an opportunity
to make comments on codereview.chromium.org even before the change is
committed.
Refer: http://dev.chromium.org/developers/contributing-code/watchlists
When invoked directly from the base of a repository, this script lists out
the watchers for files given on the command line. This is useful to verify
changes to WATCHLISTS files.
"""
import logging
import os
import re
import sys
class Watchlists(object):
"""Manage Watchlists.
This class provides mechanism to load watchlists for a repo and identify
watchers.
Usage:
wl = Watchlists("/path/to/repo/root")
watchers = wl.GetWatchersForPaths(["/path/to/file1",
"/path/to/file2",])
"""
_RULES = "WATCHLISTS"
_RULES_FILENAME = _RULES
_repo_root = None
_defns = {} # Definitions
_watchlists = {} # name to email mapping
def __init__(self, repo_root):
self._repo_root = repo_root
self._LoadWatchlistRules()
def _GetRulesFilePath(self):
return os.path.join(self._repo_root, self._RULES_FILENAME)
def _HasWatchlistsFile(self):
"""Determine if watchlists are available for this repo."""
return os.path.exists(self._GetRulesFilePath())
def _LoadWatchlistRules(self):
if not self._HasWatchlistsFile():
return
watchlists_file = open(self._GetRulesFilePath())
contents = watchlists_file.read()
watchlists_file.close()
watchlists_data = None
try:
watchlists_data = eval(contents, {'__builtins__': None}, None)
except SyntaxError, e:
logging.error("Cannot parse %s. %s" % (self._GetRulesFilePath(), e))
return
defns = watchlists_data.get("WATCHLIST_DEFINITIONS")
if not defns:
logging.error("WATCHLIST_DEFINITIONS not defined in %s" %
self._GetRulesFilePath())
return
watchlists = watchlists_data.get("WATCHLISTS")
if not watchlists:
logging.error("WATCHLISTS not defined in %s" % self._GetRulesFilePath())
return
self._defns = defns
self._watchlists = watchlists
# Verify that all watchlist names are defined
for name in watchlists:
if name not in defns:
logging.error("%s not defined in %s" % (name, self._GetRulesFilePath()))
def GetWatchersForPaths(self, paths):
"""Fetch the list of watchers for |paths|
Args:
paths: [path1, path2, ...]
Returns:
[u1@chromium.org, u2@gmail.com, ...]
"""
watchers = set() # A set, to avoid duplicates
for path in paths:
for name, rule in self._defns.iteritems():
if name not in self._watchlists: continue
rex_str = rule.get('filepath')
if not rex_str: continue
if re.search(rex_str, path):
map(watchers.add, self._watchlists[name])
return list(watchers)
def main(argv):
# Confirm that watchlists can be parsed and spew out the watchers
if len(argv) < 2:
print "Usage (from the base of repo):"
print " %s [file-1] [file-2] ...." % argv[0]
return 1
wl = Watchlists(os.getcwd())
watchers = wl.GetWatchersForPaths(argv[1:])
print watchers
if __name__ == '__main__':
main(sys.argv)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment