Clean-up the number of imports in main.py
[stgit] / stgit / main.py
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
21 import sys, os
22 from optparse import OptionParser
23
24 import stgit.commands
25 from stgit.stack import Series, StackException
26 from stgit.git import GitException
27 from stgit.commands.common import CmdException
28 from stgit.gitmergeonefile import GitMergeException
29
30 #
31 # The commands map
32 #
33 class Commands(dict):
34 """Commands class. It performs on-demand module loading
35 """
36 def __getitem__(self, key):
37 cmd_mod = self.get(key)
38 __import__('stgit.commands.' + cmd_mod)
39 return getattr(stgit.commands, cmd_mod)
40
41 commands = Commands({
42 'add': 'add',
43 'applied': 'applied',
44 'assimilate': 'assimilate',
45 'branch': 'branch',
46 'delete': 'delete',
47 'diff': 'diff',
48 'clean': 'clean',
49 'clone': 'clone',
50 'commit': 'commit',
51 'export': 'export',
52 'files': 'files',
53 'float': 'float',
54 'fold': 'fold',
55 'goto': 'goto',
56 'id': 'id',
57 'import': 'imprt',
58 'init': 'init',
59 'log': 'log',
60 'mail': 'mail',
61 'new': 'new',
62 'patches': 'patches',
63 'pick': 'pick',
64 'pop': 'pop',
65 'pull': 'pull',
66 'push': 'push',
67 'refresh': 'refresh',
68 'rename': 'rename',
69 'resolved': 'resolved',
70 'rm': 'rm',
71 'series': 'series',
72 'show': 'show',
73 'status': 'status',
74 'top': 'top',
75 'unapplied': 'unapplied',
76 'uncommit': 'uncommit'
77 })
78
79 # classification: repository, stack, patch, working copy
80 repocommands = (
81 'branch',
82 'clone',
83 'id',
84 'pull'
85 )
86 stackcommands = (
87 'applied',
88 'assimilate',
89 'clean',
90 'commit',
91 'float',
92 'goto',
93 'init',
94 'pop',
95 'push',
96 'series',
97 'top',
98 'unapplied',
99 'uncommit'
100 )
101 patchcommands = (
102 'delete',
103 'export',
104 'files',
105 'fold',
106 'import',
107 'log',
108 'mail',
109 'new',
110 'pick',
111 'refresh',
112 'rename',
113 'show'
114 )
115 wccommands = (
116 'add',
117 'diff',
118 'patches',
119 'resolved',
120 'rm',
121 'status'
122 )
123
124 def _print_helpstring(cmd):
125 print ' ' + cmd + ' ' * (12 - len(cmd)) + commands[cmd].help
126
127 def print_help():
128 print 'usage: %s <command> [options]' % os.path.basename(sys.argv[0])
129 print
130 print 'Generic commands:'
131 print ' help print the detailed command usage'
132 print ' version display version information'
133 print ' copyright display copyright information'
134 # unclassified commands if any
135 cmds = commands.keys()
136 cmds.sort()
137 for cmd in cmds:
138 if not cmd in repocommands and not cmd in stackcommands \
139 and not cmd in patchcommands and not cmd in wccommands:
140 _print_helpstring(cmd)
141 print
142
143 print 'Repository commands:'
144 for cmd in repocommands:
145 _print_helpstring(cmd)
146 print
147
148 print 'Stack commands:'
149 for cmd in stackcommands:
150 _print_helpstring(cmd)
151 print
152
153 print 'Patch commands:'
154 for cmd in patchcommands:
155 _print_helpstring(cmd)
156 print
157
158 print 'Working-copy commands:'
159 for cmd in wccommands:
160 _print_helpstring(cmd)
161
162 #
163 # The main function (command dispatcher)
164 #
165 def main():
166 """The main function
167 """
168 prog = os.path.basename(sys.argv[0])
169
170 if len(sys.argv) < 2:
171 print >> sys.stderr, 'usage: %s <command>' % prog
172 print >> sys.stderr, \
173 ' Try "%s --help" for a list of supported commands' % prog
174 sys.exit(1)
175
176 cmd = sys.argv[1]
177
178 if cmd in ['-h', '--help']:
179 if len(sys.argv) >= 3 and sys.argv[2] in commands:
180 cmd = sys.argv[2]
181 sys.argv[2] = '--help'
182 else:
183 print_help()
184 sys.exit(0)
185 if cmd == 'help':
186 if len(sys.argv) == 3 and not sys.argv[2] in ['-h', '--help']:
187 cmd = sys.argv[2]
188 if not cmd in commands:
189 print >> sys.stderr, '%s help: "%s" command unknown' \
190 % (prog, cmd)
191 sys.exit(1)
192
193 sys.argv[0] += ' %s' % cmd
194 command = commands[cmd]
195 parser = OptionParser(usage = command.usage,
196 option_list = command.options)
197 parser.print_help()
198 else:
199 print_help()
200 sys.exit(0)
201 if cmd in ['-v', '--version', 'version']:
202 from stgit.version import version
203 print 'Stacked GIT %s' % version
204 os.system('git --version')
205 print 'Python version %s' % sys.version
206 sys.exit(0)
207 if cmd in ['copyright']:
208 print __copyright__
209 sys.exit(0)
210 if not cmd in commands:
211 print >> sys.stderr, 'Unknown command: %s' % cmd
212 print >> sys.stderr, ' Try "%s help" for a list of supported ' \
213 'commands' % prog
214 sys.exit(1)
215
216 # re-build the command line arguments
217 sys.argv[0] += ' %s' % cmd
218 del(sys.argv[1])
219
220 command = commands[cmd]
221 usage = command.usage.split('\n')[0].strip()
222 parser = OptionParser(usage = usage, option_list = command.options)
223 options, args = parser.parse_args()
224 try:
225 # 'clone' doesn't expect an already initialised GIT tree. A Series
226 # object will be created after the GIT tree is cloned
227 if cmd != 'clone':
228 if hasattr(options, 'branch') and options.branch:
229 command.crt_series = Series(options.branch)
230 else:
231 command.crt_series = Series()
232 stgit.commands.common.crt_series = command.crt_series
233
234 command.func(parser, options, args)
235 except (IOError, CmdException, StackException, GitException,
236 GitMergeException), err:
237 print >> sys.stderr, '%s %s: %s' % (prog, cmd, err)
238 sys.exit(2)
239 except KeyboardInterrupt:
240 sys.exit(1)
241
242 sys.exit(0)