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