Assorted typos
[stgit.git] / stgit / commands / branch.py
blobd7ddedba73f097a53dcb0126753290845b8a848b
1 """Branch command
2 """
4 __copyright__ = """
5 Copyright (C) 2005, Chuck Lever <cel@netapp.com>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 """
21 import sys, os, time
22 from optparse import OptionParser, make_option
24 from stgit.commands.common import *
25 from stgit.utils import *
26 from stgit import stack, git, basedir
29 help = 'manage development branches'
30 usage = """%prog [options] branch-name [commit-id]
32 Create, clone, switch between, rename, or delete development branches
33 within a git repository. By default, a single branch called 'master'
34 is always created in a new repository. This subcommand allows you to
35 manage several patch series in the same repository via GIT branches.
37 When displaying the branches, the names can be prefixed with
38 's' (StGIT managed) or 'p' (protected).
40 If not given any options, switch to the named branch."""
42 options = [make_option('-c', '--create',
43 help = 'create a new development branch',
44 action = 'store_true'),
45 make_option('--clone',
46 help = 'clone the contents of the current branch',
47 action = 'store_true'),
48 make_option('--convert',
49 help = 'switch between old and new format branches',
50 action = 'store_true'),
51 make_option('--delete',
52 help = 'delete an existing development branch',
53 action = 'store_true'),
54 make_option('--force',
55 help = 'force a delete when the series is not empty',
56 action = 'store_true'),
57 make_option('-l', '--list',
58 help = 'list branches contained in this repository',
59 action = 'store_true'),
60 make_option('-p', '--protect',
61 help = 'prevent "stg pull" from modifying this branch',
62 action = 'store_true'),
63 make_option('-r', '--rename',
64 help = 'rename an existing development branch',
65 action = 'store_true'),
66 make_option('-u', '--unprotect',
67 help = 'allow "stg pull" to modify this branch',
68 action = 'store_true')]
71 def __is_current_branch(branch_name):
72 return crt_series.get_branch() == branch_name
74 def __print_branch(branch_name, length):
75 initialized = ' '
76 current = ' '
77 protected = ' '
79 branch = stack.Series(branch_name)
81 if branch.is_initialised():
82 initialized = 's'
83 if __is_current_branch(branch_name):
84 current = '>'
85 if branch.get_protected():
86 protected = 'p'
87 print current + ' ' + initialized + protected + '\t' + \
88 branch_name.ljust(length) + ' | ' + branch.get_description()
90 def __delete_branch(doomed_name, force = False):
91 doomed = stack.Series(doomed_name)
93 if doomed.get_protected():
94 raise CmdException, 'This branch is protected. Delete is not permitted'
96 print 'Deleting branch "%s"...' % doomed_name,
97 sys.stdout.flush()
99 if __is_current_branch(doomed_name):
100 check_local_changes()
101 check_conflicts()
102 check_head_top_equal()
104 if doomed_name != 'master':
105 git.switch_branch('master')
107 doomed.delete(force)
109 if doomed_name != 'master':
110 git.delete_branch(doomed_name)
112 print 'done'
114 def func(parser, options, args):
116 if options.create:
118 if len(args) == 0 or len(args) > 2:
119 parser.error('incorrect number of arguments')
121 check_local_changes()
122 check_conflicts()
123 check_head_top_equal()
125 tree_id = None
126 if len(args) >= 2:
127 try:
128 if git.rev_parse(args[1]) == git.rev_parse('refs/heads/' + args[1]):
129 # we are for sure referring to a branch
130 parentbranch = 'refs/heads/' + args[1]
131 print 'Recording "%s" as parent branch.' % parentbranch
132 elif git.rev_parse(args[1]) and re.search('/', args[1]):
133 # FIXME: should the test be more strict ?
134 parentbranch = args[1]
135 else:
136 # Note: this includes refs to StGIT patches
137 print 'Don\'t know how to determine parent branch from "%s".' % args[1]
138 parentbranch = None
139 except git.GitException:
140 # should use a more specific exception to catch only non-git refs ?
141 print 'Don\'t know how to determine parent branch from "%s".' % args[1]
142 parentbranch = None
144 tree_id = git_id(args[1])
145 else:
146 # branch stack off current branch
147 parentbranch = git.get_head_file()
149 if parentbranch:
150 parentremote = git.identify_remote(parentbranch)
151 if parentremote:
152 print 'Using "%s" remote to pull parent from.' % parentremote
153 else:
154 print 'Not identified a remote to pull parent from.'
155 else:
156 parentremote = None
158 stack.Series(args[0]).init(create_at = tree_id,
159 parent_remote = parentremote,
160 parent_branch = parentbranch)
162 print 'Branch "%s" created.' % args[0]
163 return
165 elif options.clone:
167 if len(args) == 0:
168 clone = crt_series.get_branch() + \
169 time.strftime('-%C%y%m%d-%H%M%S')
170 elif len(args) == 1:
171 clone = args[0]
172 else:
173 parser.error('incorrect number of arguments')
175 check_local_changes()
176 check_conflicts()
177 check_head_top_equal()
179 print 'Cloning current branch to "%s"...' % clone,
180 sys.stdout.flush()
181 crt_series.clone(clone)
182 print 'done'
184 return
186 elif options.convert:
188 if len(args) != 0:
189 parser.error('incorrect number of arguments')
191 crt_series.convert()
192 return
194 elif options.delete:
196 if len(args) != 1:
197 parser.error('incorrect number of arguments')
198 __delete_branch(args[0], options.force)
199 return
201 elif options.list:
203 if len(args) != 0:
204 parser.error('incorrect number of arguments')
206 branches = []
207 basepath = os.path.join(basedir.get(), 'refs', 'heads')
208 for path, files, dirs in walk_tree(basepath):
209 branches += [os.path.join(path, f) for f in files]
210 branches.sort()
212 if branches:
213 print 'Available branches:'
214 max_len = max([len(i) for i in branches])
215 for i in branches:
216 __print_branch(i, max_len)
217 else:
218 print 'No branches'
219 return
221 elif options.protect:
223 if len(args) == 0:
224 branch_name = crt_series.get_branch()
225 elif len(args) == 1:
226 branch_name = args[0]
227 else:
228 parser.error('incorrect number of arguments')
229 branch = stack.Series(branch_name)
231 if not branch.is_initialised():
232 raise CmdException, 'Branch "%s" is not controlled by StGIT' \
233 % branch_name
235 print 'Protecting branch "%s"...' % branch_name,
236 sys.stdout.flush()
237 branch.protect()
238 print 'done'
240 return
242 elif options.rename:
244 if len(args) != 2:
245 parser.error('incorrect number of arguments')
247 if __is_current_branch(args[0]):
248 raise CmdException, 'Renaming the current branch is not supported'
250 stack.Series(args[0]).rename(args[1])
252 print 'Renamed branch "%s" as "%s".' % (args[0], args[1])
254 return
256 elif options.unprotect:
258 if len(args) == 0:
259 branch_name = crt_series.get_branch()
260 elif len(args) == 1:
261 branch_name = args[0]
262 else:
263 parser.error('incorrect number of arguments')
264 branch = stack.Series(branch_name)
266 if not branch.is_initialised():
267 raise CmdException, 'Branch "%s" is not controlled by StGIT' \
268 % branch_name
270 print 'Unprotecting branch "%s"...' % branch_name,
271 sys.stdout.flush()
272 branch.unprotect()
273 print 'done'
275 return
277 elif len(args) == 1:
279 if __is_current_branch(args[0]):
280 raise CmdException, 'Branch "%s" is already the current branch' \
281 % args[0]
283 check_local_changes()
284 check_conflicts()
285 check_head_top_equal()
287 print 'Switching to branch "%s"...' % args[0],
288 sys.stdout.flush()
290 git.switch_branch(args[0])
292 print 'done'
293 return
295 # default action: print the current branch
296 if len(args) != 0:
297 parser.error('incorrect number of arguments')
299 print crt_series.get_branch()