By convention, most plugins are named bzr-xxx and are installed into a directory called xxx. Note that the directory name must be a legal Python package name, so a plugin called bzr-xxx-yyy need to be installed into a directory called xxx_yyy, i.e. ‘-‘ in a plugin name gets mapped to an underscore in the directory name.
We encourage plugin authors to make their plugins publicly available under the same license as Bazaar itself, namely GPL v2. However, there is no requirement to do so. You are free to create Bazaar plugins for private or internal use within your company and not distribute them.
By sharing your work, a larger number of people benefit. In our experience, plugin developers also benefit heavily by having more users involved in the design, testing, bug fixing and longer term maintenance. In other words, sharing leads to a better plugin faster.
If you decide to make your plugin available to others, you are welcome to have it hosted on Launchpad and added to our plugins registry. Non-experimental plugins that you or others in the community can support may also be added to the Plugins Guide, i.e. inclusion in the Guide implies a certain degree of this works as advertised.
To learn about Launchpad project registration, see https://help.launchpad.net/Projects/Registering.
To add your plugin to the registry:
A Bazaar developer will review your change and make some basic checks, e.g. the one line summary (purpose) is clear and the branch URL is correct. Once merged, your plugin will be registered and should appear shortly afterwards in the generated web page.
Information on adding your plugin to this guide is provided later in this document.
To ensure your plugin under development is available to Bazaar, set the BZR_PLUGIN_PATH environment variable to its parent directory. Alternatively, you may wish to develop your plugin within a directory under your personal plugins area (~/.bazaar/plugins on GNU/Linux) or put a symbolic link in that area pointing to your plugin under test. Finally you can use BZR_PLUGINS_AT to point to a specific directory for a specific plugin (separated by your platform’s value of os.pathsep), e.g.
You can disable loading plugins with BZR_DISABLE_PLUGINS.
If you want to stop loading all but installed plugins you can use:
BZR_PLUGIN_PATH=-site
We also encourage plugin developers to provide tests for their plugin. When you run bzr selftest, Bazaar will scan all its plugins to see if they contain a function named test_suite(). For each plugin that does, it calls the function and adds any resulting tests to the master test suite. To run just the tests for plugin xxx, the command is:
bzr selftest bp.xxx
Plugins in this guide have their documentation automatically generated from the online help provided for a plugin. Sections are ordered as follows:
High level help is specified in the docstring for the __init__.py module. You can register plugin-specific help topics in __init__.py like this:
_xxx_tutorial = """XXX Tutorial
Welcome to xxx, your new best friend. ...
"""
topic_registry.register('xxx-tutorial',
_xxx_tutorial,
'How to use xxx')
Command level help is specified in the docstring for the relevant cmd_xxx Command class.
Note
The final documentation needs to be in ReST format. Keep in mind though that the documentation should also be readable via bzr help xxx so it’s best to keep markup to a reasonable minimum.
Hooks let you provide custom code at certain processing points. The available hook point are documented in the User Reference.
Adding a new hook is done with, for example:
import bzrlib.branch
bzrlib.branch.Branch.hooks.install_named_hook('post_push', post_push_hook,
'My post_push hook')
For more information on how to write hooks, see http://doc.bazaar-vcs.org/development/en/user-guide/hooks.html.
Bazaar commands are defined as subclasses of bzrlib.commands.Command, the command name is specified by the name of the subclass, and they must be registered into bzr with the bzrlib.commands.register_command function at module import time.
To define the bzr foo-bar command:
from bzrlib.commands import Command, register_command
class cmd_foo_bar(Command):
# see bzrlib/builtins.py for information about what to put here
pass
register_command(cmd_foo_bar)
If the class name starts with cmd_, the prefix will get dropped and _ will be replaced by - characters.
TO BE DOCUMENTED.
TO BE DOCUMENTED. Once supported, explain how to:
Plugin data falls into several categories:
Configuration settings are often stored in branch.conf, locations.conf or bazaar.conf.
User-visible data for a plugin called xxx should be stored in .bzrmeta/xxx. If mutiple files are desirable, make .bzrmeta/xxx a directory or give them a common prefix within .bzrmeta, e.g. xxx-foo, xxx-bar.
Data managed behind the scenes should be stored in .bzr. Depending on the nature of the data, it may belong in a subdirectory within there, e.g. checkout, branch or repository. It’s your responsibility to ensure behind-the-scenes data is propagated and merged appropriately via custom code. You may want to use existing hooks for this or ask for new hooks to help. The Branch Baggage feature may assist as well once implemented.
It is highly recommended that plugins define a version number. This is displayed by bzr plugins and by the qplugins GUI dialog. To do this, define version_info in __init__.py like this:
version_info = (1, 2, 0, 'beta', 1)
Plugins can also declare other useful metadata such as a mimimum bzrlib version, new transports and storage formats. See Plugin API for details.
When bzr starts up, it imports every plugin, so plugins can degrade performance when they’re not being used. However, sub-modules are not loaded, only the main name.
One way you can avoid this slowdown is by putting most of your code in sub-modules, so that the plugin, itself, is small. All you really need in the __init__.py is the plugin’s Command classes, the commands to register them, and the optional test_suite().
Another way to reduce your plugin’s overhead is to use the bzrlib lazy_import functionality. That looks something like this:
from bzrlib.lazy_import import lazy_import
lazy_import(globals(), """
from bzrlib import (
branch as _mod_branch,
option,
workingtree,
)
""")
Lazy importing only works for packages and modules, not classes or functions. It defers the import until you actually need it.
To add your (registered) plugin to the Plugins Guide, submit a merge proposal to lp:bzr-alldocs. Here are the steps to follow:
Use scripts/document-plugin.py to generate plugins/en/xxx-plugin.txt. To do this, run the above script in either the top level directory (where plugins-registry.ini is) or in the plugins/en directory, passing the plugin name as the argument.
Add xxx-plugin to the relevant category in plugins/en/index.txt.
Test your changes:
cd plugins/en
make html
Open _build/html/index.html in your web browser.
Check your plugin appears as expected and it's help formatted correctly.
Add the new file and commit the changes.
Submit a merge proposal with your changes.
Integrating with Bazaar explains how to do such operations as add, commit, log and more.
Reference documentation on some key APIs is provided below. For a more detailed reference, see the complete bzrlib API documentation.
Base class for commands. Commands are the heart of the command-line bzr interface.
The command object mostly handles the mapping of command-line parameters into one or more bzrlib operations, and of the results into textual output.
Commands normally don’t have any state. All their arguments are passed in to the run method. (Subclasses may take a different policy if the behaviour of the instance needs to depend on e.g. a shell plugin and not just its Python class.)
The docstring for an actual command should give a single-line summary, then a complete description of the command. A grammar description will be inserted.
List of argument forms, marked with whether they are optional, repeated, etc.
For example: ['to_location', 'from_branch?', 'file*'] means:
Actually run the command. This is invoked with the options and arguments bound to keyword parameters.
Return 0 or None if the command was successful, or a non-zero shell error code if not. It’s OK for this method to allow an exception to raise up.
Utility function to help register a command.