OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/python |
| 2 # Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. |
| 5 |
| 6 """Watchlists |
| 7 |
| 8 Watchlists is a mechanism that allow a developer (a "watcher") to watch over |
| 9 portions of code that he is interested in. A "watcher" will be cc-ed to |
| 10 changes that modify that portion of code, thereby giving him an opportunity |
| 11 to make comments on codereview.chromium.org even before the change is |
| 12 committed. |
| 13 Refer: http://dev.chromium.org/developers/contributing-code/watchlists |
| 14 |
| 15 When invoked directly from the base of a repository, this script lists out |
| 16 the watchers for files given on the command line. This is useful to verify |
| 17 changes to WATCHLISTS files. |
| 18 """ |
| 19 |
| 20 import logging |
| 21 import os |
| 22 import re |
| 23 import sys |
| 24 |
| 25 |
| 26 class Watchlists(object): |
| 27 """Manage Watchlists. |
| 28 |
| 29 This class provides mechanism to load watchlists for a repo and identify |
| 30 watchers. |
| 31 Usage: |
| 32 wl = Watchlists("/path/to/repo/root") |
| 33 watchers = wl.GetWatchersForPaths(["/path/to/file1", |
| 34 "/path/to/file2",]) |
| 35 """ |
| 36 |
| 37 _RULES = "WATCHLISTS" |
| 38 _RULES_FILENAME = _RULES |
| 39 _repo_root = None |
| 40 _defns = {} # Definitions |
| 41 _watchlists = {} # name to email mapping |
| 42 |
| 43 def __init__(self, repo_root): |
| 44 self._repo_root = repo_root |
| 45 self._LoadWatchlistRules() |
| 46 |
| 47 def _GetRulesFilePath(self): |
| 48 return os.path.join(self._repo_root, self._RULES_FILENAME) |
| 49 |
| 50 def _HasWatchlistsFile(self): |
| 51 """Determine if watchlists are available for this repo.""" |
| 52 return os.path.exists(self._GetRulesFilePath()) |
| 53 |
| 54 def _LoadWatchlistRules(self): |
| 55 if not self._HasWatchlistsFile(): |
| 56 return |
| 57 watchlists_file = open(self._GetRulesFilePath()) |
| 58 contents = watchlists_file.read() |
| 59 watchlists_file.close() |
| 60 |
| 61 watchlists_data = None |
| 62 try: |
| 63 watchlists_data = eval(contents, {'__builtins__': None}, None) |
| 64 except SyntaxError, e: |
| 65 logging.error("Cannot parse %s. %s" % (self._GetRulesFilePath(), e)) |
| 66 return |
| 67 |
| 68 defns = watchlists_data.get("WATCHLIST_DEFINITIONS") |
| 69 if not defns: |
| 70 logging.error("WATCHLIST_DEFINITIONS not defined in %s" % |
| 71 self._GetRulesFilePath()) |
| 72 return |
| 73 watchlists = watchlists_data.get("WATCHLISTS") |
| 74 if not watchlists: |
| 75 logging.error("WATCHLISTS not defined in %s" % self._GetRulesFilePath()) |
| 76 return |
| 77 self._defns = defns |
| 78 self._watchlists = watchlists |
| 79 |
| 80 # Verify that all watchlist names are defined |
| 81 for name in watchlists: |
| 82 if name not in defns: |
| 83 logging.error("%s not defined in %s" % (name, self._GetRulesFilePath())) |
| 84 |
| 85 def GetWatchersForPaths(self, paths): |
| 86 """Fetch the list of watchers for |paths| |
| 87 |
| 88 Args: |
| 89 paths: [path1, path2, ...] |
| 90 |
| 91 Returns: |
| 92 [u1@chromium.org, u2@gmail.com, ...] |
| 93 """ |
| 94 watchers = set() # A set, to avoid duplicates |
| 95 for path in paths: |
| 96 for name, rule in self._defns.iteritems(): |
| 97 if name not in self._watchlists: continue |
| 98 rex_str = rule.get('filepath') |
| 99 if not rex_str: continue |
| 100 if re.search(rex_str, path): |
| 101 map(watchers.add, self._watchlists[name]) |
| 102 return list(watchers) |
| 103 |
| 104 |
| 105 def main(argv): |
| 106 # Confirm that watchlists can be parsed and spew out the watchers |
| 107 if len(argv) < 2: |
| 108 print "Usage (from the base of repo):" |
| 109 print " %s [file-1] [file-2] ...." % argv[0] |
| 110 return 1 |
| 111 wl = Watchlists(os.getcwd()) |
| 112 watchers = wl.GetWatchersForPaths(argv[1:]) |
| 113 print watchers |
| 114 |
| 115 |
| 116 if __name__ == '__main__': |
| 117 main(sys.argv) |
OLD | NEW |