chiark / gitweb /
Cleanup parent information on stgit branch deletion.
[stgit] / stgit / main.py
CommitLineData
41a6d859
CM
1"""Basic quilt-like functionality
2"""
3
4__copyright__ = """
5Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.com>
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License version 2 as
9published by the Free Software Foundation.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19"""
20
21import sys, os
c333afcf 22from optparse import OptionParser
41a6d859 23
c333afcf 24import stgit.commands
41a6d859 25
41a6d859
CM
26#
27# The commands map
28#
c333afcf
CM
29class Commands(dict):
30 """Commands class. It performs on-demand module loading
31 """
78340ff1
YD
32 def canonical_cmd(self, key):
33 """Return the canonical name for a possibly-shortenned
34 command name.
35 """
36 candidates = [cmd for cmd in self.keys() if cmd.startswith(key)]
37
38 if not candidates:
39 print >> sys.stderr, 'Unknown command: %s' % key
40 print >> sys.stderr, ' Try "%s help" for a list of ' \
41 'supported commands' % prog
42 sys.exit(1)
43 elif len(candidates) > 1:
44 print >> sys.stderr, 'Ambiguous command: %s' % key
45 print >> sys.stderr, ' Candidates are: %s' \
46 % ', '.join(candidates)
47 sys.exit(1)
48
49 return candidates[0]
50
c333afcf 51 def __getitem__(self, key):
514dd4f2
CM
52 """Return the command python module name based.
53 """
54 global prog
55
78340ff1 56 cmd_mod = self.get(key) or self.get(self.canonical_cmd(key))
514dd4f2 57
c333afcf
CM
58 __import__('stgit.commands.' + cmd_mod)
59 return getattr(stgit.commands, cmd_mod)
60
61commands = Commands({
62 'add': 'add',
63 'applied': 'applied',
64 'assimilate': 'assimilate',
65 'branch': 'branch',
66 'delete': 'delete',
67 'diff': 'diff',
68 'clean': 'clean',
69 'clone': 'clone',
70 'commit': 'commit',
d5ae2173 71 'cp': 'copy',
c333afcf
CM
72 'export': 'export',
73 'files': 'files',
74 'float': 'float',
75 'fold': 'fold',
76 'goto': 'goto',
841c7b2a 77 'hide': 'hide',
c333afcf
CM
78 'id': 'id',
79 'import': 'imprt',
80 'init': 'init',
81 'log': 'log',
82 'mail': 'mail',
83 'new': 'new',
84 'patches': 'patches',
85 'pick': 'pick',
86 'pop': 'pop',
87 'pull': 'pull',
88 'push': 'push',
22037590 89 'rebase': 'rebase',
c333afcf
CM
90 'refresh': 'refresh',
91 'rename': 'rename',
92 'resolved': 'resolved',
93 'rm': 'rm',
94 'series': 'series',
95 'show': 'show',
96 'status': 'status',
06848fab 97 'sync': 'sync',
c333afcf
CM
98 'top': 'top',
99 'unapplied': 'unapplied',
841c7b2a
CM
100 'uncommit': 'uncommit',
101 'unhide': 'unhide'
c333afcf 102 })
41a6d859 103
5dc51fea
YD
104# classification: repository, stack, patch, working copy
105repocommands = (
5dc51fea
YD
106 'clone',
107 'id',
5dc51fea
YD
108 )
109stackcommands = (
110 'applied',
4d0ba818 111 'assimilate',
4ec67741 112 'branch',
5dc51fea
YD
113 'clean',
114 'commit',
d98a499c 115 'float',
5dc51fea 116 'goto',
841c7b2a 117 'hide',
5dc51fea 118 'init',
4ec67741 119 'patches',
5dc51fea 120 'pop',
4ec67741 121 'pull',
5dc51fea 122 'push',
22037590 123 'rebase',
5dc51fea
YD
124 'series',
125 'top',
126 'unapplied',
841c7b2a 127 'uncommit',
4ec67741 128 'unhide',
5dc51fea
YD
129 )
130patchcommands = (
131 'delete',
132 'export',
133 'files',
134 'fold',
135 'import',
64354a2d 136 'log',
5dc51fea
YD
137 'mail',
138 'new',
139 'pick',
140 'refresh',
141 'rename',
06848fab 142 'show',
4ec67741 143 'sync',
5dc51fea
YD
144 )
145wccommands = (
146 'add',
d5ae2173 147 'cp',
5dc51fea 148 'diff',
5dc51fea
YD
149 'resolved',
150 'rm',
4ec67741 151 'status',
5dc51fea
YD
152 )
153
154def _print_helpstring(cmd):
155 print ' ' + cmd + ' ' * (12 - len(cmd)) + commands[cmd].help
156
41a6d859
CM
157def print_help():
158 print 'usage: %s <command> [options]' % os.path.basename(sys.argv[0])
159 print
5dc51fea 160 print 'Generic commands:'
f0699cc7 161 print ' help print the detailed command usage'
1e0bdf2a 162 print ' version display version information'
22ea9102 163 print ' copyright display copyright information'
5dc51fea 164 # unclassified commands if any
41a6d859
CM
165 cmds = commands.keys()
166 cmds.sort()
167 for cmd in cmds:
5dc51fea
YD
168 if not cmd in repocommands and not cmd in stackcommands \
169 and not cmd in patchcommands and not cmd in wccommands:
170 _print_helpstring(cmd)
171 print
172
173 print 'Repository commands:'
174 for cmd in repocommands:
175 _print_helpstring(cmd)
176 print
177
178 print 'Stack commands:'
179 for cmd in stackcommands:
180 _print_helpstring(cmd)
181 print
182
183 print 'Patch commands:'
184 for cmd in patchcommands:
185 _print_helpstring(cmd)
186 print
187
188 print 'Working-copy commands:'
189 for cmd in wccommands:
190 _print_helpstring(cmd)
41a6d859
CM
191
192#
193# The main function (command dispatcher)
194#
195def main():
196 """The main function
197 """
514dd4f2
CM
198 global prog
199
41a6d859
CM
200 prog = os.path.basename(sys.argv[0])
201
202 if len(sys.argv) < 2:
d00e708a 203 print >> sys.stderr, 'usage: %s <command>' % prog
41a6d859 204 print >> sys.stderr, \
f0699cc7 205 ' Try "%s --help" for a list of supported commands' % prog
41a6d859
CM
206 sys.exit(1)
207
208 cmd = sys.argv[1]
209
f0699cc7 210 if cmd in ['-h', '--help']:
78340ff1
YD
211 if len(sys.argv) >= 3:
212 cmd = commands.canonical_cmd(sys.argv[2])
f0699cc7 213 sys.argv[2] = '--help'
31c5abf2
PR
214 else:
215 print_help()
216 sys.exit(0)
f0699cc7
CM
217 if cmd == 'help':
218 if len(sys.argv) == 3 and not sys.argv[2] in ['-h', '--help']:
78340ff1 219 cmd = commands.canonical_cmd(sys.argv[2])
f0699cc7
CM
220 if not cmd in commands:
221 print >> sys.stderr, '%s help: "%s" command unknown' \
222 % (prog, cmd)
223 sys.exit(1)
224
225 sys.argv[0] += ' %s' % cmd
226 command = commands[cmd]
227 parser = OptionParser(usage = command.usage,
228 option_list = command.options)
0d4cd7ce
CM
229 from pydoc import pager
230 pager(parser.format_help())
f0699cc7 231 else:
4fe42e63 232 print_help()
f0699cc7 233 sys.exit(0)
1e0bdf2a 234 if cmd in ['-v', '--version', 'version']:
c333afcf 235 from stgit.version import version
4df2f866 236 print 'Stacked GIT %s' % version
50725547 237 os.system('git --version')
1e0bdf2a 238 print 'Python version %s' % sys.version
41a6d859 239 sys.exit(0)
22ea9102
CM
240 if cmd in ['copyright']:
241 print __copyright__
242 sys.exit(0)
41a6d859
CM
243
244 # re-build the command line arguments
78340ff1 245 sys.argv[0] += ' %s' % commands.canonical_cmd(cmd)
41a6d859
CM
246 del(sys.argv[1])
247
248 command = commands[cmd]
f0699cc7
CM
249 usage = command.usage.split('\n')[0].strip()
250 parser = OptionParser(usage = usage, option_list = command.options)
41a6d859 251 options, args = parser.parse_args()
22d87516
CM
252
253 # These modules are only used from this point onwards and do not
254 # need to be imported earlier
eee7283e 255 from stgit.config import config_setup
9e3f506f 256 from ConfigParser import ParsingError, NoSectionError
22d87516
CM
257 from stgit.stack import Series, StackException
258 from stgit.git import GitException
259 from stgit.commands.common import CmdException
260 from stgit.gitmergeonefile import GitMergeException
b3ae3e14 261 from stgit.utils import EditorException
22d87516 262
b2017c38
CM
263 try:
264 debug_level = int(os.environ['STGIT_DEBUG_LEVEL'])
265 except KeyError:
266 debug_level = 0
267 except ValueError:
268 print >> sys.stderr, 'Invalid STGIT_DEBUG_LEVEL environment variable'
269 sys.exit(1)
270
41a6d859 271 try:
eee7283e
CM
272 config_setup()
273
98290387
CM
274 # 'clone' doesn't expect an already initialised GIT tree. A Series
275 # object will be created after the GIT tree is cloned
276 if cmd != 'clone':
277 if hasattr(options, 'branch') and options.branch:
c333afcf 278 command.crt_series = Series(options.branch)
98290387 279 else:
c333afcf 280 command.crt_series = Series()
98290387 281 stgit.commands.common.crt_series = command.crt_series
9ac09909 282
41a6d859 283 command.func(parser, options, args)
9e3f506f 284 except (IOError, ParsingError, NoSectionError, CmdException,
b3ae3e14
CM
285 StackException, GitException, GitMergeException,
286 EditorException), err:
41a6d859 287 print >> sys.stderr, '%s %s: %s' % (prog, cmd, err)
b2017c38
CM
288 if debug_level:
289 raise
290 else:
291 sys.exit(2)
4d9fc826
CM
292 except KeyboardInterrupt:
293 sys.exit(1)
41a6d859
CM
294
295 sys.exit(0)