Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 #!/usr/bin/python | 1 #!/usr/bin/python | 
| 2 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2006-2009 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.3.2' | 9 __version__ = '1.3.2' | 
| 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 exceptions | 17 import exceptions | 
| 18 import fnmatch | 18 import fnmatch | 
| 19 import glob | 19 import glob | 
| 20 import logging | 20 import logging | 
| 21 import marshal # Exposed through the API. | 21 import marshal # Exposed through the API. | 
| 22 import optparse | 22 import optparse | 
| 23 import os # Somewhat exposed through the API. | 23 import os # Somewhat exposed through the API. | 
| 24 import pickle # Exposed through the API. | 24 import pickle # Exposed through the API. | 
| 25 import random | |
| 25 import re # Exposed through the API. | 26 import re # Exposed through the API. | 
| 26 import subprocess # Exposed through the API. | 27 import subprocess # Exposed through the API. | 
| 27 import sys # Parts exposed through API. | 28 import sys # Parts exposed through API. | 
| 28 import tempfile # Exposed through the API. | 29 import tempfile # Exposed through the API. | 
| 29 import traceback # Exposed through the API. | 30 import traceback # Exposed through the API. | 
| 30 import types | 31 import types | 
| 31 import unittest # Exposed through the API. | 32 import unittest # Exposed through the API. | 
| 32 import urllib2 # Exposed through the API. | 33 import urllib2 # Exposed through the API. | 
| 33 import warnings | 34 import warnings | 
| 34 | 35 | 
| 35 # Local imports. | 36 # Local imports. | 
| 36 # TODO(joi) Would be cleaner to factor out utils in gcl to separate module, but | 37 # TODO(joi) Would be cleaner to factor out utils in gcl to separate module, but | 
| 37 # for now it would only be a couple of functions so hardly worth it. | 38 # for now it would only be a couple of functions so hardly worth it. | 
| 38 import gcl | 39 import gcl | 
| 39 import gclient | 40 import gclient | 
| 40 import presubmit_canned_checks | 41 import presubmit_canned_checks | 
| 41 | 42 | 
| 42 | 43 | 
| 44 # Ask for feedback only once in program lifetime. | |
| 45 _ASKED_FOR_FEEDBACK = False | |
| 46 | |
| 47 | |
| 43 class NotImplementedException(Exception): | 48 class NotImplementedException(Exception): | 
| 44 """We're leaving placeholders in a bunch of places to remind us of the | 49 """We're leaving placeholders in a bunch of places to remind us of the | 
| 45 design of the API, but we have not implemented all of it yet. Implement as | 50 design of the API, but we have not implemented all of it yet. Implement as | 
| 46 the need arises. | 51 the need arises. | 
| 47 """ | 52 """ | 
| 48 pass | 53 pass | 
| 49 | 54 | 
| 50 | 55 | 
| 51 def normpath(path): | 56 def normpath(path): | 
| 52 '''Version of os.path.normpath that also changes backward slashes to | 57 '''Version of os.path.normpath that also changes backward slashes to | 
| (...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 773 | 778 | 
| 774 Args: | 779 Args: | 
| 775 change: The Change object. | 780 change: The Change object. | 
| 776 committing: True if 'gcl commit' is running, False if 'gcl upload' is. | 781 committing: True if 'gcl commit' is running, False if 'gcl upload' is. | 
| 777 verbose: Prints debug info. | 782 verbose: Prints debug info. | 
| 778 output_stream: A stream to write output from presubmit tests to. | 783 output_stream: A stream to write output from presubmit tests to. | 
| 779 input_stream: A stream to read input from the user. | 784 input_stream: A stream to read input from the user. | 
| 780 default_presubmit: A default presubmit script to execute in any case. | 785 default_presubmit: A default presubmit script to execute in any case. | 
| 781 may_prompt: Enable (y/n) questions on warning or error. | 786 may_prompt: Enable (y/n) questions on warning or error. | 
| 782 | 787 | 
| 788 Warning: | |
| 789 If may_prompt is true, output_streeam SHOULD be sys.stdout and input_stream | |
| 
 
Jói Sigurðsson
2009/06/25 21:19:28
output_streeam -> output_stream
 
 | |
| 790 SHOULD be sys.stdin. | |
| 791 | |
| 783 Return: | 792 Return: | 
| 784 True if execution can continue, False if not. | 793 True if execution can continue, False if not. | 
| 785 """ | 794 """ | 
| 786 presubmit_files = ListRelevantPresubmitFiles(change.AbsoluteLocalPaths(True), | 795 presubmit_files = ListRelevantPresubmitFiles(change.AbsoluteLocalPaths(True), | 
| 787 change.RepositoryRoot()) | 796 change.RepositoryRoot()) | 
| 788 if not presubmit_files and verbose: | 797 if not presubmit_files and verbose: | 
| 789 output_stream.write("Warning, no presubmit.py found.\n") | 798 output_stream.write("Warning, no presubmit.py found.\n") | 
| 790 results = [] | 799 results = [] | 
| 791 executer = PresubmitExecuter(change, committing) | 800 executer = PresubmitExecuter(change, committing) | 
| 792 if default_presubmit: | 801 if default_presubmit: | 
| (...skipping 30 matching lines...) Expand all Loading... | |
| 823 if not item._Handle(output_stream, input_stream, | 832 if not item._Handle(output_stream, input_stream, | 
| 824 may_prompt=False): | 833 may_prompt=False): | 
| 825 error_count += 1 | 834 error_count += 1 | 
| 826 output_stream.write('\n') | 835 output_stream.write('\n') | 
| 827 if not errors and warnings and may_prompt: | 836 if not errors and warnings and may_prompt: | 
| 828 output_stream.write( | 837 output_stream.write( | 
| 829 'There were presubmit warnings. Sure you want to continue? (y/N): ') | 838 'There were presubmit warnings. Sure you want to continue? (y/N): ') | 
| 830 response = input_stream.readline() | 839 response = input_stream.readline() | 
| 831 if response.strip().lower() != 'y': | 840 if response.strip().lower() != 'y': | 
| 832 error_count += 1 | 841 error_count += 1 | 
| 842 | |
| 843 global _ASKED_FOR_FEEDBACK | |
| 844 # Ask for feedback one time out of 5. | |
| 845 if (len(results) and random.randint(0, 4) == 0 and not _ASKED_FOR_FEEDBACK): | |
| 846 output_stream.write("Was the presubmit check useful? Please send feedback " | |
| 847 "& hate mail to maruel@chromium.org!\n") | |
| 848 _ASKED_FOR_FEEDBACK = True | |
| 833 return (error_count == 0) | 849 return (error_count == 0) | 
| 834 | 850 | 
| 835 | 851 | 
| 836 def ScanSubDirs(mask, recursive): | 852 def ScanSubDirs(mask, recursive): | 
| 837 if not recursive: | 853 if not recursive: | 
| 838 return [x for x in glob.glob(mask) if '.svn' not in x and '.git' not in x] | 854 return [x for x in glob.glob(mask) if '.svn' not in x and '.git' not in x] | 
| 839 else: | 855 else: | 
| 840 results = [] | 856 results = [] | 
| 841 for root, dirs, files in os.walk('.'): | 857 for root, dirs, files in os.walk('.'): | 
| 842 if '.svn' in dirs: | 858 if '.svn' in dirs: | 
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 908 options.commit, | 924 options.commit, | 
| 909 options.verbose, | 925 options.verbose, | 
| 910 sys.stdout, | 926 sys.stdout, | 
| 911 sys.stdin, | 927 sys.stdin, | 
| 912 options.default_presubmit, | 928 options.default_presubmit, | 
| 913 options.may_prompt) | 929 options.may_prompt) | 
| 914 | 930 | 
| 915 | 931 | 
| 916 if __name__ == '__main__': | 932 if __name__ == '__main__': | 
| 917 sys.exit(Main(sys.argv)) | 933 sys.exit(Main(sys.argv)) | 
| OLD | NEW |