Rudimentary support for multiple development branches
[stgit] / stgit / commands / branch.py
CommitLineData
7b1ba1a6
CL
1"""Branch command
2"""
3
4__copyright__ = """
5Copyright (C) 2005, Chuck Lever <cel@netapp.com>
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License version 2 as
9published by the Free Software Foundation.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19"""
20
21import sys, os
22from optparse import OptionParser, make_option
23
24from stgit.commands.common import *
25from stgit.utils import *
26from stgit import stack, git
27
28
29help = 'manage development branches'
30usage = """%prog [options] branch-name [commit-id]
31
32Create, list, switch between, rename, or delete development branches
33within a git repository. By default, a single branch called 'master'
34is always created in a new repository. This subcommand allows you to
35manage several patch series in the same repository.
36
37When displaying the branches, the names can be prefixed with
38's' (StGIT managed) or 'p' (protected)."""
39
40options = [make_option('-c', '--create',
41 help = 'create a new development branch',
42 action = 'store_true'),
43 make_option('--delete',
44 help = 'delete an existing development branch',
45 action = 'store_true'),
46 make_option('--force',
47 help = 'force a delete when the series is not empty',
48 action = 'store_true'),
49 make_option('-l', '--list',
50 help = 'list branches contained in this repository',
51 action = 'store_true'),
52 make_option('-r', '--rename',
53 help = 'rename an existing development branch',
54 action = 'store_true')]
55
56
57def is_current_branch(branch_name):
58 return git.get_head_file() == branch_name
59
60def print_branch(branch_name):
61 initialized = ' '
62 current = ' '
63 if os.path.isdir(os.path.join(git.base_dir, 'patches', branch_name)):
64 initialized = 's'
65 if is_current_branch(branch_name):
66 current = '>'
67 print '%s %s\t%s' % (current, initialized, branch_name)
68
69def delete_branch(doomed_name, force = False):
70 if is_current_branch(doomed_name) and doomed_name != 'master':
71 git.switch_branch('master')
72
73 stack.Series(doomed_name).delete(force)
74
75 if doomed_name != 'master':
76 git.delete_branch(doomed_name)
77
78 print 'Branch "%s" has been deleted.' % doomed_name
79
80def rename_branch(from_name, to_name):
81 if from_name == 'master':
82 raise CmdException, 'Renaming the master branch is not allowed'
83
84 to_patchdir = os.path.join(git.base_dir, 'patches', to_name)
85 if os.path.isdir(to_patchdir):
86 raise CmdException, '"%s" already exists' % to_patchdir
87 to_base = os.path.join(git.base_dir, 'refs', 'bases', to_name)
88 if os.path.isfile(to_base):
89 raise CmdException, '"%s" already exists' % to_base
90
91 git.rename_branch(from_name, to_name)
92
93 from_patchdir = os.path.join(git.base_dir, 'patches', from_name)
94 if os.path.isdir(from_patchdir):
95 os.rename(from_patchdir, to_patchdir)
96 from_base = os.path.join(git.base_dir, 'refs', 'bases', from_name)
97 if os.path.isfile(from_base):
98 os.rename(from_base, to_base)
99
100 print 'Renamed branch "%s" as "%s".' % (from_name, to_name)
101
102def func(parser, options, args):
103
104 if options.create:
105
106 if len(args) == 0 or len(args) > 2:
107 parser.error('incorrect number of arguments')
108 tree_id = None
109 if len(args) == 2:
110 tree_id = args[1]
111
112 git.create_branch(args[0], tree_id)
113 stack.Series(args[0]).init()
114
115 print 'Branch "%s" created.' % args[0]
116 return
117
118 elif options.delete:
119
120 if len(args) != 1:
121 parser.error('incorrect number of arguments')
122 delete_branch(args[0], options.force)
123 return
124
125 elif options.list:
126
127 if len(args) != 0:
128 parser.error('incorrect number of arguments')
129
130 branches = os.listdir(os.path.join(git.base_dir, 'refs', 'heads'))
131 branches.sort()
132
133 print 'Available branches:'
134 for i in branches:
135 print_branch(i)
136 return
137
138 elif options.rename:
139
140 if len(args) != 2:
141 parser.error('incorrect number of arguments')
142 rename_branch(args[0], args[1])
143 return
144
145 elif len(args) == 1:
146
147 print 'Switching to branch "%s"...' % args[0],
148 sys.stdout.flush()
149
150 git.switch_branch(args[0])
151
152 print 'done'
153 return
154
155 # default action: print the current branch
156 if len(args) != 0:
157 parser.error('incorrect number of arguments')
158
159 print git.get_head_file()