~bzr-pqm/bzr/bzr.dev

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