chiark / gitweb /
Fix the branch protect/unprotect message
[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     if os.path.isdir(os.path.join(git.base_dir, 'patches', branch_name)):
71         initialized = 's'
72     if is_current_branch(branch_name):
73         current = '>'
74     if stack.Series(branch_name).get_protected():
75         protected = 'p'
76     print '%s %s%s\t%s\t%s' % (current, initialized, protected, branch_name, \
77                                stack.Series(branch_name).get_description())
78
79 def delete_branch(doomed_name, force = False):
80     if stack.Series(doomed_name).get_protected():
81         raise CmdException, 'This branch is protected. Delete is not permitted'
82
83     if is_current_branch(doomed_name) and doomed_name != 'master':
84         git.switch_branch('master')
85
86     stack.Series(doomed_name).delete(force)
87
88     if doomed_name != 'master':
89         git.delete_branch(doomed_name)
90
91     print 'Branch "%s" has been deleted.' % doomed_name
92
93 def rename_branch(from_name, to_name):
94     if from_name == 'master':
95         raise CmdException, 'Renaming the master branch is not allowed'
96
97     to_patchdir = os.path.join(git.base_dir, 'patches', to_name)
98     if os.path.isdir(to_patchdir):
99         raise CmdException, '"%s" already exists' % to_patchdir
100     to_base = os.path.join(git.base_dir, 'refs', 'bases', to_name)
101     if os.path.isfile(to_base):
102         raise CmdException, '"%s" already exists' % to_base
103
104     git.rename_branch(from_name, to_name)
105
106     from_patchdir = os.path.join(git.base_dir, 'patches', from_name)
107     if os.path.isdir(from_patchdir):
108         os.rename(from_patchdir, to_patchdir)
109     from_base = os.path.join(git.base_dir, 'refs', 'bases', from_name)
110     if os.path.isfile(from_base):
111         os.rename(from_base, to_base)
112
113     print 'Renamed branch "%s" as "%s".' % (from_name, to_name)
114
115 def func(parser, options, args):
116
117     if options.create:
118
119         if len(args) == 0 or len(args) > 2:
120             parser.error('incorrect number of arguments')
121         tree_id = None
122         if len(args) == 2:
123             tree_id = args[1]
124
125         git.create_branch(args[0], tree_id)
126         stack.Series(args[0]).init()
127
128         print 'Branch "%s" created.' % args[0]
129         return
130
131     elif options.delete:
132
133         if len(args) != 1:
134             parser.error('incorrect number of arguments')
135         delete_branch(args[0], options.force)
136         return
137
138     elif options.list:
139
140         if len(args) != 0:
141             parser.error('incorrect number of arguments')
142
143         branches = os.listdir(os.path.join(git.base_dir, 'refs', 'heads'))
144         branches.sort()
145
146         print 'Available branches:'
147         for i in branches:
148             print_branch(i)
149         return
150
151     elif options.protect:
152
153         if len(args) == 0:
154             branch = git.get_head_file()
155         elif len(args) == 1:
156             branch = args[0]
157         else:
158             parser.error('incorrect number of arguments')
159
160         base = os.path.join(git.base_dir, 'refs', 'bases', branch)
161         if not os.path.isfile(base):
162             raise CmdException, 'Branch "%s" is not controlled by StGit' % branch
163
164         print 'Protecting branch "%s"...' % branch,
165         sys.stdout.flush()
166         stack.Series(branch).protect()
167         print 'done'
168
169         return
170
171     elif options.rename:
172
173         if len(args) != 2:
174             parser.error('incorrect number of arguments')
175         rename_branch(args[0], args[1])
176         return
177
178     elif options.unprotect:
179
180         if len(args) == 0:
181             branch = git.get_head_file()
182         elif len(args) == 1:
183             branch = args[0]
184         else:
185             parser.error('incorrect number of arguments')
186
187         base = os.path.join(git.base_dir, 'refs', 'bases', branch)
188         if not os.path.isfile(base):
189             raise CmdException, 'Branch "%s" is not controlled by StGit' % branch
190
191         print 'Unprotecting branch "%s"...' % branch,
192         sys.stdout.flush()
193         stack.Series(branch).unprotect()
194         print 'done'
195
196         return
197
198     elif len(args) == 1:
199
200         print 'Switching to branch "%s"...' % args[0],
201         sys.stdout.flush()
202
203         git.switch_branch(args[0])
204
205         print 'done'
206         return
207
208     # default action: print the current branch
209     if len(args) != 0:
210         parser.error('incorrect number of arguments')
211
212     print git.get_head_file()