Fast-forwarding does a git.switch() even when it forwarded no patches
[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'),
0b4b9499
CL
52 make_option('-p', '--protect',
53 help = 'prevent "stg pull" from modifying this branch',
54 action = 'store_true'),
7b1ba1a6
CL
55 make_option('-r', '--rename',
56 help = 'rename an existing development branch',
0b4b9499
CL
57 action = 'store_true'),
58 make_option('-u', '--unprotect',
59 help = 'allow "stg pull" to modify this branch',
7b1ba1a6
CL
60 action = 'store_true')]
61
62
fe4f6d58
CM
63def __is_current_branch(branch_name):
64 return crt_series.get_branch() == branch_name
7b1ba1a6 65
862ba51a 66def __print_branch(branch_name, length):
7b1ba1a6
CL
67 initialized = ' '
68 current = ' '
0b4b9499 69 protected = ' '
ebfd0156
CL
70
71 branch = stack.Series(branch_name)
72
2d00440c 73 if branch.is_initialised():
7b1ba1a6 74 initialized = 's'
fe4f6d58 75 if __is_current_branch(branch_name):
7b1ba1a6 76 current = '>'
ebfd0156 77 if branch.get_protected():
0b4b9499 78 protected = 'p'
862ba51a
CL
79 print current + ' ' + initialized + protected + '\t' + \
80 branch_name.ljust(length) + ' | ' + branch.get_description()
7b1ba1a6 81
fe4f6d58 82def __delete_branch(doomed_name, force = False):
ebfd0156
CL
83 doomed = stack.Series(doomed_name)
84
85 if doomed.get_protected():
0b4b9499
CL
86 raise CmdException, 'This branch is protected. Delete is not permitted'
87
fe4f6d58
CM
88 print 'Deleting branch "%s"...' % doomed_name,
89 sys.stdout.flush()
90
91 if __is_current_branch(doomed_name):
92 check_local_changes()
93 check_conflicts()
94 check_head_top_equal()
95
96 if doomed_name != 'master':
97 git.switch_branch('master')
7b1ba1a6 98
ebfd0156 99 doomed.delete(force)
7b1ba1a6
CL
100
101 if doomed_name != 'master':
102 git.delete_branch(doomed_name)
103
fe4f6d58 104 print 'done'
7b1ba1a6 105
7b1ba1a6
CL
106def func(parser, options, args):
107
108 if options.create:
109
110 if len(args) == 0 or len(args) > 2:
111 parser.error('incorrect number of arguments')
fe4f6d58
CM
112
113 check_local_changes()
114 check_conflicts()
115 check_head_top_equal()
116
7b1ba1a6
CL
117 tree_id = None
118 if len(args) == 2:
119 tree_id = args[1]
120
121 git.create_branch(args[0], tree_id)
122 stack.Series(args[0]).init()
123
124 print 'Branch "%s" created.' % args[0]
125 return
126
127 elif options.delete:
128
129 if len(args) != 1:
130 parser.error('incorrect number of arguments')
fe4f6d58 131 __delete_branch(args[0], options.force)
7b1ba1a6
CL
132 return
133
134 elif options.list:
135
136 if len(args) != 0:
137 parser.error('incorrect number of arguments')
138
bae29ddd 139 branches = os.listdir(os.path.join(git.get_base_dir(), 'refs', 'heads'))
7b1ba1a6 140 branches.sort()
862ba51a 141 max_len = max([len(i) for i in branches])
7b1ba1a6
CL
142
143 print 'Available branches:'
144 for i in branches:
862ba51a 145 __print_branch(i, max_len)
7b1ba1a6
CL
146 return
147
0b4b9499
CL
148 elif options.protect:
149
150 if len(args) == 0:
5fab7247 151 branch_name = crt_series.get_branch()
0b4b9499 152 elif len(args) == 1:
2d00440c 153 branch_name = args[0]
0b4b9499
CL
154 else:
155 parser.error('incorrect number of arguments')
2d00440c 156 branch = stack.Series(branch_name)
0b4b9499 157
2d00440c 158 if not branch.is_initialised():
fe4f6d58
CM
159 raise CmdException, 'Branch "%s" is not controlled by StGIT' \
160 % branch_name
0b4b9499 161
2d00440c 162 print 'Protecting branch "%s"...' % branch_name,
fa08ec08 163 sys.stdout.flush()
2d00440c 164 branch.protect()
fa08ec08
CM
165 print 'done'
166
0b4b9499
CL
167 return
168
7b1ba1a6
CL
169 elif options.rename:
170
171 if len(args) != 2:
172 parser.error('incorrect number of arguments')
660ba985 173
fe4f6d58
CM
174 if __is_current_branch(args[0]):
175 raise CmdException, 'Renaming the current branch is not supported'
176
660ba985
CL
177 stack.Series(args[0]).rename(args[1])
178
179 print 'Renamed branch "%s" as "%s".' % (args[0], args[1])
180
7b1ba1a6
CL
181 return
182
0b4b9499
CL
183 elif options.unprotect:
184
185 if len(args) == 0:
5fab7247 186 branch_name = crt_series.get_branch()
0b4b9499 187 elif len(args) == 1:
2d00440c 188 branch_name = args[0]
0b4b9499
CL
189 else:
190 parser.error('incorrect number of arguments')
2d00440c 191 branch = stack.Series(branch_name)
0b4b9499 192
2d00440c 193 if not branch.is_initialised():
fe4f6d58
CM
194 raise CmdException, 'Branch "%s" is not controlled by StGIT' \
195 % branch_name
0b4b9499 196
2d00440c 197 print 'Unprotecting branch "%s"...' % branch_name,
fa08ec08 198 sys.stdout.flush()
2d00440c 199 branch.unprotect()
fa08ec08
CM
200 print 'done'
201
0b4b9499
CL
202 return
203
7b1ba1a6
CL
204 elif len(args) == 1:
205
fe4f6d58
CM
206 if __is_current_branch(args[0]):
207 raise CmdException, 'Branch "%s" is already the current branch' \
208 % args[0]
209
210 check_local_changes()
211 check_conflicts()
212 check_head_top_equal()
9756a202 213
7b1ba1a6
CL
214 print 'Switching to branch "%s"...' % args[0],
215 sys.stdout.flush()
216
217 git.switch_branch(args[0])
218
219 print 'done'
220 return
221
222 # default action: print the current branch
223 if len(args) != 0:
224 parser.error('incorrect number of arguments')
225
5fab7247 226 print crt_series.get_branch()