Align branch descriptions in output of "stg branch -l"
[stgit] / stgit / commands / branch.py
1 """Branch command
2 """
3
4 __copyright__ = """
5 Copyright (C) 2005, Chuck Lever <cel@netapp.com>
6
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.
10
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.
15
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 """
20
21 import sys, os
22 from optparse import OptionParser, make_option
23
24 from stgit.commands.common import *
25 from stgit.utils import *
26 from stgit import stack, git
27
28
29 help = 'manage development branches'
30 usage = """%prog [options] branch-name [commit-id]
31
32 Create, list, 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.
36
37 When displaying the branches, the names can be prefixed with
38 's' (StGIT managed) or 'p' (protected)."""
39
40 options = [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('-p', '--protect',
53 help = 'prevent "stg pull" from modifying this branch',
54 action = 'store_true'),
55 make_option('-r', '--rename',
56 help = 'rename an existing development branch',
57 action = 'store_true'),
58 make_option('-u', '--unprotect',
59 help = 'allow "stg pull" to modify this branch',
60 action = 'store_true')]
61
62
63 def __is_current_branch(branch_name):
64 return crt_series.get_branch() == branch_name
65
66 def __print_branch(branch_name, length):
67 initialized = ' '
68 current = ' '
69 protected = ' '
70
71 branch = stack.Series(branch_name)
72
73 if branch.is_initialised():
74 initialized = 's'
75 if __is_current_branch(branch_name):
76 current = '>'
77 if branch.get_protected():
78 protected = 'p'
79 print current + ' ' + initialized + protected + '\t' + \
80 branch_name.ljust(length) + ' | ' + branch.get_description()
81
82 def __delete_branch(doomed_name, force = False):
83 doomed = stack.Series(doomed_name)
84
85 if doomed.get_protected():
86 raise CmdException, 'This branch is protected. Delete is not permitted'
87
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')
98
99 doomed.delete(force)
100
101 if doomed_name != 'master':
102 git.delete_branch(doomed_name)
103
104 print 'done'
105
106 def 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')
112
113 check_local_changes()
114 check_conflicts()
115 check_head_top_equal()
116
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')
131 __delete_branch(args[0], options.force)
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 max_len = max([len(i) for i in branches])
142
143 print 'Available branches:'
144 for i in branches:
145 __print_branch(i, max_len)
146 return
147
148 elif options.protect:
149
150 if len(args) == 0:
151 branch_name = crt_series.get_branch()
152 elif len(args) == 1:
153 branch_name = args[0]
154 else:
155 parser.error('incorrect number of arguments')
156 branch = stack.Series(branch_name)
157
158 if not branch.is_initialised():
159 raise CmdException, 'Branch "%s" is not controlled by StGIT' \
160 % branch_name
161
162 print 'Protecting branch "%s"...' % branch_name,
163 sys.stdout.flush()
164 branch.protect()
165 print 'done'
166
167 return
168
169 elif options.rename:
170
171 if len(args) != 2:
172 parser.error('incorrect number of arguments')
173
174 if __is_current_branch(args[0]):
175 raise CmdException, 'Renaming the current branch is not supported'
176
177 stack.Series(args[0]).rename(args[1])
178
179 print 'Renamed branch "%s" as "%s".' % (args[0], args[1])
180
181 return
182
183 elif options.unprotect:
184
185 if len(args) == 0:
186 branch_name = crt_series.get_branch()
187 elif len(args) == 1:
188 branch_name = args[0]
189 else:
190 parser.error('incorrect number of arguments')
191 branch = stack.Series(branch_name)
192
193 if not branch.is_initialised():
194 raise CmdException, 'Branch "%s" is not controlled by StGIT' \
195 % branch_name
196
197 print 'Unprotecting branch "%s"...' % branch_name,
198 sys.stdout.flush()
199 branch.unprotect()
200 print 'done'
201
202 return
203
204 elif len(args) == 1:
205
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()
213
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
226 print crt_series.get_branch()