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