Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(960)

Side by Side Diff: presubmit_support.py

Issue 2232203002: Support additional user presubmit scripts named PRESUBMIT*.py. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Correctly ignore PRESUBMIT_test.py and PRESUBMIT*.pyc Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | testing_support/super_mox.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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.8.0' 9 __version__ = '1.8.0'
10 10
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 487
488 The lists will be compiled as regular expression and 488 The lists will be compiled as regular expression and
489 AffectedFile.LocalPath() needs to pass both list. 489 AffectedFile.LocalPath() needs to pass both list.
490 490
491 Note: Copy-paste this function to suit your needs or use a lambda function. 491 Note: Copy-paste this function to suit your needs or use a lambda function.
492 """ 492 """
493 def Find(affected_file, items): 493 def Find(affected_file, items):
494 local_path = affected_file.LocalPath() 494 local_path = affected_file.LocalPath()
495 for item in items: 495 for item in items:
496 if self.re.match(item, local_path): 496 if self.re.match(item, local_path):
497 logging.debug("%s matched %s" % (item, local_path)) 497 logging.debug("%s matched %s", item, local_path)
498 return True 498 return True
499 return False 499 return False
500 return (Find(affected_file, white_list or self.DEFAULT_WHITE_LIST) and 500 return (Find(affected_file, white_list or self.DEFAULT_WHITE_LIST) and
501 not Find(affected_file, black_list or self.DEFAULT_BLACK_LIST)) 501 not Find(affected_file, black_list or self.DEFAULT_BLACK_LIST))
502 502
503 def AffectedSourceFiles(self, source_file): 503 def AffectedSourceFiles(self, source_file):
504 """Filter the list of AffectedTextFiles by the function source_file. 504 """Filter the list of AffectedTextFiles by the function source_file.
505 505
506 If source_file is None, InputApi.FilterSourceFile() is used. 506 If source_file is None, InputApi.FilterSourceFile() is used.
507 """ 507 """
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
639 # pylint: disable=R0201 639 # pylint: disable=R0201
640 def __init__(self, path, action, repository_root, diff_cache): 640 def __init__(self, path, action, repository_root, diff_cache):
641 self._path = path 641 self._path = path
642 self._action = action 642 self._action = action
643 self._local_root = repository_root 643 self._local_root = repository_root
644 self._is_directory = None 644 self._is_directory = None
645 self._properties = {} 645 self._properties = {}
646 self._cached_changed_contents = None 646 self._cached_changed_contents = None
647 self._cached_new_contents = None 647 self._cached_new_contents = None
648 self._diff_cache = diff_cache 648 self._diff_cache = diff_cache
649 logging.debug('%s(%s)' % (self.__class__.__name__, self._path)) 649 logging.debug('%s(%s)', self.__class__.__name__, self._path)
650 650
651 def ServerPath(self): 651 def ServerPath(self):
652 """Returns a path string that identifies the file in the SCM system. 652 """Returns a path string that identifies the file in the SCM system.
653 653
654 Returns the empty string if the file does not exist in SCM. 654 Returns the empty string if the file does not exist in SCM.
655 """ 655 """
656 return '' 656 return ''
657 657
658 def LocalPath(self): 658 def LocalPath(self):
659 """Returns the path of this file on the local disk relative to client root. 659 """Returns the path of this file on the local disk relative to client root.
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after
1086 break 1086 break
1087 parent_dir = os.path.dirname(directory) 1087 parent_dir = os.path.dirname(directory)
1088 if parent_dir == directory: 1088 if parent_dir == directory:
1089 # We hit the system root directory. 1089 # We hit the system root directory.
1090 break 1090 break
1091 directory = parent_dir 1091 directory = parent_dir
1092 1092
1093 # Look for PRESUBMIT.py in all candidate directories. 1093 # Look for PRESUBMIT.py in all candidate directories.
1094 results = [] 1094 results = []
1095 for directory in sorted(list(candidates)): 1095 for directory in sorted(list(candidates)):
1096 p = os.path.join(directory, 'PRESUBMIT.py') 1096 for f in os.listdir(directory):
1097 if os.path.isfile(p): 1097 p = os.path.join(directory, f)
1098 results.append(p) 1098 if os.path.isfile(p) and re.match(
1099 r'PRESUBMIT.*\.py$', f) and not f.startswith('PRESUBMIT_test'):
1100 results.append(p)
1099 1101
1100 logging.debug('Presubmit files: %s' % ','.join(results)) 1102 logging.debug('Presubmit files: %s', ','.join(results))
1101 return results 1103 return results
1102 1104
1103 1105
1104 class GetTrySlavesExecuter(object): 1106 class GetTrySlavesExecuter(object):
1105 @staticmethod 1107 @staticmethod
1106 def ExecPresubmitScript(script_text, presubmit_path, project, change): 1108 def ExecPresubmitScript(script_text, presubmit_path, project, change):
1107 """Executes GetPreferredTrySlaves() from a single presubmit script. 1109 """Executes GetPreferredTrySlaves() from a single presubmit script.
1108 1110
1109 This will soon be deprecated and replaced by GetPreferredTryMasters(). 1111 This will soon be deprecated and replaced by GetPreferredTryMasters().
1110 1112
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
1447 raise PresubmitFailure('"%s" had an exception.\n%s' % (presubmit_path, e)) 1449 raise PresubmitFailure('"%s" had an exception.\n%s' % (presubmit_path, e))
1448 1450
1449 # These function names must change if we make substantial changes to 1451 # These function names must change if we make substantial changes to
1450 # the presubmit API that are not backwards compatible. 1452 # the presubmit API that are not backwards compatible.
1451 if self.committing: 1453 if self.committing:
1452 function_name = 'CheckChangeOnCommit' 1454 function_name = 'CheckChangeOnCommit'
1453 else: 1455 else:
1454 function_name = 'CheckChangeOnUpload' 1456 function_name = 'CheckChangeOnUpload'
1455 if function_name in context: 1457 if function_name in context:
1456 context['__args'] = (input_api, OutputApi(self.committing)) 1458 context['__args'] = (input_api, OutputApi(self.committing))
1457 logging.debug('Running %s in %s' % (function_name, presubmit_path)) 1459 logging.debug('Running %s in %s', function_name, presubmit_path)
1458 result = eval(function_name + '(*__args)', context) 1460 result = eval(function_name + '(*__args)', context)
1459 logging.debug('Running %s done.' % function_name) 1461 logging.debug('Running %s done.', function_name)
1460 if not (isinstance(result, types.TupleType) or 1462 if not (isinstance(result, types.TupleType) or
1461 isinstance(result, types.ListType)): 1463 isinstance(result, types.ListType)):
1462 raise PresubmitFailure( 1464 raise PresubmitFailure(
1463 'Presubmit functions must return a tuple or list') 1465 'Presubmit functions must return a tuple or list')
1464 for item in result: 1466 for item in result:
1465 if not isinstance(item, OutputApi.PresubmitResult): 1467 if not isinstance(item, OutputApi.PresubmitResult):
1466 raise PresubmitFailure( 1468 raise PresubmitFailure(
1467 'All presubmit results must be of types derived from ' 1469 'All presubmit results must be of types derived from '
1468 'output_api.PresubmitResult') 1470 'output_api.PresubmitResult')
1469 else: 1471 else:
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
1602 dirs.remove('.svn') 1604 dirs.remove('.svn')
1603 if '.git' in dirs: 1605 if '.git' in dirs:
1604 dirs.remove('.git') 1606 dirs.remove('.git')
1605 for name in files: 1607 for name in files:
1606 if fnmatch.fnmatch(name, mask): 1608 if fnmatch.fnmatch(name, mask):
1607 results.append(os.path.join(root, name)) 1609 results.append(os.path.join(root, name))
1608 return results 1610 return results
1609 1611
1610 1612
1611 def ParseFiles(args, recursive): 1613 def ParseFiles(args, recursive):
1612 logging.debug('Searching for %s' % args) 1614 logging.debug('Searching for %s', args)
1613 files = [] 1615 files = []
1614 for arg in args: 1616 for arg in args:
1615 files.extend([('M', f) for f in ScanSubDirs(arg, recursive)]) 1617 files.extend([('M', f) for f in ScanSubDirs(arg, recursive)])
1616 return files 1618 return files
1617 1619
1618 1620
1619 def load_files(options, args): 1621 def load_files(options, args):
1620 """Tries to determine the SCM.""" 1622 """Tries to determine the SCM."""
1621 change_scm = scm.determine_scm(options.root) 1623 change_scm = scm.determine_scm(options.root)
1622 files = [] 1624 files = []
1623 if args: 1625 if args:
1624 files = ParseFiles(args, options.recursive) 1626 files = ParseFiles(args, options.recursive)
1625 if change_scm == 'svn': 1627 if change_scm == 'svn':
1626 change_class = SvnChange 1628 change_class = SvnChange
1627 if not files: 1629 if not files:
1628 files = scm.SVN.CaptureStatus([], options.root) 1630 files = scm.SVN.CaptureStatus([], options.root)
1629 elif change_scm == 'git': 1631 elif change_scm == 'git':
1630 change_class = GitChange 1632 change_class = GitChange
1631 upstream = options.upstream or None 1633 upstream = options.upstream or None
1632 if not files: 1634 if not files:
1633 files = scm.GIT.CaptureStatus([], options.root, upstream) 1635 files = scm.GIT.CaptureStatus([], options.root, upstream)
1634 else: 1636 else:
1635 logging.info('Doesn\'t seem under source control. Got %d files' % len(args)) 1637 logging.info('Doesn\'t seem under source control. Got %d files', len(args))
1636 if not files: 1638 if not files:
1637 return None, None 1639 return None, None
1638 change_class = Change 1640 change_class = Change
1639 return change_class, files 1641 return change_class, files
1640 1642
1641 1643
1642 class NonexistantCannedCheckFilter(Exception): 1644 class NonexistantCannedCheckFilter(Exception):
1643 pass 1645 pass
1644 1646
1645 1647
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1747 if options.rietveld_email and options.rietveld_email_file: 1749 if options.rietveld_email and options.rietveld_email_file:
1748 parser.error("Only one of --rietveld_email or --rietveld_email_file " 1750 parser.error("Only one of --rietveld_email or --rietveld_email_file "
1749 "can be passed to this program.") 1751 "can be passed to this program.")
1750 if options.rietveld_email_file: 1752 if options.rietveld_email_file:
1751 with open(options.rietveld_email_file, "rb") as f: 1753 with open(options.rietveld_email_file, "rb") as f:
1752 options.rietveld_email = f.read().strip() 1754 options.rietveld_email = f.read().strip()
1753 1755
1754 change_class, files = load_files(options, args) 1756 change_class, files = load_files(options, args)
1755 if not change_class: 1757 if not change_class:
1756 parser.error('For unversioned directory, <files> is not optional.') 1758 parser.error('For unversioned directory, <files> is not optional.')
1757 logging.info('Found %d file(s).' % len(files)) 1759 logging.info('Found %d file(s).', len(files))
1758 1760
1759 rietveld_obj, gerrit_obj = None, None 1761 rietveld_obj, gerrit_obj = None, None
1760 1762
1761 if options.rietveld_url: 1763 if options.rietveld_url:
1762 # The empty password is permitted: '' is not None. 1764 # The empty password is permitted: '' is not None.
1763 if options.rietveld_private_key_file: 1765 if options.rietveld_private_key_file:
1764 rietveld_obj = rietveld.JwtOAuth2Rietveld( 1766 rietveld_obj = rietveld.JwtOAuth2Rietveld(
1765 options.rietveld_url, 1767 options.rietveld_url,
1766 options.rietveld_email, 1768 options.rietveld_email,
1767 options.rietveld_private_key_file) 1769 options.rietveld_private_key_file)
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1820 return 2 1822 return 2
1821 1823
1822 1824
1823 if __name__ == '__main__': 1825 if __name__ == '__main__':
1824 fix_encoding.fix_encoding() 1826 fix_encoding.fix_encoding()
1825 try: 1827 try:
1826 sys.exit(main()) 1828 sys.exit(main())
1827 except KeyboardInterrupt: 1829 except KeyboardInterrupt:
1828 sys.stderr.write('interrupted\n') 1830 sys.stderr.write('interrupted\n')
1829 sys.exit(2) 1831 sys.exit(2)
OLDNEW
« no previous file with comments | « no previous file | testing_support/super_mox.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698