Track the files conflict history
[stgit] / stgit / main.py
CommitLineData
41a6d859
CM
1"""Basic quilt-like functionality
2"""
3
4__copyright__ = """
5Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.com>
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License version 2 as
9published by the Free Software Foundation.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19"""
20
21import sys, os
c333afcf 22from optparse import OptionParser
41a6d859 23
c333afcf 24import stgit.commands
41a6d859 25
41a6d859
CM
26#
27# The commands map
28#
c333afcf
CM
29class Commands(dict):
30 """Commands class. It performs on-demand module loading
31 """
32 def __getitem__(self, key):
514dd4f2
CM
33 """Return the command python module name based.
34 """
35 global prog
36
c333afcf 37 cmd_mod = self.get(key)
514dd4f2
CM
38 if not cmd_mod:
39 candidates = [cmd for cmd in self.keys() if cmd.startswith(key)]
40
41 if not candidates:
42 print >> sys.stderr, 'Unknown command: %s' % key
43 print >> sys.stderr, ' Try "%s help" for a list of ' \
44 'supported commands' % prog
45 sys.exit(1)
46 elif len(candidates) > 1:
47 print >> sys.stderr, 'Ambiguous command: %s' % key
48 print >> sys.stderr, ' Candidates are: %s' \
49 % ', '.join(candidates)
50 sys.exit(1)
51
52 cmd_mod = self.get(candidates[0])
53
c333afcf
CM
54 __import__('stgit.commands.' + cmd_mod)
55 return getattr(stgit.commands, cmd_mod)
56
57commands = Commands({
58 'add': 'add',
59 'applied': 'applied',
60 'assimilate': 'assimilate',
61 'branch': 'branch',
62 'delete': 'delete',
63 'diff': 'diff',
64 'clean': 'clean',
65 'clone': 'clone',
66 'commit': 'commit',
67 'export': 'export',
68 'files': 'files',
69 'float': 'float',
70 'fold': 'fold',
71 'goto': 'goto',
72 'id': 'id',
73 'import': 'imprt',
74 'init': 'init',
75 'log': 'log',
76 'mail': 'mail',
77 'new': 'new',
78 'patches': 'patches',
79 'pick': 'pick',
80 'pop': 'pop',
81 'pull': 'pull',
82 'push': 'push',
83 'refresh': 'refresh',
84 'rename': 'rename',
85 'resolved': 'resolved',
86 'rm': 'rm',
87 'series': 'series',
88 'show': 'show',
89 'status': 'status',
06848fab 90 'sync': 'sync',
c333afcf
CM
91 'top': 'top',
92 'unapplied': 'unapplied',
93 'uncommit': 'uncommit'
94 })
41a6d859 95
5dc51fea
YD
96# classification: repository, stack, patch, working copy
97repocommands = (
98 'branch',
99 'clone',
100 'id',
101 'pull'
102 )
103stackcommands = (
104 'applied',
4d0ba818 105 'assimilate',
5dc51fea
YD
106 'clean',
107 'commit',
d98a499c 108 'float',
5dc51fea
YD
109 'goto',
110 'init',
111 'pop',
112 'push',
113 'series',
114 'top',
115 'unapplied',
116 'uncommit'
117 )
118patchcommands = (
119 'delete',
120 'export',
121 'files',
122 'fold',
123 'import',
64354a2d 124 'log',
5dc51fea
YD
125 'mail',
126 'new',
127 'pick',
128 'refresh',
129 'rename',
06848fab
CM
130 'show',
131 'sync'
5dc51fea
YD
132 )
133wccommands = (
134 'add',
135 'diff',
136 'patches',
137 'resolved',
138 'rm',
139 'status'
140 )
141
142def _print_helpstring(cmd):
143 print ' ' + cmd + ' ' * (12 - len(cmd)) + commands[cmd].help
144
41a6d859
CM
145def print_help():
146 print 'usage: %s <command> [options]' % os.path.basename(sys.argv[0])
147 print
5dc51fea 148 print 'Generic commands:'
f0699cc7 149 print ' help print the detailed command usage'
1e0bdf2a 150 print ' version display version information'
22ea9102 151 print ' copyright display copyright information'
5dc51fea 152 # unclassified commands if any
41a6d859
CM
153 cmds = commands.keys()
154 cmds.sort()
155 for cmd in cmds:
5dc51fea
YD
156 if not cmd in repocommands and not cmd in stackcommands \
157 and not cmd in patchcommands and not cmd in wccommands:
158 _print_helpstring(cmd)
159 print
160
161 print 'Repository commands:'
162 for cmd in repocommands:
163 _print_helpstring(cmd)
164 print
165
166 print 'Stack commands:'
167 for cmd in stackcommands:
168 _print_helpstring(cmd)
169 print
170
171 print 'Patch commands:'
172 for cmd in patchcommands:
173 _print_helpstring(cmd)
174 print
175
176 print 'Working-copy commands:'
177 for cmd in wccommands:
178 _print_helpstring(cmd)
41a6d859
CM
179
180#
181# The main function (command dispatcher)
182#
183def main():
184 """The main function
185 """
514dd4f2
CM
186 global prog
187
41a6d859
CM
188 prog = os.path.basename(sys.argv[0])
189
190 if len(sys.argv) < 2:
d00e708a 191 print >> sys.stderr, 'usage: %s <command>' % prog
41a6d859 192 print >> sys.stderr, \
f0699cc7 193 ' Try "%s --help" for a list of supported commands' % prog
41a6d859
CM
194 sys.exit(1)
195
196 cmd = sys.argv[1]
197
f0699cc7 198 if cmd in ['-h', '--help']:
a9d82c36 199 if len(sys.argv) >= 3 and sys.argv[2] in commands:
31c5abf2 200 cmd = sys.argv[2]
f0699cc7 201 sys.argv[2] = '--help'
31c5abf2
PR
202 else:
203 print_help()
204 sys.exit(0)
f0699cc7
CM
205 if cmd == 'help':
206 if len(sys.argv) == 3 and not sys.argv[2] in ['-h', '--help']:
207 cmd = sys.argv[2]
208 if not cmd in commands:
209 print >> sys.stderr, '%s help: "%s" command unknown' \
210 % (prog, cmd)
211 sys.exit(1)
212
213 sys.argv[0] += ' %s' % cmd
214 command = commands[cmd]
215 parser = OptionParser(usage = command.usage,
216 option_list = command.options)
0d4cd7ce
CM
217 from pydoc import pager
218 pager(parser.format_help())
f0699cc7 219 else:
4fe42e63 220 print_help()
f0699cc7 221 sys.exit(0)
1e0bdf2a 222 if cmd in ['-v', '--version', 'version']:
c333afcf 223 from stgit.version import version
4df2f866 224 print 'Stacked GIT %s' % version
50725547 225 os.system('git --version')
1e0bdf2a 226 print 'Python version %s' % sys.version
41a6d859 227 sys.exit(0)
22ea9102
CM
228 if cmd in ['copyright']:
229 print __copyright__
230 sys.exit(0)
41a6d859
CM
231
232 # re-build the command line arguments
233 sys.argv[0] += ' %s' % cmd
234 del(sys.argv[1])
235
236 command = commands[cmd]
f0699cc7
CM
237 usage = command.usage.split('\n')[0].strip()
238 parser = OptionParser(usage = usage, option_list = command.options)
41a6d859 239 options, args = parser.parse_args()
22d87516
CM
240
241 # These modules are only used from this point onwards and do not
242 # need to be imported earlier
eee7283e 243 from stgit.config import config_setup
9e3f506f 244 from ConfigParser import ParsingError, NoSectionError
22d87516
CM
245 from stgit.stack import Series, StackException
246 from stgit.git import GitException
247 from stgit.commands.common import CmdException
248 from stgit.gitmergeonefile import GitMergeException
249
41a6d859 250 try:
eee7283e
CM
251 config_setup()
252
98290387
CM
253 # 'clone' doesn't expect an already initialised GIT tree. A Series
254 # object will be created after the GIT tree is cloned
255 if cmd != 'clone':
256 if hasattr(options, 'branch') and options.branch:
c333afcf 257 command.crt_series = Series(options.branch)
98290387 258 else:
c333afcf 259 command.crt_series = Series()
98290387 260 stgit.commands.common.crt_series = command.crt_series
9ac09909 261
41a6d859 262 command.func(parser, options, args)
9e3f506f
KH
263 except (IOError, ParsingError, NoSectionError, CmdException,
264 StackException, GitException, GitMergeException), err:
41a6d859
CM
265 print >> sys.stderr, '%s %s: %s' % (prog, cmd, err)
266 sys.exit(2)
4d9fc826
CM
267 except KeyboardInterrupt:
268 sys.exit(1)
41a6d859
CM
269
270 sys.exit(0)