737
by Martin Pool
- add plugin patch, still being integrated |
1 |
*** added file 'bzrlib/plugin.py' |
2 |
--- /dev/null
|
|
3 |
+++ bzrlib/plugin.py
|
|
4 |
@@ -0,0 +1,92 @@
|
|
5 |
+# Copyright (C) 2004, 2005 by Canonical Ltd
|
|
6 |
+
|
|
7 |
+# This program is free software; you can redistribute it and/or modify
|
|
8 |
+# it under the terms of the GNU General Public License as published by
|
|
9 |
+# the Free Software Foundation; either version 2 of the License, or
|
|
10 |
+# (at your option) any later version.
|
|
11 |
+
|
|
12 |
+# This program is distributed in the hope that it will be useful,
|
|
13 |
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14 |
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15 |
+# GNU General Public License for more details.
|
|
16 |
+
|
|
17 |
+# You should have received a copy of the GNU General Public License
|
|
18 |
+# along with this program; if not, write to the Free Software
|
|
19 |
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
20 |
+
|
|
21 |
+
|
|
22 |
+# This module implements plug-in support.
|
|
23 |
+# Any python module in $BZR_PLUGIN_PATH will be imported upon initialization
|
|
24 |
+# of bzrlib (and then forgotten about). In the plugin's main body, it should
|
|
25 |
+# update any bzrlib registries it wants to extend; for example, to add new
|
|
26 |
+# commands, import bzrlib.commands and add your new command to the
|
|
27 |
+# plugin_cmds variable.
|
|
28 |
+
|
|
29 |
+import sys, os, imp
|
|
30 |
+try:
|
|
31 |
+ set
|
|
32 |
+except NameError:
|
|
33 |
+ from sets import Set as set
|
|
34 |
+from bzrlib.trace import log_error
|
|
35 |
+
|
|
36 |
+
|
|
37 |
+def load_plugins():
|
|
38 |
+ """Find all python files which are plugins, and load them
|
|
39 |
+
|
|
40 |
+ The environment variable BZR_PLUGIN_PATH is considered a delimited set of
|
|
41 |
+ paths to look through. Each entry is searched for *.py files (and whatever
|
|
42 |
+ other extensions are used in the platform, such as *.pyd).
|
|
43 |
+ """
|
|
44 |
+ bzrpath = os.environ.get('BZR_PLUGIN_PATH', os.path.expanduser('~/.bzr/plugins'))
|
|
45 |
+
|
|
46 |
+ # The problem with imp.get_suffixes() is that it doesn't include
|
|
47 |
+ # .pyo which is technically valid
|
|
48 |
+ # It also means that "testmodule.so" will show up as both test and testmodule
|
|
49 |
+ # though it is only valid as 'test'
|
|
50 |
+ # but you should be careful, because "testmodule.py" loads as testmodule.
|
|
51 |
+ suffixes = imp.get_suffixes()
|
|
52 |
+ suffixes.append(('.pyo', 'rb', imp.PY_COMPILED))
|
|
53 |
+ package_entries = ['__init__.py', '__init__.pyc', '__init__.pyo']
|
|
54 |
+ for d in bzrpath.split(os.pathsep):
|
|
55 |
+ # going trough them one by one allows different plugins with the same
|
|
56 |
+ # filename in different directories in the path
|
|
57 |
+ if not d:
|
|
58 |
+ continue
|
|
59 |
+ plugin_names = set()
|
|
60 |
+ if not os.path.isdir(d):
|
|
61 |
+ continue
|
|
62 |
+ for f in os.listdir(d):
|
|
63 |
+ path = os.path.join(d, f)
|
|
64 |
+ if os.path.isdir(path):
|
|
65 |
+ for entry in package_entries:
|
|
66 |
+ # This directory should be a package, and thus added to
|
|
67 |
+ # the list
|
|
68 |
+ if os.path.isfile(os.path.join(path, entry)):
|
|
69 |
+ break
|
|
70 |
+ else: # This directory is not a package
|
|
71 |
+ continue
|
|
72 |
+ else:
|
|
73 |
+ for suffix_info in suffixes:
|
|
74 |
+ if f.endswith(suffix_info[0]):
|
|
75 |
+ f = f[:-len(suffix_info[0])]
|
|
76 |
+ if suffix_info[2] == imp.C_EXTENSION and f.endswith('module'):
|
|
77 |
+ f = f[:-len('module')]
|
|
78 |
+ break
|
|
79 |
+ else:
|
|
80 |
+ continue
|
|
81 |
+ plugin_names.add(f)
|
|
82 |
+
|
|
83 |
+ plugin_names = list(plugin_names)
|
|
84 |
+ plugin_names.sort()
|
|
85 |
+ for name in plugin_names:
|
|
86 |
+ try:
|
|
87 |
+ plugin_info = imp.find_module(name, [d])
|
|
88 |
+ try:
|
|
89 |
+ plugin = imp.load_module('bzrlib.plugin.' + name,
|
|
90 |
+ *plugin_info)
|
|
91 |
+ finally:
|
|
92 |
+ if plugin_info[0] is not None:
|
|
93 |
+ plugin_info[0].close()
|
|
94 |
+ except Exception, e:
|
|
95 |
+ log_error('Unable to load plugin: %r from %r\n%s' % (name, d, e))
|
|
96 |
+
|
|
97 |
||
98 |
*** modified file 'bzrlib/__init__.py' |
|
99 |
--- bzrlib/__init__.py
|
|
100 |
+++ bzrlib/__init__.py
|
|
101 |
@@ -23,6 +23,7@@
|
|
102 |
from diff import compare_trees |
|
103 |
from trace import mutter, warning, open_tracefile |
|
104 |
from log import show_log |
|
105 |
+from plugin import load_plugins
|
|
106 |
import add |
|
107 |
||
108 |
BZRDIR = ".bzr" |
|
109 |
@@ -62,4 +63,4 @@
|
|
110 |
return None |
|
111 |
except BzrError: |
|
112 |
return None |
|
113 |
-
|
|
114 |
+
|
|
115 |
||
116 |
*** modified file 'bzrlib/commands.py' |
|
117 |
--- bzrlib/commands.py
|
|
118 |
+++ bzrlib/commands.py
|
|
119 |
@@ -24,6 +24,24 @@
|
|
120 |
from bzrlib.osutils import quotefn |
|
121 |
from bzrlib import Branch, Inventory, InventoryEntry, BZRDIR, \ |
|
122 |
format_date |
|
123 |
+
|
|
124 |
+
|
|
125 |
+plugin_cmds = {}
|
|
126 |
+
|
|
127 |
+
|
|
128 |
+def register_plugin_command(cmd):
|
|
129 |
+ "Utility function to help register a command"
|
|
130 |
+ global plugin_cmds
|
|
131 |
+ k = cmd.__name__
|
|
132 |
+ if k.startswith("cmd_"):
|
|
133 |
+ k_unsquished = _unsquish_command_name(k)
|
|
134 |
+ else:
|
|
135 |
+ k_unsquished = k
|
|
136 |
+ if not plugin_cmds.has_key(k_unsquished):
|
|
137 |
+ plugin_cmds[k_unsquished] = cmd
|
|
138 |
+ else:
|
|
139 |
+ log_error('Two plugins defined the same command: %r' % k)
|
|
140 |
+ log_error('Not loading the one in %r' % sys.modules[cmd.__module__])
|
|
141 |
||
142 |
||
143 |
def _squish_command_name(cmd): |
|
144 |
@@ -68,100 +86,34 @@
|
|
145 |
revs = int(revstr) |
|
146 |
return revs |
|
147 |
||
148 |
-def _find_plugins():
|
|
149 |
- """Find all python files which are plugins, and load their commands
|
|
150 |
- to add to the list of "all commands"
|
|
151 |
-
|
|
152 |
- The environment variable BZRPATH is considered a delimited set of
|
|
153 |
- paths to look through. Each entry is searched for *.py files.
|
|
154 |
- If a directory is found, it is also searched, but they are
|
|
155 |
- not searched recursively. This allows you to revctl the plugins.
|
|
156 |
-
|
|
157 |
- Inside the plugin should be a series of cmd_* function, which inherit from
|
|
158 |
- the bzrlib.commands.Command class.
|
|
159 |
- """
|
|
160 |
- bzrpath = os.environ.get('BZRPLUGINPATH', '')
|
|
161 |
-
|
|
162 |
- plugin_cmds = {}
|
|
163 |
- if not bzrpath:
|
|
164 |
- return plugin_cmds
|
|
165 |
- _platform_extensions = {
|
|
166 |
- 'win32':'.pyd',
|
|
167 |
- 'cygwin':'.dll',
|
|
168 |
- 'darwin':'.dylib',
|
|
169 |
- 'linux2':'.so'
|
|
170 |
- }
|
|
171 |
- if _platform_extensions.has_key(sys.platform):
|
|
172 |
- platform_extension = _platform_extensions[sys.platform]
|
|
173 |
- else:
|
|
174 |
- platform_extension = None
|
|
175 |
- for d in bzrpath.split(os.pathsep):
|
|
176 |
- plugin_names = {} # This should really be a set rather than a dict
|
|
177 |
- for f in os.listdir(d):
|
|
178 |
- if f.endswith('.py'):
|
|
179 |
- f = f[:-3]
|
|
180 |
- elif f.endswith('.pyc') or f.endswith('.pyo'):
|
|
181 |
- f = f[:-4]
|
|
182 |
- elif platform_extension and f.endswith(platform_extension):
|
|
183 |
- f = f[:-len(platform_extension)]
|
|
184 |
- if f.endswidth('module'):
|
|
185 |
- f = f[:-len('module')]
|
|
186 |
- else:
|
|
187 |
- continue
|
|
188 |
- if not plugin_names.has_key(f):
|
|
189 |
- plugin_names[f] = True
|
|
190 |
-
|
|
191 |
- plugin_names = plugin_names.keys()
|
|
192 |
- plugin_names.sort()
|
|
193 |
- try:
|
|
194 |
- sys.path.insert(0, d)
|
|
195 |
- for name in plugin_names:
|
|
196 |
- try:
|
|
197 |
- old_module = None
|
|
198 |
- try:
|
|
199 |
- if sys.modules.has_key(name):
|
|
200 |
- old_module = sys.modules[name]
|
|
201 |
- del sys.modules[name]
|
|
202 |
- plugin = __import__(name, locals())
|
|
203 |
- for k in dir(plugin):
|
|
204 |
- if k.startswith('cmd_'):
|
|
205 |
- k_unsquished = _unsquish_command_name(k)
|
|
206 |
- if not plugin_cmds.has_key(k_unsquished):
|
|
207 |
- plugin_cmds[k_unsquished] = getattr(plugin, k)
|
|
208 |
- else:
|
|
209 |
- log_error('Two plugins defined the same command: %r' % k)
|
|
210 |
- log_error('Not loading the one in %r in dir %r' % (name, d))
|
|
211 |
- finally:
|
|
212 |
- if old_module:
|
|
213 |
- sys.modules[name] = old_module
|
|
214 |
- except ImportError, e:
|
|
215 |
- log_error('Unable to load plugin: %r from %r\n%s' % (name, d, e))
|
|
216 |
- finally:
|
|
217 |
- sys.path.pop(0)
|
|
218 |
- return plugin_cmds
|
|
219 |
-
|
|
220 |
-def _get_cmd_dict(include_plugins=True):
|
|
221 |
+def _get_cmd_dict(plugins_override=True):
|
|
222 |
d = {} |
|
223 |
for k, v in globals().iteritems(): |
|
224 |
if k.startswith("cmd_"): |
|
225 |
d[_unsquish_command_name(k)] = v |
|
226 |
- if include_plugins:
|
|
227 |
- d.update(_find_plugins())
|
|
228 |
+ # If we didn't load plugins, the plugin_cmds dict will be empty
|
|
229 |
+ if plugins_override:
|
|
230 |
+ d.update(plugin_cmds)
|
|
231 |
+ else:
|
|
232 |
+ d2 = {}
|
|
233 |
+ d2.update(plugin_cmds)
|
|
234 |
+ d2.update(d)
|
|
235 |
+ d = d2
|
|
236 |
return d |
|
237 |
||
238 |
-def get_all_cmds(include_plugins=True):
|
|
239 |
+def get_all_cmds(plugins_override=True):
|
|
240 |
"""Return canonical name and class for all registered commands.""" |
|
241 |
- for k, v in _get_cmd_dict(include_plugins=include_plugins).iteritems():
|
|
242 |
+ for k, v in _get_cmd_dict(plugins_override=plugins_override).iteritems():
|
|
243 |
yield k,v |
|
244 |
||
245 |
||
246 |
-def get_cmd_class(cmd,include_plugins=True):
|
|
247 |
+def get_cmd_class(cmd, plugins_override=True):
|
|
248 |
"""Return the canonical name and command class for a command. |
|
249 |
""" |
|
250 |
cmd = str(cmd) # not unicode |
|
251 |
||
252 |
# first look up this command under the specified name |
|
253 |
- cmds = _get_cmd_dict(include_plugins=include_plugins)
|
|
254 |
+ cmds = _get_cmd_dict(plugins_override=plugins_override)
|
|
255 |
try: |
|
256 |
return cmd, cmds[cmd] |
|
257 |
except KeyError: |
|
258 |
@@ -1461,6 +1413,75 @@
|
|
259 |
return argdict |
|
260 |
||
261 |
||
262 |
+def _parse_master_args(argv):
|
|
263 |
+ """Parse the arguments that always go with the original command.
|
|
264 |
+ These are things like bzr --no-plugins, etc.
|
|
265 |
+
|
|
266 |
+ There are now 2 types of option flags. Ones that come *before* the command,
|
|
267 |
+ and ones that come *after* the command.
|
|
268 |
+ Ones coming *before* the command are applied against all possible commands.
|
|
269 |
+ And are generally applied before plugins are loaded.
|
|
270 |
+
|
|
271 |
+ The current list are:
|
|
272 |
+ --builtin Allow plugins to load, but don't let them override builtin commands,
|
|
273 |
+ they will still be allowed if they do not override a builtin.
|
|
274 |
+ --no-plugins Don't load any plugins. This lets you get back to official source
|
|
275 |
+ behavior.
|
|
276 |
+ --profile Enable the hotspot profile before running the command.
|
|
277 |
+ For backwards compatibility, this is also a non-master option.
|
|
278 |
+ --version Spit out the version of bzr that is running and exit.
|
|
279 |
+ This is also a non-master option.
|
|
280 |
+ --help Run help and exit, also a non-master option (I think that should stay, though)
|
|
281 |
+
|
|
282 |
+ >>> argv, opts = _parse_master_args(['bzr', '--test'])
|
|
283 |
+ Traceback (most recent call last):
|
|
284 |
+ ...
|
|
285 |
+ BzrCommandError: Invalid master option: 'test'
|
|
286 |
+ >>> argv, opts = _parse_master_args(['bzr', '--version', 'command'])
|
|
287 |
+ >>> print argv
|
|
288 |
+ ['command']
|
|
289 |
+ >>> print opts['version']
|
|
290 |
+ True
|
|
291 |
+ >>> argv, opts = _parse_master_args(['bzr', '--profile', 'command', '--more-options'])
|
|
292 |
+ >>> print argv
|
|
293 |
+ ['command', '--more-options']
|
|
294 |
+ >>> print opts['profile']
|
|
295 |
+ True
|
|
296 |
+ >>> argv, opts = _parse_master_args(['bzr', '--no-plugins', 'command'])
|
|
297 |
+ >>> print argv
|
|
298 |
+ ['command']
|
|
299 |
+ >>> print opts['no-plugins']
|
|
300 |
+ True
|
|
301 |
+ >>> print opts['profile']
|
|
302 |
+ False
|
|
303 |
+ >>> argv, opts = _parse_master_args(['bzr', 'command', '--profile'])
|
|
304 |
+ >>> print argv
|
|
305 |
+ ['command', '--profile']
|
|
306 |
+ >>> print opts['profile']
|
|
307 |
+ False
|
|
308 |
+ """
|
|
309 |
+ master_opts = {'builtin':False,
|
|
310 |
+ 'no-plugins':False,
|
|
311 |
+ 'version':False,
|
|
312 |
+ 'profile':False,
|
|
313 |
+ 'help':False
|
|
314 |
+ }
|
|
315 |
+
|
|
316 |
+ # This is the point where we could hook into argv[0] to determine
|
|
317 |
+ # what front-end is supposed to be run
|
|
318 |
+ # For now, we are just ignoring it.
|
|
319 |
+ cmd_name = argv.pop(0)
|
|
320 |
+ for arg in argv[:]:
|
|
321 |
+ if arg[:2] != '--': # at the first non-option, we return the rest
|
|
322 |
+ break
|
|
323 |
+ arg = arg[2:] # Remove '--'
|
|
324 |
+ if arg not in master_opts:
|
|
325 |
+ # We could say that this is not an error, that we should
|
|
326 |
+ # just let it be handled by the main section instead
|
|
327 |
+ raise BzrCommandError('Invalid master option: %r' % arg)
|
|
328 |
+ argv.pop(0) # We are consuming this entry
|
|
329 |
+ master_opts[arg] = True
|
|
330 |
+ return argv, master_opts
|
|
331 |
||
332 |
def run_bzr(argv): |
|
333 |
"""Execute a command. |
|
334 |
@@ -1470,22 +1491,21 @@
|
|
335 |
""" |
|
336 |
argv = [a.decode(bzrlib.user_encoding) for a in argv] |
|
337 |
||
338 |
- include_plugins=True
|
|
339 |
try: |
|
340 |
- args, opts = parse_args(argv[1:])
|
|
341 |
- if 'help' in opts:
|
|
342 |
+ argv, master_opts = _parse_master_args(argv)
|
|
343 |
+ if not master_opts['no-plugins']:
|
|
344 |
+ bzrlib.load_plugins()
|
|
345 |
+ args, opts = parse_args(argv)
|
|
346 |
+ if 'help' in opts or master_opts['help']:
|
|
347 |
import help |
|
348 |
if args: |
|
349 |
help.help(args[0]) |
|
350 |
else: |
|
351 |
help.help() |
|
352 |
return 0 |
|
353 |
- elif 'version' in opts:
|
|
354 |
+ elif 'version' in opts or master_opts['version']:
|
|
355 |
show_version() |
|
356 |
return 0 |
|
357 |
- elif args and args[0] == 'builtin':
|
|
358 |
- include_plugins=False
|
|
359 |
- args = args[1:]
|
|
360 |
cmd = str(args.pop(0)) |
|
361 |
except IndexError: |
|
362 |
import help |
|
363 |
@@ -1493,14 +1513,15 @@
|
|
364 |
return 1 |
|
365 |
||
366 |
||
367 |
- canonical_cmd, cmd_class = get_cmd_class(cmd,include_plugins=include_plugins)
|
|
368 |
-
|
|
369 |
- # global option
|
|
370 |
+ plugins_override = not (master_opts['builtin'])
|
|
371 |
+ canonical_cmd, cmd_class = get_cmd_class(cmd, plugins_override=plugins_override)
|
|
372 |
+
|
|
373 |
+ profile = master_opts['profile']
|
|
374 |
+ # For backwards compatibility, I would rather stick with --profile being a
|
|
375 |
+ # master/global option
|
|
376 |
if 'profile' in opts: |
|
377 |
profile = True |
|
378 |
del opts['profile'] |
|
379 |
- else:
|
|
380 |
- profile = False
|
|
381 |
||
382 |
# check options are reasonable |
|
383 |
allowed = cmd_class.takes_options |
|
384 |
||
385 |
*** modified file 'testbzr' |
|
386 |
--- testbzr
|
|
387 |
+++ testbzr
|
|
388 |
@@ -149,6 +149,7 @@
|
|
389 |
"""Run a test involving creating a plugin to load, |
|
390 |
and making sure it is seen properly. |
|
391 |
""" |
|
392 |
+ orig_help = backtick('bzr help commands') # No plugins yet
|
|
393 |
mkdir('plugin_test') |
|
394 |
f = open(os.path.join('plugin_test', 'myplug.py'), 'wb') |
|
395 |
f.write("""import bzrlib, bzrlib.commands |
|
396 |
@@ -157,24 +158,36 @@
|
|
397 |
aliases = ['mplg'] |
|
398 |
def run(self): |
|
399 |
print 'Hello from my plugin' |
|
400 |
+class cmd_myplug_with_opt(bzrlib.commands.Command):
|
|
401 |
+ '''A simple plugin that requires a special option'''
|
|
402 |
+ takes_options = ['aspecialoptionthatdoesntexist']
|
|
403 |
+ def run(self, aspecialoptionthatdoesntexist=None):
|
|
404 |
+ print 'Found: %s' % aspecialoptionthatdoesntexist
|
|
405 |
+
|
|
406 |
+bzrlib.commands.register_plugin_command(cmd_myplug)
|
|
407 |
+bzrlib.commands.register_plugin_command(cmd_myplug_with_opt)
|
|
408 |
+bzrlib.commands.OPTIONS['aspecialoptionthatdoesntexist'] = str
|
|
409 |
""") |
|
410 |
f.close() |
|
411 |
||
412 |
- os.environ['BZRPLUGINPATH'] = os.path.abspath('plugin_test')
|
|
413 |
- help = backtick('bzr help commands')
|
|
414 |
+ os.environ['BZR_PLUGIN_PATH'] = os.path.abspath('plugin_test')
|
|
415 |
+ help = backtick('bzr help commands') #Help with user-visible plugins
|
|
416 |
assert help.find('myplug') != -1 |
|
417 |
assert help.find('Just a simple test plugin.') != -1 |
|
418 |
||
419 |
||
420 |
assert backtick('bzr myplug') == 'Hello from my plugin\n' |
|
421 |
assert backtick('bzr mplg') == 'Hello from my plugin\n' |
|
422 |
+ assert backtick('bzr myplug-with-opt') == 'Found: None\n'
|
|
423 |
+ assert backtick('bzr myplug-with-opt --aspecialoptionthatdoesntexist=2') == 'Found: 2\n'
|
|
424 |
||
425 |
f = open(os.path.join('plugin_test', 'override.py'), 'wb') |
|
426 |
f.write("""import bzrlib, bzrlib.commands |
|
427 |
-class cmd_commit(bzrlib.commands.cmd_commit):
|
|
428 |
- '''Commit changes into a new revision.'''
|
|
429 |
+class cmd_revno(bzrlib.commands.cmd_revno):
|
|
430 |
+ '''Show current revision number.'''
|
|
431 |
def run(self, *args, **kwargs): |
|
432 |
print "I'm sorry dave, you can't do that" |
|
433 |
+ return 1
|
|
434 |
||
435 |
class cmd_help(bzrlib.commands.cmd_help): |
|
436 |
'''Show help on a command or other topic.''' |
|
437 |
@@ -182,16 +195,67 @@
|
|
438 |
print "You have been overridden" |
|
439 |
bzrlib.commands.cmd_help.run(self, *args, **kwargs) |
|
440 |
||
441 |
+bzrlib.commands.register_plugin_command(cmd_revno)
|
|
442 |
+bzrlib.commands.register_plugin_command(cmd_help)
|
|
443 |
""") |
|
444 |
f.close() |
|
445 |
||
446 |
- newhelp = backtick('bzr help commands')
|
|
447 |
+ newhelp = backtick('bzr help commands') # Help with no new commands,
|
|
448 |
assert newhelp.startswith('You have been overridden\n') |
|
449 |
# We added a line, but the rest should work |
|
450 |
assert newhelp[25:] == help |
|
451 |
-
|
|
452 |
- assert backtick('bzr commit -m test') == "I'm sorry dave, you can't do that\n"
|
|
453 |
-
|
|
454 |
+ # Make sure we can get back to the original command
|
|
455 |
+ # Not overridden, and no extra commands present
|
|
456 |
+ assert backtick('bzr --builtin help commands') == help
|
|
457 |
+ assert backtick('bzr --no-plugins help commands') == orig_help
|
|
458 |
+
|
|
459 |
+ assert backtick('bzr revno', retcode=1) == "I'm sorry dave, you can't do that\n"
|
|
460 |
+
|
|
461 |
+ print_txt = '** Loading noop plugin'
|
|
462 |
+ f = open(os.path.join('plugin_test', 'loading.py'), 'wb')
|
|
463 |
+ f.write("""import bzrlib, bzrlib.commands
|
|
464 |
+class cmd_noop(bzrlib.commands.Command):
|
|
465 |
+ def run(self, *args, **kwargs):
|
|
466 |
+ pass
|
|
467 |
+
|
|
468 |
+print %r
|
|
469 |
+bzrlib.commands.register_plugin_command(cmd_noop)
|
|
470 |
+""" % print_txt)
|
|
471 |
+ f.close()
|
|
472 |
+ print_txt += '\n'
|
|
473 |
+
|
|
474 |
+ # Check that --builtin still loads the plugin, and enables it as
|
|
475 |
+ # an extra command, but not as an override
|
|
476 |
+ # and that --no-plugins doesn't load the command at all
|
|
477 |
+ assert backtick('bzr noop') == print_txt
|
|
478 |
+ assert backtick('bzr --builtin help')[:len(print_txt)] == print_txt
|
|
479 |
+ assert backtick('bzr --no-plugins help')[:len(print_txt)] != print_txt
|
|
480 |
+ runcmd('bzr revno', retcode=1)
|
|
481 |
+ runcmd('bzr --builtin revno', retcode=0)
|
|
482 |
+ runcmd('bzr --no-plugins revno', retcode=0)
|
|
483 |
+ runcmd('bzr --builtin noop', retcode=0)
|
|
484 |
+ runcmd('bzr --no-plugins noop', retcode=1)
|
|
485 |
+
|
|
486 |
+ # Check that packages can also be loaded
|
|
487 |
+ test_str = 'packages work'
|
|
488 |
+ os.mkdir(os.path.join('plugin_test', 'testpkg'))
|
|
489 |
+ f = open(os.path.join('plugin_test', 'testpkg', '__init__.py'), 'wb')
|
|
490 |
+ f.write("""import bzrlib, bzrlib.commands
|
|
491 |
+class testpkgcmd(bzrlib.commands.Command):
|
|
492 |
+ def run(self, *args, **kwargs):
|
|
493 |
+ print %r
|
|
494 |
+
|
|
495 |
+bzrlib.commands.register_plugin_command(testpkgcmd)
|
|
496 |
+""" % test_str)
|
|
497 |
+ f.close()
|
|
498 |
+ test_str += '\n'
|
|
499 |
+ assert backtick('bzr testpkgcmd') == print_txt + test_str
|
|
500 |
+ runcmd('bzr --no-plugins testpkgcmd', retcode=1)
|
|
501 |
+
|
|
502 |
+ # Make sure that setting BZR_PLUGIN_PATH to empty is the same as using --no-plugins
|
|
503 |
+ os.environ['BZR_PLUGIN_PATH'] = ''
|
|
504 |
+ assert backtick('bzr help commands') == orig_help
|
|
505 |
+
|
|
506 |
shutil.rmtree('plugin_test') |
|
507 |
||
508 |
try: |
|
509 |
@@ -221,6 +285,9 @@
|
|
510 |
||
511 |
runcmd(['mkdir', TESTDIR]) |
|
512 |
cd(TESTDIR) |
|
513 |
+ # This means that any command that is naively run in this directory
|
|
514 |
+ # Won't affect the parent directory.
|
|
515 |
+ runcmd('bzr init')
|
|
516 |
test_root = os.getcwd() |
|
517 |
||
518 |
progress("introductory commands") |
|
519 |