~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commands.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-06-05 21:50:09 UTC
  • mfrom: (3435.2.3 bzr.packaging_docs)
  • Revision ID: pqm@pqm.ubuntu.com-20080605215009-3svreze778r0n4xv
(Martin Albisetti) Small updates to the bzr release process
        documentation

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2008 Canonical Ltd
 
1
# Copyright (C) 2006 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,
46
47
    trace,
47
48
    win32utils,
48
49
    )
49
50
""")
50
51
 
51
 
from bzrlib import registry
 
52
from bzrlib.symbol_versioning import (
 
53
    deprecated_function,
 
54
    deprecated_method,
 
55
    )
52
56
# Compatibility
53
57
from bzrlib.option import Option
54
58
 
55
59
 
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()
 
60
plugin_cmds = {}
117
61
 
118
62
 
119
63
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
    """
120
71
    global plugin_cmds
121
 
    return plugin_cmds.register(cmd, decorate)
 
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__])
122
91
 
123
92
 
124
93
def _squish_command_name(cmd):
153
122
    """Return name->class mapping for all commands."""
154
123
    d = _builtin_commands()
155
124
    if plugins_override:
156
 
        d.update(plugin_cmds.iteritems())
 
125
        d.update(plugin_cmds)
157
126
    return d
158
127
 
159
128
    
185
154
    # In the future, we may actually support Unicode command names.
186
155
 
187
156
    # first look up this command under the specified name
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)
 
157
    cmds = _get_cmd_dict(plugins_override=plugins_override)
194
158
    try:
195
159
        return cmds[cmd_name]()
196
160
    except KeyError:
197
161
        pass
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)()
 
162
 
203
163
    # look for any command which claims this as an alias
204
164
    for real_cmd_name, cmd_class in cmds.iteritems():
205
165
        if cmd_name in cmd_class.aliases:
406
366
            result += ':See also: '
407
367
            result += ', '.join(see_also) + '\n'
408
368
 
409
 
        # If this will be rendered as plain text, convert it
 
369
        # If this will be rendered as plan text, convert it
410
370
        if plain:
411
371
            import bzrlib.help_topics
412
372
            result = bzrlib.help_topics.help_as_plain_text(result)
429
389
                    sections[label] += '\n' + section
430
390
                else:
431
391
                    sections[label] = section
432
 
 
 
392
            
433
393
        lines = text.rstrip().splitlines()
434
394
        summary = lines.pop(0)
435
395
        sections = {}
537
497
        self._setup_outf()
538
498
 
539
499
        return self.run(**all_cmd_args)
540
 
 
 
500
    
541
501
    def run(self):
542
502
        """Actually run the command.
543
503
 
715
675
def run_bzr(argv):
716
676
    """Execute a command.
717
677
 
 
678
    This is similar to main(), but without all the trappings for
 
679
    logging and error handling.  
 
680
    
718
681
    argv
719
682
       The command-line arguments, without the program name from argv[0]
720
683
       These should already be decoded. All library/test code calling
792
755
        from bzrlib.builtins import cmd_version
793
756
        cmd_version().run_argv_aliases([])
794
757
        return 0
795
 
 
 
758
        
796
759
    if not opt_no_plugins:
797
760
        from bzrlib.plugin import load_plugins
798
761
        load_plugins()
805
768
    if not opt_no_aliases:
806
769
        alias_argv = get_alias(argv[0])
807
770
        if alias_argv:
808
 
            user_encoding = osutils.get_user_encoding()
809
 
            alias_argv = [a.decode(user_encoding) for a in alias_argv]
 
771
            alias_argv = [a.decode(bzrlib.user_encoding) for a in alias_argv]
810
772
            argv[0] = alias_argv.pop(0)
811
773
 
812
774
    cmd = argv.pop(0)
819
781
    run_argv = [argv, alias_argv]
820
782
 
821
783
    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
826
784
        if opt_lsprof:
827
785
            if opt_coverage_dir:
828
786
                trace.warning(
837
795
            ret = apply_coveraged(opt_coverage_dir, run, *run_argv)
838
796
        else:
839
797
            ret = run(*run_argv)
840
 
        if 'memory' in debug.debug_flags:
841
 
            trace.debug_memory('Process status after command:', short=False)
842
798
        return ret or 0
843
799
    finally:
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
 
800
        # reset, in case we may do other commands later within the same process
 
801
        option._verbosity_level = 0
848
802
 
849
803
def display_command(func):
850
804
    """Decorator that suppresses pipe/interrupt errors."""
870
824
    import bzrlib.ui
871
825
    from bzrlib.ui.text import TextUIFactory
872
826
    bzrlib.ui.ui_factory = TextUIFactory()
873
 
 
 
827
     
874
828
    # Is this a final release version? If so, we should suppress warnings
875
829
    if bzrlib.version_info[3] == 'final':
876
830
        from bzrlib import symbol_versioning
877
831
        symbol_versioning.suppress_deprecation_warnings(override=False)
878
832
    try:
879
 
        user_encoding = osutils.get_user_encoding()
880
 
        argv = [a.decode(user_encoding) for a in argv[1:]]
 
833
        argv = [a.decode(bzrlib.user_encoding) for a in argv[1:]]
881
834
    except UnicodeDecodeError:
882
835
        raise errors.BzrError(("Parameter '%r' is unsupported by the current "
883
836
                                                            "encoding." % a))