~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commands.py

  • Committer: John Arbash Meinel
  • Date: 2006-08-14 16:16:53 UTC
  • mto: (1946.2.6 reduce-knit-churn)
  • mto: This revision was merged to the branch mainline in revision 1919.
  • Revision ID: john@arbash-meinel.com-20060814161653-54cdcdadcd4e9003
Remove bogus entry from BRANCH.TODO

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006 Canonical Ltd
 
1
# Copyright (C) 2006 by Canonical Ltd
2
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
28
28
# TODO: "--profile=cum", to change sort order.  Is there any value in leaving
29
29
# the profile output behind so it can be interactively examined?
30
30
 
 
31
import sys
31
32
import os
32
 
import sys
33
 
 
34
 
from bzrlib.lazy_import import lazy_import
35
 
lazy_import(globals(), """
 
33
from warnings import warn
 
34
import errno
36
35
import codecs
37
 
import errno
38
 
from warnings import warn
39
36
 
40
37
import bzrlib
41
 
from bzrlib import (
42
 
    errors,
43
 
    option,
44
 
    osutils,
45
 
    trace,
46
 
    )
47
 
""")
48
 
 
49
 
from bzrlib.symbol_versioning import (
50
 
    deprecated_function,
51
 
    deprecated_method,
52
 
    zero_eight,
53
 
    zero_eleven,
54
 
    )
55
 
# Compatibility
 
38
import bzrlib.errors as errors
 
39
from bzrlib.errors import (BzrError,
 
40
                           BzrCommandError,
 
41
                           BzrCheckError,
 
42
                           NotBranchError)
56
43
from bzrlib.option import Option
57
 
 
 
44
import bzrlib.osutils
 
45
from bzrlib.revisionspec import RevisionSpec
 
46
from bzrlib.symbol_versioning import (deprecated_method, zero_eight)
 
47
import bzrlib.trace
 
48
from bzrlib.trace import mutter, note, log_error, warning, be_quiet
58
49
 
59
50
plugin_cmds = {}
60
51
 
73
64
        k_unsquished = _unsquish_command_name(k)
74
65
    else:
75
66
        k_unsquished = k
76
 
    if k_unsquished not in plugin_cmds:
 
67
    if not plugin_cmds.has_key(k_unsquished):
77
68
        plugin_cmds[k_unsquished] = cmd
78
 
        trace.mutter('registered plugin command %s', k_unsquished)
 
69
        mutter('registered plugin command %s', k_unsquished)
79
70
        if decorate and k_unsquished in builtin_command_names():
80
71
            return _builtin_commands()[k_unsquished]
81
72
    elif decorate:
83
74
        plugin_cmds[k_unsquished] = cmd
84
75
        return result
85
76
    else:
86
 
        trace.log_error('Two plugins defined the same command: %r' % k)
87
 
        trace.log_error('Not loading the one in %r' % sys.modules[cmd.__module__])
 
77
        log_error('Two plugins defined the same command: %r' % k)
 
78
        log_error('Not loading the one in %r' % sys.modules[cmd.__module__])
88
79
 
89
80
 
90
81
def _squish_command_name(cmd):
138
129
    """
139
130
    from bzrlib.externalcommand import ExternalCommand
140
131
 
141
 
    # We want only 'ascii' command names, but the user may have typed
142
 
    # in a Unicode name. In that case, they should just get a
143
 
    # 'command not found' error later.
144
 
    # In the future, we may actually support Unicode command names.
 
132
    cmd_name = str(cmd_name)            # not unicode
145
133
 
146
134
    # first look up this command under the specified name
147
135
    cmds = _get_cmd_dict(plugins_override=plugins_override)
159
147
    if cmd_obj:
160
148
        return cmd_obj
161
149
 
162
 
    raise errors.BzrCommandError('unknown command "%s"' % cmd_name)
 
150
    raise BzrCommandError('unknown command "%s"' % cmd_name)
163
151
 
164
152
 
165
153
class Command(object):
231
219
 
232
220
        Maps from long option name to option object."""
233
221
        r = dict()
234
 
        r['help'] = option.Option.OPTIONS['help']
 
222
        r['help'] = Option.OPTIONS['help']
235
223
        for o in self.takes_options:
236
 
            if isinstance(o, basestring):
237
 
                o = option.Option.OPTIONS[o]
 
224
            if not isinstance(o, Option):
 
225
                o = Option.OPTIONS[o]
238
226
            r[o.name] = o
239
227
        return r
240
228
 
248
236
            self.outf = sys.stdout
249
237
            return
250
238
 
251
 
        output_encoding = osutils.get_terminal_encoding()
 
239
        output_encoding = bzrlib.osutils.get_terminal_encoding()
252
240
 
253
241
        # use 'replace' so that we don't abort if trying to write out
254
242
        # in e.g. the default C locale.
268
256
 
269
257
    def run_argv_aliases(self, argv, alias_argv=None):
270
258
        """Parse the command line and run with extra aliases in alias_argv."""
271
 
        if argv is None:
272
 
            warn("Passing None for [] is deprecated from bzrlib 0.10", 
273
 
                 DeprecationWarning, stacklevel=2)
274
 
            argv = []
275
259
        args, opts = parse_args(self, argv, alias_argv)
276
260
        if 'help' in opts:  # e.g. bzr add --help
277
261
            from bzrlib.help import help_on_command
278
262
            help_on_command(self.name())
279
263
            return 0
 
264
        # XXX: This should be handled by the parser
 
265
        allowed_names = self.options().keys()
 
266
        for oname in opts:
 
267
            if oname not in allowed_names:
 
268
                raise BzrOptionError("option '--%s' is not allowed for"
 
269
                                " command %r" % (oname, self.name()))
280
270
        # mix arguments and options into one dictionary
281
271
        cmdargs = _match_argform(self.name(), self.takes_args, args)
282
272
        cmdopts = {}
325
315
            return None
326
316
 
327
317
 
328
 
# Technically, this function hasn't been use in a *really* long time
329
 
# but we are only deprecating it now.
330
 
@deprecated_function(zero_eleven)
331
318
def parse_spec(spec):
332
319
    """
333
320
    >>> parse_spec(None)
367
354
    lookup table, something about the available options, what optargs
368
355
    they take, and which commands will accept them.
369
356
    """
370
 
    # TODO: make it a method of the Command?
371
 
    parser = option.get_optparser(command.options())
372
 
    if alias_argv is not None:
373
 
        args = alias_argv + argv
374
 
    else:
375
 
        args = argv
376
 
 
377
 
    options, args = parser.parse_args(args)
378
 
    opts = dict([(k, v) for k, v in options.__dict__.iteritems() if 
379
 
                 v is not option.OptionParser.DEFAULT_VALUE])
 
357
    # TODO: chop up this beast; make it a method of the Command
 
358
    args = []
 
359
    opts = {}
 
360
    alias_opts = {}
 
361
 
 
362
    cmd_options = command.options()
 
363
    argsover = False
 
364
    proc_aliasarg = True # Are we processing alias_argv now?
 
365
    for proc_argv in alias_argv, argv:
 
366
        while proc_argv:
 
367
            a = proc_argv.pop(0)
 
368
            if argsover:
 
369
                args.append(a)
 
370
                continue
 
371
            elif a == '-':
 
372
                args.append(a)
 
373
                continue
 
374
            elif a == '--':
 
375
                # We've received a standalone -- No more flags
 
376
                argsover = True
 
377
                continue
 
378
            if a[0] == '-':
 
379
                # option names must not be unicode
 
380
                a = str(a)
 
381
                optarg = None
 
382
                if a[1] == '-':
 
383
                    mutter("  got option %r", a)
 
384
                    if '=' in a:
 
385
                        optname, optarg = a[2:].split('=', 1)
 
386
                    else:
 
387
                        optname = a[2:]
 
388
                    if optname not in cmd_options:
 
389
                        raise BzrCommandError('unknown option "%s"' % a)
 
390
                else:
 
391
                    shortopt = a[1:]
 
392
                    if shortopt in Option.SHORT_OPTIONS:
 
393
                        # Multi-character options must have a space to delimit
 
394
                        # their value
 
395
                        # ^^^ what does this mean? mbp 20051014
 
396
                        optname = Option.SHORT_OPTIONS[shortopt].name
 
397
                    else:
 
398
                        # Single character short options, can be chained,
 
399
                        # and have their value appended to their name
 
400
                        shortopt = a[1:2]
 
401
                        if shortopt not in Option.SHORT_OPTIONS:
 
402
                            # We didn't find the multi-character name, and we
 
403
                            # didn't find the single char name
 
404
                            raise BzrCommandError('unknown option "%s"' % a)
 
405
                        optname = Option.SHORT_OPTIONS[shortopt].name
 
406
 
 
407
                        if a[2:]:
 
408
                            # There are extra things on this option
 
409
                            # see if it is the value, or if it is another
 
410
                            # short option
 
411
                            optargfn = Option.OPTIONS[optname].type
 
412
                            if optargfn is None:
 
413
                                # This option does not take an argument, so the
 
414
                                # next entry is another short option, pack it
 
415
                                # back into the list
 
416
                                proc_argv.insert(0, '-' + a[2:])
 
417
                            else:
 
418
                                # This option takes an argument, so pack it
 
419
                                # into the array
 
420
                                optarg = a[2:]
 
421
                    if optname not in cmd_options:
 
422
                        raise BzrCommandError('unknown option "%s"' % shortopt)
 
423
                if optname in opts:
 
424
                    # XXX: Do we ever want to support this, e.g. for -r?
 
425
                    if proc_aliasarg:
 
426
                        raise BzrCommandError('repeated option %r' % a)
 
427
                    elif optname in alias_opts:
 
428
                        # Replace what's in the alias with what's in the real
 
429
                        # argument
 
430
                        del alias_opts[optname]
 
431
                        del opts[optname]
 
432
                        proc_argv.insert(0, a)
 
433
                        continue
 
434
                    else:
 
435
                        raise BzrCommandError('repeated option %r' % a)
 
436
                    
 
437
                option_obj = cmd_options[optname]
 
438
                optargfn = option_obj.type
 
439
                if optargfn:
 
440
                    if optarg == None:
 
441
                        if not proc_argv:
 
442
                            raise BzrCommandError('option %r needs an argument' % a)
 
443
                        else:
 
444
                            optarg = proc_argv.pop(0)
 
445
                    opts[optname] = optargfn(optarg)
 
446
                    if proc_aliasarg:
 
447
                        alias_opts[optname] = optargfn(optarg)
 
448
                else:
 
449
                    if optarg != None:
 
450
                        raise BzrCommandError('option %r takes no argument' % optname)
 
451
                    opts[optname] = True
 
452
                    if proc_aliasarg:
 
453
                        alias_opts[optname] = True
 
454
            else:
 
455
                args.append(a)
 
456
        proc_aliasarg = False # Done with alias argv
380
457
    return args, opts
381
458
 
382
459
 
397
474
                argdict[argname + '_list'] = None
398
475
        elif ap[-1] == '+':
399
476
            if not args:
400
 
                raise errors.BzrCommandError("command %r needs one or more %s"
401
 
                                             % (cmd, argname.upper()))
 
477
                raise BzrCommandError("command %r needs one or more %s"
 
478
                        % (cmd, argname.upper()))
402
479
            else:
403
480
                argdict[argname + '_list'] = args[:]
404
481
                args = []
405
482
        elif ap[-1] == '$': # all but one
406
483
            if len(args) < 2:
407
 
                raise errors.BzrCommandError("command %r needs one or more %s"
408
 
                                             % (cmd, argname.upper()))
 
484
                raise BzrCommandError("command %r needs one or more %s"
 
485
                        % (cmd, argname.upper()))
409
486
            argdict[argname + '_list'] = args[:-1]
410
487
            args[:-1] = []
411
488
        else:
412
489
            # just a plain arg
413
490
            argname = ap
414
491
            if not args:
415
 
                raise errors.BzrCommandError("command %r requires argument %s"
416
 
                               % (cmd, argname.upper()))
 
492
                raise BzrCommandError("command %r requires argument %s"
 
493
                        % (cmd, argname.upper()))
417
494
            else:
418
495
                argdict[argname] = args.pop(0)
419
496
            
420
497
    if args:
421
 
        raise errors.BzrCommandError("extra argument to command %s: %s"
422
 
                                     % (cmd, args[0]))
 
498
        raise BzrCommandError("extra argument to command %s: %s"
 
499
                              % (cmd, args[0]))
423
500
 
424
501
    return argdict
425
502
 
532
609
        elif a == '--builtin':
533
610
            opt_builtin = True
534
611
        elif a in ('--quiet', '-q'):
535
 
            trace.be_quiet()
 
612
            be_quiet()
536
613
        else:
537
614
            argv_copy.append(a)
538
615
        i += 1
544
621
        return 0
545
622
 
546
623
    if argv[0] == '--version':
547
 
        from bzrlib.version import show_version
 
624
        from bzrlib.builtins import show_version
548
625
        show_version()
549
626
        return 0
550
627
        
563
640
            alias_argv = [a.decode(bzrlib.user_encoding) for a in alias_argv]
564
641
            argv[0] = alias_argv.pop(0)
565
642
 
566
 
    cmd = argv.pop(0)
567
 
    # We want only 'ascii' command names, but the user may have typed
568
 
    # in a Unicode name. In that case, they should just get a
569
 
    # 'command not found' error later.
 
643
    cmd = str(argv.pop(0))
570
644
 
571
645
    cmd_obj = get_cmd_object(cmd, plugins_override=not opt_builtin)
572
646
    if not getattr(cmd_obj.run_argv, 'is_deprecated', False):
586
660
        return ret or 0
587
661
    finally:
588
662
        # reset, in case we may do other commands later within the same process
589
 
        trace.be_quiet(False)
 
663
        be_quiet(False)
590
664
 
591
665
def display_command(func):
592
666
    """Decorator that suppresses pipe/interrupt errors."""
596
670
            sys.stdout.flush()
597
671
            return result
598
672
        except IOError, e:
599
 
            if getattr(e, 'errno', None) is None:
 
673
            if not hasattr(e, 'errno'):
600
674
                raise
601
675
            if e.errno != errno.EPIPE:
602
676
                # Win32 raises IOError with errno=0 on a broken pipe
614
688
    bzrlib.ui.ui_factory = TextUIFactory()
615
689
    argv = [a.decode(bzrlib.user_encoding) for a in argv[1:]]
616
690
    ret = run_bzr_catch_errors(argv)
617
 
    trace.mutter("return code %d", ret)
 
691
    mutter("return code %d", ret)
618
692
    return ret
619
693
 
620
694
 
623
697
        return run_bzr(argv)
624
698
        # do this here inside the exception wrappers to catch EPIPE
625
699
        sys.stdout.flush()
626
 
    except (KeyboardInterrupt, Exception), e:
 
700
    except Exception, e:
627
701
        # used to handle AssertionError and KeyboardInterrupt
628
702
        # specially here, but hopefully they're handled ok by the logger now
629
 
        trace.report_exception(sys.exc_info(), sys.stderr)
 
703
        bzrlib.trace.report_exception(sys.exc_info(), sys.stderr)
630
704
        if os.environ.get('BZR_PDB'):
631
705
            print '**** entering debugger'
632
706
            import pdb