~bzr-pqm/bzr/bzr.dev

329 by Martin Pool
- refactor command functions into command classes
1
# Copyright (C) 2004, 2005 by Canonical Ltd
1 by mbp at sourcefrog
import from baz patch-364
2
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
18
# TODO: probably should say which arguments are candidates for glob
19
# expansion on windows and do that at the command level.
20
1095 by Martin Pool
todo
21
# TODO: Help messages for options.
22
23
# TODO: Define arguments by objects, rather than just using names.
24
# Those objects can specify the expected type of the argument, which
25
# would help with validation and shell completion.
26
27
1092.1.48 by Robert Collins
really merge mpool
28
# TODO: Help messages for options.
29
30
# TODO: Define arguments by objects, rather than just using names.
31
# Those objects can specify the expected type of the argument, which
32
# would help with validation and shell completion.
33
34
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
35
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
36
import sys
37
import os
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
38
from warnings import warn
39
from inspect import getdoc
1 by mbp at sourcefrog
import from baz patch-364
40
41
import bzrlib
1112 by Martin Pool
- disable standard logging to .bzr.log and stderr while running
42
import bzrlib.trace
897 by Martin Pool
- merge john's revision-naming code
43
from bzrlib.trace import mutter, note, log_error, warning
974.1.82 by Aaron Bentley
Handled NotBranchError like a CommandError in main()
44
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError, NotBranchError
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
45
from bzrlib.revisionspec import RevisionSpec
800 by Martin Pool
Merge John's import-speedup branch:
46
from bzrlib import BZRDIR
1 by mbp at sourcefrog
import from baz patch-364
47
731 by Martin Pool
- merge plugin patch from john
48
plugin_cmds = {}
49
50
759 by Martin Pool
- fix up register_command() names
51
def register_command(cmd):
731 by Martin Pool
- merge plugin patch from john
52
    "Utility function to help register a command"
53
    global plugin_cmds
54
    k = cmd.__name__
55
    if k.startswith("cmd_"):
56
        k_unsquished = _unsquish_command_name(k)
57
    else:
58
        k_unsquished = k
59
    if not plugin_cmds.has_key(k_unsquished):
60
        plugin_cmds[k_unsquished] = cmd
1137 by Martin Pool
- additional trace messages for plugins
61
        mutter('registered plugin command %s', k_unsquished)      
731 by Martin Pool
- merge plugin patch from john
62
    else:
63
        log_error('Two plugins defined the same command: %r' % k)
64
        log_error('Not loading the one in %r' % sys.modules[cmd.__module__])
65
66
350 by Martin Pool
- refactor command aliases into command classes
67
def _squish_command_name(cmd):
68
    return 'cmd_' + cmd.replace('-', '_')
69
70
71
def _unsquish_command_name(cmd):
72
    assert cmd.startswith("cmd_")
73
    return cmd[4:].replace('_','-')
74
914 by Martin Pool
- fix up breakage of 'bzr log -v' by root_id patch
75
567 by Martin Pool
- New form 'bzr log -r FROM:TO'
76
def _parse_revision_str(revstr):
914 by Martin Pool
- fix up breakage of 'bzr log -v' by root_id patch
77
    """This handles a revision string -> revno.
78
1185.2.5 by Lalo Martins
moving the 'revision spec' stuff out of the Branch class and into a new
79
    This always returns a list.  The list will have one element for
80
    each revision.
897 by Martin Pool
- merge john's revision-naming code
81
82
    >>> _parse_revision_str('234')
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
83
    [<RevisionSpec_int 234>]
897 by Martin Pool
- merge john's revision-naming code
84
    >>> _parse_revision_str('234..567')
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
85
    [<RevisionSpec_int 234>, <RevisionSpec_int 567>]
897 by Martin Pool
- merge john's revision-naming code
86
    >>> _parse_revision_str('..')
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
87
    [<RevisionSpec None>, <RevisionSpec None>]
897 by Martin Pool
- merge john's revision-naming code
88
    >>> _parse_revision_str('..234')
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
89
    [<RevisionSpec None>, <RevisionSpec_int 234>]
897 by Martin Pool
- merge john's revision-naming code
90
    >>> _parse_revision_str('234..')
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
91
    [<RevisionSpec_int 234>, <RevisionSpec None>]
897 by Martin Pool
- merge john's revision-naming code
92
    >>> _parse_revision_str('234..456..789') # Maybe this should be an error
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
93
    [<RevisionSpec_int 234>, <RevisionSpec_int 456>, <RevisionSpec_int 789>]
897 by Martin Pool
- merge john's revision-naming code
94
    >>> _parse_revision_str('234....789') # Error?
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
95
    [<RevisionSpec_int 234>, <RevisionSpec None>, <RevisionSpec_int 789>]
897 by Martin Pool
- merge john's revision-naming code
96
    >>> _parse_revision_str('revid:test@other.com-234234')
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
97
    [<RevisionSpec_revid revid:test@other.com-234234>]
897 by Martin Pool
- merge john's revision-naming code
98
    >>> _parse_revision_str('revid:test@other.com-234234..revid:test@other.com-234235')
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
99
    [<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_revid revid:test@other.com-234235>]
897 by Martin Pool
- merge john's revision-naming code
100
    >>> _parse_revision_str('revid:test@other.com-234234..23')
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
101
    [<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_int 23>]
897 by Martin Pool
- merge john's revision-naming code
102
    >>> _parse_revision_str('date:2005-04-12')
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
103
    [<RevisionSpec_date date:2005-04-12>]
897 by Martin Pool
- merge john's revision-naming code
104
    >>> _parse_revision_str('date:2005-04-12 12:24:33')
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
105
    [<RevisionSpec_date date:2005-04-12 12:24:33>]
897 by Martin Pool
- merge john's revision-naming code
106
    >>> _parse_revision_str('date:2005-04-12T12:24:33')
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
107
    [<RevisionSpec_date date:2005-04-12T12:24:33>]
897 by Martin Pool
- merge john's revision-naming code
108
    >>> _parse_revision_str('date:2005-04-12,12:24:33')
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
109
    [<RevisionSpec_date date:2005-04-12,12:24:33>]
897 by Martin Pool
- merge john's revision-naming code
110
    >>> _parse_revision_str('-5..23')
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
111
    [<RevisionSpec_int -5>, <RevisionSpec_int 23>]
897 by Martin Pool
- merge john's revision-naming code
112
    >>> _parse_revision_str('-5')
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
113
    [<RevisionSpec_int -5>]
897 by Martin Pool
- merge john's revision-naming code
114
    >>> _parse_revision_str('123a')
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
115
    Traceback (most recent call last):
116
      ...
117
    BzrError: No namespace registered for string: '123a'
897 by Martin Pool
- merge john's revision-naming code
118
    >>> _parse_revision_str('abc')
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
119
    Traceback (most recent call last):
120
      ...
121
    BzrError: No namespace registered for string: 'abc'
567 by Martin Pool
- New form 'bzr log -r FROM:TO'
122
    """
897 by Martin Pool
- merge john's revision-naming code
123
    import re
124
    old_format_re = re.compile('\d*:\d*')
125
    m = old_format_re.match(revstr)
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
126
    revs = []
897 by Martin Pool
- merge john's revision-naming code
127
    if m:
128
        warning('Colon separator for revision numbers is deprecated.'
129
                ' Use .. instead')
130
        for rev in revstr.split(':'):
131
            if rev:
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
132
                revs.append(RevisionSpec(int(rev)))
133
            else:
134
                revs.append(RevisionSpec(None))
135
    else:
136
        for x in revstr.split('..'):
137
            if not x:
138
                revs.append(RevisionSpec(None))
139
            else:
140
                revs.append(RevisionSpec(x))
567 by Martin Pool
- New form 'bzr log -r FROM:TO'
141
    return revs
142
731 by Martin Pool
- merge plugin patch from john
143
974.1.9 by Aaron Bentley
Added merge-type parameter to merge.
144
def get_merge_type(typestring):
145
    """Attempt to find the merge class/factory associated with a string."""
146
    from merge import merge_types
147
    try:
148
        return merge_types[typestring][0]
149
    except KeyError:
150
        templ = '%s%%7s: %%s' % (' '*12)
151
        lines = [templ % (f[0], f[1][1]) for f in merge_types.iteritems()]
152
        type_list = '\n'.join(lines)
153
        msg = "No known merge type %s. Supported types are:\n%s" %\
154
            (typestring, type_list)
155
        raise BzrCommandError(msg)
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
156
157
158
def _builtin_commands():
1147 by Martin Pool
- split builtin commands into separate module bzrlib.builtins;
159
    import bzrlib.builtins
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
160
    r = {}
1147 by Martin Pool
- split builtin commands into separate module bzrlib.builtins;
161
    builtins = bzrlib.builtins.__dict__
162
    for name in builtins:
163
        if name.startswith("cmd_"):
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
164
            real_name = _unsquish_command_name(name)        
165
            r[real_name] = builtins[name]
166
    return r
167
168
            
169
170
def builtin_command_names():
171
    """Return list of builtin command names."""
172
    return _builtin_commands().keys()
173
    
174
175
def plugin_command_names():
176
    return plugin_cmds.keys()
177
178
179
def _get_cmd_dict(plugins_override=True):
180
    """Return name->class mapping for all commands."""
181
    d = _builtin_commands()
731 by Martin Pool
- merge plugin patch from john
182
    if plugins_override:
183
        d.update(plugin_cmds)
641 by Martin Pool
- improved external-command patch from john
184
    return d
731 by Martin Pool
- merge plugin patch from john
185
641 by Martin Pool
- improved external-command patch from john
186
    
731 by Martin Pool
- merge plugin patch from john
187
def get_all_cmds(plugins_override=True):
641 by Martin Pool
- improved external-command patch from john
188
    """Return canonical name and class for all registered commands."""
731 by Martin Pool
- merge plugin patch from john
189
    for k, v in _get_cmd_dict(plugins_override=plugins_override).iteritems():
641 by Martin Pool
- improved external-command patch from john
190
        yield k,v
191
192
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
193
def get_cmd_object(cmd_name, plugins_override=True):
350 by Martin Pool
- refactor command aliases into command classes
194
    """Return the canonical name and command class for a command.
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
195
196
    plugins_override
197
        If true, plugin commands can override builtins.
350 by Martin Pool
- refactor command aliases into command classes
198
    """
1163 by Martin Pool
- split ExternalCommand class into its own file
199
    from bzrlib.externalcommand import ExternalCommand
200
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
201
    cmd_name = str(cmd_name)            # not unicode
350 by Martin Pool
- refactor command aliases into command classes
202
203
    # first look up this command under the specified name
731 by Martin Pool
- merge plugin patch from john
204
    cmds = _get_cmd_dict(plugins_override=plugins_override)
272 by Martin Pool
- Add command aliases
205
    try:
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
206
        return cmds[cmd_name]()
272 by Martin Pool
- Add command aliases
207
    except KeyError:
350 by Martin Pool
- refactor command aliases into command classes
208
        pass
209
210
    # look for any command which claims this as an alias
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
211
    for real_cmd_name, cmd_class in cmds.iteritems():
212
        if cmd_name in cmd_class.aliases:
213
            return cmd_class()
214
215
    cmd_obj = ExternalCommand.find_command(cmd_name)
216
    if cmd_obj:
217
        return cmd_obj
218
219
    raise BzrCommandError("unknown command %r" % cmd_name)
272 by Martin Pool
- Add command aliases
220
329 by Martin Pool
- refactor command functions into command classes
221
558 by Martin Pool
- All top-level classes inherit from object
222
class Command(object):
329 by Martin Pool
- refactor command functions into command classes
223
    """Base class for commands.
224
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
225
    Commands are the heart of the command-line bzr interface.
226
227
    The command object mostly handles the mapping of command-line
228
    parameters into one or more bzrlib operations, and of the results
229
    into textual output.
230
231
    Commands normally don't have any state.  All their arguments are
232
    passed in to the run method.  (Subclasses may take a different
233
    policy if the behaviour of the instance needs to depend on e.g. a
234
    shell plugin and not just its Python class.)
235
329 by Martin Pool
- refactor command functions into command classes
236
    The docstring for an actual command should give a single-line
237
    summary, then a complete description of the command.  A grammar
238
    description will be inserted.
239
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
240
    aliases
241
        Other accepted names for this command.
242
329 by Martin Pool
- refactor command functions into command classes
243
    takes_args
244
        List of argument forms, marked with whether they are optional,
245
        repeated, etc.
246
247
    takes_options
248
        List of options that may be given for this command.
249
250
    hidden
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
251
        If true, this command isn't advertised.  This is typically
252
        for commands intended for expert users.
329 by Martin Pool
- refactor command functions into command classes
253
    """
254
    aliases = []
255
    
256
    takes_args = []
257
    takes_options = []
258
259
    hidden = False
260
    
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
261
    def __init__(self):
262
        """Construct an instance of this command."""
973 by Martin Pool
- various refactorings of command interpreter
263
        if self.__doc__ == Command.__doc__:
264
            warn("No help message set for %r" % self)
329 by Martin Pool
- refactor command functions into command classes
265
1165 by Martin Pool
- move parsing of argv into arguments and options into Command.run_argv
266
267
    def run_argv(self, argv):
268
        """Parse command line and run."""
269
        args, opts = parse_args(argv)
270
271
        if 'help' in opts:  # e.g. bzr add --help
272
            from bzrlib.help import help_on_command
273
            help_on_command(self.name())
274
            return 0
275
276
        # check options are reasonable
277
        allowed = self.takes_options
278
        for oname in opts:
279
            if oname not in allowed:
280
                raise BzrCommandError("option '--%s' is not allowed for command %r"
281
                                      % (oname, self.name()))
282
283
        # mix arguments and options into one dictionary
284
        cmdargs = _match_argform(self.name(), self.takes_args, args)
285
        cmdopts = {}
286
        for k, v in opts.items():
287
            cmdopts[k.replace('-', '_')] = v
288
289
        all_cmd_args = cmdargs.copy()
290
        all_cmd_args.update(cmdopts)
291
292
        return self.run(**all_cmd_args)
293
329 by Martin Pool
- refactor command functions into command classes
294
    
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
295
    def run(self):
296
        """Actually run the command.
329 by Martin Pool
- refactor command functions into command classes
297
298
        This is invoked with the options and arguments bound to
299
        keyword parameters.
300
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
301
        Return 0 or None if the command was successful, or a non-zero
302
        shell error code if not.  It's OK for this method to allow
303
        an exception to raise up.
329 by Martin Pool
- refactor command functions into command classes
304
        """
1147 by Martin Pool
- split builtin commands into separate module bzrlib.builtins;
305
        raise NotImplementedError()
329 by Martin Pool
- refactor command functions into command classes
306
307
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
308
    def help(self):
309
        """Return help message for this class."""
310
        if self.__doc__ is Command.__doc__:
311
            return None
312
        return getdoc(self)
313
314
    def name(self):
315
        return _unsquish_command_name(self.__class__.__name__)
316
317
493 by Martin Pool
- Merge aaron's merge command
318
def parse_spec(spec):
622 by Martin Pool
Updated merge patch from Aaron
319
    """
320
    >>> parse_spec(None)
321
    [None, None]
322
    >>> parse_spec("./")
323
    ['./', None]
324
    >>> parse_spec("../@")
325
    ['..', -1]
326
    >>> parse_spec("../f/@35")
327
    ['../f', 35]
897 by Martin Pool
- merge john's revision-naming code
328
    >>> parse_spec('./@revid:john@arbash-meinel.com-20050711044610-3ca0327c6a222f67')
329
    ['.', 'revid:john@arbash-meinel.com-20050711044610-3ca0327c6a222f67']
622 by Martin Pool
Updated merge patch from Aaron
330
    """
331
    if spec is None:
332
        return [None, None]
493 by Martin Pool
- Merge aaron's merge command
333
    if '/@' in spec:
334
        parsed = spec.split('/@')
335
        assert len(parsed) == 2
336
        if parsed[1] == "":
337
            parsed[1] = -1
338
        else:
897 by Martin Pool
- merge john's revision-naming code
339
            try:
340
                parsed[1] = int(parsed[1])
341
            except ValueError:
342
                pass # We can allow stuff like ./@revid:blahblahblah
343
            else:
344
                assert parsed[1] >=0
493 by Martin Pool
- Merge aaron's merge command
345
    else:
346
        parsed = [spec, None]
347
    return parsed
348
628 by Martin Pool
- merge aaron's updated merge/pull code
349
1 by mbp at sourcefrog
import from baz patch-364
350
# list of all available options; the rhs can be either None for an
351
# option that takes no argument, or a constructor function that checks
352
# the type.
353
OPTIONS = {
354
    'all':                    None,
571 by Martin Pool
- new --diff-options to pass options through to external
355
    'diff-options':           str,
1 by mbp at sourcefrog
import from baz patch-364
356
    'help':                   None,
389 by Martin Pool
- new commit --file option!
357
    'file':                   unicode,
628 by Martin Pool
- merge aaron's updated merge/pull code
358
    'force':                  None,
678 by Martin Pool
- export to tarballs
359
    'format':                 unicode,
545 by Martin Pool
- --forward option for log
360
    'forward':                None,
1 by mbp at sourcefrog
import from baz patch-364
361
    'message':                unicode,
594 by Martin Pool
- add --no-recurse option for add command
362
    'no-recurse':             None,
137 by mbp at sourcefrog
new --profile option
363
    'profile':                None,
567 by Martin Pool
- New form 'bzr log -r FROM:TO'
364
    'revision':               _parse_revision_str,
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
365
    'short':                  None,
1 by mbp at sourcefrog
import from baz patch-364
366
    'show-ids':               None,
12 by mbp at sourcefrog
new --timezone option for bzr log
367
    'timezone':               str,
1 by mbp at sourcefrog
import from baz patch-364
368
    'verbose':                None,
369
    'version':                None,
286 by Martin Pool
- New bzr whoami --email option
370
    'email':                  None,
885 by Martin Pool
- commit command refuses unless something is changed or --unchanged is given
371
    'unchanged':              None,
674 by Martin Pool
- check command now also checks new inventory_sha1 and
372
    'update':                 None,
807 by Martin Pool
- New log --long option
373
    'long':                   None,
849 by Martin Pool
- Put files inside an exported tarball into a top-level directory rather than
374
    'root':                   str,
974.1.8 by Aaron Bentley
Added default backups for merge-revert
375
    'no-backup':              None,
974.1.9 by Aaron Bentley
Added merge-type parameter to merge.
376
    'merge-type':             get_merge_type,
1092.1.20 by Robert Collins
import and use TestUtil to do regex based partial test runs
377
    'pattern':                str,
1 by mbp at sourcefrog
import from baz patch-364
378
    }
379
380
SHORT_OPTIONS = {
583 by Martin Pool
- add -h as short name for --help
381
    'F':                      'file', 
382
    'h':                      'help',
1 by mbp at sourcefrog
import from baz patch-364
383
    'm':                      'message',
384
    'r':                      'revision',
385
    'v':                      'verbose',
807 by Martin Pool
- New log --long option
386
    'l':                      'long',
1 by mbp at sourcefrog
import from baz patch-364
387
}
388
389
390
def parse_args(argv):
391
    """Parse command line.
392
    
393
    Arguments and options are parsed at this level before being passed
394
    down to specific command handlers.  This routine knows, from a
395
    lookup table, something about the available options, what optargs
396
    they take, and which commands will accept them.
397
31 by Martin Pool
fix up parse_args doctest
398
    >>> parse_args('--help'.split())
1 by mbp at sourcefrog
import from baz patch-364
399
    ([], {'help': True})
1144 by Martin Pool
- accept -- to terminate options
400
    >>> parse_args('help -- --invalidcmd'.split())
401
    (['help', '--invalidcmd'], {})
31 by Martin Pool
fix up parse_args doctest
402
    >>> parse_args('--version'.split())
1 by mbp at sourcefrog
import from baz patch-364
403
    ([], {'version': True})
31 by Martin Pool
fix up parse_args doctest
404
    >>> parse_args('status --all'.split())
1 by mbp at sourcefrog
import from baz patch-364
405
    (['status'], {'all': True})
31 by Martin Pool
fix up parse_args doctest
406
    >>> parse_args('commit --message=biter'.split())
17 by mbp at sourcefrog
allow --option=ARG syntax
407
    (['commit'], {'message': u'biter'})
683 by Martin Pool
- short option stacking patch from John A Meinel
408
    >>> parse_args('log -r 500'.split())
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
409
    (['log'], {'revision': [<RevisionSpec_int 500>]})
897 by Martin Pool
- merge john's revision-naming code
410
    >>> parse_args('log -r500..600'.split())
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
411
    (['log'], {'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
897 by Martin Pool
- merge john's revision-naming code
412
    >>> parse_args('log -vr500..600'.split())
1185.2.14 by Lalo Martins
fixing up users of RevisionSpec, and moving it over to commands.py
413
    (['log'], {'verbose': True, 'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
414
    >>> parse_args('log -rrevno:500..600'.split()) #the r takes an argument
415
    (['log'], {'revision': [<RevisionSpec_revno revno:500>, <RevisionSpec_int 600>]})
1 by mbp at sourcefrog
import from baz patch-364
416
    """
417
    args = []
418
    opts = {}
419
1144 by Martin Pool
- accept -- to terminate options
420
    argsover = False
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
421
    while argv:
422
        a = argv.pop(0)
1144 by Martin Pool
- accept -- to terminate options
423
        if not argsover and a[0] == '-':
264 by Martin Pool
parse_args: option names must be ascii
424
            # option names must not be unicode
425
            a = str(a)
17 by mbp at sourcefrog
allow --option=ARG syntax
426
            optarg = None
1 by mbp at sourcefrog
import from baz patch-364
427
            if a[1] == '-':
1144 by Martin Pool
- accept -- to terminate options
428
                if a == '--':
429
                    # We've received a standalone -- No more flags
430
                    argsover = True
431
                    continue
1 by mbp at sourcefrog
import from baz patch-364
432
                mutter("  got option %r" % a)
17 by mbp at sourcefrog
allow --option=ARG syntax
433
                if '=' in a:
434
                    optname, optarg = a[2:].split('=', 1)
435
                else:
436
                    optname = a[2:]
1 by mbp at sourcefrog
import from baz patch-364
437
                if optname not in OPTIONS:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
438
                    raise BzrError('unknown long option %r' % a)
1 by mbp at sourcefrog
import from baz patch-364
439
            else:
440
                shortopt = a[1:]
683 by Martin Pool
- short option stacking patch from John A Meinel
441
                if shortopt in SHORT_OPTIONS:
442
                    # Multi-character options must have a space to delimit
443
                    # their value
444
                    optname = SHORT_OPTIONS[shortopt]
445
                else:
446
                    # Single character short options, can be chained,
447
                    # and have their value appended to their name
448
                    shortopt = a[1:2]
449
                    if shortopt not in SHORT_OPTIONS:
450
                        # We didn't find the multi-character name, and we
451
                        # didn't find the single char name
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
452
                        raise BzrError('unknown short option %r' % a)
683 by Martin Pool
- short option stacking patch from John A Meinel
453
                    optname = SHORT_OPTIONS[shortopt]
454
455
                    if a[2:]:
456
                        # There are extra things on this option
457
                        # see if it is the value, or if it is another
458
                        # short option
459
                        optargfn = OPTIONS[optname]
460
                        if optargfn is None:
461
                            # This option does not take an argument, so the
462
                            # next entry is another short option, pack it back
463
                            # into the list
464
                            argv.insert(0, '-' + a[2:])
465
                        else:
466
                            # This option takes an argument, so pack it
467
                            # into the array
468
                            optarg = a[2:]
1 by mbp at sourcefrog
import from baz patch-364
469
            
470
            if optname in opts:
471
                # XXX: Do we ever want to support this, e.g. for -r?
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
472
                raise BzrError('repeated option %r' % a)
17 by mbp at sourcefrog
allow --option=ARG syntax
473
                
1 by mbp at sourcefrog
import from baz patch-364
474
            optargfn = OPTIONS[optname]
475
            if optargfn:
17 by mbp at sourcefrog
allow --option=ARG syntax
476
                if optarg == None:
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
477
                    if not argv:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
478
                        raise BzrError('option %r needs an argument' % a)
17 by mbp at sourcefrog
allow --option=ARG syntax
479
                    else:
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
480
                        optarg = argv.pop(0)
17 by mbp at sourcefrog
allow --option=ARG syntax
481
                opts[optname] = optargfn(optarg)
1 by mbp at sourcefrog
import from baz patch-364
482
            else:
17 by mbp at sourcefrog
allow --option=ARG syntax
483
                if optarg != None:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
484
                    raise BzrError('option %r takes no argument' % optname)
1 by mbp at sourcefrog
import from baz patch-364
485
                opts[optname] = True
486
        else:
487
            args.append(a)
488
489
    return args, opts
490
491
492
493
329 by Martin Pool
- refactor command functions into command classes
494
def _match_argform(cmd, takes_args, args):
1 by mbp at sourcefrog
import from baz patch-364
495
    argdict = {}
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
496
329 by Martin Pool
- refactor command functions into command classes
497
    # step through args and takes_args, allowing appropriate 0-many matches
498
    for ap in takes_args:
1 by mbp at sourcefrog
import from baz patch-364
499
        argname = ap[:-1]
500
        if ap[-1] == '?':
62 by mbp at sourcefrog
- new find_branch_root function; based on suggestion from aaron
501
            if args:
502
                argdict[argname] = args.pop(0)
196 by mbp at sourcefrog
selected-file diff
503
        elif ap[-1] == '*': # all remaining arguments
504
            if args:
505
                argdict[argname + '_list'] = args[:]
506
                args = []
507
            else:
508
                argdict[argname + '_list'] = None
1 by mbp at sourcefrog
import from baz patch-364
509
        elif ap[-1] == '+':
510
            if not args:
329 by Martin Pool
- refactor command functions into command classes
511
                raise BzrCommandError("command %r needs one or more %s"
1 by mbp at sourcefrog
import from baz patch-364
512
                        % (cmd, argname.upper()))
513
            else:
514
                argdict[argname + '_list'] = args[:]
515
                args = []
160 by mbp at sourcefrog
- basic support for moving files to different directories - have not done support for renaming them yet, but should be straightforward - some tests, but many cases are not handled yet i think
516
        elif ap[-1] == '$': # all but one
517
            if len(args) < 2:
329 by Martin Pool
- refactor command functions into command classes
518
                raise BzrCommandError("command %r needs one or more %s"
160 by mbp at sourcefrog
- basic support for moving files to different directories - have not done support for renaming them yet, but should be straightforward - some tests, but many cases are not handled yet i think
519
                        % (cmd, argname.upper()))
520
            argdict[argname + '_list'] = args[:-1]
521
            args[:-1] = []                
1 by mbp at sourcefrog
import from baz patch-364
522
        else:
523
            # just a plain arg
524
            argname = ap
525
            if not args:
329 by Martin Pool
- refactor command functions into command classes
526
                raise BzrCommandError("command %r requires argument %s"
1 by mbp at sourcefrog
import from baz patch-364
527
                        % (cmd, argname.upper()))
528
            else:
529
                argdict[argname] = args.pop(0)
530
            
531
    if args:
329 by Martin Pool
- refactor command functions into command classes
532
        raise BzrCommandError("extra argument to command %s: %s"
533
                              % (cmd, args[0]))
1 by mbp at sourcefrog
import from baz patch-364
534
535
    return argdict
536
537
538
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
539
def apply_profiled(the_callable, *args, **kwargs):
540
    import hotshot
541
    import tempfile
542
    pffileno, pfname = tempfile.mkstemp()
543
    try:
544
        prof = hotshot.Profile(pfname)
545
        try:
546
            ret = prof.runcall(the_callable, *args, **kwargs) or 0
547
        finally:
548
            prof.close()
549
550
        import hotshot.stats
551
        stats = hotshot.stats.load(pfname)
552
        #stats.strip_dirs()
553
        stats.sort_stats('time')
554
        ## XXX: Might like to write to stderr or the trace file instead but
555
        ## print_stats seems hardcoded to stdout
556
        stats.print_stats(20)
557
558
        return ret
559
    finally:
560
        os.close(pffileno)
561
        os.remove(pfname)
562
563
1 by mbp at sourcefrog
import from baz patch-364
564
def run_bzr(argv):
565
    """Execute a command.
566
567
    This is similar to main(), but without all the trappings for
245 by mbp at sourcefrog
- control files always in utf-8-unix format
568
    logging and error handling.  
973 by Martin Pool
- various refactorings of command interpreter
569
    
570
    argv
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
571
       The command-line arguments, without the program name from argv[0]
973 by Martin Pool
- various refactorings of command interpreter
572
    
573
    Returns a command status or raises an exception.
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
574
575
    Special master options: these must come before the command because
576
    they control how the command is interpreted.
577
578
    --no-plugins
579
        Do not load plugin modules at all
580
581
    --builtin
582
        Only use builtin commands.  (Plugins are still allowed to change
583
        other behaviour.)
584
585
    --profile
586
        Run under the Python profiler.
1 by mbp at sourcefrog
import from baz patch-364
587
    """
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
588
    
251 by mbp at sourcefrog
- factor out locale.getpreferredencoding()
589
    argv = [a.decode(bzrlib.user_encoding) for a in argv]
973 by Martin Pool
- various refactorings of command interpreter
590
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
591
    opt_profile = opt_no_plugins = opt_builtin = False
592
593
    # --no-plugins is handled specially at a very early stage. We need
594
    # to load plugins before doing other command parsing so that they
595
    # can override commands, but this needs to happen first.
596
1165 by Martin Pool
- move parsing of argv into arguments and options into Command.run_argv
597
    for a in argv:
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
598
        if a == '--profile':
599
            opt_profile = True
600
        elif a == '--no-plugins':
601
            opt_no_plugins = True
602
        elif a == '--builtin':
603
            opt_builtin = True
604
        else:
605
            break
606
        argv.remove(a)
607
1165 by Martin Pool
- move parsing of argv into arguments and options into Command.run_argv
608
    if (not argv) or (argv[0] == '--help'):
609
        from bzrlib.help import help
610
        if len(argv) > 1:
611
            help(argv[1])
612
        else:
613
            help()
614
        return 0
615
616
    if argv[0] == '--version':
617
        from bzrlib.builtins import show_version
618
        show_version()
619
        return 0
620
        
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
621
    if not opt_no_plugins:
973 by Martin Pool
- various refactorings of command interpreter
622
        from bzrlib.plugin import load_plugins
623
        load_plugins()
624
1165 by Martin Pool
- move parsing of argv into arguments and options into Command.run_argv
625
    cmd = str(argv.pop(0))
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
626
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
627
    cmd_obj = get_cmd_object(cmd, plugins_override=not opt_builtin)
1 by mbp at sourcefrog
import from baz patch-364
628
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
629
    if opt_profile:
1165 by Martin Pool
- move parsing of argv into arguments and options into Command.run_argv
630
        ret = apply_profiled(cmd_obj.run_argv, argv)
137 by mbp at sourcefrog
new --profile option
631
    else:
1165 by Martin Pool
- move parsing of argv into arguments and options into Command.run_argv
632
        ret = cmd_obj.run_argv(argv)
633
    return ret or 0
1 by mbp at sourcefrog
import from baz patch-364
634
635
636
def main(argv):
1104 by Martin Pool
- Add a simple UIFactory
637
    import bzrlib.ui
1111 by Martin Pool
- add functions to enable and disable default logging, so that we can
638
    bzrlib.trace.log_startup(argv)
1104 by Martin Pool
- Add a simple UIFactory
639
    bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory()
640
1185.3.20 by Martin Pool
- run_bzr_captured also includes logged errors in
641
    return run_bzr_catch_errors(argv[1:])
1185.3.19 by Martin Pool
- split out commandline error reporting for ease of testing
642
643
644
def run_bzr_catch_errors(argv):
1 by mbp at sourcefrog
import from baz patch-364
645
    try:
260 by Martin Pool
- remove atexit() dependency for writing out execution times
646
        try:
974.1.82 by Aaron Bentley
Handled NotBranchError like a CommandError in main()
647
            try:
1185.3.20 by Martin Pool
- run_bzr_captured also includes logged errors in
648
                return run_bzr(argv)
974.1.82 by Aaron Bentley
Handled NotBranchError like a CommandError in main()
649
            finally:
650
                # do this here inside the exception wrappers to catch EPIPE
651
                sys.stdout.flush()
652
        #wrap common errors as CommandErrors.
653
        except (NotBranchError,), e:
654
            raise BzrCommandError(str(e))
1097 by Martin Pool
- send trace messages out through python logging module
655
    except BzrCommandError, e:
656
        # command line syntax error, etc
657
        log_error(str(e))
658
        return 1
659
    except BzrError, e:
660
        bzrlib.trace.log_exception()
661
        return 1
662
    except AssertionError, e:
663
        bzrlib.trace.log_exception('assertion failed: ' + str(e))
664
        return 3
665
    except KeyboardInterrupt, e:
666
        bzrlib.trace.note('interrupted')
667
        return 2
668
    except Exception, e:
669
        import errno
670
        if (isinstance(e, IOError) 
671
            and hasattr(e, 'errno')
672
            and e.errno == errno.EPIPE):
673
            bzrlib.trace.note('broken pipe')
674
            return 2
675
        else:
1108 by Martin Pool
- more cleanups of error reporting
676
            bzrlib.trace.log_exception()
1097 by Martin Pool
- send trace messages out through python logging module
677
            return 2
1 by mbp at sourcefrog
import from baz patch-364
678
679
680
if __name__ == '__main__':
681
    sys.exit(main(sys.argv))