Better error message when renaming patches to same name
[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
fe4f6d58 66def __print_branch(branch_name):
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'
c1fe1f99 79 print '%s %s%s\t%s\t%s' % (current, initialized, protected, branch_name, \
ebfd0156 80 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
139 branches = os.listdir(os.path.join(git.base_dir, 'refs', 'heads'))
140 branches.sort()
141
142 print 'Available branches:'
143 for i in branches:
fe4f6d58 144 __print_branch(i)
7b1ba1a6
CL
145 return
146
0b4b9499
CL
147 elif options.protect:
148
149 if len(args) == 0:
2d00440c 150 branch_name = git.get_head_file()
0b4b9499 151 elif len(args) == 1:
2d00440c 152 branch_name = args[0]
0b4b9499
CL
153 else:
154 parser.error('incorrect number of arguments')
2d00440c 155 branch = stack.Series(branch_name)
0b4b9499 156
2d00440c 157 if not branch.is_initialised():
fe4f6d58
CM
158 raise CmdException, 'Branch "%s" is not controlled by StGIT' \
159 % branch_name
0b4b9499 160
2d00440c 161 print 'Protecting branch "%s"...' % branch_name,
fa08ec08 162 sys.stdout.flush()
2d00440c 163 branch.protect()
fa08ec08
CM
164 print 'done'
165
0b4b9499
CL
166 return
167
7b1ba1a6
CL
168 elif options.rename:
169
170 if len(args) != 2:
171 parser.error('incorrect number of arguments')
660ba985 172
fe4f6d58
CM
173 if __is_current_branch(args[0]):
174 raise CmdException, 'Renaming the current branch is not supported'
175
660ba985
CL
176 stack.Series(args[0]).rename(args[1])
177
178 print 'Renamed branch "%s" as "%s".' % (args[0], args[1])
179
7b1ba1a6
CL
180 return
181
0b4b9499
CL
182 elif options.unprotect:
183
184 if len(args) == 0:
2d00440c 185 branch_name = git.get_head_file()
0b4b9499 186 elif len(args) == 1:
2d00440c 187 branch_name = args[0]
0b4b9499
CL
188 else:
189 parser.error('incorrect number of arguments')
2d00440c 190 branch = stack.Series(branch_name)
0b4b9499 191
2d00440c 192 if not branch.is_initialised():
fe4f6d58
CM
193 raise CmdException, 'Branch "%s" is not controlled by StGIT' \
194 % branch_name
0b4b9499 195
2d00440c 196 print 'Unprotecting branch "%s"...' % branch_name,
fa08ec08 197 sys.stdout.flush()
2d00440c 198 branch.unprotect()
fa08ec08
CM
199 print 'done'
200
0b4b9499
CL
201 return
202
7b1ba1a6
CL
203 elif len(args) == 1:
204
fe4f6d58
CM
205 if __is_current_branch(args[0]):
206 raise CmdException, 'Branch "%s" is already the current branch' \
207 % args[0]
208
209 check_local_changes()
210 check_conflicts()
211 check_head_top_equal()
9756a202 212
7b1ba1a6
CL
213 print 'Switching to branch "%s"...' % args[0],
214 sys.stdout.flush()
215
216 git.switch_branch(args[0])
217
218 print 'done'
219 return
220
221 # default action: print the current branch
222 if len(args) != 0:
223 parser.error('incorrect number of arguments')
224
225 print git.get_head_file()