blob: 083acae1b908a6797ebb0bddbda0b16c072869b6 [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
Raul Tambre80ee78e2019-05-06 22:41:05 +00008from __future__ import print_function
9
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000010import argparse
11import sys
12
13import subprocess2
14
15from git_common import upstream, current_branch, run, tags, set_branch_config
iannucci@chromium.org10fbe872014-05-16 22:31:13 +000016from git_common import get_or_create_merge_base, root, manual_merge_base
Henrique Ferreiro9f273d02019-02-22 10:10:27 +000017from git_common import get_branch_tree, topo_iter
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000018
19import git_rebase_update
20
21def main(args):
22 root_ref = root()
23
24 parser = argparse.ArgumentParser()
25 g = parser.add_mutually_exclusive_group()
26 g.add_argument('new_parent', nargs='?',
27 help='New parent branch (or tag) to reparent to.')
28 g.add_argument('--root', action='store_true',
29 help='Reparent to the configured root branch (%s).' % root_ref)
30 g.add_argument('--lkgr', action='store_true',
31 help='Reparent to the lkgr tag.')
32 opts = parser.parse_args(args)
33
34 # TODO(iannucci): Allow specification of the branch-to-reparent
35
36 branch = current_branch()
iannucci@chromium.orgf3e37a02015-12-04 19:03:23 +000037
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000038 if opts.root:
39 new_parent = root_ref
40 elif opts.lkgr:
41 new_parent = 'lkgr'
42 else:
tandrii@chromium.org41a9ce42015-08-06 17:57:12 +000043 if not opts.new_parent:
44 parser.error('Must specify new parent somehow')
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000045 new_parent = opts.new_parent
46 cur_parent = upstream(branch)
47
48 if branch == 'HEAD' or not branch:
49 parser.error('Must be on the branch you want to reparent')
50 if new_parent == cur_parent:
51 parser.error('Cannot reparent a branch to its existing parent')
52
iannucci@chromium.orgf3e37a02015-12-04 19:03:23 +000053 if not cur_parent:
54 msg = (
55 "Unable to determine %s@{upstream}.\n\nThis can happen if you didn't use "
56 "`git new-branch` to create the branch and haven't used "
57 "`git branch --set-upstream-to` to assign it one.\n\nPlease assign an "
58 "upstream branch and then run this command again."
59 )
Raul Tambre80ee78e2019-05-06 22:41:05 +000060 print(msg % branch, file=sys.stderr)
iannucci@chromium.orgf3e37a02015-12-04 19:03:23 +000061 return 1
62
iannucci@chromium.org10fbe872014-05-16 22:31:13 +000063 mbase = get_or_create_merge_base(branch, cur_parent)
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000064
65 all_tags = tags()
66 if cur_parent in all_tags:
67 cur_parent += ' [tag]'
68
69 try:
70 run('show-ref', new_parent)
71 except subprocess2.CalledProcessError:
Raul Tambre80ee78e2019-05-06 22:41:05 +000072 print('fatal: invalid reference: %s' % new_parent, file=sys.stderr)
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000073 return 1
74
75 if new_parent in all_tags:
Raul Tambre80ee78e2019-05-06 22:41:05 +000076 print("Reparenting %s to track %s [tag] (was %s)" % (branch, new_parent,
77 cur_parent))
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000078 set_branch_config(branch, 'remote', '.')
79 set_branch_config(branch, 'merge', new_parent)
80 else:
Raul Tambre80ee78e2019-05-06 22:41:05 +000081 print("Reparenting %s to track %s (was %s)" % (branch, new_parent,
82 cur_parent))
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000083 run('branch', '--set-upstream-to', new_parent, branch)
84
iannucci@chromium.org10fbe872014-05-16 22:31:13 +000085 manual_merge_base(branch, mbase, new_parent)
86
Henrique Ferreiro9f273d02019-02-22 10:10:27 +000087 # ONLY rebase-update the branch which moved (and dependants)
88 _, branch_tree = get_branch_tree()
89 branches = [branch]
90 for branch, parent in topo_iter(branch_tree):
91 if parent in branches:
92 branches.append(branch)
93 return git_rebase_update.main(['--no-fetch'] + branches)
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000094
95
96if __name__ == '__main__': # pragma: no cover
sbc@chromium.org013731e2015-02-26 18:28:43 +000097 try:
98 sys.exit(main(sys.argv[1:]))
99 except KeyboardInterrupt:
100 sys.stderr.write('interrupted\n')
101 sys.exit(1)