Generalize branch renaming
[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 git.get_head_file() == branch_name
65
66 def print_branch(branch_name):
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 '%s %s%s\t%s\t%s' % (current, initialized, protected, branch_name, \
80 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 if is_current_branch(doomed_name) and doomed_name != 'master':
89 git.switch_branch('master')
90
91 doomed.delete(force)
92
93 if doomed_name != 'master':
94 git.delete_branch(doomed_name)
95
96 print 'Branch "%s" has been deleted.' % doomed_name
97
98 def func(parser, options, args):
99
100 if options.create:
101
102 if len(args) == 0 or len(args) > 2:
103 parser.error('incorrect number of arguments')
104 tree_id = None
105 if len(args) == 2:
106 tree_id = args[1]
107
108 git.create_branch(args[0], tree_id)
109 stack.Series(args[0]).init()
110
111 print 'Branch "%s" created.' % args[0]
112 return
113
114 elif options.delete:
115
116 if len(args) != 1:
117 parser.error('incorrect number of arguments')
118 delete_branch(args[0], options.force)
119 return
120
121 elif options.list:
122
123 if len(args) != 0:
124 parser.error('incorrect number of arguments')
125
126 branches = os.listdir(os.path.join(git.base_dir, 'refs', 'heads'))
127 branches.sort()
128
129 print 'Available branches:'
130 for i in branches:
131 print_branch(i)
132 return
133
134 elif options.protect:
135
136 if len(args) == 0:
137 branch_name = git.get_head_file()
138 elif len(args) == 1:
139 branch_name = args[0]
140 else:
141 parser.error('incorrect number of arguments')
142 branch = stack.Series(branch_name)
143
144 if not branch.is_initialised():
145 raise CmdException, 'Branch "%s" is not controlled by StGit' % branch_name
146
147 print 'Protecting branch "%s"...' % branch_name,
148 sys.stdout.flush()
149 branch.protect()
150 print 'done'
151
152 return
153
154 elif options.rename:
155
156 if len(args) != 2:
157 parser.error('incorrect number of arguments')
158
159 stack.Series(args[0]).rename(args[1])
160
161 print 'Renamed branch "%s" as "%s".' % (args[0], args[1])
162
163 return
164
165 elif options.unprotect:
166
167 if len(args) == 0:
168 branch_name = git.get_head_file()
169 elif len(args) == 1:
170 branch_name = args[0]
171 else:
172 parser.error('incorrect number of arguments')
173 branch = stack.Series(branch_name)
174
175 if not branch.is_initialised():
176 raise CmdException, 'Branch "%s" is not controlled by StGit' % branch_name
177
178 print 'Unprotecting branch "%s"...' % branch_name,
179 sys.stdout.flush()
180 branch.unprotect()
181 print 'done'
182
183 return
184
185 elif len(args) == 1:
186
187 if args[0] == git.get_head_file():
188 raise CmdException, 'Branch "%s" is already the current branch' % args[0]
189
190 print 'Switching to branch "%s"...' % args[0],
191 sys.stdout.flush()
192
193 git.switch_branch(args[0])
194
195 print 'done'
196 return
197
198 # default action: print the current branch
199 if len(args) != 0:
200 parser.error('incorrect number of arguments')
201
202 print git.get_head_file()