32
def register_plugin_command(cmd):
33
"Utility function to help register a command"
36
if k.startswith("cmd_"):
37
k_unsquished = _unsquish_command_name(k)
40
if not plugin_cmds.has_key(k_unsquished):
41
plugin_cmds[k_unsquished] = cmd
43
log_error('Two plugins defined the same command: %r' % k)
44
log_error('Not loading the one in %r' % sys.modules[cmd.__module__])
29
47
def _squish_command_name(cmd):
30
48
return 'cmd_' + cmd.replace('-', '_')
72
"""Find all python files which are plugins, and load their commands
73
to add to the list of "all commands"
75
The environment variable BZRPATH is considered a delimited set of
76
paths to look through. Each entry is searched for *.py files.
77
If a directory is found, it is also searched, but they are
78
not searched recursively. This allows you to revctl the plugins.
80
Inside the plugin should be a series of cmd_* function, which inherit from
81
the bzrlib.commands.Command class.
83
bzrpath = os.environ.get('BZRPLUGINPATH', '')
88
_platform_extensions = {
94
if _platform_extensions.has_key(sys.platform):
95
platform_extension = _platform_extensions[sys.platform]
97
platform_extension = None
98
for d in bzrpath.split(os.pathsep):
99
plugin_names = {} # This should really be a set rather than a dict
100
for f in os.listdir(d):
101
if f.endswith('.py'):
103
elif f.endswith('.pyc') or f.endswith('.pyo'):
105
elif platform_extension and f.endswith(platform_extension):
106
f = f[:-len(platform_extension)]
107
if f.endswidth('module'):
108
f = f[:-len('module')]
111
if not plugin_names.has_key(f):
112
plugin_names[f] = True
114
plugin_names = plugin_names.keys()
117
sys.path.insert(0, d)
118
for name in plugin_names:
122
if sys.modules.has_key(name):
123
old_module = sys.modules[name]
124
del sys.modules[name]
125
plugin = __import__(name, locals())
126
for k in dir(plugin):
127
if k.startswith('cmd_'):
128
k_unsquished = _unsquish_command_name(k)
129
if not plugin_cmds.has_key(k_unsquished):
130
plugin_cmds[k_unsquished] = getattr(plugin, k)
132
log_error('Two plugins defined the same command: %r' % k)
133
log_error('Not loading the one in %r in dir %r' % (name, d))
136
sys.modules[name] = old_module
137
except ImportError, e:
138
log_error('Unable to load plugin: %r from %r\n%s' % (name, d, e))
143
def _get_cmd_dict(include_plugins=True):
91
def _get_cmd_dict(plugins_override=True):
145
93
for k, v in globals().iteritems():
146
94
if k.startswith("cmd_"):
147
95
d[_unsquish_command_name(k)] = v
149
d.update(_find_plugins())
96
# If we didn't load plugins, the plugin_cmds dict will be empty
100
d2 = plugin_cmds.copy()
152
def get_all_cmds(include_plugins=True):
106
def get_all_cmds(plugins_override=True):
153
107
"""Return canonical name and class for all registered commands."""
154
for k, v in _get_cmd_dict(include_plugins=include_plugins).iteritems():
108
for k, v in _get_cmd_dict(plugins_override=plugins_override).iteritems():
158
def get_cmd_class(cmd,include_plugins=True):
112
def get_cmd_class(cmd, plugins_override=True):
159
113
"""Return the canonical name and command class for a command.
161
115
cmd = str(cmd) # not unicode
163
117
# first look up this command under the specified name
164
cmds = _get_cmd_dict(include_plugins=include_plugins)
118
cmds = _get_cmd_dict(plugins_override=plugins_override)
166
120
return cmd, cmds[cmd]
1429
def _parse_master_args(argv):
1430
"""Parse the arguments that always go with the original command.
1431
These are things like bzr --no-plugins, etc.
1433
There are now 2 types of option flags. Ones that come *before* the command,
1434
and ones that come *after* the command.
1435
Ones coming *before* the command are applied against all possible commands.
1436
And are generally applied before plugins are loaded.
1438
The current list are:
1439
--builtin Allow plugins to load, but don't let them override builtin commands,
1440
they will still be allowed if they do not override a builtin.
1441
--no-plugins Don't load any plugins. This lets you get back to official source
1443
--profile Enable the hotspot profile before running the command.
1444
For backwards compatibility, this is also a non-master option.
1445
--version Spit out the version of bzr that is running and exit.
1446
This is also a non-master option.
1447
--help Run help and exit, also a non-master option (I think that should stay, though)
1449
>>> argv, opts = _parse_master_args(['bzr', '--test'])
1450
Traceback (most recent call last):
1452
BzrCommandError: Invalid master option: 'test'
1453
>>> argv, opts = _parse_master_args(['bzr', '--version', 'command'])
1456
>>> print opts['version']
1458
>>> argv, opts = _parse_master_args(['bzr', '--profile', 'command', '--more-options'])
1460
['command', '--more-options']
1461
>>> print opts['profile']
1463
>>> argv, opts = _parse_master_args(['bzr', '--no-plugins', 'command'])
1466
>>> print opts['no-plugins']
1468
>>> print opts['profile']
1470
>>> argv, opts = _parse_master_args(['bzr', 'command', '--profile'])
1472
['command', '--profile']
1473
>>> print opts['profile']
1476
master_opts = {'builtin':False,
1483
# This is the point where we could hook into argv[0] to determine
1484
# what front-end is supposed to be run
1485
# For now, we are just ignoring it.
1486
cmd_name = argv.pop(0)
1488
if arg[:2] != '--': # at the first non-option, we return the rest
1490
arg = arg[2:] # Remove '--'
1491
if arg not in master_opts:
1492
# We could say that this is not an error, that we should
1493
# just let it be handled by the main section instead
1494
raise BzrCommandError('Invalid master option: %r' % arg)
1495
argv.pop(0) # We are consuming this entry
1496
master_opts[arg] = True
1497
return argv, master_opts
1476
1501
def run_bzr(argv):
1477
1502
"""Execute a command.
1482
1507
argv = [a.decode(bzrlib.user_encoding) for a in argv]
1484
include_plugins=True
1486
args, opts = parse_args(argv[1:])
1510
# some options like --builtin and --no-plugins have special effects
1511
argv, master_opts = _parse_master_args(argv)
1512
if 'no-plugins' not in master_opts:
1513
bzrlib.load_plugins()
1515
args, opts = parse_args(argv)
1517
if master_opts['help']:
1518
from bzrlib.help import help
1487
1525
if 'help' in opts:
1526
from bzrlib.help import help
1494
1532
elif 'version' in opts:
1507
canonical_cmd, cmd_class = get_cmd_class(cmd,include_plugins=include_plugins)
1545
plugins_override = not (master_opts['builtin'])
1546
canonical_cmd, cmd_class = get_cmd_class(cmd, plugins_override=plugins_override)
1548
profile = master_opts['profile']
1549
# For backwards compatibility, I would rather stick with --profile being a
1550
# master/global option
1510
1551
if 'profile' in opts:
1512
1553
del opts['profile']
1516
1555
# check options are reasonable
1517
1556
allowed = cmd_class.takes_options