~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commands.py

1st cut merge of bzr.dev r3907

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006 Canonical Ltd
 
1
# Copyright (C) 2006, 2008 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
43
43
    errors,
44
44
    option,
45
45
    osutils,
46
 
    registry,
47
46
    trace,
48
47
    win32utils,
49
48
    )
50
49
""")
51
50
 
52
 
from bzrlib.symbol_versioning import (
53
 
    deprecated_function,
54
 
    deprecated_method,
55
 
    )
 
51
from bzrlib import registry
56
52
# Compatibility
57
53
from bzrlib.option import Option
58
54
 
59
55
 
60
 
plugin_cmds = {}
 
56
class CommandInfo(object):
 
57
    """Information about a command."""
 
58
 
 
59
    def __init__(self, aliases):
 
60
        """The list of aliases for the command."""
 
61
        self.aliases = aliases
 
62
 
 
63
    @classmethod
 
64
    def from_command(klass, command):
 
65
        """Factory to construct a CommandInfo from a command."""
 
66
        return klass(command.aliases)
 
67
 
 
68
 
 
69
class CommandRegistry(registry.Registry):
 
70
 
 
71
    @staticmethod
 
72
    def _get_name(command_name):
 
73
        if command_name.startswith("cmd_"):
 
74
            return _unsquish_command_name(command_name)
 
75
        else:
 
76
            return command_name
 
77
 
 
78
    def register(self, cmd, decorate=False):
 
79
        """Utility function to help register a command
 
80
 
 
81
        :param cmd: Command subclass to register
 
82
        :param decorate: If true, allow overriding an existing command
 
83
            of the same name; the old command is returned by this function.
 
84
            Otherwise it is an error to try to override an existing command.
 
85
        """
 
86
        k = cmd.__name__
 
87
        k_unsquished = self._get_name(k)
 
88
        try:
 
89
            previous = self.get(k_unsquished)
 
90
        except KeyError:
 
91
            previous = _builtin_commands().get(k_unsquished)
 
92
        info = CommandInfo.from_command(cmd)
 
93
        try:
 
94
            registry.Registry.register(self, k_unsquished, cmd,
 
95
                                       override_existing=decorate, info=info)
 
96
        except KeyError:
 
97
            trace.log_error('Two plugins defined the same command: %r' % k)
 
98
            trace.log_error('Not loading the one in %r' %
 
99
                            sys.modules[cmd.__module__])
 
100
            trace.log_error('Previously this command was registered from %r' %
 
101
                            sys.modules[previous.__module__])
 
102
        return previous
 
103
 
 
104
    def register_lazy(self, command_name, aliases, module_name):
 
105
        """Register a command without loading its module.
 
106
 
 
107
        :param command_name: The primary name of the command.
 
108
        :param aliases: A list of aliases for the command.
 
109
        :module_name: The module that the command lives in.
 
110
        """
 
111
        key = self._get_name(command_name)
 
112
        registry.Registry.register_lazy(self, key, module_name, command_name,
 
113
                                        info=CommandInfo(aliases))
 
114
 
 
115
 
 
116
plugin_cmds = CommandRegistry()
61
117
 
62
118
 
63
119
def register_command(cmd, decorate=False):
64
 
    """Utility function to help register a command
65
 
 
66
 
    :param cmd: Command subclass to register
67
 
    :param decorate: If true, allow overriding an existing command
68
 
        of the same name; the old command is returned by this function.
69
 
        Otherwise it is an error to try to override an existing command.
70
 
    """
71
120
    global plugin_cmds
72
 
    k = cmd.__name__
73
 
    if k.startswith("cmd_"):
74
 
        k_unsquished = _unsquish_command_name(k)
75
 
    else:
76
 
        k_unsquished = k
77
 
    if k_unsquished not in plugin_cmds:
78
 
        plugin_cmds[k_unsquished] = cmd
79
 
        ## trace.mutter('registered plugin command %s', k_unsquished)
80
 
        if decorate and k_unsquished in builtin_command_names():
81
 
            return _builtin_commands()[k_unsquished]
82
 
    elif decorate:
83
 
        result = plugin_cmds[k_unsquished]
84
 
        plugin_cmds[k_unsquished] = cmd
85
 
        return result
86
 
    else:
87
 
        trace.log_error('Two plugins defined the same command: %r' % k)
88
 
        trace.log_error('Not loading the one in %r' % sys.modules[cmd.__module__])
89
 
        trace.log_error('Previously this command was registered from %r' %
90
 
                        sys.modules[plugin_cmds[k_unsquished].__module__])
 
121
    return plugin_cmds.register(cmd, decorate)
91
122
 
92
123
 
93
124
def _squish_command_name(cmd):
122
153
    """Return name->class mapping for all commands."""
123
154
    d = _builtin_commands()
124
155
    if plugins_override:
125
 
        d.update(plugin_cmds)
 
156
        d.update(plugin_cmds.iteritems())
126
157
    return d
127
158
 
128
159
    
154
185
    # In the future, we may actually support Unicode command names.
155
186
 
156
187
    # first look up this command under the specified name
157
 
    cmds = _get_cmd_dict(plugins_override=plugins_override)
 
188
    if plugins_override:
 
189
        try:
 
190
            return plugin_cmds.get(cmd_name)()
 
191
        except KeyError:
 
192
            pass
 
193
    cmds = _get_cmd_dict(plugins_override=False)
158
194
    try:
159
195
        return cmds[cmd_name]()
160
196
    except KeyError:
161
197
        pass
162
 
 
 
198
    if plugins_override:
 
199
        for key in plugin_cmds.keys():
 
200
            info = plugin_cmds.get_info(key)
 
201
            if cmd_name in info.aliases:
 
202
                return plugin_cmds.get(key)()
163
203
    # look for any command which claims this as an alias
164
204
    for real_cmd_name, cmd_class in cmds.iteritems():
165
205
        if cmd_name in cmd_class.aliases:
366
406
            result += ':See also: '
367
407
            result += ', '.join(see_also) + '\n'
368
408
 
369
 
        # If this will be rendered as plan text, convert it
 
409
        # If this will be rendered as plain text, convert it
370
410
        if plain:
371
411
            import bzrlib.help_topics
372
412
            result = bzrlib.help_topics.help_as_plain_text(result)
389
429
                    sections[label] += '\n' + section
390
430
                else:
391
431
                    sections[label] = section
392
 
            
 
432
 
393
433
        lines = text.rstrip().splitlines()
394
434
        summary = lines.pop(0)
395
435
        sections = {}
497
537
        self._setup_outf()
498
538
 
499
539
        return self.run(**all_cmd_args)
500
 
    
 
540
 
501
541
    def run(self):
502
542
        """Actually run the command.
503
543
 
675
715
def run_bzr(argv):
676
716
    """Execute a command.
677
717
 
678
 
    This is similar to main(), but without all the trappings for
679
 
    logging and error handling.  
680
 
    
681
718
    argv
682
719
       The command-line arguments, without the program name from argv[0]
683
720
       These should already be decoded. All library/test code calling
755
792
        from bzrlib.builtins import cmd_version
756
793
        cmd_version().run_argv_aliases([])
757
794
        return 0
758
 
        
 
795
 
759
796
    if not opt_no_plugins:
760
797
        from bzrlib.plugin import load_plugins
761
798
        load_plugins()
768
805
    if not opt_no_aliases:
769
806
        alias_argv = get_alias(argv[0])
770
807
        if alias_argv:
771
 
            alias_argv = [a.decode(bzrlib.user_encoding) for a in alias_argv]
 
808
            user_encoding = osutils.get_user_encoding()
 
809
            alias_argv = [a.decode(user_encoding) for a in alias_argv]
772
810
            argv[0] = alias_argv.pop(0)
773
811
 
774
812
    cmd = argv.pop(0)
781
819
    run_argv = [argv, alias_argv]
782
820
 
783
821
    try:
 
822
        # We can be called recursively (tests for example), but we don't want
 
823
        # the verbosity level to propagate.
 
824
        saved_verbosity_level = option._verbosity_level
 
825
        option._verbosity_level = 0
784
826
        if opt_lsprof:
785
827
            if opt_coverage_dir:
786
828
                trace.warning(
796
838
        else:
797
839
            ret = run(*run_argv)
798
840
        if 'memory' in debug.debug_flags:
799
 
            try:
800
 
                status_file = file('/proc/%s/status' % os.getpid(), 'rb')
801
 
            except IOError:
802
 
                pass
803
 
            else:
804
 
                status = status_file.read()
805
 
                status_file.close()
806
 
                trace.note("Process status after command:")
807
 
                for line in status.splitlines():
808
 
                    trace.note(line)
 
841
            trace.debug_memory('Process status after command:', short=False)
809
842
        return ret or 0
810
843
    finally:
811
 
        # reset, in case we may do other commands later within the same process
812
 
        option._verbosity_level = 0
 
844
        # reset, in case we may do other commands later within the same
 
845
        # process. Commands that want to execute sub-commands must propagate
 
846
        # --verbose in their own way.
 
847
        option._verbosity_level = saved_verbosity_level
813
848
 
814
849
def display_command(func):
815
850
    """Decorator that suppresses pipe/interrupt errors."""
835
870
    import bzrlib.ui
836
871
    from bzrlib.ui.text import TextUIFactory
837
872
    bzrlib.ui.ui_factory = TextUIFactory()
838
 
     
 
873
 
839
874
    # Is this a final release version? If so, we should suppress warnings
840
875
    if bzrlib.version_info[3] == 'final':
841
876
        from bzrlib import symbol_versioning
842
877
        symbol_versioning.suppress_deprecation_warnings(override=False)
843
878
    try:
844
 
        argv = [a.decode(bzrlib.user_encoding) for a in argv[1:]]
 
879
        user_encoding = osutils.get_user_encoding()
 
880
        argv = [a.decode(user_encoding) for a in argv[1:]]
845
881
    except UnicodeDecodeError:
846
882
        raise errors.BzrError(("Parameter '%r' is unsupported by the current "
847
883
                                                            "encoding." % a))