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

Side by Side Diff: git_cl.py

Issue 2076683002: ABANDONED. Remove obsolete git cl dcommit. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@dcommit-warn
Patch Set: Updated patchset dependency Created 4 years, 6 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 | tests/git_cl_test.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 # Copyright (C) 2008 Evan Martin <martine@danga.com> 6 # Copyright (C) 2008 Evan Martin <martine@danga.com>
7 7
8 """A git-command for integrating reviews on Rietveld and Gerrit.""" 8 """A git-command for integrating reviews on Rietveld and Gerrit."""
9 9
10 from __future__ import print_function 10 from __future__ import print_function
(...skipping 3740 matching lines...) Expand 10 before | Expand all | Expand 10 after
3751 3751
3752 3752
3753 def IsSubmoduleMergeCommit(ref): 3753 def IsSubmoduleMergeCommit(ref):
3754 # When submodules are added to the repo, we expect there to be a single 3754 # When submodules are added to the repo, we expect there to be a single
3755 # non-git-svn merge commit at remote HEAD with a signature comment. 3755 # non-git-svn merge commit at remote HEAD with a signature comment.
3756 pattern = '^SVN changes up to revision [0-9]*$' 3756 pattern = '^SVN changes up to revision [0-9]*$'
3757 cmd = ['rev-list', '--merges', '--grep=%s' % pattern, '%s^!' % ref] 3757 cmd = ['rev-list', '--merges', '--grep=%s' % pattern, '%s^!' % ref]
3758 return RunGit(cmd) != '' 3758 return RunGit(cmd) != ''
3759 3759
3760 3760
3761 def SendUpstream(parser, args, cmd): 3761 def SendUpstream(parser, args):
3762 """Common code for CMDland and CmdDCommit 3762 """Common code for CMDland
3763 3763
3764 In case of Gerrit, uses Gerrit REST api to "submit" the issue, which pushes 3764 In case of Gerrit, uses Gerrit REST api to "submit" the issue, which pushes
3765 upstream and closes the issue automatically and atomically. 3765 upstream and closes the issue automatically and atomically.
3766 3766
3767 Otherwise (in case of Rietveld): 3767 Otherwise (in case of Rietveld):
3768 Squashes branch into a single commit. 3768 Squashes branch into a single commit.
3769 Updates changelog with metadata (e.g. pointer to review). 3769 Updates changelog with metadata (e.g. pointer to review).
3770 Pushes/dcommits the code upstream. 3770 Pushes the code upstream.
3771 Updates review and closes. 3771 Updates review and closes.
3772 """ 3772 """
3773 parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks', 3773 parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks',
3774 help='bypass upload presubmit hook') 3774 help='bypass upload presubmit hook')
3775 parser.add_option('-m', dest='message', 3775 parser.add_option('-m', dest='message',
3776 help="override review description") 3776 help="override review description")
3777 parser.add_option('-f', action='store_true', dest='force', 3777 parser.add_option('-f', action='store_true', dest='force',
3778 help="force yes to questions (don't prompt)") 3778 help="force yes to questions (don't prompt)")
3779 parser.add_option('-c', dest='contributor', 3779 parser.add_option('-c', dest='contributor',
3780 help="external contributor for patch (appended to " + 3780 help="external contributor for patch (appended to " +
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3813 print() 3813 print()
3814 print('Either reparent this branch on top of origin/master:') 3814 print('Either reparent this branch on top of origin/master:')
3815 print(' git reparent-branch --root') 3815 print(' git reparent-branch --root')
3816 print() 3816 print()
3817 print('OR run `git rebase-update` if you think the parent branch is ') 3817 print('OR run `git rebase-update` if you think the parent branch is ')
3818 print('already committed.') 3818 print('already committed.')
3819 print() 3819 print()
3820 print(' Current parent: %r' % upstream_branch) 3820 print(' Current parent: %r' % upstream_branch)
3821 return 1 3821 return 1
3822 3822
3823 if not args or cmd == 'land': 3823 if not args:
3824 # Default to merging against our best guess of the upstream branch. 3824 # Default to merging against our best guess of the upstream branch.
3825 args = [cl.GetUpstreamBranch()] 3825 args = [cl.GetUpstreamBranch()]
3826 3826
3827 if options.contributor: 3827 if options.contributor:
3828 if not re.match('^.*\s<\S+@\S+>$', options.contributor): 3828 if not re.match('^.*\s<\S+@\S+>$', options.contributor):
3829 print("Please provide contibutor as 'First Last <email@example.com>'") 3829 print("Please provide contibutor as 'First Last <email@example.com>'")
3830 return 1 3830 return 1
3831 3831
3832 base_branch = args[0] 3832 base_branch = args[0]
3833 base_has_submodules = IsSubmoduleMergeCommit(base_branch) 3833 base_has_submodules = IsSubmoduleMergeCommit(base_branch)
3834 3834
3835 if git_common.is_dirty_git_tree(cmd): 3835 if git_common.is_dirty_git_tree(cmd='land'):
3836 return 1 3836 return 1
3837 3837
3838 # This rev-list syntax means "show all commits not in my branch that 3838 # This rev-list syntax means "show all commits not in my branch that
3839 # are in base_branch". 3839 # are in base_branch".
3840 upstream_commits = RunGit(['rev-list', '^' + cl.GetBranchRef(), 3840 upstream_commits = RunGit(['rev-list', '^' + cl.GetBranchRef(),
3841 base_branch]).splitlines() 3841 base_branch]).splitlines()
3842 if upstream_commits: 3842 if upstream_commits:
3843 print('Base branch "%s" has %d commits ' 3843 print('Base branch "%s" has %d commits '
3844 'not in this branch.' % (base_branch, len(upstream_commits))) 3844 'not in this branch.' % (base_branch, len(upstream_commits)))
3845 print('Run "git merge %s" before attempting to %s.' % (base_branch, cmd)) 3845 print('Run "git merge %s" before attempting to land.' % (base_branch,))
3846 return 1 3846 return 1
3847 3847
3848 # This is the revision `svn dcommit` will commit on top of. 3848 # This is the revision `svn dcommit` will commit on top of.
3849 svn_head = None 3849 svn_head = None
3850 if cmd == 'dcommit' or base_has_submodules: 3850 if base_has_submodules:
3851 svn_head = RunGit(['log', '--grep=^git-svn-id:', '-1', 3851 svn_head = RunGit(['log', '--grep=^git-svn-id:', '-1',
3852 '--pretty=format:%H']) 3852 '--pretty=format:%H'])
3853 3853
3854 if cmd == 'dcommit':
3855 # If the base_head is a submodule merge commit, the first parent of the
3856 # base_head should be a git-svn commit, which is what we're interested in.
3857 base_svn_head = base_branch
3858 if base_has_submodules:
3859 base_svn_head += '^1'
3860
3861 extra_commits = RunGit(['rev-list', '^' + svn_head, base_svn_head])
3862 if extra_commits:
3863 print('This branch has %d additional commits not upstreamed yet.'
3864 % len(extra_commits.splitlines()))
3865 print('Upstream "%s" or rebase this branch on top of the upstream trunk '
3866 'before attempting to %s.' % (base_branch, cmd))
3867 return 1
3868
3869 merge_base = RunGit(['merge-base', base_branch, 'HEAD']).strip() 3854 merge_base = RunGit(['merge-base', base_branch, 'HEAD']).strip()
3870 if not options.bypass_hooks: 3855 if not options.bypass_hooks:
3871 author = None 3856 author = None
3872 if options.contributor: 3857 if options.contributor:
3873 author = re.search(r'\<(.*)\>', options.contributor).group(1) 3858 author = re.search(r'\<(.*)\>', options.contributor).group(1)
3874 hook_results = cl.RunHook( 3859 hook_results = cl.RunHook(
3875 committing=True, 3860 committing=True,
3876 may_prompt=not options.force, 3861 may_prompt=not options.force,
3877 verbose=options.verbose, 3862 verbose=options.verbose,
3878 change=cl.GetChange(merge_base, author)) 3863 change=cl.GetChange(merge_base, author))
3879 if not hook_results.should_continue(): 3864 if not hook_results.should_continue():
3880 return 1 3865 return 1
3881 3866
3882 # Check the tree status if the tree status URL is set. 3867 # Check the tree status if the tree status URL is set.
3883 status = GetTreeStatus() 3868 status = GetTreeStatus()
3884 if 'closed' == status: 3869 if 'closed' == status:
3885 print('The tree is closed. Please wait for it to reopen. Use ' 3870 print('The tree is closed. Please wait for it to reopen. Use '
3886 '"git cl %s --bypass-hooks" to commit on a closed tree.' % cmd) 3871 '"git cl land --bypass-hooks" to commit on a closed tree.')
3887 return 1 3872 return 1
3888 elif 'unknown' == status: 3873 elif 'unknown' == status:
3889 print('Unable to determine tree status. Please verify manually and ' 3874 print('Unable to determine tree status. Please verify manually and '
3890 'use "git cl %s --bypass-hooks" to commit on a closed tree.' % cmd) 3875 'use "git cl land --bypass-hooks" to commit on a closed tree.')
3891 return 1 3876 return 1
3892 3877
3893 change_desc = ChangeDescription(options.message) 3878 change_desc = ChangeDescription(options.message)
3894 if not change_desc.description and cl.GetIssue(): 3879 if not change_desc.description and cl.GetIssue():
3895 change_desc = ChangeDescription(cl.GetDescription()) 3880 change_desc = ChangeDescription(cl.GetDescription())
3896 3881
3897 if not change_desc.description: 3882 if not change_desc.description:
3898 if not cl.GetIssue() and options.bypass_hooks: 3883 if not cl.GetIssue() and options.bypass_hooks:
3899 change_desc = ChangeDescription(CreateDescriptionFromLog([merge_base])) 3884 change_desc = ChangeDescription(CreateDescriptionFromLog([merge_base]))
3900 else: 3885 else:
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
3963 'commit', '--author', options.contributor, 3948 'commit', '--author', options.contributor,
3964 '-m', commit_desc.description, 3949 '-m', commit_desc.description,
3965 ]) 3950 ])
3966 else: 3951 else:
3967 RunGit(['commit', '-m', commit_desc.description]) 3952 RunGit(['commit', '-m', commit_desc.description])
3968 if base_has_submodules: 3953 if base_has_submodules:
3969 cherry_pick_commit = RunGit(['rev-list', 'HEAD^!']).rstrip() 3954 cherry_pick_commit = RunGit(['rev-list', 'HEAD^!']).rstrip()
3970 RunGit(['branch', CHERRY_PICK_BRANCH, svn_head]) 3955 RunGit(['branch', CHERRY_PICK_BRANCH, svn_head])
3971 RunGit(['checkout', CHERRY_PICK_BRANCH]) 3956 RunGit(['checkout', CHERRY_PICK_BRANCH])
3972 RunGit(['cherry-pick', cherry_pick_commit]) 3957 RunGit(['cherry-pick', cherry_pick_commit])
3973 if cmd == 'land': 3958 remote, branch = cl.FetchUpstreamTuple(cl.GetBranch())
3974 remote, branch = cl.FetchUpstreamTuple(cl.GetBranch()) 3959 mirror = settings.GetGitMirror(remote)
3975 mirror = settings.GetGitMirror(remote) 3960 pushurl = mirror.url if mirror else remote
3976 pushurl = mirror.url if mirror else remote 3961 pending_prefix = settings.GetPendingRefPrefix()
3977 pending_prefix = settings.GetPendingRefPrefix() 3962 if not pending_prefix or branch.startswith(pending_prefix):
3978 if not pending_prefix or branch.startswith(pending_prefix): 3963 # If not using refs/pending/heads/* at all, or target ref is already set
3979 # If not using refs/pending/heads/* at all, or target ref is already set 3964 # to pending, then push to the target ref directly.
3980 # to pending, then push to the target ref directly. 3965 retcode, output = RunGitWithCode(
3981 retcode, output = RunGitWithCode( 3966 ['push', '--porcelain', pushurl, 'HEAD:%s' % branch])
3982 ['push', '--porcelain', pushurl, 'HEAD:%s' % branch]) 3967 pushed_to_pending = pending_prefix and branch.startswith(pending_prefix)
3983 pushed_to_pending = pending_prefix and branch.startswith(pending_prefix)
3984 else:
3985 # Cherry-pick the change on top of pending ref and then push it.
3986 assert branch.startswith('refs/'), branch
3987 assert pending_prefix[-1] == '/', pending_prefix
3988 pending_ref = pending_prefix + branch[len('refs/'):]
3989 retcode, output = PushToGitPending(pushurl, pending_ref, branch)
3990 pushed_to_pending = (retcode == 0)
3991 if retcode == 0:
3992 revision = RunGit(['rev-parse', 'HEAD']).strip()
3993 else: 3968 else:
3994 # dcommit the merge branch. 3969 # Cherry-pick the change on top of pending ref and then push it.
3995 cmd_args = [ 3970 assert branch.startswith('refs/'), branch
3996 'svn', 'dcommit', 3971 assert pending_prefix[-1] == '/', pending_prefix
3997 '-C%s' % options.similarity, 3972 pending_ref = pending_prefix + branch[len('refs/'):]
3998 '--no-rebase', '--rmdir', 3973 retcode, output = PushToGitPending(pushurl, pending_ref, branch)
3999 ] 3974 pushed_to_pending = (retcode == 0)
4000 if settings.GetForceHttpsCommitUrl(): 3975 if retcode == 0:
4001 # Allow forcing https commit URLs for some projects that don't allow 3976 revision = RunGit(['rev-parse', 'HEAD']).strip()
4002 # committing to http URLs (like Google Code).
4003 remote_url = cl.GetGitSvnRemoteUrl()
4004 if urlparse.urlparse(remote_url).scheme == 'http':
4005 remote_url = remote_url.replace('http://', 'https://')
4006 cmd_args.append('--commit-url=%s' % remote_url)
4007 _, output = RunGitWithCode(cmd_args)
4008 if 'Committed r' in output:
4009 revision = re.match(
4010 '.*?\nCommitted r(\\d+)', output, re.DOTALL).group(1)
4011 logging.debug(output) 3977 logging.debug(output)
4012 finally: 3978 finally:
4013 # And then swap back to the original branch and clean up. 3979 # And then swap back to the original branch and clean up.
4014 RunGit(['checkout', '-q', cl.GetBranch()]) 3980 RunGit(['checkout', '-q', cl.GetBranch()])
4015 RunGit(['branch', '-D', MERGE_BRANCH]) 3981 RunGit(['branch', '-D', MERGE_BRANCH])
4016 if base_has_submodules: 3982 if base_has_submodules:
4017 RunGit(['branch', '-D', CHERRY_PICK_BRANCH]) 3983 RunGit(['branch', '-D', CHERRY_PICK_BRANCH])
4018 3984
4019 if not revision: 3985 if not revision:
4020 print('Failed to push. If this persists, please file a bug.') 3986 print('Failed to push. If this persists, please file a bug.')
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
4053 comment += ' (presubmit successful).' 4019 comment += ' (presubmit successful).'
4054 cl.RpcServer().add_comment(cl.GetIssue(), comment) 4020 cl.RpcServer().add_comment(cl.GetIssue(), comment)
4055 cl.SetIssue(None) 4021 cl.SetIssue(None)
4056 4022
4057 if pushed_to_pending: 4023 if pushed_to_pending:
4058 _, branch = cl.FetchUpstreamTuple(cl.GetBranch()) 4024 _, branch = cl.FetchUpstreamTuple(cl.GetBranch())
4059 print('The commit is in the pending queue (%s).' % pending_ref) 4025 print('The commit is in the pending queue (%s).' % pending_ref)
4060 print('It will show up on %s in ~1 min, once it gets a Cr-Commit-Position ' 4026 print('It will show up on %s in ~1 min, once it gets a Cr-Commit-Position '
4061 'footer.' % branch) 4027 'footer.' % branch)
4062 4028
4063 hook = POSTUPSTREAM_HOOK_PATTERN % cmd 4029 hook = POSTUPSTREAM_HOOK_PATTERN % 'land'
4064 if os.path.isfile(hook): 4030 if os.path.isfile(hook):
4065 RunCommand([hook, merge_base], error_ok=True) 4031 RunCommand([hook, merge_base], error_ok=True)
4066 4032
4067 return 1 if killed else 0 4033 return 1 if killed else 0
4068 4034
4069 4035
4070 def WaitForRealCommit(remote, pushed_commit, local_base_ref, real_ref): 4036 def WaitForRealCommit(remote, pushed_commit, local_base_ref, real_ref):
4071 print() 4037 print()
4072 print('Waiting for commit to be landed on %s...' % real_ref) 4038 print('Waiting for commit to be landed on %s...' % real_ref)
4073 print('(If you are impatient, you may Ctrl-C once without harm)') 4039 print('(If you are impatient, you may Ctrl-C once without harm)')
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
4154 print('All attempts to push to pending ref failed.') 4120 print('All attempts to push to pending ref failed.')
4155 return code, out 4121 return code, out
4156 4122
4157 4123
4158 def IsFatalPushFailure(push_stdout): 4124 def IsFatalPushFailure(push_stdout):
4159 """True if retrying push won't help.""" 4125 """True if retrying push won't help."""
4160 return '(prohibited by Gerrit)' in push_stdout 4126 return '(prohibited by Gerrit)' in push_stdout
4161 4127
4162 4128
4163 @subcommand.usage('[upstream branch to apply against]') 4129 @subcommand.usage('[upstream branch to apply against]')
4164 def CMDdcommit(parser, args):
4165 """Commits the current changelist via git-svn."""
4166 if not settings.GetIsGitSvn():
4167 if git_footers.get_footer_svn_id():
4168 # If it looks like previous commits were mirrored with git-svn.
4169 message = """This repository appears to be a git-svn mirror, but no
4170 upstream SVN master is set. You probably need to run 'git auto-svn' once."""
4171 else:
4172 message = """This doesn't appear to be an SVN repository.
4173 If your project has a true, writeable git repository, you probably want to run
4174 'git cl land' instead.
4175 If your project has a git mirror of an upstream SVN master, you probably need
4176 to run 'git svn init'.
4177
4178 Using the wrong command might cause your commit to appear to succeed, and the
4179 review to be closed, without actually landing upstream. If you choose to
4180 proceed, please verify that the commit lands upstream as expected."""
4181 print(message)
4182 ask_for_data('[Press enter to dcommit or ctrl-C to quit]')
4183 # TODO(tandrii): kill this post SVN migration with
4184 # https://codereview.chromium.org/2076683002
4185 print('WARNING: chrome infrastructure is migrating SVN repos to Git.\n'
4186 'Please let us know of this project you are committing to:'
4187 ' http://crbug.com/600451')
4188 return SendUpstream(parser, args, 'dcommit')
4189
4190
4191 @subcommand.usage('[upstream branch to apply against]')
4192 def CMDland(parser, args): 4130 def CMDland(parser, args):
4193 """Commits the current changelist via git.""" 4131 """Commits the current changelist via git."""
4194 if settings.GetIsGitSvn() or git_footers.get_footer_svn_id(): 4132 if settings.GetIsGitSvn() or git_footers.get_footer_svn_id():
4195 print('This appears to be an SVN repository.') 4133 print('This appears to be an SVN repository.')
4196 print('Are you sure you didn\'t mean \'git cl dcommit\'?') 4134 print('Are you sure you didn\'t mean \'git cl dcommit\'?')
Michael Moss 2016/08/15 15:26:32 Change this too, maybe remove the get_footer_svn_i
4197 print('(Ignore if this is the first commit after migrating from svn->git)') 4135 print('(Ignore if this is the first commit after migrating from svn->git)')
4198 ask_for_data('[Press enter to push or ctrl-C to quit]') 4136 ask_for_data('[Press enter to push or ctrl-C to quit]')
4199 return SendUpstream(parser, args, 'land') 4137 return SendUpstream(parser, args)
4200 4138
4201 4139
4202 @subcommand.usage('<patch url or issue id or issue url>') 4140 @subcommand.usage('<patch url or issue id or issue url>')
4203 def CMDpatch(parser, args): 4141 def CMDpatch(parser, args):
4204 """Patches in a code review.""" 4142 """Patches in a code review."""
4205 parser.add_option('-b', dest='newbranch', 4143 parser.add_option('-b', dest='newbranch',
4206 help='create a new branch off trunk for the patch') 4144 help='create a new branch off trunk for the patch')
4207 parser.add_option('-f', '--force', action='store_true', 4145 parser.add_option('-f', '--force', action='store_true',
4208 help='with -b, clobber any existing branch') 4146 help='with -b, clobber any existing branch')
4209 parser.add_option('-d', '--directory', action='store', metavar='DIR', 4147 parser.add_option('-d', '--directory', action='store', metavar='DIR',
(...skipping 824 matching lines...) Expand 10 before | Expand all | Expand 10 after
5034 if __name__ == '__main__': 4972 if __name__ == '__main__':
5035 # These affect sys.stdout so do it outside of main() to simplify mocks in 4973 # These affect sys.stdout so do it outside of main() to simplify mocks in
5036 # unit testing. 4974 # unit testing.
5037 fix_encoding.fix_encoding() 4975 fix_encoding.fix_encoding()
5038 setup_color.init() 4976 setup_color.init()
5039 try: 4977 try:
5040 sys.exit(main(sys.argv[1:])) 4978 sys.exit(main(sys.argv[1:]))
5041 except KeyboardInterrupt: 4979 except KeyboardInterrupt:
5042 sys.stderr.write('interrupted\n') 4980 sys.stderr.write('interrupted\n')
5043 sys.exit(1) 4981 sys.exit(1)
OLDNEW
« no previous file with comments | « no previous file | tests/git_cl_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698