chiark / gitweb /
Make Series.refresh_patch automatically save the undo information
[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
5e888f30 25from stgit.out import *
41a6d859 26
41a6d859
CM
27#
28# The commands map
29#
c333afcf
CM
30class Commands(dict):
31 """Commands class. It performs on-demand module loading
32 """
78340ff1
YD
33 def canonical_cmd(self, key):
34 """Return the canonical name for a possibly-shortenned
35 command name.
36 """
37 candidates = [cmd for cmd in self.keys() if cmd.startswith(key)]
38
39 if not candidates:
27ac2b7e
KH
40 out.error('Unknown command: %s' % key,
41 'Try "%s help" for a list of supported commands' % prog)
78340ff1
YD
42 sys.exit(1)
43 elif len(candidates) > 1:
27ac2b7e
KH
44 out.error('Ambiguous command: %s' % key,
45 'Candidates are: %s' % ', '.join(candidates))
78340ff1
YD
46 sys.exit(1)
47
48 return candidates[0]
49
c333afcf 50 def __getitem__(self, key):
514dd4f2
CM
51 """Return the command python module name based.
52 """
53 global prog
54
78340ff1 55 cmd_mod = self.get(key) or self.get(self.canonical_cmd(key))
514dd4f2 56
c333afcf
CM
57 __import__('stgit.commands.' + cmd_mod)
58 return getattr(stgit.commands, cmd_mod)
59
60commands = Commands({
61 'add': 'add',
62 'applied': 'applied',
c333afcf
CM
63 'branch': 'branch',
64 'delete': 'delete',
65 'diff': 'diff',
66 'clean': 'clean',
67 'clone': 'clone',
68 'commit': 'commit',
d5ae2173 69 'cp': 'copy',
ed60fdae 70 'edit': 'edit',
c333afcf
CM
71 'export': 'export',
72 'files': 'files',
73 'float': 'float',
74 'fold': 'fold',
75 'goto': 'goto',
841c7b2a 76 'hide': 'hide',
c333afcf
CM
77 'id': 'id',
78 'import': 'imprt',
79 'init': 'init',
80 'log': 'log',
81 'mail': 'mail',
82 'new': 'new',
83 'patches': 'patches',
84 'pick': 'pick',
85 'pop': 'pop',
86 'pull': 'pull',
87 'push': 'push',
22037590 88 'rebase': 'rebase',
c333afcf
CM
89 'refresh': 'refresh',
90 'rename': 'rename',
051090dd 91 'repair': 'repair',
c333afcf
CM
92 'resolved': 'resolved',
93 'rm': 'rm',
94 'series': 'series',
95 'show': 'show',
6f1c5e3c 96 'sink': 'sink',
c333afcf 97 'status': 'status',
06848fab 98 'sync': 'sync',
c333afcf
CM
99 'top': 'top',
100 'unapplied': 'unapplied',
841c7b2a
CM
101 'uncommit': 'uncommit',
102 'unhide': 'unhide'
c333afcf 103 })
41a6d859 104
5dc51fea
YD
105# classification: repository, stack, patch, working copy
106repocommands = (
5dc51fea
YD
107 'clone',
108 'id',
5dc51fea
YD
109 )
110stackcommands = (
111 'applied',
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',
051090dd 124 'repair',
5dc51fea 125 'series',
6f1c5e3c 126 'sink',
5dc51fea
YD
127 'top',
128 'unapplied',
841c7b2a 129 'uncommit',
4ec67741 130 'unhide',
5dc51fea
YD
131 )
132patchcommands = (
133 'delete',
d8b2e601 134 'edit',
5dc51fea
YD
135 'export',
136 'files',
137 'fold',
138 'import',
64354a2d 139 'log',
5dc51fea
YD
140 'mail',
141 'new',
142 'pick',
143 'refresh',
144 'rename',
06848fab 145 'show',
4ec67741 146 'sync',
5dc51fea
YD
147 )
148wccommands = (
149 'add',
d5ae2173 150 'cp',
5dc51fea 151 'diff',
5dc51fea
YD
152 'resolved',
153 'rm',
4ec67741 154 'status',
5dc51fea
YD
155 )
156
157def _print_helpstring(cmd):
158 print ' ' + cmd + ' ' * (12 - len(cmd)) + commands[cmd].help
159
41a6d859
CM
160def print_help():
161 print 'usage: %s <command> [options]' % os.path.basename(sys.argv[0])
162 print
5dc51fea 163 print 'Generic commands:'
f0699cc7 164 print ' help print the detailed command usage'
1e0bdf2a 165 print ' version display version information'
22ea9102 166 print ' copyright display copyright information'
5dc51fea 167 # unclassified commands if any
41a6d859
CM
168 cmds = commands.keys()
169 cmds.sort()
170 for cmd in cmds:
5dc51fea
YD
171 if not cmd in repocommands and not cmd in stackcommands \
172 and not cmd in patchcommands and not cmd in wccommands:
173 _print_helpstring(cmd)
174 print
175
176 print 'Repository commands:'
177 for cmd in repocommands:
178 _print_helpstring(cmd)
179 print
180
181 print 'Stack commands:'
182 for cmd in stackcommands:
183 _print_helpstring(cmd)
184 print
185
186 print 'Patch commands:'
187 for cmd in patchcommands:
188 _print_helpstring(cmd)
189 print
190
191 print 'Working-copy commands:'
192 for cmd in wccommands:
193 _print_helpstring(cmd)
41a6d859
CM
194
195#
196# The main function (command dispatcher)
197#
198def main():
199 """The main function
200 """
514dd4f2
CM
201 global prog
202
41a6d859
CM
203 prog = os.path.basename(sys.argv[0])
204
205 if len(sys.argv) < 2:
d00e708a 206 print >> sys.stderr, 'usage: %s <command>' % prog
41a6d859 207 print >> sys.stderr, \
f0699cc7 208 ' Try "%s --help" for a list of supported commands' % prog
41a6d859
CM
209 sys.exit(1)
210
211 cmd = sys.argv[1]
212
f0699cc7 213 if cmd in ['-h', '--help']:
78340ff1
YD
214 if len(sys.argv) >= 3:
215 cmd = commands.canonical_cmd(sys.argv[2])
f0699cc7 216 sys.argv[2] = '--help'
31c5abf2
PR
217 else:
218 print_help()
219 sys.exit(0)
f0699cc7
CM
220 if cmd == 'help':
221 if len(sys.argv) == 3 and not sys.argv[2] in ['-h', '--help']:
78340ff1 222 cmd = commands.canonical_cmd(sys.argv[2])
f0699cc7 223 if not cmd in commands:
27ac2b7e 224 out.error('%s help: "%s" command unknown' % (prog, cmd))
f0699cc7
CM
225 sys.exit(1)
226
227 sys.argv[0] += ' %s' % cmd
228 command = commands[cmd]
229 parser = OptionParser(usage = command.usage,
230 option_list = command.options)
0d4cd7ce
CM
231 from pydoc import pager
232 pager(parser.format_help())
f0699cc7 233 else:
4fe42e63 234 print_help()
f0699cc7 235 sys.exit(0)
1e0bdf2a 236 if cmd in ['-v', '--version', 'version']:
c333afcf 237 from stgit.version import version
4df2f866 238 print 'Stacked GIT %s' % version
50725547 239 os.system('git --version')
1e0bdf2a 240 print 'Python version %s' % sys.version
41a6d859 241 sys.exit(0)
22ea9102
CM
242 if cmd in ['copyright']:
243 print __copyright__
244 sys.exit(0)
41a6d859
CM
245
246 # re-build the command line arguments
3faeaeb1
CM
247 cmd = commands.canonical_cmd(cmd)
248 sys.argv[0] += ' %s' % cmd
41a6d859
CM
249 del(sys.argv[1])
250
251 command = commands[cmd]
f0699cc7
CM
252 usage = command.usage.split('\n')[0].strip()
253 parser = OptionParser(usage = usage, option_list = command.options)
41a6d859 254 options, args = parser.parse_args()
6dd8fafa 255 directory = command.directory
22d87516
CM
256
257 # These modules are only used from this point onwards and do not
258 # need to be imported earlier
87c93eab 259 from stgit.exception import StgException
eee7283e 260 from stgit.config import config_setup
9e3f506f 261 from ConfigParser import ParsingError, NoSectionError
87c93eab 262 from stgit.stack import Series
22d87516 263
b2017c38 264 try:
4200335f 265 debug_level = int(os.environ.get('STGIT_DEBUG_LEVEL', 0))
b2017c38 266 except ValueError:
27ac2b7e 267 out.error('Invalid STGIT_DEBUG_LEVEL environment variable')
b2017c38
CM
268 sys.exit(1)
269
41a6d859 270 try:
6dd8fafa 271 directory.setup()
eee7283e
CM
272 config_setup()
273
44a01a58
KH
274 # Some commands don't (always) need an initialized series.
275 if directory.needs_current_series:
98290387 276 if hasattr(options, 'branch') and options.branch:
c333afcf 277 command.crt_series = Series(options.branch)
98290387 278 else:
c333afcf 279 command.crt_series = Series()
9ac09909 280
41a6d859 281 command.func(parser, options, args)
87c93eab 282 except (StgException, IOError, ParsingError, NoSectionError), err:
762f6c8c 283 out.error(str(err), title = '%s %s' % (prog, cmd))
fe104619 284 if debug_level > 0:
b2017c38
CM
285 raise
286 else:
287 sys.exit(2)
4d9fc826
CM
288 except KeyboardInterrupt:
289 sys.exit(1)
41a6d859
CM
290
291 sys.exit(0)