chiark / gitweb /
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()