OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Enables directory-specific presubmit checks to run at upload and/or commit. | 6 """Enables directory-specific presubmit checks to run at upload and/or commit. |
7 """ | 7 """ |
8 | 8 |
9 __version__ = '1.6.1' | 9 __version__ = '1.6.1' |
10 | 10 |
11 # TODO(joi) Add caching where appropriate/needed. The API is designed to allow | 11 # TODO(joi) Add caching where appropriate/needed. The API is designed to allow |
12 # caching (between all different invocations of presubmit scripts for a given | 12 # caching (between all different invocations of presubmit scripts for a given |
13 # change). We should add it as our presubmit scripts start feeling slow. | 13 # change). We should add it as our presubmit scripts start feeling slow. |
14 | 14 |
15 import cPickle # Exposed through the API. | 15 import cPickle # Exposed through the API. |
16 import cStringIO # Exposed through the API. | 16 import cStringIO # Exposed through the API. |
17 import contextlib | |
17 import fnmatch | 18 import fnmatch |
18 import glob | 19 import glob |
19 import inspect | 20 import inspect |
20 import json # Exposed through the API. | 21 import json # Exposed through the API. |
21 import logging | 22 import logging |
22 import marshal # Exposed through the API. | 23 import marshal # Exposed through the API. |
23 import optparse | 24 import optparse |
24 import os # Somewhat exposed through the API. | 25 import os # Somewhat exposed through the API. |
25 import pickle # Exposed through the API. | 26 import pickle # Exposed through the API. |
26 import random | 27 import random |
(...skipping 1164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1191 if not files: | 1192 if not files: |
1192 files = scm.GIT.CaptureStatus([], options.root, None) | 1193 files = scm.GIT.CaptureStatus([], options.root, None) |
1193 else: | 1194 else: |
1194 logging.info('Doesn\'t seem under source control. Got %d files' % len(args)) | 1195 logging.info('Doesn\'t seem under source control. Got %d files' % len(args)) |
1195 if not files: | 1196 if not files: |
1196 return None, None | 1197 return None, None |
1197 change_class = Change | 1198 change_class = Change |
1198 return change_class, files | 1199 return change_class, files |
1199 | 1200 |
1200 | 1201 |
1202 class NonexistantCannedCheckFilter(Exception): | |
1203 pass | |
1204 | |
M-A Ruel
2013/03/08 02:09:02
2 lines
| |
1205 @contextlib.contextmanager | |
1206 def canned_check_filter(method_names): | |
1207 filtered = {} | |
1208 try: | |
1209 for method_name in method_names: | |
1210 if hasattr(presubmit_canned_checks, method_name): | |
M-A Ruel
2013/03/08 02:09:02
if not hasattr():
raise
then align -2 lines 1211
| |
1211 filtered[method_name] = getattr(presubmit_canned_checks, method_name) | |
1212 setattr(presubmit_canned_checks, method_name, lambda *_a, **_kw: []) | |
1213 else: | |
1214 raise NonexistantCannedCheckFilter(method_name) | |
1215 yield | |
1216 finally: | |
1217 for name, method in filtered.iteritems(): | |
1218 setattr(presubmit_canned_checks, name, method) | |
1219 | |
1220 | |
1201 def Main(argv): | 1221 def Main(argv): |
1202 parser = optparse.OptionParser(usage="%prog [options] <files...>", | 1222 parser = optparse.OptionParser(usage="%prog [options] <files...>", |
1203 version="%prog " + str(__version__)) | 1223 version="%prog " + str(__version__)) |
1204 parser.add_option("-c", "--commit", action="store_true", default=False, | 1224 parser.add_option("-c", "--commit", action="store_true", default=False, |
1205 help="Use commit instead of upload checks") | 1225 help="Use commit instead of upload checks") |
1206 parser.add_option("-u", "--upload", action="store_false", dest='commit', | 1226 parser.add_option("-u", "--upload", action="store_false", dest='commit', |
1207 help="Use upload instead of commit checks") | 1227 help="Use upload instead of commit checks") |
1208 parser.add_option("-r", "--recursive", action="store_true", | 1228 parser.add_option("-r", "--recursive", action="store_true", |
1209 help="Act recursively") | 1229 help="Act recursively") |
1210 parser.add_option("-v", "--verbose", action="count", default=0, | 1230 parser.add_option("-v", "--verbose", action="count", default=0, |
1211 help="Use 2 times for more debug info") | 1231 help="Use 2 times for more debug info") |
1212 parser.add_option("--name", default='no name') | 1232 parser.add_option("--name", default='no name') |
1213 parser.add_option("--author") | 1233 parser.add_option("--author") |
1214 parser.add_option("--description", default='') | 1234 parser.add_option("--description", default='') |
1215 parser.add_option("--issue", type='int', default=0) | 1235 parser.add_option("--issue", type='int', default=0) |
1216 parser.add_option("--patchset", type='int', default=0) | 1236 parser.add_option("--patchset", type='int', default=0) |
1217 parser.add_option("--root", default=os.getcwd(), | 1237 parser.add_option("--root", default=os.getcwd(), |
1218 help="Search for PRESUBMIT.py up to this directory. " | 1238 help="Search for PRESUBMIT.py up to this directory. " |
1219 "If inherit-review-settings-ok is present in this " | 1239 "If inherit-review-settings-ok is present in this " |
1220 "directory, parent directories up to the root file " | 1240 "directory, parent directories up to the root file " |
1221 "system directories will also be searched.") | 1241 "system directories will also be searched.") |
1222 parser.add_option("--default_presubmit") | 1242 parser.add_option("--default_presubmit") |
1223 parser.add_option("--may_prompt", action='store_true', default=False) | 1243 parser.add_option("--may_prompt", action='store_true', default=False) |
1244 parser.add_option("--skip_canned", action='append', default=[], | |
1245 help="A list of checks to skip which appear in " | |
1246 "presubmit_canned_checks. Can be provided multiple times " | |
1247 "to skip multiple canned checks.") | |
1224 parser.add_option("--rietveld_url", help=optparse.SUPPRESS_HELP) | 1248 parser.add_option("--rietveld_url", help=optparse.SUPPRESS_HELP) |
1225 parser.add_option("--rietveld_email", help=optparse.SUPPRESS_HELP) | 1249 parser.add_option("--rietveld_email", help=optparse.SUPPRESS_HELP) |
1226 parser.add_option("--rietveld_password", help=optparse.SUPPRESS_HELP) | 1250 parser.add_option("--rietveld_password", help=optparse.SUPPRESS_HELP) |
1227 options, args = parser.parse_args(argv) | 1251 options, args = parser.parse_args(argv) |
1228 if options.verbose >= 2: | 1252 if options.verbose >= 2: |
1229 logging.basicConfig(level=logging.DEBUG) | 1253 logging.basicConfig(level=logging.DEBUG) |
1230 elif options.verbose: | 1254 elif options.verbose: |
1231 logging.basicConfig(level=logging.INFO) | 1255 logging.basicConfig(level=logging.INFO) |
1232 else: | 1256 else: |
1233 logging.basicConfig(level=logging.ERROR) | 1257 logging.basicConfig(level=logging.ERROR) |
1234 change_class, files = load_files(options, args) | 1258 change_class, files = load_files(options, args) |
1235 if not change_class: | 1259 if not change_class: |
1236 parser.error('For unversioned directory, <files> is not optional.') | 1260 parser.error('For unversioned directory, <files> is not optional.') |
1237 logging.info('Found %d file(s).' % len(files)) | 1261 logging.info('Found %d file(s).' % len(files)) |
1238 rietveld_obj = None | 1262 rietveld_obj = None |
1239 if options.rietveld_url: | 1263 if options.rietveld_url: |
1240 rietveld_obj = rietveld.CachingRietveld( | 1264 rietveld_obj = rietveld.CachingRietveld( |
1241 options.rietveld_url, | 1265 options.rietveld_url, |
1242 options.rietveld_email, | 1266 options.rietveld_email, |
1243 options.rietveld_password) | 1267 options.rietveld_password) |
1244 try: | 1268 try: |
1245 results = DoPresubmitChecks( | 1269 with canned_check_filter(options.skip_canned): |
1246 change_class(options.name, | 1270 results = DoPresubmitChecks( |
1247 options.description, | 1271 change_class(options.name, |
1248 options.root, | 1272 options.description, |
1249 files, | 1273 options.root, |
1250 options.issue, | 1274 files, |
1251 options.patchset, | 1275 options.issue, |
1252 options.author), | 1276 options.patchset, |
1253 options.commit, | 1277 options.author), |
1254 options.verbose, | 1278 options.commit, |
1255 sys.stdout, | 1279 options.verbose, |
1256 sys.stdin, | 1280 sys.stdout, |
1257 options.default_presubmit, | 1281 sys.stdin, |
1258 options.may_prompt, | 1282 options.default_presubmit, |
1259 rietveld_obj) | 1283 options.may_prompt, |
1284 rietveld_obj) | |
1260 return not results.should_continue() | 1285 return not results.should_continue() |
1286 except NonexistantCannedCheckFilter, e: | |
1287 print >> sys.stderr, ( | |
1288 'Attempted to skip nonexistent canned presubmit check: %s' % e.message) | |
1289 return 2 | |
1261 except PresubmitFailure, e: | 1290 except PresubmitFailure, e: |
1262 print >> sys.stderr, e | 1291 print >> sys.stderr, e |
1263 print >> sys.stderr, 'Maybe your depot_tools is out of date?' | 1292 print >> sys.stderr, 'Maybe your depot_tools is out of date?' |
1264 print >> sys.stderr, 'If all fails, contact maruel@' | 1293 print >> sys.stderr, 'If all fails, contact maruel@' |
1265 return 2 | 1294 return 2 |
1266 | 1295 |
1267 | 1296 |
1268 if __name__ == '__main__': | 1297 if __name__ == '__main__': |
1269 fix_encoding.fix_encoding() | 1298 fix_encoding.fix_encoding() |
1270 sys.exit(Main(None)) | 1299 sys.exit(Main(None)) |
OLD | NEW |