summaryrefslogtreecommitdiff
path: root/doc/developers/plugin-api.txt
diff options
context:
space:
mode:
Diffstat (limited to 'doc/developers/plugin-api.txt')
-rw-r--r--doc/developers/plugin-api.txt262
1 files changed, 262 insertions, 0 deletions
diff --git a/doc/developers/plugin-api.txt b/doc/developers/plugin-api.txt
new file mode 100644
index 0000000..8915487
--- /dev/null
+++ b/doc/developers/plugin-api.txt
@@ -0,0 +1,262 @@
+==========
+Plugin API
+==========
+
+
+
+:Date: 2009-01-23
+
+.. contents::
+
+Introduction
+============
+
+bzrlib has a very flexible internal structure allowing plugins for many
+operations. Plugins can add commands, new storage formats, diff and merge
+features and more. This document provides an overview of the API and
+conventions for plugin authors.
+
+If you're writing a plugin and have questions not addressed by this
+document, please ask us.
+
+See also
+--------
+
+ * `Bazaar Developer Documentation Catalog <../index.html>`_.
+ * `Bazaar Plugins Guide <http://doc.bazaar.canonical.com/plugins/en/plugin-development.html>`_ for
+ more suggestions about particular APIs.
+
+
+Structure of a plugin
+=====================
+
+Plugins are Python modules under ``bzrlib.plugins``. They can be installed
+either into the PYTHONPATH in that location, or in ~/.bazaar/plugins.
+
+Plugins should have a setup.py.
+
+As for other Python modules, the name of the directory must match the
+expected name of the plugin.
+
+
+Plugin metadata before installation
+===================================
+
+Plugins can export a summary of what they provide, and what versions of bzrlib
+they are compatible with. This allows tools to be written to work with plugins,
+such as to generate a directory of plugins, or install them via a
+symlink/checkout to ~/.bazaar/plugins.
+
+This interface allows bzr to interrogate a plugin without actually loading
+it. This is useful because loading a plugin may have side effects such
+as registering or overriding commands, or the plugin may raise an error,
+if for example a prerequisite is not present.
+
+
+Metadata protocol
+-----------------
+
+A plugin that supports the bzr plugin metadata protocol will do two
+things. Firstly, the ``setup.py`` for the plugin will guard the call to
+``setup()``::
+
+ if __name__ == 'main':
+ setup(...)
+
+Secondly, the setup module will have one or more of the following variables
+present at module scope. Any variables that are missing will be given the
+defaults from the table. An example of every variable is provided after
+the full list.
+
++------------------------+---------+----------------------------------------+
+| Variable | Default | Definition |
++========================+=========+========================================+
+| bzr_plugin_name | None | The name the plugin package should be |
+| | | given on disk. The plugin is then |
+| | | available to python at |
+| | | bzrlib.plugins.NAME |
++------------------------+---------+----------------------------------------+
+| bzr_commands | [] | A list of the commands that the plugin |
+| | | provides. Commands that already exist |
+| | | in bzr and are decorated by the plugin |
+| | | do not need to be listed (but it is not|
+| | | harmful if you do list them). |
++------------------------+---------+----------------------------------------+
+| bzr_plugin_version | None | A version_info 5-tuple with the plugins|
+| | | version. |
++------------------------+---------+----------------------------------------+
+| bzr_minimum_version | None | A version_info 3-tuple for comparison |
+| | | with the bzrlib minimum and current |
+| | | version, for determining likely |
+| | | compatibility. |
++------------------------+---------+----------------------------------------+
+| bzr_maximum_version | None | A version_info 3-tuple like |
+| | | bzr_minimum_version but checking the |
+| | | upper limits supported. |
++------------------------+---------+----------------------------------------+
+| bzr_control_formats | {} | A dictionary of descriptions of version|
+| | | control directories. See |
+| | | `Control Formats` below. |
++------------------------+---------+----------------------------------------+
+| bzr_checkout_formats | {} | A dictionary of tree_format_string -> |
+| | | human description strings, for tree |
+| | | formats that drop into the |
+| | | ``.bzr/checkout`` metadir system. |
++------------------------+---------+----------------------------------------+
+| bzr_branch_formats | {} | As bzr_checkout_formats but for |
+| | | branches. |
++------------------------+---------+----------------------------------------+
+| bzr_repository_formats | {} | As bzr_checkout_formats but for |
+| | | repositories. |
++------------------------+---------+----------------------------------------+
+| bzr_transports | [] | URL prefixes for which this plugin |
+| | | will register transports. |
++------------------------+---------+----------------------------------------+
+
+Control Formats
+---------------
+
+Because disk format detection for formats that bzr does not understand at
+all can be useful, we allow a declarative description of the shape of a
+control directory. Each description has a name for showing to users, and a
+dictonary of relative paths, and the content needed at each path. Paths
+that end in '/' are required to be directories and the value for that key
+is ignored. Other paths are required to be regular files, and the value
+for that key is either None, in which case the file is statted but the
+content is ignored, or a literal string which is compared against for
+the content of the file. Thus::
+
+ # (look for a .hg directory)
+ bzr_control_formats = {"Mercurial":{'.hg/': None}}
+
+ # (look for a file called .svn/format with contents 4\n).
+ bzr_control_formats = {"Subversion":{'.svn/format': '4\n'}}
+
+
+Example
+-------
+
+An example setup.py follows::
+
+ #!/usr/bin/env python2.4
+ from distutils.core import setup
+
+ bzr_plugin_name = 'demo'
+ bzr_commands = [
+ 'new-command',
+ ]
+
+ bzr_branch_formats = {
+ "Branch label on disk\n":"demo branch",
+ }
+
+ bzr_control_formats = {"Subversion":{'.svn/format': '4\n'}}
+
+ bzr_transports = ["hg+ssh://"]
+
+ bzr_plugin_version = (1, 3, 0, 'dev', 0)
+ bzr_minimum_version = (1, 0, 0)
+
+ if __name__ == 'main':
+ setup(name="Demo",
+ version="1.3.0dev0",
+ description="Demo plugin for plugin metadata.",
+ author="Canonical Ltd",
+ author_email="bazaar@lists.canonical.com",
+ license = "GNU GPL v2",
+ url="https://launchpad.net/bzr-demo",
+ packages=['bzrlib.plugins.demo',
+ 'bzrlib.plugins.demo.tests',
+ ],
+ package_dir={'bzrlib.plugins.demo': '.'})
+
+
+Plugin metadata after installation
+==================================
+
+After a plugin has been installed, metadata can be more easily obtained by
+looking inside the module object -- in other words, for variables defined
+in the plugin's ``__init__.py``.
+
+Help and documentation
+----------------------
+
+The module docstring is used as the plugin description shown by ``bzr
+plugins``. As with all Python docstrings, the first line should be a
+short complete sentence summarizing the plugin. The full docstring is
+shown by ``bzr help PLUGIN_NAME``.
+
+This is a user-visible docstring so should be prefixed with ``__doc__ =``
+to ensure help works under ``python -OO`` with docstrings stripped.
+
+API version
+-----------
+
+Plugins can and should declare that they depend on a particular version of
+bzrlib like so::
+
+ from bzrlib.api import require_api
+
+ require_api(bzrlib, (1, 11, 0))
+
+Please see `API versioning <api-versioning.html>`_ for more details on the API
+metadata protocol used by bzrlib.
+
+Plugin version
+--------------
+
+The plugin should expose a version tuple to describe its own version.
+Some plugins use a version number that corresponds to the version of bzr
+they're released against, but you can use whatever you want. For example::
+
+ version_info = (1, 10, 0)
+
+
+Detecting whether code's being loaded as a plugin
+-------------------------------------------------
+
+You may have a Python module that can be used as a bzr plugin and also in
+other places. To detect whether the module is being loaded by bzr, use
+something like this::
+
+ if __name__ == 'bzrlib.plugins.loggerhead':
+ # register with bzrlib...
+
+
+Plugin performance
+==================
+
+Plugins should avoid doing work or loading code from the plugin or
+external libraries, if they're just installed but not actually active,
+because this slows down every invocation of bzr. The bzrlib APIs
+generally allow the plugin to 'lazily' register methods to invoke if a
+particular disk format or seen or a particular command is run.
+
+
+Plugin registrations
+====================
+
+The plugin ``__init__.py`` runs when the plugin is loaded during bzr
+startup. Generally the plugin won't want to actually do anything at this
+time other than register or override functions to be called later.
+
+The plugin can import bzrlib and call any function.
+Some interesting APIs are described in `Bazaar Plugins Guide <http://doc.bazaar.canonical.com/plugins/en/plugin-development.html>`_.
+
+
+Publishing your plugin
+======================
+
+When your plugin is basically working you might like to share it with
+other people. Here are some steps to consider:
+
+ * make a project on Launchpad.net like
+ <https://launchpad.net/bzr-fastimport>
+ and publish the branches or tarballs there
+
+ * include the plugin in <http://wiki.bazaar.canonical.com/BzrPlugins>
+
+ * post about it to the ``bazaar-announce`` list at ``lists.canonical.com``
+
+..
+ vim: ft=rst tw=74 ai shiftwidth=4