diff --git a/git_cl.py b/git_cl.py index f86a78176..72770a145 100755 --- a/git_cl.py +++ b/git_cl.py @@ -1552,7 +1552,7 @@ def GerritUpload(options, args, cl): return 0 -def RietveldUpload(options, args, cl): +def RietveldUpload(options, args, cl, change): """upload the patch to rietveld.""" upload_args = ['--assume_yes'] # Don't ask about untracked files. upload_args.extend(['--server', cl.GetRietveldServer()]) @@ -1579,6 +1579,22 @@ def RietveldUpload(options, args, cl): change_desc = ChangeDescription(message) if options.reviewers: change_desc.update_reviewers(options.reviewers) + if options.auto_bots: + masters = presubmit_support.DoGetTryMasters( + change, + change.LocalPaths(), + settings.GetRoot(), + None, + None, + options.verbose, + sys.stdout) + + if masters: + change_description = change_desc.description + '\nCQ_TRYBOTS=' + lst = [] + for master, mapping in masters.iteritems(): + lst.append(master + ':' + ','.join(mapping.keys())) + change_desc.set_description(change_description + ';'.join(lst)) if not options.force: change_desc.prompt() @@ -1709,6 +1725,8 @@ def CMDupload(parser, args): 'use for CL. Default: master') parser.add_option('--email', default=None, help='email address to use to connect to Rietveld') + parser.add_option('--auto-bots', default=False, action='store_true', + help='Autogenerate which trybots to use for this CL') add_git_similarity(parser) (options, args) = parser.parse_args(args) @@ -1768,7 +1786,7 @@ def CMDupload(parser, args): print_stats(options.similarity, options.find_copies, args) if settings.GetIsGerrit(): return GerritUpload(options, args, cl) - ret = RietveldUpload(options, args, cl) + ret = RietveldUpload(options, args, cl, change) if not ret: git_set_branch_value('last-upload-hash', RunGit(['rev-parse', 'HEAD']).strip()) diff --git a/tests/git_cl_test.py b/tests/git_cl_test.py index 1e70e1b32..570904cf6 100755 --- a/tests/git_cl_test.py +++ b/tests/git_cl_test.py @@ -10,6 +10,7 @@ import StringIO import stat import sys import unittest +import re sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) @@ -18,7 +19,7 @@ from testing_support.auto_stub import TestCase import git_cl import git_common import subprocess2 - +import presubmit_support class PresubmitMock(object): def __init__(self, *args, **kwargs): @@ -750,6 +751,117 @@ class TestGitCl(TestCase): actual.append(obj.description) self.assertEqual(expected, actual) + def test_trybots_from_PRESUBMIT(self): + TEST_MASTER = 'testMaster' + TEST_BUILDER = 'testBuilder' + MASTERS = {TEST_MASTER:{TEST_BUILDER:['a']}} + self.mock(presubmit_support, 'DoGetTryMasters', + lambda *args: MASTERS) + + change_mock = ChangeMock() + changelist_mock = ChangelistMock(change_mock) + self.mock(git_cl, 'is_dirty_git_tree', lambda x: False) + self.mock(git_cl, 'print_stats', lambda *arg: True) + self.mock(git_cl, 'Changelist', lambda *args: changelist_mock) + self.mock(git_cl, 'CreateDescriptionFromLog', lambda arg: 'Commit message') + self.mock(git_cl.ChangeDescription, 'prompt', lambda self: None) + + self.calls = [ + ((['git', 'config', 'rietveld.autoupdate',],), + ''), + ((['git', 'config', 'gerrit.host',],), + ''), + ((['git', 'rev-parse', '--show-cdup',],), + ''), + ((['git', 'config', 'rietveld.private',],), + ''), + ((['git', 'config', '--local', '--get-regexp', '^svn-remote\\.'],), + ''), + ((['git', 'config', 'rietveld.project',],), + ''), + ((['git', 'rev-parse', 'HEAD',],), + ''), + ] + + stored_description = [] + def check_upload(args): + i = 0 + for arg in args: + if arg == '--message': + break + i += 1 + + self.assertTrue(i < len(args)) + stored_description.append(args[i+1]) + return 1, 2 + self.mock(git_cl.upload, 'RealMain', check_upload) + + git_cl.main(['upload', '--bypass-hooks', '--auto-bots']) + found = re.search("CQ_TRYBOTS=(.*?)$", stored_description[0]) + self.assertTrue(found) + self.assertEqual(found.group(1), '%s:%s' % (TEST_MASTER, TEST_BUILDER)) + + +class ChangelistMock(object): + def __init__(self, change_mock): + self.change_mock = change_mock + + # Disable "Method could be a function" + # pylint: disable=R0201 + def GetChange(self, *args): + return self.change_mock + + def GetIssue(self): + return None + + def GetBranch(self): + return [] + + def GetCommonAncestorWithUpstream(self): + return [] + + def GetCCList(self): + return [] + + def GetGitBaseUrlFromConfig(self): + return '' + + def GetRemoteUrl(self): + return '' + + def GetRietveldServer(self): + return None + + def SetWatchers(self, *args): + pass + + def SetIssue(self, issue): + pass + + def SetPatchset(self, issue): + pass + + +class ChangeMock(object): + def __init__(self): + self.stored_description = None + + # Disable "Method could be a function" + # pylint: disable=R0201 + def SetDescriptionText(self, desc): + self.stored_description = desc + + def FullDescriptionText(self): + return 'HIHI TEST DESCRIPTION' + + def RepositoryRoot(self): + return [] + + def AffectedFiles(self): + return [] + + def LocalPaths(self): + return None if __name__ == '__main__': git_cl.logging.basicConfig(