|
26.1.5
by Ian Clatworthy
Add plugin installation and development sections under Introduction |
1 |
Developing a plugin |
2 |
=================== |
|
3 |
||
4 |
Naming |
|
5 |
------ |
|
6 |
||
7 |
By convention, most plugins are named bzr-xxx and are installed into a |
|
8 |
directory called xxx. Note that the directory name must be a legal |
|
9 |
Python package name, so a plugin called bzr-xxx-yyy need to be installed |
|
10 |
into a directory called xxx_yyy, i.e. '-' in a plugin name gets mapped to |
|
11 |
an underscore in the directory name. |
|
12 |
||
13 |
||
14 |
Licensing |
|
15 |
--------- |
|
16 |
||
17 |
We encourage plugin authors to make their plugins publicly available |
|
18 |
under the same license as Bazaar itself, namely GPL v2. However, there |
|
19 |
is no requirement to do so. You are free to create Bazaar plugins for |
|
20 |
private or internal use within your company and not distribute them. |
|
21 |
||
22 |
By sharing your work, a larger number of people benefit. In our experience, |
|
23 |
plugin developers also benefit heavily by having more users involved in |
|
24 |
the design, testing, bug fixing and longer term maintenance. In other words, |
|
25 |
sharing leads to a better plugin faster. |
|
26 |
||
27 |
||
28 |
Registration |
|
29 |
------------ |
|
30 |
||
31 |
If you decide to make your plugin available to others, you are welcome to |
|
32 |
have it hosted on Launchpad and added to our plugins registry. |
|
33 |
Non-experimental plugins that you or others in the community can support |
|
34 |
may also be added to the Plugins Guide, i.e. inclusion in the Guide implies |
|
35 |
a certain degree of *this works as advertised*. |
|
36 |
||
37 |
To learn about Launchpad project registration, see |
|
38 |
https://help.launchpad.net/Projects/Registering. |
|
39 |
||
40 |
To add your plugin to the registry: |
|
41 |
||
42 |
1. Fetch a copy of the lp:bzr-alldocs project. |
|
43 |
2. Edit plugin-registry.ini and commit the change. |
|
44 |
3. Submit a merge proposal. |
|
45 |
||
46 |
A Bazaar developer will review your change and make some basic checks, e.g. |
|
47 |
the one line summary (``purpose``) is clear and the branch URL is correct. |
|
48 |
Once merged, your plugin will be registered and should appear shortly |
|
49 |
afterwards in the generated web page. |
|
50 |
||
51 |
Information on adding your plugin to this guide is provided later in this |
|
52 |
document. |
|
53 |
||
54 |
||
55 |
Testing |
|
56 |
------- |
|
57 |
||
58 |
To ensure your plugin under development is available to Bazaar, set |
|
59 |
the ``BZR_PLUGIN_PATH`` environment variable to its parent directory. |
|
60 |
Alternatively, you may wish to develop your plugin within a directory |
|
61 |
under your personal plugins area (``~/.bazaar/plugins`` on GNU/Linux) |
|
|
68
by Jonathan Riddell
expand documentation for using environment variables to specify which plugins to load |
62 |
or put a symbolic link in that area pointing to your plugin under |
63 |
test. Finally you can use ``BZR_PLUGINS_AT`` to point to a specific |
|
64 |
directory for a specific plugin (separated by your platform's value of |
|
65 |
os.pathsep), e.g. |
|
66 |
||
67 |
export BZR_PLUGINS_AT=qbzr@/home/me/qbzr:explorer@/home/me/explorer |
|
68 |
||
69 |
You can disable loading plugins with ``BZR_DISABLE_PLUGINS``. |
|
70 |
||
71 |
If you want to stop loading all but installed plugins you can use: |
|
72 |
||
73 |
BZR_PLUGIN_PATH=-site |
|
|
26.1.5
by Ian Clatworthy
Add plugin installation and development sections under Introduction |
74 |
|
75 |
We also encourage plugin developers to provide tests for their plugin. |
|
76 |
When you run ``bzr selftest``, Bazaar will scan all its plugins to see if |
|
77 |
they contain a function named ``test_suite()``. For each plugin that does, |
|
78 |
it calls the function and adds any resulting tests to the master test suite. |
|
79 |
To run just the tests for plugin xxx, the command is:: |
|
80 |
||
81 |
bzr selftest bp.xxx |
|
82 |
||
83 |
||
84 |
Providing help |
|
85 |
-------------- |
|
86 |
||
87 |
Plugins in this guide have their documentation automatically |
|
88 |
generated from the online help provided for a plugin. Sections are |
|
89 |
ordered as follows: |
|
90 |
||
91 |
1. High level introduction |
|
|
26.1.11
by Ian Clatworthy
Update the dev guide to note that plugin-specific topics aren't included yet |
92 |
2. Plugin-specific help topics (COMING SOON) |
|
26.1.5
by Ian Clatworthy
Add plugin installation and development sections under Introduction |
93 |
3. Commands defined or extended by the plugin. |
94 |
||
95 |
High level help is specified in the docstring for the ``__init__.py`` module. |
|
96 |
You can register plugin-specific help topics in ``__init__.py`` like this:: |
|
97 |
||
98 |
_xxx_tutorial = """XXX Tutorial |
|
99 |
||
100 |
Welcome to xxx, your new best friend. ... |
|
101 |
""" |
|
102 |
topic_registry.register('xxx-tutorial',
|
|
103 |
_xxx_tutorial, |
|
104 |
'How to use xxx') |
|
105 |
||
106 |
Command level help is specified in the docstring for the relevant |
|
107 |
``cmd_xxx`` Command class. |
|
108 |
||
109 |
.. note:: |
|
110 |
||
111 |
The final documentation needs to be in ReST format. Keep in mind though |
|
112 |
that the documentation should also be readable via ``bzr help xxx`` so |
|
113 |
it's best to keep markup to a reasonable minimum. |
|
114 |
||
115 |
||
116 |
Providing custom code via hooks |
|
117 |
------------------------------- |
|
118 |
||
119 |
Hooks let you provide custom code at certain processing points. |
|
120 |
The available hook point are documented in the `User Reference |
|
121 |
<http://doc.bazaar-vcs.org/development/en/user-reference/index.html#hooks>`_. |
|
122 |
||
123 |
Adding a new hook is done with, for example:: |
|
124 |
||
125 |
import bzrlib.branch |
|
126 |
bzrlib.branch.Branch.hooks.install_named_hook('post_push', post_push_hook,
|
|
127 |
'My post_push hook') |
|
128 |
||
129 |
For more information on how to write hooks, |
|
130 |
see http://doc.bazaar-vcs.org/development/en/user-guide/hooks.html. |
|
131 |
||
132 |
||
133 |
Defining a new command |
|
134 |
---------------------- |
|
135 |
||
136 |
Bazaar commands are defined as subclasses of ``bzrlib.commands.Command``, the |
|
137 |
command name is specified by the name of the subclass, and they must be |
|
138 |
registered into ``bzr`` with the ``bzrlib.commands.register_command`` function |
|
139 |
at module import time. |
|
140 |
||
141 |
To define the ``bzr foo-bar`` command:: |
|
142 |
||
143 |
from bzrlib.commands import Command, register_command |
|
144 |
||
145 |
class cmd_foo_bar(Command): |
|
146 |
# see bzrlib/builtins.py for information about what to put here |
|
147 |
pass |
|
148 |
||
149 |
register_command(cmd_foo_bar) |
|
150 |
||
151 |
If the class name starts with ``cmd_``, the prefix will get dropped |
|
152 |
and ``_`` will be replaced by ``-`` characters. |
|
153 |
||
154 |
||
155 |
Extending an existing command |
|
156 |
----------------------------- |
|
157 |
||
158 |
TO BE DOCUMENTED. |
|
159 |
||
160 |
||
161 |
GUI integration |
|
162 |
--------------- |
|
163 |
||
164 |
TO BE DOCUMENTED. Once supported, explain how to: |
|
165 |
||
166 |
* Register a toolset in the toolbox, providing easy access to new commands. |
|
167 |
* Define custom widgets for command options in qrun. |
|
168 |
||
169 |
||
170 |
Managing data |
|
171 |
------------- |
|
172 |
||
173 |
Plugin data falls into several categories: |
|
174 |
||
175 |
* Configuration settings. |
|
176 |
* Data the user can see and version control. |
|
177 |
* Data behind the scenes. |
|
178 |
||
179 |
Configuration settings are often stored in ``branch.conf``, |
|
180 |
``locations.conf`` or ``bazaar.conf``. |
|
181 |
||
182 |
User-visible data for a plugin called xxx should be stored in |
|
183 |
``.bzrmeta/xxx``. If mutiple files are desirable, make ``.bzrmeta/xxx`` |
|
184 |
a directory or give them a common prefix within ``.bzrmeta``, e.g. |
|
185 |
``xxx-foo``, ``xxx-bar``. |
|
186 |
||
187 |
Data managed behind the scenes should be stored in ``.bzr``. |
|
188 |
Depending on the nature of the data, it may belong in a subdirectory |
|
189 |
within there, e.g. ``checkout``, ``branch`` or ``repository``. |
|
190 |
It's your responsibility to ensure behind-the-scenes data is |
|
191 |
propagated and merged appropriately via custom code. You may want |
|
192 |
to use existing hooks for this or ask for new hooks to help. The |
|
193 |
`Branch Baggage <http://wiki.bazaar.canonical.com/DraftSpecs/BranchBaggage>`_ |
|
194 |
feature may assist as well once implemented. |
|
195 |
||
196 |
||
197 |
Useful metadata |
|
198 |
--------------- |
|
199 |
||
200 |
It is highly recommended that plugins define a version number. This |
|
201 |
is displayed by ``bzr plugins`` and by the ``qplugins`` GUI dialog. |
|
202 |
To do this, define ``version_info`` in ``__init__.py`` like this:: |
|
203 |
||
204 |
version_info = (1, 2, 0, 'beta', 1) |
|
205 |
||
206 |
Plugins can also declare other useful metadata such as a mimimum |
|
207 |
bzrlib version, new transports and storage formats. See |
|
208 |
`Plugin API <http://doc.bazaar-vcs.org/bzr.dev/developers/plugin-api.html>`_ |
|
209 |
for details. |
|
210 |
||
211 |
||
212 |
Performance tips |
|
213 |
---------------- |
|
214 |
||
215 |
When bzr starts up, it imports every plugin, so plugins can degrade |
|
216 |
performance when they're not being used. However, sub-modules are not |
|
217 |
loaded, only the main name. |
|
218 |
||
219 |
One way you can avoid this slowdown is by putting most of your code |
|
220 |
in sub-modules, so that the plugin, itself, is small. All you really |
|
221 |
need in the ``__init__.py`` is the plugin's Command classes, the |
|
222 |
commands to register them, and the optional ``test_suite()``. |
|
223 |
||
224 |
Another way to reduce your plugin's overhead is to use the bzrlib |
|
225 |
lazy_import functionality. That looks something like this:: |
|
226 |
||
227 |
from bzrlib.lazy_import import lazy_import |
|
228 |
lazy_import(globals(), """ |
|
229 |
from bzrlib import ( |
|
230 |
branch as _mod_branch, |
|
231 |
option, |
|
232 |
workingtree, |
|
233 |
) |
|
234 |
""") |
|
235 |
||
236 |
Lazy importing only works for packages and modules, not classes or |
|
237 |
functions. It defers the import until you actually need it. |
|
238 |
||
239 |
||
240 |
Adding your plugin to the Plugins Guide |
|
241 |
--------------------------------------- |
|
242 |
||
243 |
To add your (registered) plugin to the Plugins Guide, submit a merge |
|
244 |
proposal to lp:bzr-alldocs. Here are the steps to follow: |
|
245 |
||
246 |
1. Use ``scripts/document-plugin.py`` to generate ``plugins/en/xxx-plugin.txt``. |
|
|
34
by Ian Clatworthy
Smarter detection of plugin registry and generated file locations |
247 |
To do this, run the above script in either the top level directory |
248 |
(where ``plugins-registry.ini`` is) or in the ``plugins/en`` directory, |
|
249 |
passing the plugin name as the argument. |
|
|
26.1.5
by Ian Clatworthy
Add plugin installation and development sections under Introduction |
250 |
|
251 |
2. Add *xxx-plugin* to the relevant category in ``plugins/en/index.txt``. |
|
252 |
||
253 |
3. Test your changes:: |
|
254 |
||
255 |
cd plugins/en |
|
256 |
make html |
|
257 |
Open _build/html/index.html in your web browser. |
|
258 |
Check your plugin appears as expected and it's help formatted correctly. |
|
259 |
||
260 |
4. Add the new file and commit the changes. |
|
261 |
||
262 |
5. Submit a merge proposal with your changes. |
|
263 |
||
264 |
||
265 |
Learning more |
|
266 |
------------- |
|
267 |
||
268 |
`Integrating with Bazaar <http://wiki.bazaar.canonical.com/Integrating_with_Bazaar>`_ |
|
269 |
explains how to do such operations as ``add``, ``commit``, ``log`` and more. |
|
270 |
||
271 |
Reference documentation on some key APIs is provided below. For a more |
|
272 |
detailed reference, see the `complete bzrlib API documentation |
|
273 |
<http://starship.python.net/crew/mwh/bzrlibapi/>`_. |
|
274 |
||
275 |
||
276 |
Mini API Reference |
|
277 |
------------------ |
|
278 |
||
279 |
Command Class |
|
280 |
~~~~~~~~~~~~~ |
|
281 |
||
282 |
Base class for commands. Commands are the heart of the command-line bzr |
|
283 |
interface. |
|
284 |
||
285 |
The command object mostly handles the mapping of command-line parameters into |
|
286 |
one or more bzrlib operations, and of the results into textual output. |
|
287 |
||
288 |
Commands normally don't have any state. All their arguments are passed in to |
|
289 |
the run method. (Subclasses may take a different policy if the behaviour of the |
|
290 |
instance needs to depend on e.g. a shell plugin and not just its Python class.) |
|
291 |
||
292 |
The docstring for an actual command should give a single-line summary, then a |
|
293 |
complete description of the command. A grammar description will be inserted. |
|
294 |
||
295 |
aliases |
|
296 |
Other accepted names for this command. |
|
297 |
||
298 |
takes_args |
|
299 |
List of argument forms, marked with whether they are optional, |
|
300 |
repeated, etc. |
|
301 |
||
302 |
For example: ``['to_location', 'from_branch?', 'file*']`` means: |
|
303 |
||
304 |
* 'to_location' is required |
|
305 |
* 'from_branch' is optional |
|
306 |
* 'file' can be specified 0 or more times |
|
307 |
||
308 |
takes_options |
|
309 |
List of options that may be given for this command. These can be either |
|
310 |
strings, referring to globally-defined options, or option objects. |
|
311 |
Retrieve through options(). |
|
312 |
||
313 |
hidden |
|
314 |
If true, this command isn't advertised. This is typically for commands |
|
315 |
intended for expert users. |
|
316 |
||
317 |
run() |
|
318 |
Actually run the command. This is invoked with the options and arguments |
|
319 |
bound to keyword parameters. |
|
320 |
||
321 |
Return 0 or None if the command was successful, or a non-zero shell error |
|
322 |
code if not. It's OK for this method to allow an exception to raise up. |
|
323 |
||
324 |
||
325 |
register_command Function |
|
326 |
~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
327 |
||
328 |
Utility function to help register a command. |
|
329 |
||
330 |
param *cmd* |
|
331 |
Command subclass to register |
|
332 |
||
333 |
param *decorate* |
|
334 |
If true, allow overriding an existing command of the same name; the old |
|
335 |
command is returned by this function. Otherwise it is an error to try to |
|
336 |
override an existing command. |