134
139
def _builtin_commands():
135
140
import bzrlib.builtins
141
return _scan_module_for_commands(bzrlib.builtins)
144
def _scan_module_for_commands(module):
137
builtins = bzrlib.builtins.__dict__
138
for name in builtins:
146
for name, obj in module.__dict__.iteritems():
139
147
if name.startswith("cmd_"):
140
148
real_name = _unsquish_command_name(name)
141
r[real_name] = builtins[name]
153
def _list_bzr_commands(names):
154
"""Find commands from bzr's core and plugins."""
155
# to eliminate duplicates
156
names.update(builtin_command_names())
157
names.update(plugin_command_names())
161
def all_command_names():
162
"""Return a set of all command names."""
164
for hook in Command.hooks['list_commands']:
167
raise AssertionError(
168
'hook %s returned None' % Command.hooks.get_hook_name(hook))
145
172
def builtin_command_names():
146
"""Return list of builtin command names."""
173
"""Return list of builtin command names.
175
Use of all_command_names() is encouraged rather than builtin_command_names
176
and/or plugin_command_names.
147
178
return _builtin_commands().keys()
150
181
def plugin_command_names():
182
"""Returns command names from commands registered by plugins."""
151
183
return plugin_cmds.keys()
154
def _get_cmd_dict(plugins_override=True):
155
"""Return name->class mapping for all commands."""
186
@deprecated_function(deprecated_in((1, 17, 0)))
187
def get_all_cmds(plugins_override=False):
188
"""Return canonical name and class for most commands.
190
NB: This does not return all commands since the introduction of
191
command hooks, and returning the class is not sufficient to
192
get correctly setup commands, which is why it is deprecated.
194
Use 'all_command_names' + 'get_cmd_object' instead.
156
196
d = _builtin_commands()
157
197
if plugins_override:
158
198
d.update(plugin_cmds.iteritems())
162
def get_all_cmds(plugins_override=True):
163
"""Return canonical name and class for all registered commands."""
164
for k, v in _get_cmd_dict(plugins_override=plugins_override).iteritems():
199
for k, v in d.iteritems():
168
203
def get_cmd_object(cmd_name, plugins_override=True):
169
"""Return the canonical name and command class for a command.
204
"""Return the command object for a command.
172
207
If true, plugin commands can override builtins.
175
cmd = _get_cmd_object(cmd_name, plugins_override)
176
# Allow plugins to extend commands
177
for hook in Command.hooks['extend_command']:
210
return _get_cmd_object(cmd_name, plugins_override)
181
212
raise errors.BzrCommandError('unknown command "%s"' % cmd_name)
184
215
def _get_cmd_object(cmd_name, plugins_override=True):
185
"""Worker for get_cmd_object which raises KeyError rather than BzrCommandError."""
186
from bzrlib.externalcommand import ExternalCommand
216
"""Get a command object.
218
:param cmd_name: The name of the command.
219
:param plugins_override: Allow plugins to override builtins.
220
:return: A Command object instance
221
:raises KeyError: If no command is found.
188
223
# We want only 'ascii' command names, but the user may have typed
189
224
# in a Unicode name. In that case, they should just get a
190
225
# 'command not found' error later.
191
226
# In the future, we may actually support Unicode command names.
193
# first look up this command under the specified name
229
for hook in Command.hooks['get_command']:
230
cmd = hook(cmd, cmd_name)
231
if cmd is not None and not plugins_override and not cmd.plugin_name():
232
# We've found a non-plugin command, don't permit it to be
236
for hook in Command.hooks['get_missing_command']:
243
# Allow plugins to extend commands
244
for hook in Command.hooks['extend_command']:
249
def _try_plugin_provider(cmd_name):
250
"""Probe for a plugin provider having cmd_name."""
252
plugin_metadata, provider = probe_for_provider(cmd_name)
253
raise errors.CommandAvailableInPlugin(cmd_name,
254
plugin_metadata, provider)
255
except errors.NoPluginAvailable:
259
def probe_for_provider(cmd_name):
260
"""Look for a provider for cmd_name.
262
:param cmd_name: The command name.
263
:return: plugin_metadata, provider for getting cmd_name.
264
:raises NoPluginAvailable: When no provider can supply the plugin.
266
# look for providers that provide this command but aren't installed
267
for provider in command_providers_registry:
196
return plugin_cmds.get(cmd_name)()
269
return provider.plugin_for_command(cmd_name), provider
270
except errors.NoPluginAvailable:
199
cmds = _get_cmd_dict(plugins_override=False)
272
raise errors.NoPluginAvailable(cmd_name)
275
def _get_bzr_command(cmd_or_None, cmd_name):
276
"""Get a command from bzr's core."""
277
cmds = _builtin_commands()
201
279
return cmds[cmd_name]()
205
for key in plugin_cmds.keys():
206
info = plugin_cmds.get_info(key)
207
if cmd_name in info.aliases:
208
return plugin_cmds.get(key)()
209
282
# look for any command which claims this as an alias
210
283
for real_cmd_name, cmd_class in cmds.iteritems():
211
284
if cmd_name in cmd_class.aliases:
212
285
return cmd_class()
289
def _get_external_command(cmd_or_None, cmd_name):
290
"""Lookup a command that is a shell script."""
291
# Only do external command lookups when no command is found so far.
292
if cmd_or_None is not None:
294
from bzrlib.externalcommand import ExternalCommand
214
295
cmd_obj = ExternalCommand.find_command(cmd_name)
218
# look for plugins that provide this command but aren't installed
219
for provider in command_providers_registry:
221
plugin_metadata = provider.plugin_for_command(cmd_name)
222
except errors.NoPluginAvailable:
225
raise errors.CommandAvailableInPlugin(cmd_name,
226
plugin_metadata, provider)
300
def _get_plugin_command(cmd_or_None, cmd_name):
301
"""Get a command from bzr's plugins."""
303
return plugin_cmds.get(cmd_name)()
306
for key in plugin_cmds.keys():
307
info = plugin_cmds.get_info(key)
308
if cmd_name in info.aliases:
309
return plugin_cmds.get(key)()
230
313
class Command(object):
608
695
"Called after creating a command object to allow modifications "
609
696
"such as adding or removing options, docs etc. Called with the "
610
697
"new bzrlib.commands.Command object.", (1, 13), None))
698
self.create_hook(HookPoint('get_command',
699
"Called when creating a single command. Called with "
700
"(cmd_or_None, command_name). get_command should either return "
701
"the cmd_or_None parameter, or a replacement Command object that "
702
"should be used for the command. Note that the Command.hooks "
703
"hooks are core infrastructure. Many users will prefer to use "
704
"bzrlib.commands.register_command or plugin_cmds.register_lazy.",
706
self.create_hook(HookPoint('get_missing_command',
707
"Called when creating a single command if no command could be "
708
"found. Called with (command_name). get_missing_command should "
709
"either return None, or a Command object to be used for the "
710
"command.", (1, 17), None))
711
self.create_hook(HookPoint('list_commands',
712
"Called when enumerating commands. Called with a set of "
713
"cmd_name strings for all the commands found so far. This set "
714
" is safe to mutate - e.g. to remove a command. "
715
"list_commands should return the updated set of command names.",
612
718
Command.hooks = CommandHooks()