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