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