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