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