chiark / gitweb /
27a2e98d59847929dc942767f3fc16eab3cd47e5
[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('-r', '--rename',
53                        help = 'rename an existing development branch',
54                        action = 'store_true')]
55
56
57 def is_current_branch(branch_name):
58     return git.get_head_file() == branch_name
59
60 def print_branch(branch_name):
61     initialized = ' '
62     current = ' '
63     if os.path.isdir(os.path.join(git.base_dir, 'patches', branch_name)):
64         initialized = 's'
65     if is_current_branch(branch_name):
66         current = '>'
67     print '%s %s\t%s' % (current, initialized, branch_name)
68
69 def delete_branch(doomed_name, force = False):
70     if is_current_branch(doomed_name) and doomed_name != 'master':
71         git.switch_branch('master')
72
73     stack.Series(doomed_name).delete(force)
74
75     if doomed_name != 'master':
76         git.delete_branch(doomed_name)
77
78     print 'Branch "%s" has been deleted.' % doomed_name
79
80 def rename_branch(from_name, to_name):
81     if from_name == 'master':
82         raise CmdException, 'Renaming the master branch is not allowed'
83
84     to_patchdir = os.path.join(git.base_dir, 'patches', to_name)
85     if os.path.isdir(to_patchdir):
86         raise CmdException, '"%s" already exists' % to_patchdir
87     to_base = os.path.join(git.base_dir, 'refs', 'bases', to_name)
88     if os.path.isfile(to_base):
89         raise CmdException, '"%s" already exists' % to_base
90
91     git.rename_branch(from_name, to_name)
92
93     from_patchdir = os.path.join(git.base_dir, 'patches', from_name)
94     if os.path.isdir(from_patchdir):
95         os.rename(from_patchdir, to_patchdir)
96     from_base = os.path.join(git.base_dir, 'refs', 'bases', from_name)
97     if os.path.isfile(from_base):
98         os.rename(from_base, to_base)
99
100     print 'Renamed branch "%s" as "%s".' % (from_name, to_name)
101
102 def func(parser, options, args):
103
104     if options.create:
105
106         if len(args) == 0 or len(args) > 2:
107             parser.error('incorrect number of arguments')
108         tree_id = None
109         if len(args) == 2:
110             tree_id = args[1]
111
112         git.create_branch(args[0], tree_id)
113         stack.Series(args[0]).init()
114
115         print 'Branch "%s" created.' % args[0]
116         return
117
118     elif options.delete:
119
120         if len(args) != 1:
121             parser.error('incorrect number of arguments')
122         delete_branch(args[0], options.force)
123         return
124
125     elif options.list:
126
127         if len(args) != 0:
128             parser.error('incorrect number of arguments')
129
130         branches = os.listdir(os.path.join(git.base_dir, 'refs', 'heads'))
131         branches.sort()
132
133         print 'Available branches:'
134         for i in branches:
135             print_branch(i)
136         return
137
138     elif options.rename:
139
140         if len(args) != 2:
141             parser.error('incorrect number of arguments')
142         rename_branch(args[0], args[1])
143         return
144
145     elif len(args) == 1:
146
147         print 'Switching to branch "%s"...' % args[0],
148         sys.stdout.flush()
149
150         git.switch_branch(args[0])
151
152         print 'done'
153         return
154
155     # default action: print the current branch
156     if len(args) != 0:
157         parser.error('incorrect number of arguments')
158
159     print git.get_head_file()