/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to doc/developers/plugin-development.txt

  • Committer: Jelmer Vernooij
  • Date: 2018-11-20 08:11:03 UTC
  • mto: This revision was merged to the branch mainline in revision 7209.
  • Revision ID: jelmer@jelmer.uk-20181120081103-qx2dpf4rca0okzd3
Import plugin-development.txt.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
Developing a plugin
 
2
===================
 
3
 
 
4
Naming
 
5
------
 
6
 
 
7
By convention, most plugins are named brz-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 brz-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 Breezy itself, namely GPL v2. However, there
 
19
is no requirement to do so. You are free to create Breezy 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:brz-alldocs project.
 
43
2. Edit plugin-registry.ini and commit the change.
 
44
3. Submit a merge proposal.
 
45
 
 
46
A Breezy 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 Breezy, set
 
59
the ``BRZ_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)
 
62
or put a symbolic link in that area pointing to your plugin under
 
63
test.  Finally you can use ``BRZ_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 BRZ_PLUGINS_AT=qbrz@/home/me/qbrz:explorer@/home/me/explorer
 
68
 
 
69
You can disable loading plugins with ``BRZ_DISABLE_PLUGINS``.
 
70
 
 
71
If you want to stop loading all but installed plugins you can use:
 
72
 
 
73
  BRZ_PLUGIN_PATH=-site
 
74
 
 
75
We also encourage plugin developers to provide tests for their plugin.
 
76
When you run ``brz selftest``, Breezy 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
  brz 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
 
92
2. Plugin-specific help topics (COMING SOON)
 
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 ``brz 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 breezy.branch
 
126
  breezy.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
Breezy commands are defined as subclasses of ``breezy.commands.Command``, the
 
137
command name is specified by the name of the subclass, and they must be
 
138
registered into ``brz`` with the ``breezy.commands.register_command`` function
 
139
at module import time.
 
140
 
 
141
To define the ``brz foo-bar`` command::
 
142
 
 
143
  from breezy.commands import Command, register_command
 
144
 
 
145
  class cmd_foo_bar(Command):
 
146
    # see breezy/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
Managing data
 
156
-------------
 
157
 
 
158
Plugin data falls into several categories:
 
159
 
 
160
* Configuration settings.
 
161
* Data the user can see and version control.
 
162
* Data behind the scenes.
 
163
 
 
164
Configuration settings are often stored in ``branch.conf``,
 
165
``locations.conf`` or ``bazaar.conf``.
 
166
 
 
167
User-visible data for a plugin called xxx should be stored in
 
168
``.brzmeta/xxx``. If mutiple files are desirable, make ``.brzmeta/xxx``
 
169
a directory or give them a common prefix within ``.brzmeta``, e.g.
 
170
``xxx-foo``, ``xxx-bar``.
 
171
 
 
172
Data managed behind the scenes should be stored in ``.brz``.
 
173
Depending on the nature of the data, it may belong in a subdirectory
 
174
within there, e.g. ``checkout``, ``branch`` or ``repository``.
 
175
It's your responsibility to ensure behind-the-scenes data is
 
176
propagated and merged appropriately via custom code. You may want
 
177
to use existing hooks for this or ask for new hooks to help. The
 
178
`Branch Baggage <http://wiki.bazaar.canonical.com/DraftSpecs/BranchBaggage>`_
 
179
feature may assist as well once implemented.
 
180
 
 
181
 
 
182
Useful metadata
 
183
---------------
 
184
 
 
185
It is highly recommended that plugins define a version number. This
 
186
is displayed by ``brz plugins`` and by the ``qplugins`` GUI dialog.
 
187
To do this, define ``version_info`` in ``__init__.py`` like this::
 
188
 
 
189
  version_info = (1, 2, 0, 'beta', 1)
 
190
 
 
191
Plugins can also declare other useful metadata such as a mimimum
 
192
breezy version, new transports and storage formats. See
 
193
`Plugin API <plugin-api>`_ for details.
 
194
 
 
195
 
 
196
Performance tips
 
197
----------------
 
198
 
 
199
When brz starts up, it imports every plugin, so plugins can degrade
 
200
performance when they're not being used. However, sub-modules are not
 
201
loaded, only the main name.
 
202
 
 
203
One way you can avoid this slowdown is by putting most of your code
 
204
in sub-modules, so that the plugin, itself, is small. All you really
 
205
need in the ``__init__.py`` is the plugin's Command classes, the
 
206
commands to register them, and the optional ``test_suite()``.
 
207
 
 
208
Another way to reduce your plugin's overhead is to use the breezy
 
209
lazy_import functionality. That looks something like this::
 
210
 
 
211
  from breezy.lazy_import import lazy_import
 
212
  lazy_import(globals(), """
 
213
  from breezy import (
 
214
      branch as _mod_branch,
 
215
      option,
 
216
      workingtree,
 
217
      )
 
218
  """)
 
219
 
 
220
Lazy importing only works for packages and modules, not classes or
 
221
functions. It defers the import until you actually need it.
 
222
 
 
223
 
 
224
Learning more
 
225
-------------
 
226
 
 
227
`Integrating with Breezy <http://wiki.bazaar.canonical.com/Integrating_with_Breezy>`_
 
228
explains how to do such operations as ``add``, ``commit``, ``log`` and more.
 
229
 
 
230
Reference documentation on some key APIs is provided below. For a more
 
231
detailed reference, see the `complete breezy API documentation <api/index>`_.
 
232
 
 
233
 
 
234
Mini API Reference
 
235
------------------
 
236
 
 
237
Command Class
 
238
~~~~~~~~~~~~~
 
239
 
 
240
Base class for commands. Commands are the heart of the command-line brz
 
241
interface.
 
242
 
 
243
The command object mostly handles the mapping of command-line parameters into
 
244
one or more breezy operations, and of the results into textual output.
 
245
 
 
246
Commands normally don't have any state. All their arguments are passed in to
 
247
the run method. (Subclasses may take a different policy if the behaviour of the
 
248
instance needs to depend on e.g. a shell plugin and not just its Python class.)
 
249
 
 
250
The docstring for an actual command should give a single-line summary, then a
 
251
complete description of the command. A grammar description will be inserted.
 
252
 
 
253
aliases
 
254
    Other accepted names for this command.
 
255
 
 
256
takes_args
 
257
    List of argument forms, marked with whether they are optional,
 
258
    repeated, etc.
 
259
 
 
260
    For example: ``['to_location', 'from_branch?', 'file*']`` means:
 
261
 
 
262
    * 'to_location' is required
 
263
    * 'from_branch' is optional
 
264
    * 'file' can be specified 0 or more times
 
265
 
 
266
takes_options
 
267
    List of options that may be given for this command. These can be either
 
268
    strings, referring to globally-defined options, or option objects.
 
269
    Retrieve through options().
 
270
 
 
271
hidden
 
272
    If true, this command isn't advertised. This is typically for commands
 
273
    intended for expert users.
 
274
 
 
275
run()
 
276
    Actually run the command. This is invoked with the options and arguments
 
277
    bound to keyword parameters.
 
278
 
 
279
    Return 0 or None if the command was successful, or a non-zero shell error
 
280
    code if not. It's OK for this method to allow an exception to raise up.
 
281
 
 
282
 
 
283
register_command Function
 
284
~~~~~~~~~~~~~~~~~~~~~~~~~
 
285
 
 
286
Utility function to help register a command.
 
287
 
 
288
param *cmd*
 
289
  Command subclass to register
 
290
 
 
291
param *decorate*
 
292
  If true, allow overriding an existing command of the same name; the old
 
293
  command is returned by this function. Otherwise it is an error to try to
 
294
  override an existing command.