blob: 3087588c9869ff6a3998dc206fceaa9009a69395 [file] [log] [blame]
Josip Sokcevic4de5dea2022-03-23 21:15:14 +00001#!/usr/bin/env python3
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +00002# 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.
techtonik@gmail.comb14fccd2016-04-20 04:10:09 +00005"""
Josip Sokcevic9c0dc302020-11-20 18:41:25 +00006Create new branch tracking origin HEAD by default.
techtonik@gmail.comb14fccd2016-04-20 04:10:09 +00007"""
8
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +00009import argparse
10import sys
11
Edward Lemur84101642020-02-21 21:40:34 +000012import git_common
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000013import subprocess2
14
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000015
Mike Frysinger124bb8e2023-09-06 05:48:55 +000016def create_new_branch(branch_name,
17 upstream_current=False,
18 upstream=None,
19 inject_current=False):
20 upstream = upstream or git_common.root()
21 try:
22 if inject_current:
23 below = git_common.current_branch()
24 if below is None:
25 raise Exception('no current branch')
26 above = git_common.upstream(below)
27 if above is None:
28 raise Exception('branch %s has no upstream' % (below))
29 git_common.run('checkout', '--track', above, '-b', branch_name)
30 git_common.run('branch', '--set-upstream-to', branch_name, below)
31 elif upstream_current:
32 git_common.run('checkout', '--track', '-b', branch_name)
33 else:
34 if upstream in git_common.tags():
35 # TODO(iannucci): ensure that basis_ref is an ancestor of HEAD?
36 git_common.run('checkout', '--no-track', '-b', branch_name,
37 git_common.hash_one(upstream))
38 git_common.set_config('branch.%s.remote' % branch_name, '.')
39 git_common.set_config('branch.%s.merge' % branch_name, upstream)
40 else:
41 # TODO(iannucci): Detect unclean workdir then stash+pop if we
42 # need to teleport to a conflicting portion of history?
43 git_common.run('checkout', '--track', upstream, '-b',
44 branch_name)
45 git_common.get_or_create_merge_base(branch_name)
46 except subprocess2.CalledProcessError as cpe:
47 sys.stdout.write(cpe.stdout.decode('utf-8', 'replace'))
48 sys.stderr.write(cpe.stderr.decode('utf-8', 'replace'))
49 return 1
50 sys.stderr.write('Switched to branch %s.\n' % branch_name)
51 return 0
52
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000053
54def main(args):
Mike Frysinger124bb8e2023-09-06 05:48:55 +000055 parser = argparse.ArgumentParser(
56 formatter_class=argparse.ArgumentDefaultsHelpFormatter,
57 description=__doc__,
58 )
59 parser.add_argument('branch_name')
60 g = parser.add_mutually_exclusive_group()
61 g.add_argument('--upstream-current',
62 '--upstream_current',
63 action='store_true',
64 help='set upstream branch to current branch.')
65 g.add_argument('--upstream',
66 metavar='REF',
67 help='upstream branch (or tag) to track.')
68 g.add_argument('--inject-current',
69 '--inject_current',
70 action='store_true',
71 help='new branch adopts current branch\'s upstream,' +
72 ' and new branch becomes current branch\'s upstream.')
73 g.add_argument('--lkgr',
74 action='store_const',
75 const='lkgr',
76 dest='upstream',
77 help='set basis ref for new branch to lkgr.')
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000078
Mike Frysinger124bb8e2023-09-06 05:48:55 +000079 opts = parser.parse_args(args)
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000080
Mike Frysinger124bb8e2023-09-06 05:48:55 +000081 return create_new_branch(opts.branch_name, opts.upstream_current,
82 opts.upstream, opts.inject_current)
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000083
84
85if __name__ == '__main__': # pragma: no cover
Mike Frysinger124bb8e2023-09-06 05:48:55 +000086 try:
87 sys.exit(main(sys.argv[1:]))
88 except KeyboardInterrupt:
89 sys.stderr.write('interrupted\n')
90 sys.exit(1)