Hooks
Hooks are a way to customize the behavior of Bazaar. Bazaar will invoke hooks at certain points of time to help it make a decision or to perform an action. For the latest documentation, see:
Using hooks in the User Guide
Hooks in the User Reference
Some design and implementation notes are given below.
Contents
Requested improvements (Dec 2007)
- Support shell scripts, not just in-process Python hooks
- Support more events:
Other ideas:
- different merge algorithms for specific files or file types
- external diff for certain file types
Probably better as a plugin --AaronBentley
- What about pre/post hooks for all commands? Might actually be easier to implement. (The only issue is that then you're hooking commands instead of operations - seems fragile and locks us into supporting things we may not want to longer term)
Configuration issues
Want to configure hooks that are:
- global to all/multiple branches accessed by a user
- global to all users accessing a branch or set of branches
Want to make it easy for users across the community to share hooks.
Hooks supported by various tools
Bazaar 1.0:
Event |
Pre |
Post |
Special |
Comments |
commit |
X |
X |
|
|
uncommit |
|
X |
|
|
push |
|
X |
|
|
pull |
|
X |
|
|
set-rh |
|
|
X |
run any time revision history updated |
Subversion 1.4:
Event |
Pre |
Post |
Special |
commit |
X |
X |
(start) |
revprop-change |
X |
X |
|
lock |
X |
X |
|
unlock |
X |
X |
|
Git 1.5:
Event |
Pre |
Post |
Special |
commit |
X |
X |
(commit-msg) |
applypatch |
X |
X |
(applypatch-msg) |
receive |
X |
X |
|
checkout |
|
X |
|
merge |
|
X |
|
update |
|
X |
X |
Mercurial 0.95:
Event |
Pre |
Post |
Special |
commit |
X |
X |
(pretxncommit) |
changegroup |
X |
X |
(pretxnchangegroup) |
outgoing |
X |
X |
|
incoming |
|
|
X |
tag |
X |
X |
|
update |
X |
X |
|
Activating hooks in various tools
In Bazaar:
- write a plugin that registers a subroutine as a named hook
- ensure that plugin is configured on every users' computer
In Subversion:
- Go to the hooks directory on the repository, rename xxxx.tmpl to xxxx, edit it and make it executable.
In Git:
- Go to the hooks directory, edit xxxx and make it executable.
In Hg:
Add lines to [hooks] section of .hgrc file in the format event.name = script.
- Ensure lines are configured in everyone's .hgrc file.
If script starts with python:, then it's a python callable that's executed in-process, instead of a script. The .name bit is optional but required when wanting to run multiple hooks on the one event.
Configuration Ideas
Specify hooks in directories
In addition to plugins installing hooks, users can provide shell scripts to run when hooks are triggered. The scripts to run for hook xxx are specified in the following directories:
- BZR_HOME/hooks/type/xxx.d - global hooks for the current user
- .bzr/hooks/type/xxx.d - hooks for all users of that branch.
where type is (for example) branch or server. On Unix, non-executable files are ignored. On Windows, all files are assumed to be scripts. Directories within the xxx directory are ignored so users can disable scripts by moving them into subdirectories called template or keep for example. The filenames serve as the hook labels.
Advantages: approach familiar to Subversion and Git users; considered bzr-like in design, i.e. like plugins, just put the files there and that's all that's required; no need to search the path for scripts.
Disadvantages: no way (yet) to specify hooks that only apply to selected locations for this user.
Specify hooks in config files
In this approach, entries are added to the various configuration files and the PATH is searched to find the various commands. Hooks to activate for all branches are specified in bazaar.conf, hooks that apply to all users of a branch are specified in branch.conf. If required, users can specify hooks that only apply to certain branches in locations.conf.
The hooks to install for a given hook type xxx are defined in a section called xxx-hooks. For example:
[pre-export-hooks] docs = make docs [post-commit-message-hooks] validate = checkCommitMsg
For locations.conf, a nested section is required. For example:
[http://example.com/] [[pre-export-hooks]] docs = make docs
Advantages: familiar to Hg users; scheme can be extended to specify python hooks the same way, so python hooks don't need to have logic seeing whether they ought to be enabled for a given branch.
Disadvantages: Permitting shell commands in branch.conf allows malicious users to 0wn you. Also considered un-bzr-like.
Shell Script Signature Ideas
There are several ways of passing information from Python into scripts including:
- command line parameters
- standard input
- environment variables
Each method has its share of problems, particularly on older Windows systems, e.g. command line parsing, environment size limits. Rather than always using one method, it is suggested that the script signature for each hook be customized for that hook and documented along with the Python signature. For example, the Python signature for the server_started hook is:
def hook(backing_urls, public_url)
The proposed script signature is:
- backing_urls - pass one per line on stdin
- public_url - pass as a command line parameter.
Implementation ideas
Another Idea
To my mind hooks should be simple to use, that is one of the overriding features that are needed. I mean if you were a rocket scientist, you would just re-write the Bazaar library, wouldnt you, making it solve Einsteins Grand Unified Field Thory as you checked in files? Easy. For the rest of us, hooks have massive potential for customisation but there is certainly a danger of making them so hard to use that the man on the clapham omnibus cannot use this power.
- I would like to see all hooks have the same parameter list so that they become interchangeable. Weather they are interchangeable, or even if it is desirable to interchange them, depends entirely on what the hook does and its design of course.
- I would also like to see a perfile and per directory hook being available.
- I would like to see a parameter passed that is specifically for passing user data between hooks.
If I put this sugestion in the wrong place please feel free to move it.