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
22 from optparse
import OptionParser
, make_option
24 from stgit
.commands
.common
import *
25 from stgit
.utils
import *
26 from stgit
import stack
, git
29 help = 'manage development branches'
30 usage
= """%prog [options] branch-name [commit-id]
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.
37 When displaying the branches, the names can be prefixed with
38 's' (StGIT managed) or 'p' (protected)."""
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')]
63 def is_current_branch(branch_name
):
64 return git
.get_head_file() == branch_name
66 def print_branch(branch_name
):
71 branch
= stack
.Series(branch_name
)
73 if branch
.is_initialised():
75 if is_current_branch(branch_name
):
77 if branch
.get_protected():
79 print '%s %s%s\t%s\t%s' %
(current
, initialized
, protected
, branch_name
, \
80 branch
.get_description())
82 def delete_branch(doomed_name
, force
= False):
83 doomed
= stack
.Series(doomed_name
)
85 if doomed
.get_protected():
86 raise CmdException
, 'This branch is protected. Delete is not permitted'
88 if is_current_branch(doomed_name
) and doomed_name
!= 'master':
89 git
.switch_branch('master')
93 if doomed_name
!= 'master':
94 git
.delete_branch(doomed_name
)
96 print 'Branch "%s" has been deleted.' % doomed_name
98 def rename_branch(from_name
, to_name
):
99 if from_name
== 'master':
100 raise CmdException
, 'Renaming the master branch is not allowed'
102 to_patchdir
= os
.path
.join(git
.base_dir
, 'patches', to_name
)
103 if os
.path
.isdir(to_patchdir
):
104 raise CmdException
, '"%s" already exists' % to_patchdir
105 to_base
= os
.path
.join(git
.base_dir
, 'refs', 'bases', to_name
)
106 if os
.path
.isfile(to_base
):
107 raise CmdException
, '"%s" already exists' % to_base
109 git
.rename_branch(from_name
, to_name
)
111 from_patchdir
= os
.path
.join(git
.base_dir
, 'patches', from_name
)
112 if os
.path
.isdir(from_patchdir
):
113 os
.rename(from_patchdir
, to_patchdir
)
114 from_base
= os
.path
.join(git
.base_dir
, 'refs', 'bases', from_name
)
115 if os
.path
.isfile(from_base
):
116 os
.rename(from_base
, to_base
)
118 print 'Renamed branch "%s" as "%s".' %
(from_name
, to_name
)
120 def func(parser
, options
, args
):
124 if len(args
) == 0 or len(args
) > 2:
125 parser
.error('incorrect number of arguments')
130 git
.create_branch(args
[0], tree_id
)
131 stack
.Series(args
[0]).init()
133 print 'Branch "%s" created.' % args
[0]
139 parser
.error('incorrect number of arguments')
140 delete_branch(args
[0], options
.force
)
146 parser
.error('incorrect number of arguments')
148 branches
= os
.listdir(os
.path
.join(git
.base_dir
, 'refs', 'heads'))
151 print 'Available branches:'
156 elif options
.protect
:
159 branch_name
= git
.get_head_file()
161 branch_name
= args
[0]
163 parser
.error('incorrect number of arguments')
164 branch
= stack
.Series(branch_name
)
166 if not branch
.is_initialised():
167 raise CmdException
, 'Branch "%s" is not controlled by StGit' % branch_name
169 print 'Protecting branch "%s"...' % branch_name
,
179 parser
.error('incorrect number of arguments')
180 rename_branch(args
[0], args
[1])
183 elif options
.unprotect
:
186 branch_name
= git
.get_head_file()
188 branch_name
= args
[0]
190 parser
.error('incorrect number of arguments')
191 branch
= stack
.Series(branch_name
)
193 if not branch
.is_initialised():
194 raise CmdException
, 'Branch "%s" is not controlled by StGit' % branch_name
196 print 'Unprotecting branch "%s"...' % branch_name
,
205 if args
[0] == git
.get_head_file():
206 raise CmdException
, 'Branch "%s" is already the current branch' % args
[0]
208 print 'Switching to branch "%s"...' % args
[0],
211 git
.switch_branch(args
[0])
216 # default action: print the current branch
218 parser
.error('incorrect number of arguments')
220 print git
.get_head_file()