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

Side by Side Diff: git_cl.py

Issue 1835963003: Gerrit git cl: stop creating a shadow branch. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@H150
Patch Set: Created 4 years, 8 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') | tests/git_cl_test.py » ('J')
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 distutils.version import LooseVersion 10 from distutils.version import LooseVersion
(...skipping 2506 matching lines...) Expand 10 before | Expand all | Expand 10 after
2517 def GerritUpload(options, args, cl, change): 2517 def GerritUpload(options, args, cl, change):
2518 """upload the current branch to gerrit.""" 2518 """upload the current branch to gerrit."""
2519 # We assume the remote called "origin" is the one we want. 2519 # We assume the remote called "origin" is the one we want.
2520 # It is probably not worthwhile to support different workflows. 2520 # It is probably not worthwhile to support different workflows.
2521 gerrit_remote = 'origin' 2521 gerrit_remote = 'origin'
2522 2522
2523 remote, remote_branch = cl.GetRemoteBranch() 2523 remote, remote_branch = cl.GetRemoteBranch()
2524 branch = GetTargetRef(remote, remote_branch, options.target_branch, 2524 branch = GetTargetRef(remote, remote_branch, options.target_branch,
2525 pending_prefix='') 2525 pending_prefix='')
2526 2526
2527 change_desc = ChangeDescription(
2528 options.message or CreateDescriptionFromLog(args))
2529 if not change_desc.description:
2530 print "\nDescription is empty. Aborting..."
2531 return 1
2532
2533 if options.title: 2527 if options.title:
2534 print "\nPatch titles (-t) are not supported in Gerrit. Aborting..." 2528 print "\nPatch titles (-t) are not supported in Gerrit. Aborting..."
2535 return 1 2529 return 1
2536 2530
2537 if options.squash: 2531 if options.squash:
2538 # Try to get the message from a previous upload. 2532 if cl.GetIssue():
2539 shadow_branch = 'refs/heads/git_cl_uploads/' + cl.GetBranch() 2533 # Try to get the message from a previous upload.
2540 message = RunGitSilent(['show', '--format=%B', '-s', shadow_branch]) 2534 message = cl.GetDescription()
2541 if not message: 2535 if not message:
2536 DieWithError(
2537 'failed to fetch description from current Gerrit issue %d\n'
2538 '%s' % (cl.GetIssue(), cl.GetIssueURL()))
2539 # Issues already on Gerrit really must have exactly 1 Change-Id.
Bernhard Bauer 2016/03/29 08:22:49 In practice this could fail (e.g. an old CL that w
tandrii(chromium) 2016/03/29 08:37:41 Didn't know it was possible, but let's assume so.
Bernhard Bauer 2016/03/29 09:03:21 If a commit is pushed that doesn't have a Change-I
tandrii(chromium) 2016/03/29 13:06:24 Ah, i see.
2540 change_ids = git_footers.get_footer_change_id(message)
2541 assert len(change_ids) == 1
2542 change_desc = ChangeDescription(message)
2543 else:
2544 change_desc = ChangeDescription(
2545 options.message or CreateDescriptionFromLog(args))
2542 if not options.force: 2546 if not options.force:
2543 change_desc.prompt() 2547 change_desc.prompt()
2544 if not change_desc.description: 2548 if not change_desc.description:
2545 print "Description is empty; aborting." 2549 print "Description is empty; aborting."
2546 return 1 2550 return 1
2547 message = change_desc.description 2551 message = change_desc.description
2548 change_ids = git_footers.get_footer_change_id(message) 2552 change_ids = git_footers.get_footer_change_id(message)
2549 if len(change_ids) > 1: 2553 if len(change_ids) > 1:
2550 DieWithError('too many Change-Id footers in %s branch' % shadow_branch) 2554 DieWithError('too many Change-Id footers, at most 1 allowed.')
2551 if not change_ids: 2555 if not change_ids:
2556 # Generate the Change-Id automatically.
2552 message = git_footers.add_footer_change_id( 2557 message = git_footers.add_footer_change_id(
2553 message, GenerateGerritChangeId(message)) 2558 message, GenerateGerritChangeId(message))
2554 change_desc.set_description(message) 2559 change_desc.set_description(message)
2555 change_ids = git_footers.get_footer_change_id(message) 2560 change_ids = git_footers.get_footer_change_id(message)
2556 assert len(change_ids) == 1 2561 assert len(change_ids) == 1
2557 2562 change_id = change_ids[0]
2558 change_id = change_ids[0]
2559 2563
2560 remote, upstream_branch = cl.FetchUpstreamTuple(cl.GetBranch()) 2564 remote, upstream_branch = cl.FetchUpstreamTuple(cl.GetBranch())
2561 if remote is '.': 2565 if remote is '.':
2562 # If our upstream branch is local, we base our squashed commit on its 2566 # If our upstream branch is local, we base our squashed commit on its
2563 # squashed version. 2567 # squashed version.
2564 parent = ('refs/heads/git_cl_uploads/' + 2568 upstream_branch_name = scm.GIT.ShortBranchName(upstream_branch)
2565 scm.GIT.ShortBranchName(upstream_branch)) 2569 # Check the squashed hash of the parent.
2566 2570 parent = RunGit(['config',
2567 # Verify that the upstream branch has been uploaded too, otherwise Gerrit 2571 'branch.%s.gerritsquashhash' % upstream_branch_name],
2568 # will create additional CLs when uploading. 2572 error_ok=True).strip()
2569 if (RunGitSilent(['rev-parse', upstream_branch + ':']) != 2573 # Verify that the upstream branch has been uploaded too, otherwise
2570 RunGitSilent(['rev-parse', parent + ':'])): 2574 # Gerrit will create additional CLs when uploading.
2571 print 'Upload upstream branch ' + upstream_branch + ' first.' 2575 if not parent or (RunGitSilent(['rev-parse', upstream_branch + ':']) !=
2572 return 1 2576 RunGitSilent(['rev-parse', parent + ':'])):
2577 # TODO(tandrii): remove "old depot_tools" part on April 12, 2016.
2578 DieWithError(
2579 'Upload upstream branch %s first.\n'
2580 'Note: maybe you\'ve uploaded it with --no-squash or with old\n'
Bernhard Bauer 2016/03/29 08:22:49 Nit: "[...] with an old version [...]".
tandrii(chromium) 2016/03/29 13:06:24 Done.
2581 ' version of depot_tools. If so, then re-upload it with:\n'
2582 ' git cl upload --squash\n' % upstream_branch_name)
2573 else: 2583 else:
2574 parent = cl.GetCommonAncestorWithUpstream() 2584 parent = cl.GetCommonAncestorWithUpstream()
2575 2585
2576 tree = RunGit(['rev-parse', 'HEAD:']).strip() 2586 tree = RunGit(['rev-parse', 'HEAD:']).strip()
2577 ref_to_push = RunGit(['commit-tree', tree, '-p', parent, 2587 ref_to_push = RunGit(['commit-tree', tree, '-p', parent,
2578 '-m', message]).strip() 2588 '-m', message]).strip()
2579 else: 2589 else:
2590 change_desc = ChangeDescription(
2591 options.message or CreateDescriptionFromLog(args))
2592 if not change_desc.description:
2593 print "\nDescription is empty. Aborting..."
ukai 2016/03/29 02:16:16 nit: DieWithError? what is difference between Die
tandrii(chromium) 2016/03/29 08:37:41 Same thing, afaiu. This was copy-paste from above,
tandrii(chromium) 2016/03/29 13:06:24 Done.
2594 return 1
2595
2580 if not git_footers.get_footer_change_id(change_desc.description): 2596 if not git_footers.get_footer_change_id(change_desc.description):
2581 DownloadGerritHook(False) 2597 DownloadGerritHook(False)
2582 change_desc.set_description(AddChangeIdToCommitMessage(options, args)) 2598 change_desc.set_description(AddChangeIdToCommitMessage(options, args))
2583 ref_to_push = 'HEAD' 2599 ref_to_push = 'HEAD'
2584 parent = '%s/%s' % (gerrit_remote, branch) 2600 parent = '%s/%s' % (gerrit_remote, branch)
2585 change_id = git_footers.get_footer_change_id(change_desc.description)[0] 2601 change_id = git_footers.get_footer_change_id(change_desc.description)[0]
2586 2602
2603 assert change_desc
2587 commits = RunGitSilent(['rev-list', '%s..%s' % (parent, 2604 commits = RunGitSilent(['rev-list', '%s..%s' % (parent,
2588 ref_to_push)]).splitlines() 2605 ref_to_push)]).splitlines()
2589 if len(commits) > 1: 2606 if len(commits) > 1:
2590 print('WARNING: This will upload %d commits. Run the following command ' 2607 print('WARNING: This will upload %d commits. Run the following command '
2591 'to see which commits will be uploaded: ' % len(commits)) 2608 'to see which commits will be uploaded: ' % len(commits))
2592 print('git log %s..%s' % (parent, ref_to_push)) 2609 print('git log %s..%s' % (parent, ref_to_push))
2593 print('You can also use `git squash-branch` to squash these into a single ' 2610 print('You can also use `git squash-branch` to squash these into a single '
2594 'commit.') 2611 'commit.')
2595 ask_for_data('About to upload; enter to confirm.') 2612 ask_for_data('About to upload; enter to confirm.')
2596 2613
(...skipping 26 matching lines...) Expand all
2623 if options.squash: 2640 if options.squash:
2624 regex = re.compile(r'remote:\s+https?://[\w\-\.\/]*/(\d+)\s.*') 2641 regex = re.compile(r'remote:\s+https?://[\w\-\.\/]*/(\d+)\s.*')
2625 change_numbers = [m.group(1) 2642 change_numbers = [m.group(1)
2626 for m in map(regex.match, push_stdout.splitlines()) 2643 for m in map(regex.match, push_stdout.splitlines())
2627 if m] 2644 if m]
2628 if len(change_numbers) != 1: 2645 if len(change_numbers) != 1:
2629 DieWithError( 2646 DieWithError(
2630 ('Created|Updated %d issues on Gerrit, but only 1 expected.\n' 2647 ('Created|Updated %d issues on Gerrit, but only 1 expected.\n'
2631 'Change-Id: %s') % (len(change_numbers), change_id)) 2648 'Change-Id: %s') % (len(change_numbers), change_id))
2632 cl.SetIssue(change_numbers[0]) 2649 cl.SetIssue(change_numbers[0])
2633 head = RunGit(['rev-parse', 'HEAD']).strip() 2650 RunGit(['config', 'branch.%s.gerritsquashhash' % cl.GetBranch(),
2634 RunGit(['update-ref', '-m', 'Uploaded ' + head, shadow_branch, ref_to_push]) 2651 ref_to_push])
2635 return 0 2652 return 0
2636 2653
2637 2654
2638 def GetTargetRef(remote, remote_branch, target_branch, pending_prefix): 2655 def GetTargetRef(remote, remote_branch, target_branch, pending_prefix):
2639 """Computes the remote branch ref to use for the CL. 2656 """Computes the remote branch ref to use for the CL.
2640 2657
2641 Args: 2658 Args:
2642 remote (str): The git remote for the CL. 2659 remote (str): The git remote for the CL.
2643 remote_branch (str): The git remote branch for the CL. 2660 remote_branch (str): The git remote branch for the CL.
2644 target_branch (str): The target branch specified by the user. 2661 target_branch (str): The target branch specified by the user.
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
2915 auth.add_auth_options(parser) 2932 auth.add_auth_options(parser)
2916 (options, args) = parser.parse_args(args) 2933 (options, args) = parser.parse_args(args)
2917 auth_config = auth.extract_auth_config_from_options(options) 2934 auth_config = auth.extract_auth_config_from_options(options)
2918 2935
2919 if git_common.is_dirty_git_tree('upload'): 2936 if git_common.is_dirty_git_tree('upload'):
2920 return 1 2937 return 1
2921 2938
2922 options.reviewers = cleanup_list(options.reviewers) 2939 options.reviewers = cleanup_list(options.reviewers)
2923 options.cc = cleanup_list(options.cc) 2940 options.cc = cleanup_list(options.cc)
2924 2941
2942 # For sanity of test expectations, do this otherwise lazy-loading *now*.
2943 settings.GetIsGerrit()
2944
2925 cl = Changelist(auth_config=auth_config) 2945 cl = Changelist(auth_config=auth_config)
2926 if args: 2946 if args:
2927 # TODO(ukai): is it ok for gerrit case? 2947 # TODO(ukai): is it ok for gerrit case?
2928 base_branch = args[0] 2948 base_branch = args[0]
2929 else: 2949 else:
2930 if cl.GetBranch() is None: 2950 if cl.GetBranch() is None:
2931 DieWithError('Can\'t upload from detached HEAD state. Get on a branch!') 2951 DieWithError('Can\'t upload from detached HEAD state. Get on a branch!')
2932 2952
2933 # Default to diffing against common ancestor of upstream branch 2953 # Default to diffing against common ancestor of upstream branch
2934 base_branch = cl.GetCommonAncestorWithUpstream() 2954 base_branch = cl.GetCommonAncestorWithUpstream()
(...skipping 1389 matching lines...) Expand 10 before | Expand all | Expand 10 after
4324 if __name__ == '__main__': 4344 if __name__ == '__main__':
4325 # These affect sys.stdout so do it outside of main() to simplify mocks in 4345 # These affect sys.stdout so do it outside of main() to simplify mocks in
4326 # unit testing. 4346 # unit testing.
4327 fix_encoding.fix_encoding() 4347 fix_encoding.fix_encoding()
4328 colorama.init() 4348 colorama.init()
4329 try: 4349 try:
4330 sys.exit(main(sys.argv[1:])) 4350 sys.exit(main(sys.argv[1:]))
4331 except KeyboardInterrupt: 4351 except KeyboardInterrupt:
4332 sys.stderr.write('interrupted\n') 4352 sys.stderr.write('interrupted\n')
4333 sys.exit(1) 4353 sys.exit(1)
OLDNEW
« no previous file with comments | « no previous file | tests/git_cl_test.py » ('j') | tests/git_cl_test.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698