Commit | Line | Data |
---|---|---|
41a6d859 CM |
1 | """Basic quilt-like functionality |
2 | """ | |
3 | ||
4 | __copyright__ = """ | |
5 | Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.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 | ||
08986eda | 21 | import sys, os, traceback |
41a6d859 | 22 | |
c333afcf | 23 | import stgit.commands |
5e888f30 | 24 | from stgit.out import * |
575bbdae | 25 | from stgit import argparse, run, utils |
41a6d859 | 26 | |
41a6d859 CM |
27 | # |
28 | # The commands map | |
29 | # | |
c333afcf CM |
30 | class 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) | |
5be69cd8 | 42 | sys.exit(utils.STGIT_GENERAL_ERROR) |
78340ff1 | 43 | elif len(candidates) > 1: |
27ac2b7e KH |
44 | out.error('Ambiguous command: %s' % key, |
45 | 'Candidates are: %s' % ', '.join(candidates)) | |
5be69cd8 | 46 | sys.exit(utils.STGIT_GENERAL_ERROR) |
78340ff1 YD |
47 | |
48 | return candidates[0] | |
49 | ||
c333afcf | 50 | def __getitem__(self, key): |
78340ff1 | 51 | cmd_mod = self.get(key) or self.get(self.canonical_cmd(key)) |
33ff9cdd KH |
52 | return stgit.commands.get_command(cmd_mod) |
53 | ||
54 | cmd_list = stgit.commands.get_commands() | |
55 | commands = Commands((cmd, mod) for cmd, (mod, kind, help) | |
56 | in cmd_list.iteritems()) | |
57 | ||
41a6d859 CM |
58 | def print_help(): |
59 | print 'usage: %s <command> [options]' % os.path.basename(sys.argv[0]) | |
60 | ||
5dc51fea | 61 | print 'Generic commands:' |
f0699cc7 | 62 | print ' help print the detailed command usage' |
1e0bdf2a | 63 | print ' version display version information' |
22ea9102 | 64 | print ' copyright display copyright information' |
5dc51fea | 65 | |
33ff9cdd | 66 | stgit.commands.pretty_command_list(cmd_list, sys.stdout) |
41a6d859 CM |
67 | |
68 | # | |
69 | # The main function (command dispatcher) | |
70 | # | |
36a06e01 | 71 | def _main(): |
41a6d859 CM |
72 | """The main function |
73 | """ | |
514dd4f2 CM |
74 | global prog |
75 | ||
41a6d859 CM |
76 | prog = os.path.basename(sys.argv[0]) |
77 | ||
78 | if len(sys.argv) < 2: | |
d00e708a | 79 | print >> sys.stderr, 'usage: %s <command>' % prog |
41a6d859 | 80 | print >> sys.stderr, \ |
f0699cc7 | 81 | ' Try "%s --help" for a list of supported commands' % prog |
5be69cd8 | 82 | sys.exit(utils.STGIT_GENERAL_ERROR) |
41a6d859 CM |
83 | |
84 | cmd = sys.argv[1] | |
85 | ||
f0699cc7 | 86 | if cmd in ['-h', '--help']: |
78340ff1 YD |
87 | if len(sys.argv) >= 3: |
88 | cmd = commands.canonical_cmd(sys.argv[2]) | |
f0699cc7 | 89 | sys.argv[2] = '--help' |
31c5abf2 PR |
90 | else: |
91 | print_help() | |
5be69cd8 | 92 | sys.exit(utils.STGIT_SUCCESS) |
f0699cc7 CM |
93 | if cmd == 'help': |
94 | if len(sys.argv) == 3 and not sys.argv[2] in ['-h', '--help']: | |
78340ff1 | 95 | cmd = commands.canonical_cmd(sys.argv[2]) |
f0699cc7 | 96 | if not cmd in commands: |
27ac2b7e | 97 | out.error('%s help: "%s" command unknown' % (prog, cmd)) |
5be69cd8 | 98 | sys.exit(utils.STGIT_GENERAL_ERROR) |
f0699cc7 CM |
99 | |
100 | sys.argv[0] += ' %s' % cmd | |
101 | command = commands[cmd] | |
575bbdae | 102 | parser = argparse.make_option_parser(command) |
0d4cd7ce CM |
103 | from pydoc import pager |
104 | pager(parser.format_help()) | |
f0699cc7 | 105 | else: |
4fe42e63 | 106 | print_help() |
5be69cd8 | 107 | sys.exit(utils.STGIT_SUCCESS) |
1e0bdf2a | 108 | if cmd in ['-v', '--version', 'version']: |
c333afcf | 109 | from stgit.version import version |
4df2f866 | 110 | print 'Stacked GIT %s' % version |
50725547 | 111 | os.system('git --version') |
1e0bdf2a | 112 | print 'Python version %s' % sys.version |
5be69cd8 | 113 | sys.exit(utils.STGIT_SUCCESS) |
22ea9102 CM |
114 | if cmd in ['copyright']: |
115 | print __copyright__ | |
5be69cd8 | 116 | sys.exit(utils.STGIT_SUCCESS) |
41a6d859 CM |
117 | |
118 | # re-build the command line arguments | |
3faeaeb1 CM |
119 | cmd = commands.canonical_cmd(cmd) |
120 | sys.argv[0] += ' %s' % cmd | |
41a6d859 CM |
121 | del(sys.argv[1]) |
122 | ||
123 | command = commands[cmd] | |
575bbdae | 124 | parser = argparse.make_option_parser(command) |
41a6d859 | 125 | options, args = parser.parse_args() |
6dd8fafa | 126 | directory = command.directory |
22d87516 CM |
127 | |
128 | # These modules are only used from this point onwards and do not | |
129 | # need to be imported earlier | |
87c93eab | 130 | from stgit.exception import StgException |
eee7283e | 131 | from stgit.config import config_setup |
9e3f506f | 132 | from ConfigParser import ParsingError, NoSectionError |
87c93eab | 133 | from stgit.stack import Series |
22d87516 | 134 | |
41a6d859 | 135 | try: |
4200335f | 136 | debug_level = int(os.environ.get('STGIT_DEBUG_LEVEL', 0)) |
b2017c38 | 137 | except ValueError: |
27ac2b7e | 138 | out.error('Invalid STGIT_DEBUG_LEVEL environment variable') |
5be69cd8 | 139 | sys.exit(utils.STGIT_GENERAL_ERROR) |
b2017c38 CM |
140 | |
141 | try: | |
6dd8fafa | 142 | directory.setup() |
eee7283e CM |
143 | config_setup() |
144 | ||
44a01a58 KH |
145 | # Some commands don't (always) need an initialized series. |
146 | if directory.needs_current_series: | |
98290387 | 147 | if hasattr(options, 'branch') and options.branch: |
c333afcf | 148 | command.crt_series = Series(options.branch) |
98290387 | 149 | else: |
c333afcf | 150 | command.crt_series = Series() |
9ac09909 | 151 | |
f9cc5e69 | 152 | ret = command.func(parser, options, args) |
87c93eab | 153 | except (StgException, IOError, ParsingError, NoSectionError), err: |
117ed129 | 154 | directory.write_log(cmd) |
762f6c8c | 155 | out.error(str(err), title = '%s %s' % (prog, cmd)) |
fe104619 | 156 | if debug_level > 0: |
08986eda KH |
157 | traceback.print_exc() |
158 | sys.exit(utils.STGIT_COMMAND_ERROR) | |
f3167489 KH |
159 | except SystemExit: |
160 | # Triggered by the option parser when it finds bad commandline | |
161 | # parameters. | |
162 | sys.exit(utils.STGIT_COMMAND_ERROR) | |
4d9fc826 | 163 | except KeyboardInterrupt: |
5be69cd8 | 164 | sys.exit(utils.STGIT_GENERAL_ERROR) |
08986eda KH |
165 | except: |
166 | out.error('Unhandled exception:') | |
167 | traceback.print_exc() | |
168 | sys.exit(utils.STGIT_BUG_ERROR) | |
41a6d859 | 169 | |
117ed129 | 170 | directory.write_log(cmd) |
f9cc5e69 | 171 | sys.exit(ret or utils.STGIT_SUCCESS) |
36a06e01 KH |
172 | |
173 | def main(): | |
174 | try: | |
175 | _main() | |
176 | finally: | |
177 | run.finish_logging() |