~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
275
    
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
276
    def run(self):
277
        """Actually run the command.
329 by Martin Pool
- refactor command functions into command classes
278
279
        This is invoked with the options and arguments bound to
280
        keyword parameters.
281
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
282
        Return 0 or None if the command was successful, or a non-zero
283
        shell error code if not.  It's OK for this method to allow
284
        an exception to raise up.
329 by Martin Pool
- refactor command functions into command classes
285
        """
1147 by Martin Pool
- split builtin commands into separate module bzrlib.builtins;
286
        raise NotImplementedError()
329 by Martin Pool
- refactor command functions into command classes
287
288
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
289
    def help(self):
290
        """Return help message for this class."""
291
        if self.__doc__ is Command.__doc__:
292
            return None
293
        return getdoc(self)
294
295
    def name(self):
296
        return _unsquish_command_name(self.__class__.__name__)
297
298
493 by Martin Pool
- Merge aaron's merge command
299
def parse_spec(spec):
622 by Martin Pool
Updated merge patch from Aaron
300
    """
301
    >>> parse_spec(None)
302
    [None, None]
303
    >>> parse_spec("./")
304
    ['./', None]
305
    >>> parse_spec("../@")
306
    ['..', -1]
307
    >>> parse_spec("../f/@35")
308
    ['../f', 35]
897 by Martin Pool
- merge john's revision-naming code
309
    >>> parse_spec('./@revid:john@arbash-meinel.com-20050711044610-3ca0327c6a222f67')
310
    ['.', 'revid:john@arbash-meinel.com-20050711044610-3ca0327c6a222f67']
622 by Martin Pool
Updated merge patch from Aaron
311
    """
312
    if spec is None:
313
        return [None, None]
493 by Martin Pool
- Merge aaron's merge command
314
    if '/@' in spec:
315
        parsed = spec.split('/@')
316
        assert len(parsed) == 2
317
        if parsed[1] == "":
318
            parsed[1] = -1
319
        else:
897 by Martin Pool
- merge john's revision-naming code
320
            try:
321
                parsed[1] = int(parsed[1])
322
            except ValueError:
323
                pass # We can allow stuff like ./@revid:blahblahblah
324
            else:
325
                assert parsed[1] >=0
493 by Martin Pool
- Merge aaron's merge command
326
    else:
327
        parsed = [spec, None]
328
    return parsed
329
628 by Martin Pool
- merge aaron's updated merge/pull code
330
331
755 by Martin Pool
- new 'plugins' command
332
1 by mbp at sourcefrog
import from baz patch-364
333
# list of all available options; the rhs can be either None for an
334
# option that takes no argument, or a constructor function that checks
335
# the type.
336
OPTIONS = {
337
    'all':                    None,
571 by Martin Pool
- new --diff-options to pass options through to external
338
    'diff-options':           str,
1 by mbp at sourcefrog
import from baz patch-364
339
    'help':                   None,
389 by Martin Pool
- new commit --file option!
340
    'file':                   unicode,
628 by Martin Pool
- merge aaron's updated merge/pull code
341
    'force':                  None,
678 by Martin Pool
- export to tarballs
342
    'format':                 unicode,
545 by Martin Pool
- --forward option for log
343
    'forward':                None,
1 by mbp at sourcefrog
import from baz patch-364
344
    'message':                unicode,
594 by Martin Pool
- add --no-recurse option for add command
345
    'no-recurse':             None,
137 by mbp at sourcefrog
new --profile option
346
    'profile':                None,
567 by Martin Pool
- New form 'bzr log -r FROM:TO'
347
    'revision':               _parse_revision_str,
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
348
    'short':                  None,
1 by mbp at sourcefrog
import from baz patch-364
349
    'show-ids':               None,
12 by mbp at sourcefrog
new --timezone option for bzr log
350
    'timezone':               str,
1 by mbp at sourcefrog
import from baz patch-364
351
    'verbose':                None,
352
    'version':                None,
286 by Martin Pool
- New bzr whoami --email option
353
    'email':                  None,
885 by Martin Pool
- commit command refuses unless something is changed or --unchanged is given
354
    'unchanged':              None,
674 by Martin Pool
- check command now also checks new inventory_sha1 and
355
    'update':                 None,
807 by Martin Pool
- New log --long option
356
    'long':                   None,
849 by Martin Pool
- Put files inside an exported tarball into a top-level directory rather than
357
    'root':                   str,
974.1.8 by Aaron Bentley
Added default backups for merge-revert
358
    'no-backup':              None,
974.1.9 by Aaron Bentley
Added merge-type parameter to merge.
359
    'merge-type':             get_merge_type,
1092.1.20 by Robert Collins
import and use TestUtil to do regex based partial test runs
360
    'pattern':                str,
1 by mbp at sourcefrog
import from baz patch-364
361
    }
362
363
SHORT_OPTIONS = {
583 by Martin Pool
- add -h as short name for --help
364
    'F':                      'file', 
365
    'h':                      'help',
1 by mbp at sourcefrog
import from baz patch-364
366
    'm':                      'message',
367
    'r':                      'revision',
368
    'v':                      'verbose',
807 by Martin Pool
- New log --long option
369
    'l':                      'long',
1 by mbp at sourcefrog
import from baz patch-364
370
}
371
372
373
def parse_args(argv):
374
    """Parse command line.
375
    
376
    Arguments and options are parsed at this level before being passed
377
    down to specific command handlers.  This routine knows, from a
378
    lookup table, something about the available options, what optargs
379
    they take, and which commands will accept them.
380
31 by Martin Pool
fix up parse_args doctest
381
    >>> parse_args('--help'.split())
1 by mbp at sourcefrog
import from baz patch-364
382
    ([], {'help': True})
1144 by Martin Pool
- accept -- to terminate options
383
    >>> parse_args('help -- --invalidcmd'.split())
384
    (['help', '--invalidcmd'], {})
31 by Martin Pool
fix up parse_args doctest
385
    >>> parse_args('--version'.split())
1 by mbp at sourcefrog
import from baz patch-364
386
    ([], {'version': True})
31 by Martin Pool
fix up parse_args doctest
387
    >>> parse_args('status --all'.split())
1 by mbp at sourcefrog
import from baz patch-364
388
    (['status'], {'all': True})
31 by Martin Pool
fix up parse_args doctest
389
    >>> parse_args('commit --message=biter'.split())
17 by mbp at sourcefrog
allow --option=ARG syntax
390
    (['commit'], {'message': u'biter'})
683 by Martin Pool
- short option stacking patch from John A Meinel
391
    >>> parse_args('log -r 500'.split())
897 by Martin Pool
- merge john's revision-naming code
392
    (['log'], {'revision': [500]})
393
    >>> parse_args('log -r500..600'.split())
683 by Martin Pool
- short option stacking patch from John A Meinel
394
    (['log'], {'revision': [500, 600]})
897 by Martin Pool
- merge john's revision-naming code
395
    >>> parse_args('log -vr500..600'.split())
683 by Martin Pool
- short option stacking patch from John A Meinel
396
    (['log'], {'verbose': True, 'revision': [500, 600]})
897 by Martin Pool
- merge john's revision-naming code
397
    >>> parse_args('log -rv500..600'.split()) #the r takes an argument
398
    (['log'], {'revision': ['v500', 600]})
1 by mbp at sourcefrog
import from baz patch-364
399
    """
400
    args = []
401
    opts = {}
402
1144 by Martin Pool
- accept -- to terminate options
403
    argsover = False
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
404
    while argv:
405
        a = argv.pop(0)
1144 by Martin Pool
- accept -- to terminate options
406
        if not argsover and a[0] == '-':
264 by Martin Pool
parse_args: option names must be ascii
407
            # option names must not be unicode
408
            a = str(a)
17 by mbp at sourcefrog
allow --option=ARG syntax
409
            optarg = None
1 by mbp at sourcefrog
import from baz patch-364
410
            if a[1] == '-':
1144 by Martin Pool
- accept -- to terminate options
411
                if a == '--':
412
                    # We've received a standalone -- No more flags
413
                    argsover = True
414
                    continue
1 by mbp at sourcefrog
import from baz patch-364
415
                mutter("  got option %r" % a)
17 by mbp at sourcefrog
allow --option=ARG syntax
416
                if '=' in a:
417
                    optname, optarg = a[2:].split('=', 1)
418
                else:
419
                    optname = a[2:]
1 by mbp at sourcefrog
import from baz patch-364
420
                if optname not in OPTIONS:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
421
                    raise BzrError('unknown long option %r' % a)
1 by mbp at sourcefrog
import from baz patch-364
422
            else:
423
                shortopt = a[1:]
683 by Martin Pool
- short option stacking patch from John A Meinel
424
                if shortopt in SHORT_OPTIONS:
425
                    # Multi-character options must have a space to delimit
426
                    # their value
427
                    optname = SHORT_OPTIONS[shortopt]
428
                else:
429
                    # Single character short options, can be chained,
430
                    # and have their value appended to their name
431
                    shortopt = a[1:2]
432
                    if shortopt not in SHORT_OPTIONS:
433
                        # We didn't find the multi-character name, and we
434
                        # didn't find the single char name
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
435
                        raise BzrError('unknown short option %r' % a)
683 by Martin Pool
- short option stacking patch from John A Meinel
436
                    optname = SHORT_OPTIONS[shortopt]
437
438
                    if a[2:]:
439
                        # There are extra things on this option
440
                        # see if it is the value, or if it is another
441
                        # short option
442
                        optargfn = OPTIONS[optname]
443
                        if optargfn is None:
444
                            # This option does not take an argument, so the
445
                            # next entry is another short option, pack it back
446
                            # into the list
447
                            argv.insert(0, '-' + a[2:])
448
                        else:
449
                            # This option takes an argument, so pack it
450
                            # into the array
451
                            optarg = a[2:]
1 by mbp at sourcefrog
import from baz patch-364
452
            
453
            if optname in opts:
454
                # 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
455
                raise BzrError('repeated option %r' % a)
17 by mbp at sourcefrog
allow --option=ARG syntax
456
                
1 by mbp at sourcefrog
import from baz patch-364
457
            optargfn = OPTIONS[optname]
458
            if optargfn:
17 by mbp at sourcefrog
allow --option=ARG syntax
459
                if optarg == None:
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
460
                    if not argv:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
461
                        raise BzrError('option %r needs an argument' % a)
17 by mbp at sourcefrog
allow --option=ARG syntax
462
                    else:
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
463
                        optarg = argv.pop(0)
17 by mbp at sourcefrog
allow --option=ARG syntax
464
                opts[optname] = optargfn(optarg)
1 by mbp at sourcefrog
import from baz patch-364
465
            else:
17 by mbp at sourcefrog
allow --option=ARG syntax
466
                if optarg != None:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
467
                    raise BzrError('option %r takes no argument' % optname)
1 by mbp at sourcefrog
import from baz patch-364
468
                opts[optname] = True
469
        else:
470
            args.append(a)
471
472
    return args, opts
473
474
475
476
329 by Martin Pool
- refactor command functions into command classes
477
def _match_argform(cmd, takes_args, args):
1 by mbp at sourcefrog
import from baz patch-364
478
    argdict = {}
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
479
329 by Martin Pool
- refactor command functions into command classes
480
    # step through args and takes_args, allowing appropriate 0-many matches
481
    for ap in takes_args:
1 by mbp at sourcefrog
import from baz patch-364
482
        argname = ap[:-1]
483
        if ap[-1] == '?':
62 by mbp at sourcefrog
- new find_branch_root function; based on suggestion from aaron
484
            if args:
485
                argdict[argname] = args.pop(0)
196 by mbp at sourcefrog
selected-file diff
486
        elif ap[-1] == '*': # all remaining arguments
487
            if args:
488
                argdict[argname + '_list'] = args[:]
489
                args = []
490
            else:
491
                argdict[argname + '_list'] = None
1 by mbp at sourcefrog
import from baz patch-364
492
        elif ap[-1] == '+':
493
            if not args:
329 by Martin Pool
- refactor command functions into command classes
494
                raise BzrCommandError("command %r needs one or more %s"
1 by mbp at sourcefrog
import from baz patch-364
495
                        % (cmd, argname.upper()))
496
            else:
497
                argdict[argname + '_list'] = args[:]
498
                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
499
        elif ap[-1] == '$': # all but one
500
            if len(args) < 2:
329 by Martin Pool
- refactor command functions into command classes
501
                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
502
                        % (cmd, argname.upper()))
503
            argdict[argname + '_list'] = args[:-1]
504
            args[:-1] = []                
1 by mbp at sourcefrog
import from baz patch-364
505
        else:
506
            # just a plain arg
507
            argname = ap
508
            if not args:
329 by Martin Pool
- refactor command functions into command classes
509
                raise BzrCommandError("command %r requires argument %s"
1 by mbp at sourcefrog
import from baz patch-364
510
                        % (cmd, argname.upper()))
511
            else:
512
                argdict[argname] = args.pop(0)
513
            
514
    if args:
329 by Martin Pool
- refactor command functions into command classes
515
        raise BzrCommandError("extra argument to command %s: %s"
516
                              % (cmd, args[0]))
1 by mbp at sourcefrog
import from baz patch-364
517
518
    return argdict
519
520
521
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
522
def apply_profiled(the_callable, *args, **kwargs):
523
    import hotshot
524
    import tempfile
525
    pffileno, pfname = tempfile.mkstemp()
526
    try:
527
        prof = hotshot.Profile(pfname)
528
        try:
529
            ret = prof.runcall(the_callable, *args, **kwargs) or 0
530
        finally:
531
            prof.close()
532
533
        import hotshot.stats
534
        stats = hotshot.stats.load(pfname)
535
        #stats.strip_dirs()
536
        stats.sort_stats('time')
537
        ## XXX: Might like to write to stderr or the trace file instead but
538
        ## print_stats seems hardcoded to stdout
539
        stats.print_stats(20)
540
541
        return ret
542
    finally:
543
        os.close(pffileno)
544
        os.remove(pfname)
545
546
1 by mbp at sourcefrog
import from baz patch-364
547
def run_bzr(argv):
548
    """Execute a command.
549
550
    This is similar to main(), but without all the trappings for
245 by mbp at sourcefrog
- control files always in utf-8-unix format
551
    logging and error handling.  
973 by Martin Pool
- various refactorings of command interpreter
552
    
553
    argv
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
554
       The command-line arguments, without the program name from argv[0]
973 by Martin Pool
- various refactorings of command interpreter
555
    
556
    Returns a command status or raises an exception.
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
557
558
    Special master options: these must come before the command because
559
    they control how the command is interpreted.
560
561
    --no-plugins
562
        Do not load plugin modules at all
563
564
    --builtin
565
        Only use builtin commands.  (Plugins are still allowed to change
566
        other behaviour.)
567
568
    --profile
569
        Run under the Python profiler.
1 by mbp at sourcefrog
import from baz patch-364
570
    """
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
571
    
251 by mbp at sourcefrog
- factor out locale.getpreferredencoding()
572
    argv = [a.decode(bzrlib.user_encoding) for a in argv]
973 by Martin Pool
- various refactorings of command interpreter
573
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
574
    opt_profile = opt_no_plugins = opt_builtin = False
575
576
    # --no-plugins is handled specially at a very early stage. We need
577
    # to load plugins before doing other command parsing so that they
578
    # can override commands, but this needs to happen first.
579
580
    for a in argv[:]:
581
        if a == '--profile':
582
            opt_profile = True
583
        elif a == '--no-plugins':
584
            opt_no_plugins = True
585
        elif a == '--builtin':
586
            opt_builtin = True
587
        else:
588
            break
589
        argv.remove(a)
590
591
    if not opt_no_plugins:
973 by Martin Pool
- various refactorings of command interpreter
592
        from bzrlib.plugin import load_plugins
593
        load_plugins()
594
595
    args, opts = parse_args(argv)
596
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
597
    if 'help' in opts:
973 by Martin Pool
- various refactorings of command interpreter
598
        from bzrlib.help import help
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
599
        if args:
600
            help(args[0])
973 by Martin Pool
- various refactorings of command interpreter
601
        else:
602
            help()
603
        return 0            
604
        
605
    if 'version' in opts:
1147 by Martin Pool
- split builtin commands into separate module bzrlib.builtins;
606
        from bzrlib.builtins import show_version
973 by Martin Pool
- various refactorings of command interpreter
607
        show_version()
608
        return 0
609
    
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
610
    if not args:
1099 by Martin Pool
- 'bzr' with no arguments shows the summary help.
611
        from bzrlib.help import help
612
        help(None)
613
        return 0
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
614
    
615
    cmd = str(args.pop(0))
616
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
617
    cmd_obj = get_cmd_object(cmd, plugins_override=not opt_builtin)
1 by mbp at sourcefrog
import from baz patch-364
618
619
    # check options are reasonable
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
620
    allowed = cmd_obj.takes_options
1 by mbp at sourcefrog
import from baz patch-364
621
    for oname in opts:
622
        if oname not in allowed:
381 by Martin Pool
- Better message when a wrong argument is given
623
            raise BzrCommandError("option '--%s' is not allowed for command %r"
329 by Martin Pool
- refactor command functions into command classes
624
                                  % (oname, cmd))
176 by mbp at sourcefrog
New cat command contributed by janmar.
625
137 by mbp at sourcefrog
new --profile option
626
    # mix arguments and options into one dictionary
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
627
    cmdargs = _match_argform(cmd, cmd_obj.takes_args, args)
329 by Martin Pool
- refactor command functions into command classes
628
    cmdopts = {}
136 by mbp at sourcefrog
new --show-ids option for 'deleted' command
629
    for k, v in opts.items():
329 by Martin Pool
- refactor command functions into command classes
630
        cmdopts[k.replace('-', '_')] = v
1 by mbp at sourcefrog
import from baz patch-364
631
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
632
    all_cmd_args = cmdargs.copy()
633
    all_cmd_args.update(cmdopts)
634
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
635
    if opt_profile:
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
636
        ret = apply_profiled(cmd_obj.run, **all_cmd_args)
137 by mbp at sourcefrog
new --profile option
637
    else:
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
638
        ret = cmd_obj.run(**all_cmd_args)
639
640
    if ret is None:
641
        ret = 0
642
    return ret
1 by mbp at sourcefrog
import from baz patch-364
643
644
645
def main(argv):
1104 by Martin Pool
- Add a simple UIFactory
646
    import bzrlib.ui
1111 by Martin Pool
- add functions to enable and disable default logging, so that we can
647
    bzrlib.trace.log_startup(argv)
1104 by Martin Pool
- Add a simple UIFactory
648
    bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory()
649
1 by mbp at sourcefrog
import from baz patch-364
650
    try:
260 by Martin Pool
- remove atexit() dependency for writing out execution times
651
        try:
1097 by Martin Pool
- send trace messages out through python logging module
652
            return run_bzr(argv[1:])
653
        finally:
654
            # do this here inside the exception wrappers to catch EPIPE
655
            sys.stdout.flush()
656
    except BzrCommandError, e:
657
        # command line syntax error, etc
658
        log_error(str(e))
659
        return 1
660
    except BzrError, e:
661
        bzrlib.trace.log_exception()
662
        return 1
663
    except AssertionError, e:
664
        bzrlib.trace.log_exception('assertion failed: ' + str(e))
665
        return 3
666
    except KeyboardInterrupt, e:
667
        bzrlib.trace.note('interrupted')
668
        return 2
669
    except Exception, e:
670
        import errno
671
        if (isinstance(e, IOError) 
672
            and hasattr(e, 'errno')
673
            and e.errno == errno.EPIPE):
674
            bzrlib.trace.note('broken pipe')
675
            return 2
676
        else:
1108 by Martin Pool
- more cleanups of error reporting
677
            bzrlib.trace.log_exception()
1097 by Martin Pool
- send trace messages out through python logging module
678
            return 2
1 by mbp at sourcefrog
import from baz patch-364
679
680
681
if __name__ == '__main__':
682
    sys.exit(main(sys.argv))