1 """Basic quilt-like functionality
5 Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.com>
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.
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.
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
21 import sys, os, traceback
22 from optparse import OptionParser
25 from stgit.out import *
26 from stgit import run, utils
32 """Commands class. It performs on-demand module loading
34 def canonical_cmd(self, key):
35 """Return the canonical name for a possibly-shortenned
38 candidates = [cmd for cmd in self.keys() if cmd.startswith(key)]
41 out.error('Unknown command: %s' % key,
42 'Try "%s help" for a list of supported commands' % prog)
43 sys.exit(utils.STGIT_GENERAL_ERROR)
44 elif len(candidates) > 1:
45 out.error('Ambiguous command: %s' % key,
46 'Candidates are: %s' % ', '.join(candidates))
47 sys.exit(utils.STGIT_GENERAL_ERROR)
51 def __getitem__(self, key):
52 """Return the command python module name based.
56 cmd_mod = self.get(key) or self.get(self.canonical_cmd(key))
58 __import__('stgit.commands.' + cmd_mod)
59 return getattr(stgit.commands, cmd_mod)
67 'coalesce': 'coalesce',
91 'resolved': 'resolved',
98 'uncommit': 'uncommit',
102 # classification: repository, stack, patch, working copy
150 def _print_helpstring(cmd):
151 print ' ' + cmd + ' ' * (12 - len(cmd)) + commands[cmd].help
154 print 'usage: %s <command> [options]' % os.path.basename(sys.argv[0])
156 print 'Generic commands:'
157 print ' help print the detailed command usage'
158 print ' version display version information'
159 print ' copyright display copyright information'
160 # unclassified commands if any
161 cmds = commands.keys()
164 if not cmd in repocommands and not cmd in stackcommands \
165 and not cmd in patchcommands and not cmd in wccommands:
166 _print_helpstring(cmd)
169 print 'Repository commands:'
170 for cmd in repocommands:
171 _print_helpstring(cmd)
174 print 'Stack commands:'
175 for cmd in stackcommands:
176 _print_helpstring(cmd)
179 print 'Patch commands:'
180 for cmd in patchcommands:
181 _print_helpstring(cmd)
184 print 'Working-copy commands:'
185 for cmd in wccommands:
186 _print_helpstring(cmd)
189 # The main function (command dispatcher)
196 prog = os.path.basename(sys.argv[0])
198 if len(sys.argv) < 2:
199 print >> sys.stderr, 'usage: %s <command>' % prog
200 print >> sys.stderr, \
201 ' Try "%s --help" for a list of supported commands' % prog
202 sys.exit(utils.STGIT_GENERAL_ERROR)
206 if cmd in ['-h', '--help']:
207 if len(sys.argv) >= 3:
208 cmd = commands.canonical_cmd(sys.argv[2])
209 sys.argv[2] = '--help'
212 sys.exit(utils.STGIT_SUCCESS)
214 if len(sys.argv) == 3 and not sys.argv[2] in ['-h', '--help']:
215 cmd = commands.canonical_cmd(sys.argv[2])
216 if not cmd in commands:
217 out.error('%s help: "%s" command unknown' % (prog, cmd))
218 sys.exit(utils.STGIT_GENERAL_ERROR)
220 sys.argv[0] += ' %s' % cmd
221 command = commands[cmd]
222 parser = OptionParser(usage = command.usage,
223 option_list = command.options)
224 from pydoc import pager
225 pager(parser.format_help())
228 sys.exit(utils.STGIT_SUCCESS)
229 if cmd in ['-v', '--version', 'version']:
230 from stgit.version import version
231 print 'Stacked GIT %s' % version
232 os.system('git --version')
233 print 'Python version %s' % sys.version
234 sys.exit(utils.STGIT_SUCCESS)
235 if cmd in ['copyright']:
237 sys.exit(utils.STGIT_SUCCESS)
239 # re-build the command line arguments
240 cmd = commands.canonical_cmd(cmd)
241 sys.argv[0] += ' %s' % cmd
244 command = commands[cmd]
245 usage = command.usage.split('\n')[0].strip()
246 parser = OptionParser(usage = usage, option_list = command.options)
247 options, args = parser.parse_args()
248 directory = command.directory
250 # These modules are only used from this point onwards and do not
251 # need to be imported earlier
252 from stgit.exception import StgException
253 from stgit.config import config_setup
254 from ConfigParser import ParsingError, NoSectionError
255 from stgit.stack import Series
258 debug_level = int(os.environ.get('STGIT_DEBUG_LEVEL', 0))
260 out.error('Invalid STGIT_DEBUG_LEVEL environment variable')
261 sys.exit(utils.STGIT_GENERAL_ERROR)
267 # Some commands don't (always) need an initialized series.
268 if directory.needs_current_series:
269 if hasattr(options, 'branch') and options.branch:
270 command.crt_series = Series(options.branch)
272 command.crt_series = Series()
274 ret = command.func(parser, options, args)
275 except (StgException, IOError, ParsingError, NoSectionError), err:
276 out.error(str(err), title = '%s %s' % (prog, cmd))
278 traceback.print_exc()
279 sys.exit(utils.STGIT_COMMAND_ERROR)
281 # Triggered by the option parser when it finds bad commandline
283 sys.exit(utils.STGIT_COMMAND_ERROR)
284 except KeyboardInterrupt:
285 sys.exit(utils.STGIT_GENERAL_ERROR)
287 out.error('Unhandled exception:')
288 traceback.print_exc()
289 sys.exit(utils.STGIT_BUG_ERROR)
291 sys.exit(ret or utils.STGIT_SUCCESS)