~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
1393.1.27 by Martin Pool
- clean up profile code and change default sort order
27
# TODO: "--profile=cum", to change sort order.  Is there any value in leaving
28
# the profile output behind so it can be interactively examined?
29
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
30
import sys
31
import os
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
32
from warnings import warn
33
from inspect import getdoc
1185.12.56 by Aaron Bentley
Prevented display commands from printing broken pipe errors
34
import errno
1 by mbp at sourcefrog
import from baz patch-364
35
36
import bzrlib
1112 by Martin Pool
- disable standard logging to .bzr.log and stderr while running
37
import bzrlib.trace
1185.33.42 by Martin Pool
[patch] make --quiet a global option (robey)
38
from bzrlib.trace import mutter, note, log_error, warning, be_quiet
1495 by Robert Collins
Add a --create-prefix to the new push command.
39
from bzrlib.errors import (BzrError, 
40
                           BzrCheckError,
41
                           BzrCommandError,
42
                           BzrOptionError,
1534.7.154 by Aaron Bentley
Removed changes from bzr.ab 1529..1536
43
                           NotBranchError)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
44
from bzrlib.revisionspec import RevisionSpec
1185.16.41 by Martin Pool
[patch] define cli options as objects, not strings
45
from bzrlib.option import Option
1 by mbp at sourcefrog
import from baz patch-364
46
731 by Martin Pool
- merge plugin patch from john
47
plugin_cmds = {}
48
49
1492 by Robert Collins
Support decoration of commands.
50
def register_command(cmd, decorate=False):
731 by Martin Pool
- merge plugin patch from john
51
    "Utility function to help register a command"
52
    global plugin_cmds
53
    k = cmd.__name__
54
    if k.startswith("cmd_"):
55
        k_unsquished = _unsquish_command_name(k)
56
    else:
57
        k_unsquished = k
58
    if not plugin_cmds.has_key(k_unsquished):
59
        plugin_cmds[k_unsquished] = cmd
1137 by Martin Pool
- additional trace messages for plugins
60
        mutter('registered plugin command %s', k_unsquished)      
1492 by Robert Collins
Support decoration of commands.
61
        if decorate and k_unsquished in builtin_command_names():
62
            return _builtin_commands()[k_unsquished]
63
    elif decorate:
64
        result = plugin_cmds[k_unsquished]
65
        plugin_cmds[k_unsquished] = cmd
66
        return result
731 by Martin Pool
- merge plugin patch from john
67
    else:
68
        log_error('Two plugins defined the same command: %r' % k)
69
        log_error('Not loading the one in %r' % sys.modules[cmd.__module__])
70
71
350 by Martin Pool
- refactor command aliases into command classes
72
def _squish_command_name(cmd):
73
    return 'cmd_' + cmd.replace('-', '_')
74
75
76
def _unsquish_command_name(cmd):
77
    assert cmd.startswith("cmd_")
78
    return cmd[4:].replace('_','-')
79
914 by Martin Pool
- fix up breakage of 'bzr log -v' by root_id patch
80
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
81
def _builtin_commands():
1147 by Martin Pool
- split builtin commands into separate module bzrlib.builtins;
82
    import bzrlib.builtins
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
83
    r = {}
1147 by Martin Pool
- split builtin commands into separate module bzrlib.builtins;
84
    builtins = bzrlib.builtins.__dict__
85
    for name in builtins:
86
        if name.startswith("cmd_"):
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
87
            real_name = _unsquish_command_name(name)        
88
            r[real_name] = builtins[name]
89
    return r
90
91
            
92
93
def builtin_command_names():
94
    """Return list of builtin command names."""
95
    return _builtin_commands().keys()
96
    
97
98
def plugin_command_names():
99
    return plugin_cmds.keys()
100
101
102
def _get_cmd_dict(plugins_override=True):
103
    """Return name->class mapping for all commands."""
104
    d = _builtin_commands()
731 by Martin Pool
- merge plugin patch from john
105
    if plugins_override:
106
        d.update(plugin_cmds)
641 by Martin Pool
- improved external-command patch from john
107
    return d
731 by Martin Pool
- merge plugin patch from john
108
641 by Martin Pool
- improved external-command patch from john
109
    
731 by Martin Pool
- merge plugin patch from john
110
def get_all_cmds(plugins_override=True):
641 by Martin Pool
- improved external-command patch from john
111
    """Return canonical name and class for all registered commands."""
731 by Martin Pool
- merge plugin patch from john
112
    for k, v in _get_cmd_dict(plugins_override=plugins_override).iteritems():
641 by Martin Pool
- improved external-command patch from john
113
        yield k,v
114
115
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
116
def get_cmd_object(cmd_name, plugins_override=True):
350 by Martin Pool
- refactor command aliases into command classes
117
    """Return the canonical name and command class for a command.
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
118
119
    plugins_override
120
        If true, plugin commands can override builtins.
350 by Martin Pool
- refactor command aliases into command classes
121
    """
1163 by Martin Pool
- split ExternalCommand class into its own file
122
    from bzrlib.externalcommand import ExternalCommand
123
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
124
    cmd_name = str(cmd_name)            # not unicode
350 by Martin Pool
- refactor command aliases into command classes
125
126
    # first look up this command under the specified name
731 by Martin Pool
- merge plugin patch from john
127
    cmds = _get_cmd_dict(plugins_override=plugins_override)
272 by Martin Pool
- Add command aliases
128
    try:
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
129
        return cmds[cmd_name]()
272 by Martin Pool
- Add command aliases
130
    except KeyError:
350 by Martin Pool
- refactor command aliases into command classes
131
        pass
132
133
    # look for any command which claims this as an alias
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
134
    for real_cmd_name, cmd_class in cmds.iteritems():
135
        if cmd_name in cmd_class.aliases:
136
            return cmd_class()
137
138
    cmd_obj = ExternalCommand.find_command(cmd_name)
139
    if cmd_obj:
140
        return cmd_obj
141
142
    raise BzrCommandError("unknown command %r" % cmd_name)
272 by Martin Pool
- Add command aliases
143
329 by Martin Pool
- refactor command functions into command classes
144
558 by Martin Pool
- All top-level classes inherit from object
145
class Command(object):
329 by Martin Pool
- refactor command functions into command classes
146
    """Base class for commands.
147
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
148
    Commands are the heart of the command-line bzr interface.
149
150
    The command object mostly handles the mapping of command-line
151
    parameters into one or more bzrlib operations, and of the results
152
    into textual output.
153
154
    Commands normally don't have any state.  All their arguments are
155
    passed in to the run method.  (Subclasses may take a different
156
    policy if the behaviour of the instance needs to depend on e.g. a
157
    shell plugin and not just its Python class.)
158
329 by Martin Pool
- refactor command functions into command classes
159
    The docstring for an actual command should give a single-line
160
    summary, then a complete description of the command.  A grammar
161
    description will be inserted.
162
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
163
    aliases
164
        Other accepted names for this command.
165
329 by Martin Pool
- refactor command functions into command classes
166
    takes_args
167
        List of argument forms, marked with whether they are optional,
168
        repeated, etc.
169
1534.4.25 by Robert Collins
Add a --transport parameter to the test suite to set the default transport to be used in the test suite.
170
                Examples:
171
172
                ['to_location', 'from_branch?', 'file*']
173
174
                'to_location' is required
175
                'from_branch' is optional
176
                'file' can be specified 0 or more times
1185.37.4 by Jamie Wilkinson
add some examples to the documentation for Command.takes_args
177
329 by Martin Pool
- refactor command functions into command classes
178
    takes_options
1185.16.43 by Martin Pool
- clean up handling of option objects
179
        List of options that may be given for this command.  These can
180
        be either strings, referring to globally-defined options,
181
        or option objects.  Retrieve through options().
329 by Martin Pool
- refactor command functions into command classes
182
183
    hidden
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
184
        If true, this command isn't advertised.  This is typically
185
        for commands intended for expert users.
329 by Martin Pool
- refactor command functions into command classes
186
    """
187
    aliases = []
188
    takes_args = []
189
    takes_options = []
190
191
    hidden = False
192
    
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
193
    def __init__(self):
194
        """Construct an instance of this command."""
973 by Martin Pool
- various refactorings of command interpreter
195
        if self.__doc__ == Command.__doc__:
196
            warn("No help message set for %r" % self)
329 by Martin Pool
- refactor command functions into command classes
197
1185.16.43 by Martin Pool
- clean up handling of option objects
198
    def options(self):
199
        """Return dict of valid options for this command.
200
201
        Maps from long option name to option object."""
202
        r = dict()
1185.16.48 by mbp at sourcefrog
- more refactoring of and tests for option parsing
203
        r['help'] = Option.OPTIONS['help']
1185.16.43 by Martin Pool
- clean up handling of option objects
204
        for o in self.takes_options:
205
            if not isinstance(o, Option):
206
                o = Option.OPTIONS[o]
207
            r[o.name] = o
208
        return r
1165 by Martin Pool
- move parsing of argv into arguments and options into Command.run_argv
209
1534.7.154 by Aaron Bentley
Removed changes from bzr.ab 1529..1536
210
    def run_argv(self, argv):
1165 by Martin Pool
- move parsing of argv into arguments and options into Command.run_argv
211
        """Parse command line and run."""
1534.7.154 by Aaron Bentley
Removed changes from bzr.ab 1529..1536
212
        args, opts = parse_args(self, argv)
1165 by Martin Pool
- move parsing of argv into arguments and options into Command.run_argv
213
        if 'help' in opts:  # e.g. bzr add --help
214
            from bzrlib.help import help_on_command
215
            help_on_command(self.name())
216
            return 0
1185.16.48 by mbp at sourcefrog
- more refactoring of and tests for option parsing
217
        # XXX: This should be handled by the parser
1185.16.43 by Martin Pool
- clean up handling of option objects
218
        allowed_names = self.options().keys()
1165 by Martin Pool
- move parsing of argv into arguments and options into Command.run_argv
219
        for oname in opts:
1185.16.43 by Martin Pool
- clean up handling of option objects
220
            if oname not in allowed_names:
1165 by Martin Pool
- move parsing of argv into arguments and options into Command.run_argv
221
                raise BzrCommandError("option '--%s' is not allowed for command %r"
222
                                      % (oname, self.name()))
223
        # mix arguments and options into one dictionary
224
        cmdargs = _match_argform(self.name(), self.takes_args, args)
225
        cmdopts = {}
226
        for k, v in opts.items():
227
            cmdopts[k.replace('-', '_')] = v
228
229
        all_cmd_args = cmdargs.copy()
230
        all_cmd_args.update(cmdopts)
231
232
        return self.run(**all_cmd_args)
329 by Martin Pool
- refactor command functions into command classes
233
    
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
234
    def run(self):
235
        """Actually run the command.
329 by Martin Pool
- refactor command functions into command classes
236
237
        This is invoked with the options and arguments bound to
238
        keyword parameters.
239
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
240
        Return 0 or None if the command was successful, or a non-zero
241
        shell error code if not.  It's OK for this method to allow
242
        an exception to raise up.
329 by Martin Pool
- refactor command functions into command classes
243
        """
1147 by Martin Pool
- split builtin commands into separate module bzrlib.builtins;
244
        raise NotImplementedError()
329 by Martin Pool
- refactor command functions into command classes
245
246
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
247
    def help(self):
248
        """Return help message for this class."""
249
        if self.__doc__ is Command.__doc__:
250
            return None
251
        return getdoc(self)
252
253
    def name(self):
254
        return _unsquish_command_name(self.__class__.__name__)
255
256
493 by Martin Pool
- Merge aaron's merge command
257
def parse_spec(spec):
622 by Martin Pool
Updated merge patch from Aaron
258
    """
259
    >>> parse_spec(None)
260
    [None, None]
261
    >>> parse_spec("./")
262
    ['./', None]
263
    >>> parse_spec("../@")
264
    ['..', -1]
265
    >>> parse_spec("../f/@35")
266
    ['../f', 35]
897 by Martin Pool
- merge john's revision-naming code
267
    >>> parse_spec('./@revid:john@arbash-meinel.com-20050711044610-3ca0327c6a222f67')
268
    ['.', 'revid:john@arbash-meinel.com-20050711044610-3ca0327c6a222f67']
622 by Martin Pool
Updated merge patch from Aaron
269
    """
270
    if spec is None:
271
        return [None, None]
493 by Martin Pool
- Merge aaron's merge command
272
    if '/@' in spec:
273
        parsed = spec.split('/@')
274
        assert len(parsed) == 2
275
        if parsed[1] == "":
276
            parsed[1] = -1
277
        else:
897 by Martin Pool
- merge john's revision-naming code
278
            try:
279
                parsed[1] = int(parsed[1])
280
            except ValueError:
281
                pass # We can allow stuff like ./@revid:blahblahblah
282
            else:
283
                assert parsed[1] >=0
493 by Martin Pool
- Merge aaron's merge command
284
    else:
285
        parsed = [spec, None]
286
    return parsed
287
1185.16.48 by mbp at sourcefrog
- more refactoring of and tests for option parsing
288
def parse_args(command, argv):
1 by mbp at sourcefrog
import from baz patch-364
289
    """Parse command line.
290
    
291
    Arguments and options are parsed at this level before being passed
292
    down to specific command handlers.  This routine knows, from a
293
    lookup table, something about the available options, what optargs
294
    they take, and which commands will accept them.
295
    """
1185.16.49 by mbp at sourcefrog
- more refactoring and tests of commandline
296
    # TODO: chop up this beast; make it a method of the Command
1 by mbp at sourcefrog
import from baz patch-364
297
    args = []
298
    opts = {}
299
1185.16.48 by mbp at sourcefrog
- more refactoring of and tests for option parsing
300
    cmd_options = command.options()
1144 by Martin Pool
- accept -- to terminate options
301
    argsover = False
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
302
    while argv:
303
        a = argv.pop(0)
1185.16.49 by mbp at sourcefrog
- more refactoring and tests of commandline
304
        if argsover:
305
            args.append(a)
306
            continue
307
        elif a == '--':
308
            # We've received a standalone -- No more flags
309
            argsover = True
310
            continue
311
        if a[0] == '-':
264 by Martin Pool
parse_args: option names must be ascii
312
            # option names must not be unicode
313
            a = str(a)
17 by mbp at sourcefrog
allow --option=ARG syntax
314
            optarg = None
1 by mbp at sourcefrog
import from baz patch-364
315
            if a[1] == '-':
1185.31.4 by John Arbash Meinel
Fixing mutter() calls to not have to do string processing.
316
                mutter("  got option %r", a)
17 by mbp at sourcefrog
allow --option=ARG syntax
317
                if '=' in a:
318
                    optname, optarg = a[2:].split('=', 1)
319
                else:
320
                    optname = a[2:]
1185.16.48 by mbp at sourcefrog
- more refactoring of and tests for option parsing
321
                if optname not in cmd_options:
1495 by Robert Collins
Add a --create-prefix to the new push command.
322
                    raise BzrOptionError('unknown long option %r for command %s'
323
                        % (a, command.name()))
1 by mbp at sourcefrog
import from baz patch-364
324
            else:
325
                shortopt = a[1:]
1185.16.41 by Martin Pool
[patch] define cli options as objects, not strings
326
                if shortopt in Option.SHORT_OPTIONS:
683 by Martin Pool
- short option stacking patch from John A Meinel
327
                    # Multi-character options must have a space to delimit
328
                    # their value
1185.16.44 by Martin Pool
doc
329
                    # ^^^ what does this mean? mbp 20051014
1185.16.41 by Martin Pool
[patch] define cli options as objects, not strings
330
                    optname = Option.SHORT_OPTIONS[shortopt].name
683 by Martin Pool
- short option stacking patch from John A Meinel
331
                else:
332
                    # Single character short options, can be chained,
333
                    # and have their value appended to their name
334
                    shortopt = a[1:2]
1185.16.41 by Martin Pool
[patch] define cli options as objects, not strings
335
                    if shortopt not in Option.SHORT_OPTIONS:
683 by Martin Pool
- short option stacking patch from John A Meinel
336
                        # We didn't find the multi-character name, and we
337
                        # didn't find the single char name
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
338
                        raise BzrError('unknown short option %r' % a)
1185.16.41 by Martin Pool
[patch] define cli options as objects, not strings
339
                    optname = Option.SHORT_OPTIONS[shortopt].name
683 by Martin Pool
- short option stacking patch from John A Meinel
340
341
                    if a[2:]:
342
                        # There are extra things on this option
343
                        # see if it is the value, or if it is another
344
                        # short option
1185.16.41 by Martin Pool
[patch] define cli options as objects, not strings
345
                        optargfn = Option.OPTIONS[optname].type
683 by Martin Pool
- short option stacking patch from John A Meinel
346
                        if optargfn is None:
347
                            # This option does not take an argument, so the
348
                            # next entry is another short option, pack it back
349
                            # into the list
350
                            argv.insert(0, '-' + a[2:])
351
                        else:
352
                            # This option takes an argument, so pack it
353
                            # into the array
354
                            optarg = a[2:]
1 by mbp at sourcefrog
import from baz patch-364
355
            
1185.35.24 by Aaron Bentley
Fixed handling of short options not accepted by the command
356
                if optname not in cmd_options:
357
                    raise BzrOptionError('unknown short option %r for command'
358
                        ' %s' % (shortopt, command.name()))
1 by mbp at sourcefrog
import from baz patch-364
359
            if optname in opts:
360
                # 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
361
                raise BzrError('repeated option %r' % a)
17 by mbp at sourcefrog
allow --option=ARG syntax
362
                
1185.16.48 by mbp at sourcefrog
- more refactoring of and tests for option parsing
363
            option_obj = cmd_options[optname]
364
            optargfn = option_obj.type
1 by mbp at sourcefrog
import from baz patch-364
365
            if optargfn:
17 by mbp at sourcefrog
allow --option=ARG syntax
366
                if optarg == None:
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
367
                    if not argv:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
368
                        raise BzrError('option %r needs an argument' % a)
17 by mbp at sourcefrog
allow --option=ARG syntax
369
                    else:
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
370
                        optarg = argv.pop(0)
17 by mbp at sourcefrog
allow --option=ARG syntax
371
                opts[optname] = optargfn(optarg)
1 by mbp at sourcefrog
import from baz patch-364
372
            else:
17 by mbp at sourcefrog
allow --option=ARG syntax
373
                if optarg != None:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
374
                    raise BzrError('option %r takes no argument' % optname)
1 by mbp at sourcefrog
import from baz patch-364
375
                opts[optname] = True
376
        else:
377
            args.append(a)
378
    return args, opts
379
380
329 by Martin Pool
- refactor command functions into command classes
381
def _match_argform(cmd, takes_args, args):
1 by mbp at sourcefrog
import from baz patch-364
382
    argdict = {}
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
383
329 by Martin Pool
- refactor command functions into command classes
384
    # step through args and takes_args, allowing appropriate 0-many matches
385
    for ap in takes_args:
1 by mbp at sourcefrog
import from baz patch-364
386
        argname = ap[:-1]
387
        if ap[-1] == '?':
62 by mbp at sourcefrog
- new find_branch_root function; based on suggestion from aaron
388
            if args:
389
                argdict[argname] = args.pop(0)
196 by mbp at sourcefrog
selected-file diff
390
        elif ap[-1] == '*': # all remaining arguments
391
            if args:
392
                argdict[argname + '_list'] = args[:]
393
                args = []
394
            else:
395
                argdict[argname + '_list'] = None
1 by mbp at sourcefrog
import from baz patch-364
396
        elif ap[-1] == '+':
397
            if not args:
329 by Martin Pool
- refactor command functions into command classes
398
                raise BzrCommandError("command %r needs one or more %s"
1 by mbp at sourcefrog
import from baz patch-364
399
                        % (cmd, argname.upper()))
400
            else:
401
                argdict[argname + '_list'] = args[:]
402
                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
403
        elif ap[-1] == '$': # all but one
404
            if len(args) < 2:
329 by Martin Pool
- refactor command functions into command classes
405
                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
406
                        % (cmd, argname.upper()))
407
            argdict[argname + '_list'] = args[:-1]
408
            args[:-1] = []                
1 by mbp at sourcefrog
import from baz patch-364
409
        else:
410
            # just a plain arg
411
            argname = ap
412
            if not args:
329 by Martin Pool
- refactor command functions into command classes
413
                raise BzrCommandError("command %r requires argument %s"
1 by mbp at sourcefrog
import from baz patch-364
414
                        % (cmd, argname.upper()))
415
            else:
416
                argdict[argname] = args.pop(0)
417
            
418
    if args:
329 by Martin Pool
- refactor command functions into command classes
419
        raise BzrCommandError("extra argument to command %s: %s"
420
                              % (cmd, args[0]))
1 by mbp at sourcefrog
import from baz patch-364
421
422
    return argdict
423
424
425
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
426
def apply_profiled(the_callable, *args, **kwargs):
427
    import hotshot
428
    import tempfile
1393.1.27 by Martin Pool
- clean up profile code and change default sort order
429
    import hotshot.stats
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
430
    pffileno, pfname = tempfile.mkstemp()
431
    try:
432
        prof = hotshot.Profile(pfname)
433
        try:
434
            ret = prof.runcall(the_callable, *args, **kwargs) or 0
435
        finally:
436
            prof.close()
437
        stats = hotshot.stats.load(pfname)
1393.1.27 by Martin Pool
- clean up profile code and change default sort order
438
        stats.strip_dirs()
439
        stats.sort_stats('cum')   # 'time'
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
440
        ## XXX: Might like to write to stderr or the trace file instead but
441
        ## print_stats seems hardcoded to stdout
442
        stats.print_stats(20)
443
        return ret
444
    finally:
445
        os.close(pffileno)
446
        os.remove(pfname)
447
448
1540.2.7 by Robey Pointer
add --lsprof-file option to specify a file for writing lsprof data to (instead of dumping a pretty-print to the terminal)
449
def apply_lsprofiled(filename, the_callable, *args, **kwargs):
1185.33.85 by Martin Pool
New --lsprof option from Denys Duchier
450
    from bzrlib.lsprof import profile
1540.2.7 by Robey Pointer
add --lsprof-file option to specify a file for writing lsprof data to (instead of dumping a pretty-print to the terminal)
451
    import cPickle
452
    ret, stats = profile(the_callable, *args, **kwargs)
1185.33.85 by Martin Pool
New --lsprof option from Denys Duchier
453
    stats.sort()
1540.2.7 by Robey Pointer
add --lsprof-file option to specify a file for writing lsprof data to (instead of dumping a pretty-print to the terminal)
454
    if filename is None:
455
        stats.pprint()
456
    else:
457
        stats.freeze()
458
        cPickle.dump(stats, open(filename, 'w'), 2)
459
        print 'Profile data written to %r.' % filename
1185.33.85 by Martin Pool
New --lsprof option from Denys Duchier
460
    return ret
461
1 by mbp at sourcefrog
import from baz patch-364
462
def run_bzr(argv):
463
    """Execute a command.
464
465
    This is similar to main(), but without all the trappings for
245 by mbp at sourcefrog
- control files always in utf-8-unix format
466
    logging and error handling.  
973 by Martin Pool
- various refactorings of command interpreter
467
    
468
    argv
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
469
       The command-line arguments, without the program name from argv[0]
973 by Martin Pool
- various refactorings of command interpreter
470
    
471
    Returns a command status or raises an exception.
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
472
473
    Special master options: these must come before the command because
474
    they control how the command is interpreted.
475
476
    --no-plugins
477
        Do not load plugin modules at all
478
479
    --builtin
480
        Only use builtin commands.  (Plugins are still allowed to change
481
        other behaviour.)
482
483
    --profile
1185.33.85 by Martin Pool
New --lsprof option from Denys Duchier
484
        Run under the Python hotshot profiler.
485
486
    --lsprof
487
        Run under the Python lsprof profiler.
1 by mbp at sourcefrog
import from baz patch-364
488
    """
251 by mbp at sourcefrog
- factor out locale.getpreferredencoding()
489
    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.
490
1185.33.85 by Martin Pool
New --lsprof option from Denys Duchier
491
    opt_lsprof = opt_profile = opt_no_plugins = opt_builtin = False
1540.2.7 by Robey Pointer
add --lsprof-file option to specify a file for writing lsprof data to (instead of dumping a pretty-print to the terminal)
492
    opt_lsprof_file = None
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
493
494
    # --no-plugins is handled specially at a very early stage. We need
495
    # to load plugins before doing other command parsing so that they
496
    # can override commands, but this needs to happen first.
497
1540.2.7 by Robey Pointer
add --lsprof-file option to specify a file for writing lsprof data to (instead of dumping a pretty-print to the terminal)
498
    argv_copy = []
499
    i = 0
500
    while i < len(argv):
501
        a = argv[i]
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
502
        if a == '--profile':
503
            opt_profile = True
1185.33.85 by Martin Pool
New --lsprof option from Denys Duchier
504
        elif a == '--lsprof':
505
            opt_lsprof = True
1540.2.7 by Robey Pointer
add --lsprof-file option to specify a file for writing lsprof data to (instead of dumping a pretty-print to the terminal)
506
        elif a == '--lsprof-file':
507
            opt_lsprof_file = argv[i + 1]
508
            i += 1
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
509
        elif a == '--no-plugins':
510
            opt_no_plugins = True
511
        elif a == '--builtin':
512
            opt_builtin = True
1185.33.42 by Martin Pool
[patch] make --quiet a global option (robey)
513
        elif a in ('--quiet', '-q'):
514
            be_quiet()
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
515
        else:
1540.2.7 by Robey Pointer
add --lsprof-file option to specify a file for writing lsprof data to (instead of dumping a pretty-print to the terminal)
516
            argv_copy.append(a)
517
        i += 1
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
518
1540.2.7 by Robey Pointer
add --lsprof-file option to specify a file for writing lsprof data to (instead of dumping a pretty-print to the terminal)
519
    argv = argv_copy
1165 by Martin Pool
- move parsing of argv into arguments and options into Command.run_argv
520
    if (not argv) or (argv[0] == '--help'):
521
        from bzrlib.help import help
522
        if len(argv) > 1:
523
            help(argv[1])
524
        else:
525
            help()
526
        return 0
527
528
    if argv[0] == '--version':
529
        from bzrlib.builtins import show_version
530
        show_version()
531
        return 0
532
        
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
533
    if not opt_no_plugins:
973 by Martin Pool
- various refactorings of command interpreter
534
        from bzrlib.plugin import load_plugins
535
        load_plugins()
1551.3.11 by Aaron Bentley
Merge from Robert
536
    else:
537
        from bzrlib.plugin import disable_plugins
538
        disable_plugins()
973 by Martin Pool
- various refactorings of command interpreter
539
1165 by Martin Pool
- move parsing of argv into arguments and options into Command.run_argv
540
    cmd = str(argv.pop(0))
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
541
1162 by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to
542
    cmd_obj = get_cmd_object(cmd, plugins_override=not opt_builtin)
1534.7.154 by Aaron Bentley
Removed changes from bzr.ab 1529..1536
543
1185.33.42 by Martin Pool
[patch] make --quiet a global option (robey)
544
    try:
1185.33.85 by Martin Pool
New --lsprof option from Denys Duchier
545
        if opt_lsprof:
1540.2.7 by Robey Pointer
add --lsprof-file option to specify a file for writing lsprof data to (instead of dumping a pretty-print to the terminal)
546
            ret = apply_lsprofiled(opt_lsprof_file, cmd_obj.run_argv, argv)
1185.33.85 by Martin Pool
New --lsprof option from Denys Duchier
547
        elif opt_profile:
1534.7.154 by Aaron Bentley
Removed changes from bzr.ab 1529..1536
548
            ret = apply_profiled(cmd_obj.run_argv, argv)
1185.33.42 by Martin Pool
[patch] make --quiet a global option (robey)
549
        else:
1534.7.154 by Aaron Bentley
Removed changes from bzr.ab 1529..1536
550
            ret = cmd_obj.run_argv(argv)
1185.33.42 by Martin Pool
[patch] make --quiet a global option (robey)
551
        return ret or 0
552
    finally:
553
        # reset, in case we may do other commands later within the same process
554
        be_quiet(False)
267 by Martin Pool
- better reporting of errors
555
1185.12.56 by Aaron Bentley
Prevented display commands from printing broken pipe errors
556
def display_command(func):
1185.33.18 by Martin Pool
[patch] handle bad IOError subclass raised by urlopen
557
    """Decorator that suppresses pipe/interrupt errors."""
1185.12.56 by Aaron Bentley
Prevented display commands from printing broken pipe errors
558
    def ignore_pipe(*args, **kwargs):
559
        try:
1185.35.22 by Aaron Bentley
Handled more pipe errors for display commands.
560
            result = func(*args, **kwargs)
561
            sys.stdout.flush()
562
            return result
1185.12.56 by Aaron Bentley
Prevented display commands from printing broken pipe errors
563
        except IOError, e:
1185.33.18 by Martin Pool
[patch] handle bad IOError subclass raised by urlopen
564
            if not hasattr(e, 'errno'):
565
                raise
1185.12.56 by Aaron Bentley
Prevented display commands from printing broken pipe errors
566
            if e.errno != errno.EPIPE:
567
                raise
1185.33.18 by Martin Pool
[patch] handle bad IOError subclass raised by urlopen
568
            pass
1185.12.69 by Aaron Bentley
Ignored ^C in display commands
569
        except KeyboardInterrupt:
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
570
            pass
1185.12.56 by Aaron Bentley
Prevented display commands from printing broken pipe errors
571
    return ignore_pipe
267 by Martin Pool
- better reporting of errors
572
1185.43.6 by Martin Pool
Enable logging early enough to save argv
573
1 by mbp at sourcefrog
import from baz patch-364
574
def main(argv):
1104 by Martin Pool
- Add a simple UIFactory
575
    import bzrlib.ui
1185.49.21 by John Arbash Meinel
Refactored bzrlib/ui.py into a module with the possibility for multiple ui forms.
576
    from bzrlib.ui.text import TextUIFactory
1185.43.8 by Martin Pool
Don't enable default logging twice
577
    ## bzrlib.trace.enable_default_logging()
1111 by Martin Pool
- add functions to enable and disable default logging, so that we can
578
    bzrlib.trace.log_startup(argv)
1185.49.21 by John Arbash Meinel
Refactored bzrlib/ui.py into a module with the possibility for multiple ui forms.
579
    bzrlib.ui.ui_factory = TextUIFactory()
1185.43.6 by Martin Pool
Enable logging early enough to save argv
580
    ret = run_bzr_catch_errors(argv[1:])
581
    mutter("return code %d", ret)
582
    return ret
1185.3.19 by Martin Pool
- split out commandline error reporting for ease of testing
583
584
585
def run_bzr_catch_errors(argv):
1 by mbp at sourcefrog
import from baz patch-364
586
    try:
260 by Martin Pool
- remove atexit() dependency for writing out execution times
587
        try:
1393.1.64 by Martin Pool
- improved display of some errors, including NotBranchError
588
            return run_bzr(argv)
589
        finally:
590
            # do this here inside the exception wrappers to catch EPIPE
591
            sys.stdout.flush()
1097 by Martin Pool
- send trace messages out through python logging module
592
    except Exception, e:
1185.33.19 by Martin Pool
Run postmortem debugger if BZR_PDB is set
593
        # used to handle AssertionError and KeyboardInterrupt
594
        # specially here, but hopefully they're handled ok by the logger now
1097 by Martin Pool
- send trace messages out through python logging module
595
        import errno
596
        if (isinstance(e, IOError) 
597
            and hasattr(e, 'errno')
598
            and e.errno == errno.EPIPE):
599
            bzrlib.trace.note('broken pipe')
1185.35.21 by Aaron Bentley
Changed error status to 3
600
            return 3
1097 by Martin Pool
- send trace messages out through python logging module
601
        else:
1185.33.20 by Martin Pool
Really enter the debugger on failure
602
            bzrlib.trace.log_exception()
1185.33.19 by Martin Pool
Run postmortem debugger if BZR_PDB is set
603
            if os.environ.get('BZR_PDB'):
1185.33.20 by Martin Pool
Really enter the debugger on failure
604
                print '**** entering debugger'
1185.33.19 by Martin Pool
Run postmortem debugger if BZR_PDB is set
605
                import pdb
1185.33.20 by Martin Pool
Really enter the debugger on failure
606
                pdb.post_mortem(sys.exc_traceback)
1185.35.21 by Aaron Bentley
Changed error status to 3
607
            return 3
1 by mbp at sourcefrog
import from baz patch-364
608
609
if __name__ == '__main__':
610
    sys.exit(main(sys.argv))