blob: 00ee742c73c2d489f6223cd5d12d06c873a3d1e3 [file] [log] [blame]
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +00001#!/usr/bin/env python
2# Copyright 2014 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Change the upstream of the current branch."""
7
8import argparse
9import sys
10
11import subprocess2
12
13from git_common import upstream, current_branch, run, tags, set_branch_config
iannucci@chromium.org10fbe872014-05-16 22:31:13 +000014from git_common import get_or_create_merge_base, root, manual_merge_base
Henrique Ferreiro9f273d02019-02-22 10:10:27 +000015from git_common import get_branch_tree, topo_iter
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000016
17import git_rebase_update
18
19def main(args):
20 root_ref = root()
21
22 parser = argparse.ArgumentParser()
23 g = parser.add_mutually_exclusive_group()
24 g.add_argument('new_parent', nargs='?',
25 help='New parent branch (or tag) to reparent to.')
26 g.add_argument('--root', action='store_true',
27 help='Reparent to the configured root branch (%s).' % root_ref)
28 g.add_argument('--lkgr', action='store_true',
29 help='Reparent to the lkgr tag.')
30 opts = parser.parse_args(args)
31
32 # TODO(iannucci): Allow specification of the branch-to-reparent
33
34 branch = current_branch()
iannucci@chromium.orgf3e37a02015-12-04 19:03:23 +000035
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000036 if opts.root:
37 new_parent = root_ref
38 elif opts.lkgr:
39 new_parent = 'lkgr'
40 else:
tandrii@chromium.org41a9ce42015-08-06 17:57:12 +000041 if not opts.new_parent:
42 parser.error('Must specify new parent somehow')
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000043 new_parent = opts.new_parent
44 cur_parent = upstream(branch)
45
46 if branch == 'HEAD' or not branch:
47 parser.error('Must be on the branch you want to reparent')
48 if new_parent == cur_parent:
49 parser.error('Cannot reparent a branch to its existing parent')
50
iannucci@chromium.orgf3e37a02015-12-04 19:03:23 +000051 if not cur_parent:
52 msg = (
53 "Unable to determine %s@{upstream}.\n\nThis can happen if you didn't use "
54 "`git new-branch` to create the branch and haven't used "
55 "`git branch --set-upstream-to` to assign it one.\n\nPlease assign an "
56 "upstream branch and then run this command again."
57 )
58 print >> sys.stderr, msg % branch
59 return 1
60
iannucci@chromium.org10fbe872014-05-16 22:31:13 +000061 mbase = get_or_create_merge_base(branch, cur_parent)
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000062
63 all_tags = tags()
64 if cur_parent in all_tags:
65 cur_parent += ' [tag]'
66
67 try:
68 run('show-ref', new_parent)
69 except subprocess2.CalledProcessError:
70 print >> sys.stderr, 'fatal: invalid reference: %s' % new_parent
71 return 1
72
73 if new_parent in all_tags:
74 print ("Reparenting %s to track %s [tag] (was %s)"
75 % (branch, new_parent, cur_parent))
76 set_branch_config(branch, 'remote', '.')
77 set_branch_config(branch, 'merge', new_parent)
78 else:
79 print ("Reparenting %s to track %s (was %s)"
80 % (branch, new_parent, cur_parent))
81 run('branch', '--set-upstream-to', new_parent, branch)
82
iannucci@chromium.org10fbe872014-05-16 22:31:13 +000083 manual_merge_base(branch, mbase, new_parent)
84
Henrique Ferreiro9f273d02019-02-22 10:10:27 +000085 # ONLY rebase-update the branch which moved (and dependants)
86 _, branch_tree = get_branch_tree()
87 branches = [branch]
88 for branch, parent in topo_iter(branch_tree):
89 if parent in branches:
90 branches.append(branch)
91 return git_rebase_update.main(['--no-fetch'] + branches)
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000092
93
94if __name__ == '__main__': # pragma: no cover
sbc@chromium.org013731e2015-02-26 18:28:43 +000095 try:
96 sys.exit(main(sys.argv[1:]))
97 except KeyboardInterrupt:
98 sys.stderr.write('interrupted\n')
99 sys.exit(1)