Normalize StGit and Git spellings
[stgit.git] / stgit / main.py
bloba2917f881a223650d4962c1ec5743cc349d71011
1 """Basic quilt-like functionality"""
3 import os
4 import sys
5 import traceback
7 import stgit.commands
8 from stgit import argparse, run, utils
9 from stgit.compat import environ_get, fsdecode_utf8
10 from stgit.config import config
11 from stgit.out import out
12 from stgit.pager import pager
14 __copyright__ = """
15 Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.com>
17 This program is free software; you can redistribute it and/or modify
18 it under the terms of the GNU General Public License version 2 as
19 published by the Free Software Foundation.
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, see http://www.gnu.org/licenses/.
28 """
31 class CommandAlias:
32 def __init__(self, name, command):
33 self._command = command
34 self.__name__ = name
35 self.usage = ['<arguments>']
36 self.help = 'Alias for "%s <arguments>".' % self._command
37 self.options = []
39 def func(self, args):
40 cmd = self._command.split() + args
41 p = run.Run(*cmd)
42 p.discard_exitcode().run()
43 return p.exitcode
46 def is_cmd_alias(cmd):
47 return isinstance(cmd, CommandAlias)
50 def append_alias_commands(cmd_list):
51 for (name, command) in config.getstartswith('stgit.alias.'):
52 name = utils.strip_prefix('stgit.alias.', name)
53 cmd_list.append((name, CommandAlias(name, command), 'Alias commands', command))
57 # The commands map
59 class Commands(dict):
60 """Commands class. It performs on-demand module loading"""
62 def canonical_cmd(self, key):
63 """Return the canonical name for a possibly-shortened command name."""
64 candidates = [cmd for cmd in self if cmd.startswith(key)]
66 if not candidates:
67 out.error(
68 'Unknown command: %s' % key,
69 'Try "%s help" for a list of supported commands' % prog,
71 sys.exit(utils.STGIT_GENERAL_ERROR)
72 elif len(candidates) == 1:
73 return candidates[0]
74 elif key in candidates:
75 return key
76 else:
77 out.error(
78 'Ambiguous command: %s' % key,
79 'Candidates are: %s' % ', '.join(candidates),
81 sys.exit(utils.STGIT_GENERAL_ERROR)
83 def __getitem__(self, key):
84 cmd_mod = self.get(key) or self.get(self.canonical_cmd(key))
85 if is_cmd_alias(cmd_mod):
86 return cmd_mod
87 else:
88 return stgit.commands.get_command(cmd_mod)
91 cmd_list = stgit.commands.get_commands()
92 append_alias_commands(cmd_list)
93 commands = Commands((cmd, mod) for cmd, mod, _, _ in cmd_list)
96 def print_help():
97 print('usage: %s <command> [options]' % os.path.basename(sys.argv[0]))
98 print()
99 print('Generic commands:')
100 print(' help print the detailed command usage')
101 print(' version display version information')
102 print(' copyright display copyright information')
103 print()
104 stgit.commands.pretty_command_list(cmd_list, sys.stdout)
107 def _main():
108 global prog
110 sys.argv = list(map(fsdecode_utf8, sys.argv))
112 prog = os.path.basename(sys.argv[0])
114 if len(sys.argv) < 2:
115 print('usage: %s <command>' % prog, file=sys.stderr)
116 print(
117 ' Try "%s --help" for a list of supported commands' % prog, file=sys.stderr
119 sys.exit(utils.STGIT_GENERAL_ERROR)
121 cmd = sys.argv[1]
123 if cmd in ['-h', '--help']:
124 if len(sys.argv) >= 3:
125 cmd = commands.canonical_cmd(sys.argv[2])
126 sys.argv[2] = '--help'
127 else:
128 print_help()
129 sys.exit(utils.STGIT_SUCCESS)
130 if cmd == 'help':
131 if len(sys.argv) == 3 and not sys.argv[2] in ['-h', '--help']:
132 cmd = commands.canonical_cmd(sys.argv[2])
133 sys.argv[0] += ' %s' % cmd
134 command = commands[cmd]
135 parser = argparse.make_option_parser(command)
136 if is_cmd_alias(command):
137 parser.remove_option('-h')
138 pager(parser.format_help().encode())
139 else:
140 print_help()
141 sys.exit(utils.STGIT_SUCCESS)
142 if cmd in ['-v', '--version', 'version']:
143 from stgit.version import get_version
145 print('Stacked Git %s' % get_version())
146 os.system('git --version')
147 print('Python version %s' % sys.version)
148 sys.exit(utils.STGIT_SUCCESS)
149 if cmd in ['copyright']:
150 print(__copyright__)
151 sys.exit(utils.STGIT_SUCCESS)
153 # re-build the command line arguments
154 cmd = commands.canonical_cmd(cmd)
155 sys.argv[0] += ' %s' % cmd
156 del sys.argv[1]
158 command = commands[cmd]
159 if is_cmd_alias(command):
160 sys.exit(command.func(sys.argv[1:]))
162 parser = argparse.make_option_parser(command)
164 # These modules are only used from this point onwards and do not
165 # need to be imported earlier
166 try:
167 from configparser import NoSectionError, ParsingError
168 except ImportError:
169 from ConfigParser import NoSectionError, ParsingError
170 from stgit.config import config_setup
171 from stgit.exception import StgException
172 from stgit.lib.git import MergeConflictException
174 try:
175 debug_level = int(environ_get('STGIT_DEBUG_LEVEL', 0))
176 except ValueError:
177 out.error('Invalid STGIT_DEBUG_LEVEL environment variable')
178 sys.exit(utils.STGIT_GENERAL_ERROR)
180 try:
181 (options, args) = parser.parse_args()
182 command.directory.setup()
183 config_setup()
184 ret = command.func(parser, options, args)
185 except MergeConflictException as err:
186 if debug_level > 1:
187 traceback.print_exc(file=sys.stderr)
188 for conflict in err.conflicts:
189 out.err(conflict)
190 sys.exit(utils.STGIT_CONFLICT)
191 except (StgException, IOError, ParsingError, NoSectionError) as err:
192 if debug_level > 0:
193 traceback.print_exc(file=sys.stderr)
194 out.error(str(err), title='%s %s' % (prog, cmd))
195 sys.exit(utils.STGIT_COMMAND_ERROR)
196 except SystemExit:
197 # Triggered by the option parser when it finds bad commandline
198 # parameters.
199 sys.exit(utils.STGIT_COMMAND_ERROR)
200 except KeyboardInterrupt:
201 sys.exit(utils.STGIT_GENERAL_ERROR)
202 except BaseException:
203 out.error('Unhandled exception:')
204 traceback.print_exc(file=sys.stderr)
205 sys.exit(utils.STGIT_BUG_ERROR)
207 sys.exit(ret or utils.STGIT_SUCCESS)
210 def main():
211 try:
212 _main()
213 finally:
214 run.finish_logging()