remove formatting of git log entry on an imported patch
[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
cc3db2b1 21import sys, os, time
7b1ba1a6
CL
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
cc3db2b1 32Create, clone, switch between, rename, or delete development branches
7b1ba1a6
CL
33within a git repository. By default, a single branch called 'master'
34is always created in a new repository. This subcommand allows you to
cc3db2b1 35manage several patch series in the same repository via GIT branches.
7b1ba1a6
CL
36
37When displaying the branches, the names can be prefixed with
a8032a85
CL
38's' (StGIT managed) or 'p' (protected).
39
40If not given any options, switch to the named branch."""
7b1ba1a6
CL
41
42options = [make_option('-c', '--create',
43 help = 'create a new development branch',
44 action = 'store_true'),
cc3db2b1
CL
45 make_option('--clone',
46 help = 'clone the contents of the current branch',
47 action = 'store_true'),
7b1ba1a6
CL
48 make_option('--delete',
49 help = 'delete an existing development branch',
50 action = 'store_true'),
51 make_option('--force',
52 help = 'force a delete when the series is not empty',
53 action = 'store_true'),
54 make_option('-l', '--list',
55 help = 'list branches contained in this repository',
56 action = 'store_true'),
0b4b9499
CL
57 make_option('-p', '--protect',
58 help = 'prevent "stg pull" from modifying this branch',
59 action = 'store_true'),
7b1ba1a6
CL
60 make_option('-r', '--rename',
61 help = 'rename an existing development branch',
0b4b9499
CL
62 action = 'store_true'),
63 make_option('-u', '--unprotect',
64 help = 'allow "stg pull" to modify this branch',
7b1ba1a6
CL
65 action = 'store_true')]
66
67
fe4f6d58
CM
68def __is_current_branch(branch_name):
69 return crt_series.get_branch() == branch_name
7b1ba1a6 70
862ba51a 71def __print_branch(branch_name, length):
7b1ba1a6
CL
72 initialized = ' '
73 current = ' '
0b4b9499 74 protected = ' '
ebfd0156
CL
75
76 branch = stack.Series(branch_name)
77
2d00440c 78 if branch.is_initialised():
7b1ba1a6 79 initialized = 's'
fe4f6d58 80 if __is_current_branch(branch_name):
7b1ba1a6 81 current = '>'
ebfd0156 82 if branch.get_protected():
0b4b9499 83 protected = 'p'
862ba51a
CL
84 print current + ' ' + initialized + protected + '\t' + \
85 branch_name.ljust(length) + ' | ' + branch.get_description()
7b1ba1a6 86
fe4f6d58 87def __delete_branch(doomed_name, force = False):
ebfd0156
CL
88 doomed = stack.Series(doomed_name)
89
90 if doomed.get_protected():
0b4b9499
CL
91 raise CmdException, 'This branch is protected. Delete is not permitted'
92
fe4f6d58
CM
93 print 'Deleting branch "%s"...' % doomed_name,
94 sys.stdout.flush()
95
96 if __is_current_branch(doomed_name):
97 check_local_changes()
98 check_conflicts()
99 check_head_top_equal()
100
101 if doomed_name != 'master':
102 git.switch_branch('master')
7b1ba1a6 103
ebfd0156 104 doomed.delete(force)
7b1ba1a6
CL
105
106 if doomed_name != 'master':
107 git.delete_branch(doomed_name)
108
fe4f6d58 109 print 'done'
7b1ba1a6 110
7b1ba1a6
CL
111def func(parser, options, args):
112
113 if options.create:
114
115 if len(args) == 0 or len(args) > 2:
116 parser.error('incorrect number of arguments')
fe4f6d58
CM
117
118 check_local_changes()
119 check_conflicts()
120 check_head_top_equal()
121
7b1ba1a6
CL
122 tree_id = None
123 if len(args) == 2:
124 tree_id = args[1]
125
126 git.create_branch(args[0], tree_id)
127 stack.Series(args[0]).init()
128
129 print 'Branch "%s" created.' % args[0]
130 return
131
cc3db2b1
CL
132 elif options.clone:
133
134 if len(args) == 0:
135 clone = crt_series.get_branch() + \
136 time.strftime('-%C%y%m%d-%H%M%S')
137 elif len(args) == 1:
138 clone = args[0]
139 else:
140 parser.error('incorrect number of arguments')
141
142 check_local_changes()
143 check_conflicts()
144 check_head_top_equal()
145
146 print 'Cloning current branch to "%s"...' % clone,
147 sys.stdout.flush()
148 crt_series.clone(clone)
149 print 'done'
150
151 return
152
7b1ba1a6
CL
153 elif options.delete:
154
155 if len(args) != 1:
156 parser.error('incorrect number of arguments')
fe4f6d58 157 __delete_branch(args[0], options.force)
7b1ba1a6
CL
158 return
159
160 elif options.list:
161
162 if len(args) != 0:
163 parser.error('incorrect number of arguments')
164
bae29ddd 165 branches = os.listdir(os.path.join(git.get_base_dir(), 'refs', 'heads'))
7b1ba1a6 166 branches.sort()
862ba51a 167 max_len = max([len(i) for i in branches])
7b1ba1a6
CL
168
169 print 'Available branches:'
170 for i in branches:
862ba51a 171 __print_branch(i, max_len)
7b1ba1a6
CL
172 return
173
0b4b9499
CL
174 elif options.protect:
175
176 if len(args) == 0:
5fab7247 177 branch_name = crt_series.get_branch()
0b4b9499 178 elif len(args) == 1:
2d00440c 179 branch_name = args[0]
0b4b9499
CL
180 else:
181 parser.error('incorrect number of arguments')
2d00440c 182 branch = stack.Series(branch_name)
0b4b9499 183
2d00440c 184 if not branch.is_initialised():
fe4f6d58
CM
185 raise CmdException, 'Branch "%s" is not controlled by StGIT' \
186 % branch_name
0b4b9499 187
2d00440c 188 print 'Protecting branch "%s"...' % branch_name,
fa08ec08 189 sys.stdout.flush()
2d00440c 190 branch.protect()
fa08ec08
CM
191 print 'done'
192
0b4b9499
CL
193 return
194
7b1ba1a6
CL
195 elif options.rename:
196
197 if len(args) != 2:
198 parser.error('incorrect number of arguments')
660ba985 199
fe4f6d58
CM
200 if __is_current_branch(args[0]):
201 raise CmdException, 'Renaming the current branch is not supported'
202
660ba985
CL
203 stack.Series(args[0]).rename(args[1])
204
205 print 'Renamed branch "%s" as "%s".' % (args[0], args[1])
206
7b1ba1a6
CL
207 return
208
0b4b9499
CL
209 elif options.unprotect:
210
211 if len(args) == 0:
5fab7247 212 branch_name = crt_series.get_branch()
0b4b9499 213 elif len(args) == 1:
2d00440c 214 branch_name = args[0]
0b4b9499
CL
215 else:
216 parser.error('incorrect number of arguments')
2d00440c 217 branch = stack.Series(branch_name)
0b4b9499 218
2d00440c 219 if not branch.is_initialised():
fe4f6d58
CM
220 raise CmdException, 'Branch "%s" is not controlled by StGIT' \
221 % branch_name
0b4b9499 222
2d00440c 223 print 'Unprotecting branch "%s"...' % branch_name,
fa08ec08 224 sys.stdout.flush()
2d00440c 225 branch.unprotect()
fa08ec08
CM
226 print 'done'
227
0b4b9499
CL
228 return
229
7b1ba1a6
CL
230 elif len(args) == 1:
231
fe4f6d58
CM
232 if __is_current_branch(args[0]):
233 raise CmdException, 'Branch "%s" is already the current branch' \
234 % args[0]
235
236 check_local_changes()
237 check_conflicts()
238 check_head_top_equal()
9756a202 239
7b1ba1a6
CL
240 print 'Switching to branch "%s"...' % args[0],
241 sys.stdout.flush()
242
243 git.switch_branch(args[0])
244
245 print 'done'
246 return
247
248 # default action: print the current branch
249 if len(args) != 0:
250 parser.error('incorrect number of arguments')
251
5fab7247 252 print crt_series.get_branch()