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