~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commands.py

Fix BzrDir.create_workingtree for NULL_REVISION

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2004, 2005 by Canonical Ltd
2
 
 
 
1
# Copyright (C) 2006 by Canonical Ltd
 
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
 
 
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
18
# TODO: probably should say which arguments are candidates for glob
19
19
# expansion on windows and do that at the command level.
20
20
 
21
 
# TODO: Help messages for options.
22
 
 
23
21
# TODO: Define arguments by objects, rather than just using names.
24
22
# Those objects can specify the expected type of the argument, which
25
 
# would help with validation and shell completion.
 
23
# would help with validation and shell completion.  They could also provide
 
24
# help/explanation for that argument in a structured way.
 
25
 
 
26
# TODO: Specific "examples" property on commands for consistent formatting.
26
27
 
27
28
# TODO: "--profile=cum", to change sort order.  Is there any value in leaving
28
29
# the profile output behind so it can be interactively examined?
29
30
 
30
 
import sys
 
31
import codecs
 
32
import errno
31
33
import os
32
34
from warnings import warn
33
 
from inspect import getdoc
34
 
import errno
 
35
import sys
35
36
 
36
37
import bzrlib
37
 
import bzrlib.trace
38
 
from bzrlib.trace import mutter, note, log_error, warning, be_quiet
39
 
from bzrlib.errors import (BzrError, 
 
38
import bzrlib.errors as errors
 
39
from bzrlib.errors import (BzrError,
 
40
                           BzrCommandError,
40
41
                           BzrCheckError,
41
 
                           BzrCommandError,
42
 
                           BzrOptionError,
43
42
                           NotBranchError)
 
43
from bzrlib import option
 
44
from bzrlib.option import Option
 
45
import bzrlib.osutils
44
46
from bzrlib.revisionspec import RevisionSpec
45
 
from bzrlib import BZRDIR
46
 
from bzrlib.option import Option
 
47
from bzrlib.symbol_versioning import (deprecated_method, zero_eight)
 
48
import bzrlib.trace
 
49
from bzrlib.trace import mutter, note, log_error, warning, be_quiet
47
50
 
48
51
plugin_cmds = {}
49
52
 
50
53
 
51
54
def register_command(cmd, decorate=False):
52
 
    "Utility function to help register a command"
 
55
    """Utility function to help register a command
 
56
 
 
57
    :param cmd: Command subclass to register
 
58
    :param decorate: If true, allow overriding an existing command
 
59
        of the same name; the old command is returned by this function.
 
60
        Otherwise it is an error to try to override an existing command.
 
61
    """
53
62
    global plugin_cmds
54
63
    k = cmd.__name__
55
64
    if k.startswith("cmd_"):
58
67
        k_unsquished = k
59
68
    if not plugin_cmds.has_key(k_unsquished):
60
69
        plugin_cmds[k_unsquished] = cmd
61
 
        mutter('registered plugin command %s', k_unsquished)      
 
70
        mutter('registered plugin command %s', k_unsquished)
62
71
        if decorate and k_unsquished in builtin_command_names():
63
72
            return _builtin_commands()[k_unsquished]
64
73
    elif decorate:
85
94
    builtins = bzrlib.builtins.__dict__
86
95
    for name in builtins:
87
96
        if name.startswith("cmd_"):
88
 
            real_name = _unsquish_command_name(name)        
 
97
            real_name = _unsquish_command_name(name)
89
98
            r[real_name] = builtins[name]
90
99
    return r
91
 
 
92
100
            
93
101
 
94
102
def builtin_command_names():
122
130
    """
123
131
    from bzrlib.externalcommand import ExternalCommand
124
132
 
125
 
    cmd_name = str(cmd_name)            # not unicode
 
133
    # We want only 'ascii' command names, but the user may have typed
 
134
    # in a Unicode name. In that case, they should just get a
 
135
    # 'command not found' error later.
 
136
    # In the future, we may actually support Unicode command names.
126
137
 
127
138
    # first look up this command under the specified name
128
139
    cmds = _get_cmd_dict(plugins_override=plugins_override)
140
151
    if cmd_obj:
141
152
        return cmd_obj
142
153
 
143
 
    raise BzrCommandError("unknown command %r" % cmd_name)
 
154
    raise BzrCommandError('unknown command "%s"' % cmd_name)
144
155
 
145
156
 
146
157
class Command(object):
168
179
        List of argument forms, marked with whether they are optional,
169
180
        repeated, etc.
170
181
 
171
 
                Examples:
172
 
 
173
 
                ['to_location', 'from_branch?', 'file*']
174
 
 
175
 
                'to_location' is required
176
 
                'from_branch' is optional
177
 
                'file' can be specified 0 or more times
 
182
                Examples:
 
183
 
 
184
                ['to_location', 'from_branch?', 'file*']
 
185
 
 
186
                'to_location' is required
 
187
                'from_branch' is optional
 
188
                'file' can be specified 0 or more times
178
189
 
179
190
    takes_options
180
191
        List of options that may be given for this command.  These can
184
195
    hidden
185
196
        If true, this command isn't advertised.  This is typically
186
197
        for commands intended for expert users.
 
198
 
 
199
    encoding_type
 
200
        Command objects will get a 'outf' attribute, which has been
 
201
        setup to properly handle encoding of unicode strings.
 
202
        encoding_type determines what will happen when characters cannot
 
203
        be encoded
 
204
            strict - abort if we cannot decode
 
205
            replace - put in a bogus character (typically '?')
 
206
            exact - do not encode sys.stdout
 
207
 
187
208
    """
188
209
    aliases = []
189
210
    takes_args = []
190
211
    takes_options = []
 
212
    encoding_type = 'strict'
191
213
 
192
214
    hidden = False
193
215
    
203
225
        r = dict()
204
226
        r['help'] = Option.OPTIONS['help']
205
227
        for o in self.takes_options:
206
 
            if not isinstance(o, Option):
 
228
            if isinstance(o, basestring):
207
229
                o = Option.OPTIONS[o]
208
230
            r[o.name] = o
209
231
        return r
210
232
 
 
233
    def _setup_outf(self):
 
234
        """Return a file linked to stdout, which has proper encoding."""
 
235
        assert self.encoding_type in ['strict', 'exact', 'replace']
 
236
 
 
237
        # Originally I was using self.stdout, but that looks
 
238
        # *way* too much like sys.stdout
 
239
        if self.encoding_type == 'exact':
 
240
            self.outf = sys.stdout
 
241
            return
 
242
 
 
243
        output_encoding = bzrlib.osutils.get_terminal_encoding()
 
244
 
 
245
        # use 'replace' so that we don't abort if trying to write out
 
246
        # in e.g. the default C locale.
 
247
        self.outf = codecs.getwriter(output_encoding)(sys.stdout, errors=self.encoding_type)
 
248
        # For whatever reason codecs.getwriter() does not advertise its encoding
 
249
        # it just returns the encoding of the wrapped file, which is completely
 
250
        # bogus. So set the attribute, so we can find the correct encoding later.
 
251
        self.outf.encoding = output_encoding
 
252
 
 
253
    @deprecated_method(zero_eight)
211
254
    def run_argv(self, argv):
212
 
        """Parse command line and run."""
213
 
        args, opts = parse_args(self, argv)
 
255
        """Parse command line and run.
 
256
        
 
257
        See run_argv_aliases for the 0.8 and beyond api.
 
258
        """
 
259
        return self.run_argv_aliases(argv)
 
260
 
 
261
    def run_argv_aliases(self, argv, alias_argv=None):
 
262
        """Parse the command line and run with extra aliases in alias_argv."""
 
263
        if argv is None:
 
264
            warn("Passing None for [] is deprecated from bzrlib 0.10", 
 
265
                 DeprecationWarning, stacklevel=2)
 
266
            argv = []
 
267
        args, opts = parse_args(self, argv, alias_argv)
214
268
        if 'help' in opts:  # e.g. bzr add --help
215
269
            from bzrlib.help import help_on_command
216
270
            help_on_command(self.name())
217
271
            return 0
218
 
        # XXX: This should be handled by the parser
219
 
        allowed_names = self.options().keys()
220
 
        for oname in opts:
221
 
            if oname not in allowed_names:
222
 
                raise BzrCommandError("option '--%s' is not allowed for command %r"
223
 
                                      % (oname, self.name()))
224
272
        # mix arguments and options into one dictionary
225
273
        cmdargs = _match_argform(self.name(), self.takes_args, args)
226
274
        cmdopts = {}
230
278
        all_cmd_args = cmdargs.copy()
231
279
        all_cmd_args.update(cmdopts)
232
280
 
 
281
        self._setup_outf()
 
282
 
233
283
        return self.run(**all_cmd_args)
234
284
    
235
285
    def run(self):
242
292
        shell error code if not.  It's OK for this method to allow
243
293
        an exception to raise up.
244
294
        """
245
 
        raise NotImplementedError()
246
 
 
 
295
        raise NotImplementedError('no implementation of command %r' 
 
296
                                  % self.name())
247
297
 
248
298
    def help(self):
249
299
        """Return help message for this class."""
 
300
        from inspect import getdoc
250
301
        if self.__doc__ is Command.__doc__:
251
302
            return None
252
303
        return getdoc(self)
254
305
    def name(self):
255
306
        return _unsquish_command_name(self.__class__.__name__)
256
307
 
 
308
    def plugin_name(self):
 
309
        """Get the name of the plugin that provides this command.
 
310
 
 
311
        :return: The name of the plugin or None if the command is builtin.
 
312
        """
 
313
        mod_parts = self.__module__.split('.')
 
314
        if len(mod_parts) >= 3 and mod_parts[1] == 'plugins':
 
315
            return mod_parts[2]
 
316
        else:
 
317
            return None
 
318
 
257
319
 
258
320
def parse_spec(spec):
259
321
    """
286
348
        parsed = [spec, None]
287
349
    return parsed
288
350
 
289
 
def parse_args(command, argv):
 
351
def parse_args(command, argv, alias_argv=None):
290
352
    """Parse command line.
291
353
    
292
354
    Arguments and options are parsed at this level before being passed
294
356
    lookup table, something about the available options, what optargs
295
357
    they take, and which commands will accept them.
296
358
    """
297
 
    # TODO: chop up this beast; make it a method of the Command
298
 
    args = []
299
 
    opts = {}
300
 
 
301
 
    cmd_options = command.options()
302
 
    argsover = False
303
 
    while argv:
304
 
        a = argv.pop(0)
305
 
        if argsover:
306
 
            args.append(a)
307
 
            continue
308
 
        elif a == '--':
309
 
            # We've received a standalone -- No more flags
310
 
            argsover = True
311
 
            continue
312
 
        if a[0] == '-':
313
 
            # option names must not be unicode
314
 
            a = str(a)
315
 
            optarg = None
316
 
            if a[1] == '-':
317
 
                mutter("  got option %r", a)
318
 
                if '=' in a:
319
 
                    optname, optarg = a[2:].split('=', 1)
320
 
                else:
321
 
                    optname = a[2:]
322
 
                if optname not in cmd_options:
323
 
                    raise BzrOptionError('unknown long option %r for command %s'
324
 
                        % (a, command.name()))
325
 
            else:
326
 
                shortopt = a[1:]
327
 
                if shortopt in Option.SHORT_OPTIONS:
328
 
                    # Multi-character options must have a space to delimit
329
 
                    # their value
330
 
                    # ^^^ what does this mean? mbp 20051014
331
 
                    optname = Option.SHORT_OPTIONS[shortopt].name
332
 
                else:
333
 
                    # Single character short options, can be chained,
334
 
                    # and have their value appended to their name
335
 
                    shortopt = a[1:2]
336
 
                    if shortopt not in Option.SHORT_OPTIONS:
337
 
                        # We didn't find the multi-character name, and we
338
 
                        # didn't find the single char name
339
 
                        raise BzrError('unknown short option %r' % a)
340
 
                    optname = Option.SHORT_OPTIONS[shortopt].name
341
 
 
342
 
                    if a[2:]:
343
 
                        # There are extra things on this option
344
 
                        # see if it is the value, or if it is another
345
 
                        # short option
346
 
                        optargfn = Option.OPTIONS[optname].type
347
 
                        if optargfn is None:
348
 
                            # This option does not take an argument, so the
349
 
                            # next entry is another short option, pack it back
350
 
                            # into the list
351
 
                            argv.insert(0, '-' + a[2:])
352
 
                        else:
353
 
                            # This option takes an argument, so pack it
354
 
                            # into the array
355
 
                            optarg = a[2:]
356
 
            
357
 
                if optname not in cmd_options:
358
 
                    raise BzrOptionError('unknown short option %r for command'
359
 
                        ' %s' % (shortopt, command.name()))
360
 
            if optname in opts:
361
 
                # XXX: Do we ever want to support this, e.g. for -r?
362
 
                raise BzrError('repeated option %r' % a)
363
 
                
364
 
            option_obj = cmd_options[optname]
365
 
            optargfn = option_obj.type
366
 
            if optargfn:
367
 
                if optarg == None:
368
 
                    if not argv:
369
 
                        raise BzrError('option %r needs an argument' % a)
370
 
                    else:
371
 
                        optarg = argv.pop(0)
372
 
                opts[optname] = optargfn(optarg)
373
 
            else:
374
 
                if optarg != None:
375
 
                    raise BzrError('option %r takes no argument' % optname)
376
 
                opts[optname] = True
377
 
        else:
378
 
            args.append(a)
 
359
    # TODO: make it a method of the Command?
 
360
    parser = option.get_optparser(command.options())
 
361
    if alias_argv is not None:
 
362
        args = alias_argv + argv
 
363
    else:
 
364
        args = argv
 
365
 
 
366
    options, args = parser.parse_args(args)
 
367
    opts = dict([(k, v) for k, v in options.__dict__.iteritems() if 
 
368
                 v is not option.OptionParser.DEFAULT_VALUE])
379
369
    return args, opts
380
370
 
381
371
 
406
396
                raise BzrCommandError("command %r needs one or more %s"
407
397
                        % (cmd, argname.upper()))
408
398
            argdict[argname + '_list'] = args[:-1]
409
 
            args[:-1] = []                
 
399
            args[:-1] = []
410
400
        else:
411
401
            # just a plain arg
412
402
            argname = ap
447
437
        os.remove(pfname)
448
438
 
449
439
 
450
 
def apply_lsprofiled(the_callable, *args, **kwargs):
 
440
def apply_lsprofiled(filename, the_callable, *args, **kwargs):
451
441
    from bzrlib.lsprof import profile
452
 
    ret,stats = profile(the_callable,*args,**kwargs)
 
442
    import cPickle
 
443
    ret, stats = profile(the_callable, *args, **kwargs)
453
444
    stats.sort()
454
 
    stats.pprint()
 
445
    if filename is None:
 
446
        stats.pprint()
 
447
    else:
 
448
        stats.freeze()
 
449
        cPickle.dump(stats, open(filename, 'w'), 2)
 
450
        print 'Profile data written to %r.' % filename
455
451
    return ret
456
452
 
 
453
 
 
454
def get_alias(cmd):
 
455
    """Return an expanded alias, or None if no alias exists"""
 
456
    import bzrlib.config
 
457
    alias = bzrlib.config.GlobalConfig().get_alias(cmd)
 
458
    if (alias):
 
459
        return alias.split(' ')
 
460
    return None
 
461
 
 
462
 
457
463
def run_bzr(argv):
458
464
    """Execute a command.
459
465
 
462
468
    
463
469
    argv
464
470
       The command-line arguments, without the program name from argv[0]
 
471
       These should already be decoded. All library/test code calling
 
472
       run_bzr should be passing valid strings (don't need decoding).
465
473
    
466
474
    Returns a command status or raises an exception.
467
475
 
471
479
    --no-plugins
472
480
        Do not load plugin modules at all
473
481
 
 
482
    --no-aliases
 
483
        Do not allow aliases
 
484
 
474
485
    --builtin
475
486
        Only use builtin commands.  (Plugins are still allowed to change
476
487
        other behaviour.)
481
492
    --lsprof
482
493
        Run under the Python lsprof profiler.
483
494
    """
484
 
    argv = [a.decode(bzrlib.user_encoding) for a in argv]
 
495
    argv = list(argv)
485
496
 
486
 
    opt_lsprof = opt_profile = opt_no_plugins = opt_builtin = False
 
497
    opt_lsprof = opt_profile = opt_no_plugins = opt_builtin =  \
 
498
                opt_no_aliases = False
 
499
    opt_lsprof_file = None
487
500
 
488
501
    # --no-plugins is handled specially at a very early stage. We need
489
502
    # to load plugins before doing other command parsing so that they
490
503
    # can override commands, but this needs to happen first.
491
504
 
492
 
    for a in argv:
 
505
    argv_copy = []
 
506
    i = 0
 
507
    while i < len(argv):
 
508
        a = argv[i]
493
509
        if a == '--profile':
494
510
            opt_profile = True
495
511
        elif a == '--lsprof':
496
512
            opt_lsprof = True
 
513
        elif a == '--lsprof-file':
 
514
            opt_lsprof = True
 
515
            opt_lsprof_file = argv[i + 1]
 
516
            i += 1
497
517
        elif a == '--no-plugins':
498
518
            opt_no_plugins = True
 
519
        elif a == '--no-aliases':
 
520
            opt_no_aliases = True
499
521
        elif a == '--builtin':
500
522
            opt_builtin = True
501
523
        elif a in ('--quiet', '-q'):
502
524
            be_quiet()
503
525
        else:
504
 
            continue
505
 
        argv.remove(a)
 
526
            argv_copy.append(a)
 
527
        i += 1
506
528
 
507
 
    if (not argv) or (argv[0] == '--help'):
508
 
        from bzrlib.help import help
509
 
        if len(argv) > 1:
510
 
            help(argv[1])
511
 
        else:
512
 
            help()
 
529
    argv = argv_copy
 
530
    if (not argv):
 
531
        from bzrlib.builtins import cmd_help
 
532
        cmd_help().run_argv_aliases([])
513
533
        return 0
514
534
 
515
535
    if argv[0] == '--version':
516
 
        from bzrlib.builtins import show_version
 
536
        from bzrlib.version import show_version
517
537
        show_version()
518
538
        return 0
519
539
        
520
540
    if not opt_no_plugins:
521
541
        from bzrlib.plugin import load_plugins
522
542
        load_plugins()
523
 
 
524
 
    cmd = str(argv.pop(0))
 
543
    else:
 
544
        from bzrlib.plugin import disable_plugins
 
545
        disable_plugins()
 
546
 
 
547
    alias_argv = None
 
548
 
 
549
    if not opt_no_aliases:
 
550
        alias_argv = get_alias(argv[0])
 
551
        if alias_argv:
 
552
            alias_argv = [a.decode(bzrlib.user_encoding) for a in alias_argv]
 
553
            argv[0] = alias_argv.pop(0)
 
554
 
 
555
    cmd = argv.pop(0)
 
556
    # We want only 'ascii' command names, but the user may have typed
 
557
    # in a Unicode name. In that case, they should just get a
 
558
    # 'command not found' error later.
525
559
 
526
560
    cmd_obj = get_cmd_object(cmd, plugins_override=not opt_builtin)
 
561
    if not getattr(cmd_obj.run_argv, 'is_deprecated', False):
 
562
        run = cmd_obj.run_argv
 
563
        run_argv = [argv]
 
564
    else:
 
565
        run = cmd_obj.run_argv_aliases
 
566
        run_argv = [argv, alias_argv]
527
567
 
528
568
    try:
529
569
        if opt_lsprof:
530
 
            ret = apply_lsprofiled(cmd_obj.run_argv, argv)
 
570
            ret = apply_lsprofiled(opt_lsprof_file, run, *run_argv)
531
571
        elif opt_profile:
532
 
            ret = apply_profiled(cmd_obj.run_argv, argv)
 
572
            ret = apply_profiled(run, *run_argv)
533
573
        else:
534
 
            ret = cmd_obj.run_argv(argv)
 
574
            ret = run(*run_argv)
535
575
        return ret or 0
536
576
    finally:
537
577
        # reset, in case we may do other commands later within the same process
548
588
            if not hasattr(e, 'errno'):
549
589
                raise
550
590
            if e.errno != errno.EPIPE:
551
 
                raise
 
591
                # Win32 raises IOError with errno=0 on a broken pipe
 
592
                if sys.platform != 'win32' or e.errno != 0:
 
593
                    raise
552
594
            pass
553
595
        except KeyboardInterrupt:
554
596
            pass
558
600
def main(argv):
559
601
    import bzrlib.ui
560
602
    from bzrlib.ui.text import TextUIFactory
561
 
    ## bzrlib.trace.enable_default_logging()
562
 
    bzrlib.trace.log_startup(argv)
563
603
    bzrlib.ui.ui_factory = TextUIFactory()
564
 
    ret = run_bzr_catch_errors(argv[1:])
 
604
    argv = [a.decode(bzrlib.user_encoding) for a in argv[1:]]
 
605
    ret = run_bzr_catch_errors(argv)
565
606
    mutter("return code %d", ret)
566
607
    return ret
567
608
 
568
609
 
569
610
def run_bzr_catch_errors(argv):
570
611
    try:
571
 
        try:
572
 
            return run_bzr(argv)
573
 
        finally:
574
 
            # do this here inside the exception wrappers to catch EPIPE
575
 
            sys.stdout.flush()
 
612
        return run_bzr(argv)
 
613
        # do this here inside the exception wrappers to catch EPIPE
 
614
        sys.stdout.flush()
576
615
    except Exception, e:
577
616
        # used to handle AssertionError and KeyboardInterrupt
578
617
        # specially here, but hopefully they're handled ok by the logger now
579
 
        import errno
580
 
        if (isinstance(e, IOError) 
581
 
            and hasattr(e, 'errno')
582
 
            and e.errno == errno.EPIPE):
583
 
            bzrlib.trace.note('broken pipe')
584
 
            return 3
585
 
        else:
586
 
            bzrlib.trace.log_exception()
587
 
            if os.environ.get('BZR_PDB'):
588
 
                print '**** entering debugger'
589
 
                import pdb
590
 
                pdb.post_mortem(sys.exc_traceback)
591
 
            return 3
 
618
        bzrlib.trace.report_exception(sys.exc_info(), sys.stderr)
 
619
        if os.environ.get('BZR_PDB'):
 
620
            print '**** entering debugger'
 
621
            import pdb
 
622
            pdb.post_mortem(sys.exc_traceback)
 
623
        return 3
592
624
 
593
625
if __name__ == '__main__':
594
626
    sys.exit(main(sys.argv))