diff --git a/gcl.py b/gcl.py index f2f976c2a..38899518c 100755 --- a/gcl.py +++ b/gcl.py @@ -607,7 +607,7 @@ Basic commands: [--send_mail] [--no_try] [--no_presubmit] Uploads the changelist to the server for review. - gcl commit change_name [--force] + gcl commit change_name [--no_presubmit] [--force] Commits the changelist to the repository. gcl lint change_name @@ -1023,11 +1023,13 @@ def DoPresubmitChecks(change_info, committing): """Imports presubmit, then calls presubmit.DoPresubmitChecks.""" # Need to import here to avoid circular dependency. import presubmit_support + root_presubmit = GetCachedFile('PRESUBMIT.py', use_root=True) result = presubmit_support.DoPresubmitChecks(change_info, committing, verbose=False, output_stream=sys.stdout, - input_stream=sys.stdin) + input_stream=sys.stdin, + default_presubmit=root_presubmit) if not result: print "\nPresubmit errors, can't continue (use --no_presubmit to bypass)" return result diff --git a/presubmit_support.py b/presubmit_support.py index 7c73ab05a..96d138040 100755 --- a/presubmit_support.py +++ b/presubmit_support.py @@ -603,7 +603,8 @@ def DoPresubmitChecks(change_info, committing, verbose, output_stream, - input_stream): + input_stream, + default_presubmit): """Runs all presubmit checks that apply to the files in the change. This finds all PRESUBMIT.py files in directories enclosing the files in the @@ -619,19 +620,24 @@ def DoPresubmitChecks(change_info, verbose: Prints debug info. output_stream: A stream to write output from presubmit tests to. input_stream: A stream to read input from the user. + default_presubmit: A default presubmit script to execute in any case. Return: True if execution can continue, False if not. """ presubmit_files = ListRelevantPresubmitFiles(change_info.FileList()) if not presubmit_files and verbose: - print "Warning, no presubmit.py found." + output_stream.write("Warning, no presubmit.py found.") results = [] executer = PresubmitExecuter(change_info, committing) + if default_presubmit: + if verbose: + output_stream.write("Running default presubmit script") + results += executer.ExecPresubmitScript(default_presubmit, 'PRESUBMIT.py') for filename in presubmit_files: filename = os.path.abspath(filename) if verbose: - print "Running %s" % filename + output_stream.write("Running %s" % filename) # Accept CRLF presubmit script. presubmit_script = gcl.ReadFile(filename, 'rU') results += executer.ExecPresubmitScript(presubmit_script, filename) @@ -701,11 +707,12 @@ def Main(argv): files = ParseFiles(args, options.recursive) if options.verbose: print "Found %d files." % len(files) - return DoPresubmitChecks(gcl.ChangeInfo(name='temp', files=files), - options.commit, - options.verbose, - sys.stdout, - sys.stdin) + return not DoPresubmitChecks(gcl.ChangeInfo(name='temp', files=files), + options.commit, + options.verbose, + sys.stdout, + sys.stdin, + default_presubmit=None) if __name__ == '__main__': diff --git a/tests/gcl_unittest.py b/tests/gcl_unittest.py index 43914eece..c636b4f5f 100755 --- a/tests/gcl_unittest.py +++ b/tests/gcl_unittest.py @@ -79,7 +79,7 @@ class GclUnittest(GclTestsBase): dummy = StringIO.StringIO() gcl.sys.stdout = dummy gcl.Help() - self.assertEquals(len(dummy.getvalue()), 1815) + self.assertEquals(len(dummy.getvalue()), 1832) finally: gcl.sys.stdout = old_stdout diff --git a/tests/presubmit_unittest.py b/tests/presubmit_unittest.py index c449c710f..75480d6fa 100755 --- a/tests/presubmit_unittest.py +++ b/tests/presubmit_unittest.py @@ -62,16 +62,18 @@ class PresubmitTestsBase(unittest.TestCase): self.fail('Should not attempt to read file that is directory.') elif path.endswith('PRESUBMIT.py'): # used in testDoPresubmitChecks - return ('def CheckChangeOnUpload(input_api, output_api):\n' - ' if not input_api.change.NOSUCHKEY:\n' - ' return [output_api.PresubmitError("!!")]\n' - ' elif not input_api.change.REALLYNOSUCHKEY:\n' - ' return [output_api.PresubmitPromptWarning("??")]\n' - ' elif not input_api.change.REALLYABSOLUTELYNOSUCHKEY:\n' - ' return [output_api.PresubmitPromptWarning("??"),\n' - ' output_api.PresubmitError("XX!!XX")]\n' - ' else:\n' - ' return ()') + return """ +def CheckChangeOnUpload(input_api, output_api): + if not input_api.change.NOSUCHKEY: + return [output_api.PresubmitError("!!")] + elif not input_api.change.REALLYNOSUCHKEY: + return [output_api.PresubmitPromptWarning("??")] + elif not input_api.change.REALLYABSOLUTELYNOSUCHKEY: + return [output_api.PresubmitPromptWarning("??"), + output_api.PresubmitError("XX!!XX")] + else: + return () +""" else: return 'one:%s\r\ntwo:%s' % (path, path) gcl.ReadFile = MockReadFile @@ -303,8 +305,9 @@ class PresubmitUnittest(PresubmitTestsBase): output = StringIO.StringIO() input = StringIO.StringIO('y\n') - self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input)) - self.failUnless(output.getvalue().count('!!')) + self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, + None)) + self.assertEqual(output.getvalue().count('!!'), 2) def testDoPresubmitChecksPromptsAfterWarnings(self): description_lines = ('Hello there', @@ -320,8 +323,9 @@ class PresubmitUnittest(PresubmitTestsBase): output = StringIO.StringIO() input = StringIO.StringIO('n\n') # say no to the warning - self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input)) - self.failUnless(output.getvalue().count('??')) + self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, + None)) + self.assertEqual(output.getvalue().count('??'), 2) output = StringIO.StringIO() input = StringIO.StringIO('y\n') # say yes to the warning @@ -330,7 +334,8 @@ class PresubmitUnittest(PresubmitTestsBase): False, True, output, - input)) + input, + None)) self.failUnless(output.getvalue().count('??')) def testDoPresubmitChecksNoWarningPromptIfErrors(self): @@ -348,10 +353,40 @@ class PresubmitUnittest(PresubmitTestsBase): output = StringIO.StringIO() input = StringIO.StringIO() # should be unused - self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input)) - self.failUnless(output.getvalue().count('??')) - self.failUnless(output.getvalue().count('XX!!XX')) - self.failIf(output.getvalue().count('(y/N)')) + self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, + None)) + self.assertEqual(output.getvalue().count('??'), 2) + self.assertEqual(output.getvalue().count('XX!!XX'), 2) + self.assertEqual(output.getvalue().count('(y/N)'), 0) + + def testDoDefaultPresubmitChecks(self): + description_lines = ('Hello there', + 'this is a change', + 'STORY=http://tracker/123') + files = [ + ['A', 'haspresubmit\\blat.cc'], + ] + ci = gcl.ChangeInfo(name='mychange', + description='\n'.join(description_lines), + files=files) + + output = StringIO.StringIO() + input = StringIO.StringIO('y\n') + # Always fail. + DEFAULT_SCRIPT = """ +def CheckChangeOnUpload(input_api, output_api): + print 'This is a test' + return [output_api.PresubmitError("!!")] +""" + def MockReadFile(dummy): + return '' + gcl.ReadFile = MockReadFile + def MockIsFile(dummy): + return False + os.path.isfile = MockIsFile + self.failIf(presubmit.DoPresubmitChecks(ci, False, True, output, input, + DEFAULT_SCRIPT)) + self.assertEquals(output.getvalue().count('!!'), 1) def testDirectoryHandling(self): files = [