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-d872f2087c98experimental/szager/collated-output
parent
899410c9ee
commit
b2ab494a8b
@ -0,0 +1,24 @@
|
||||
# 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'],
|
||||
},
|
||||
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
#!/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)
|
Loading…
Reference in New Issue