Rev 2790: (Nam Nguyen) Pre-commit hook in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Mon Sep 3 14:07:31 BST 2007
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 2790
revision-id: pqm at pqm.ubuntu.com-20070903130729-qdcrag0a7vcpzfgm
parent: pqm at pqm.ubuntu.com-20070903110923-pj5pw0wsf1u922j9
parent: ian.clatworthy at internode.on.net-20070903123214-kgrq7hubbtkmkn7i
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Mon 2007-09-03 14:07:29 +0100
message:
(Nam Nguyen) Pre-commit hook
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/commit.py commit.py-20050511101309-79ec1a0168e0e825
bzrlib/tests/branch_implementations/test_commit.py test_commit.py-20070206022134-117z1i5b644p63r0-1
bzrlib/tests/test_branch.py test_branch.py-20060116013032-97819aa07b8ab3b5
bzrlib/tests/workingtree_implementations/test_commit.py test_commit.py-20060421013633-1610ec2331c8190f
doc/en/user-reference/hooks.txt hooks.txt-20070830033044-xxu2rced13f72dka-1
------------------------------------------------------------
revno: 2789.1.1
merged: ian.clatworthy at internode.on.net-20070903123214-kgrq7hubbtkmkn7i
parent: pqm at pqm.ubuntu.com-20070903110923-pj5pw0wsf1u922j9
parent: nguyen at guy-20070902053708-hjup9c46zj1jxml1
committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
branch nick: ianc-integration
timestamp: Mon 2007-09-03 22:32:14 +1000
message:
(Nam Nguyen) Pre-commit hook
------------------------------------------------------------
revno: 2659.3.10
merged: nguyen at guy-20070902053708-hjup9c46zj1jxml1
parent: namnguyen-20070827083837-t6a5oewzvdct6j8i
parent: pqm at pqm.ubuntu.com-20070901160444-hcr66zejwyy0jezc
committer: Nam Nguyen <Nam Nguyen at GUY>
branch nick: precommit
timestamp: Sun 2007-09-02 13:37:08 +0800
message:
merge with bzr.dev and update hooks.txt to list pre_commit hook.
doc/en/user-reference/hooks.txt:
* added a section for pre_commit_hook
------------------------------------------------------------
revno: 2659.3.9
merged: namnguyen-20070827083837-t6a5oewzvdct6j8i
parent: namnguyen-20070827032116-11p0vjw01wn4l53y
committer: NamNguyen
branch nick: precommit
timestamp: Mon 2007-08-27 16:38:37 +0800
message:
branch.py:
* ``pre_commit`` hook's signature is changed to::
hook(local, master, old_revno, old_revid, future_revno, future_revid,
tree_delta, future_tree)
* made it clear that pre_commit hooks must not modify neither
the delta nor future_tree
commit.py:
* replaced ``affected_ids`` with ``tree_delta``
* only compute ``future_tree`` and ``tree_delta`` once
------------------------------------------------------------
revno: 2659.3.8
merged: namnguyen-20070827032116-11p0vjw01wn4l53y
parent: namnguyen-20070815091606-2gqalm977ys9e21w
parent: pqm at pqm.ubuntu.com-20070825182243-a3w20rpadbfz8euc
committer: NamNguyen
branch nick: precommit
timestamp: Mon 2007-08-27 11:21:16 +0800
message:
merge with bzr.dev
------------------------------------------------------------
revno: 2659.3.7
merged: namnguyen-20070815091606-2gqalm977ys9e21w
parent: namnguyen-20070815090632-w0xcl6t5if19m2oj
committer: NamNguyen
branch nick: precommit
timestamp: Wed 2007-08-15 17:16:06 +0800
message:
NEWS:
* Pull the NEWS entry to IN DEVELOPMENT
------------------------------------------------------------
revno: 2659.3.6
merged: namnguyen-20070815090632-w0xcl6t5if19m2oj
parent: namnguyen-20070815074942-rd91twf3wm3enomx
committer: NamNguyen
branch nick: precommit
timestamp: Wed 2007-08-15 17:06:32 +0800
message:
branch_implementations/test_commit.py:
* renamed test_pre_commit_paths to test_pre_commit_ids
* added cases for ``added``, ``deleted``, ``renamed``, ``modified``, and
``modified and renamed``
------------------------------------------------------------
revno: 2659.3.5
merged: namnguyen-20070815074942-rd91twf3wm3enomx
parent: namnguyen-20070807082534-7xw955iabtlxuayj
parent: pqm at pqm.ubuntu.com-20070815055603-t0fwzxv6if6sr7c6
committer: NamNguyen
branch nick: precommit
timestamp: Wed 2007-08-15 15:49:42 +0800
message:
merge with bzr.dev
------------------------------------------------------------
revno: 2659.3.4
merged: namnguyen-20070807082534-7xw955iabtlxuayj
parent: namnguyen-20070807082328-6i934n9gdj5fd17a
parent: pqm at pqm.ubuntu.com-20070807061316-b32atzzop4r4y21g
committer: NamNguyen
branch nick: precommit
timestamp: Tue 2007-08-07 16:25:34 +0800
message:
merged with bzr.dev
------------------------------------------------------------
revno: 2659.3.3
merged: namnguyen-20070807082328-6i934n9gdj5fd17a
parent: namnguyen-20070801063025-pb139zkmbuwg5ga6
parent: pqm at pqm.ubuntu.com-20070801000518-wyeivv59zhkh9cbp
committer: NamNguyen
branch nick: precommit
timestamp: Tue 2007-08-07 16:23:28 +0800
message:
Changed ``pre_commit`` hook signature.
The hook's signature is now
::
hook(local, master, old_revno, old_revid, new_revno, new_revid,
affected_ids, future_revision_tree)
``affected_ids`` is a dictionary of (change_type, ids). change_type is
a string describing the change (e.g. 'added', 'deleted', 'modified'), and
ids is a list of inventory entry ids.
Hooks can get an added file easier than before:
::
for id in affected_ids.get('added', []):
if future_revision_tree.kind(id) == 'file':
file = future_revision_tree.get_file(id)
...
------------------------------------------------------------
revno: 2659.3.2
merged: namnguyen-20070801063025-pb139zkmbuwg5ga6
parent: namnguyen-20070801061414-u0tzrfgcz6z604lz
committer: NamNguyen
branch nick: precommit
timestamp: Wed 2007-08-01 14:30:25 +0800
message:
Fix NEWS entry of the last commit.
------------------------------------------------------------
revno: 2659.3.1
merged: namnguyen-20070801061414-u0tzrfgcz6z604lz
parent: pqm at pqm.ubuntu.com-20070730051419-0jdj7g8fm4iuoz7h
committer: NamNguyen
branch nick: precommit
timestamp: Wed 2007-08-01 14:14:14 +0800
message:
``Branch.hooks`` now supports ``pre_commit`` hook.
The hook's signature is
::
hook(local, master, old_revno, old_revid, new_revno, new_revid,
deleted_paths, added_paths, future_revision_tree)
``deleted_paths`` and ``added_paths`` are lists of paths. Renamed paths are
recorded in both ``deleted_paths`` and ``added_paths`` (i.e. deleted then
added).
``future_revision_tree`` is obtained from ``CommitBuilder.revision_tree``
to save hooks from getting it from the branch again.
For example, hooks can get a file:
::
for path in added_paths:
id = future_revision_tree.path2id(path)
if future_revision_tree.kind(id) == 'file':
file = future_revision_tree.get_file(id)
...
or export a tree and do ``make check`` or similar
::
import bzrlib.export
bzrlib.export.export(future_revision_tree, 'tmp_space')
If the commit is to be rejected, hooks should raise an ``Exception``.
=== modified file 'NEWS'
--- a/NEWS 2007-09-03 10:17:35 +0000
+++ b/NEWS 2007-09-03 12:32:14 +0000
@@ -48,6 +48,9 @@
verbosity level but do respect *quiet vs normal vs verbose* when
generating output. (Ian Clatworthy)
+ * ``Branch.hooks`` now supports ``pre_commit`` hook. The hook's signature
+ is documented in BranchHooks constructor. (Nam T. Nguyen, #102747)
+
BUG FIXES:
* ``bzr plugins`` now lists the version number for each plugin in square
=== modified file 'bzrlib/branch.py'
--- a/bzrlib/branch.py 2007-08-20 13:07:12 +0000
+++ b/bzrlib/branch.py 2007-08-27 08:38:37 +0000
@@ -999,6 +999,16 @@
# is read locked and the target branches write locked. The local
# branch is the low-latency branch.
self['post_pull'] = []
+ # invoked before a commit operation takes place.
+ # the api signature is
+ # (local, master, old_revno, old_revid, future_revno, future_revid,
+ # tree_delta, future_tree).
+ # old_revid is NULL_REVISION for the first commit to a branch
+ # tree_delta is a TreeDelta object describing changes from the basis
+ # revision, hooks MUST NOT modify this delta
+ # future_tree is an in-memory tree obtained from
+ # CommitBuilder.revision_tree() and hooks MUST NOT modify this tree
+ self['pre_commit'] = []
# invoked after a commit operation completes.
# the api signature is
# (local, master, old_revno, old_revid, new_revno, new_revid)
=== modified file 'bzrlib/commit.py'
--- a/bzrlib/commit.py 2007-08-28 01:58:42 +0000
+++ b/bzrlib/commit.py 2007-09-02 05:37:08 +0000
@@ -254,7 +254,7 @@
self._check_bound_branch()
# Check that the working tree is up to date
- old_revno,new_revno = self._check_out_of_date_tree()
+ old_revno, new_revno = self._check_out_of_date_tree()
if self.config is None:
self.config = self.branch.get_config()
@@ -275,7 +275,7 @@
# information in the progress bar during the relevant stages.
self.pb_stage_name = ""
self.pb_stage_count = 0
- self.pb_stage_total = 4
+ self.pb_stage_total = 5
if self.bound_branch:
self.pb_stage_total += 1
self.pb.show_pct = False
@@ -296,6 +296,7 @@
entries_title="Directory")
self.builder = self.branch.get_commit_builder(self.parents,
self.config, timestamp, timezone, committer, revprops, rev_id)
+
try:
self._update_builder_with_changes()
self._check_pointless()
@@ -315,10 +316,13 @@
# Add revision data to the local branch
self.rev_id = self.builder.commit(self.message)
+
except:
self.builder.abort()
raise
+ self._process_pre_hooks(old_revno, new_revno)
+
# Upload revision data to the master.
# this will propagate merged revisions too if needed.
if self.bound_branch:
@@ -339,7 +343,7 @@
rev_tree = self.builder.revision_tree()
self.work_tree.set_parent_trees([(self.rev_id, rev_tree)])
self.reporter.completed(new_revno, self.rev_id)
- self._process_hooks(old_revno, new_revno)
+ self._process_post_hooks(old_revno, new_revno)
finally:
self._cleanup()
return self.rev_id
@@ -465,10 +469,15 @@
new_revno = 1
return old_revno,new_revno
- def _process_hooks(self, old_revno, new_revno):
- """Process any registered commit hooks."""
+ def _process_pre_hooks(self, old_revno, new_revno):
+ """Process any registered pre commit hooks."""
+ self._set_progress_stage("Running pre_commit hooks")
+ self._process_hooks("pre_commit", old_revno, new_revno)
+
+ def _process_post_hooks(self, old_revno, new_revno):
+ """Process any registered post commit hooks."""
# Process the post commit hooks, if any
- self._set_progress_stage("Running post commit hooks")
+ self._set_progress_stage("Running post_commit hooks")
# old style commit hooks - should be deprecated ? (obsoleted in
# 0.15)
if self.config.post_commit() is not None:
@@ -479,6 +488,13 @@
{'branch':self.branch,
'bzrlib':bzrlib,
'rev_id':self.rev_id})
+ # process new style post commit hooks
+ self._process_hooks("post_commit", old_revno, new_revno)
+
+ def _process_hooks(self, hook_name, old_revno, new_revno):
+ if not Branch.hooks[hook_name]:
+ return
+
# new style commit hooks:
if not self.bound_branch:
hook_master = self.branch
@@ -493,19 +509,30 @@
old_revid = self.parents[0]
else:
old_revid = bzrlib.revision.NULL_REVISION
- for hook in Branch.hooks['post_commit']:
+
+ if hook_name == "pre_commit":
+ future_tree = self.builder.revision_tree()
+ tree_delta = future_tree.changes_from(self.basis_tree,
+ include_root=True)
+
+ for hook in Branch.hooks[hook_name]:
# show the running hook in the progress bar. As hooks may
# end up doing nothing (e.g. because they are not configured by
# the user) this is still showing progress, not showing overall
# actions - its up to each plugin to show a UI if it want's to
# (such as 'Emailing diff to foo at example.com').
- self.pb_stage_name = "Running post commit hooks [%s]" % \
- Branch.hooks.get_hook_name(hook)
+ self.pb_stage_name = "Running %s hooks [%s]" % \
+ (hook_name, Branch.hooks.get_hook_name(hook))
self._emit_progress()
if 'hooks' in debug.debug_flags:
mutter("Invoking commit hook: %r", hook)
- hook(hook_local, hook_master, old_revno, old_revid, new_revno,
- self.rev_id)
+ if hook_name == "post_commit":
+ hook(hook_local, hook_master, old_revno, old_revid, new_revno,
+ self.rev_id)
+ elif hook_name == "pre_commit":
+ hook(hook_local, hook_master,
+ old_revno, old_revid, new_revno, self.rev_id,
+ tree_delta, future_tree)
def _cleanup(self):
"""Cleanup any open locks, progress bars etc."""
=== modified file 'bzrlib/tests/branch_implementations/test_commit.py'
--- a/bzrlib/tests/branch_implementations/test_commit.py 2007-02-06 02:33:42 +0000
+++ b/bzrlib/tests/branch_implementations/test_commit.py 2007-09-03 12:32:14 +0000
@@ -21,6 +21,7 @@
from bzrlib.tests.branch_implementations.test_branch import TestCaseWithBranch
from bzrlib.revision import NULL_REVISION
from bzrlib.transport import get_transport
+from bzrlib.delta import TreeDelta
class TestCommit(TestCaseWithBranch):
@@ -59,6 +60,12 @@
('post_commit', local_base, master.base, old_revno, old_revid,
new_revno, new_revid, local_locked, master.is_locked()))
+ def capture_pre_commit_hook(self, local, master, old_revno, old_revid,
+ new_revno, new_revid,
+ tree_delta, future_tree):
+ self.hook_calls.append(('pre_commit', old_revno, old_revid,
+ new_revno, new_revid, tree_delta))
+
def test_post_commit_to_origin(self):
tree = self.make_branch_and_memory_tree('branch')
Branch.hooks.install_hook('post_commit',
@@ -112,3 +119,98 @@
],
self.hook_calls)
tree.unlock()
+
+ def test_pre_commit_passes(self):
+ empty_delta = TreeDelta()
+ root_delta = TreeDelta()
+ root_delta.added = [('', '', 'directory')]
+ tree = self.make_branch_and_memory_tree('branch')
+ tree.lock_write()
+ tree.add('', '')
+ Branch.hooks.install_hook("pre_commit", self.capture_pre_commit_hook)
+ revid1 = tree.commit('first revision')
+ revid2 = tree.commit('second revision')
+ self.assertEqual([
+ ('pre_commit', 0, NULL_REVISION, 1, revid1, root_delta),
+ ('pre_commit', 1, revid1, 2, revid2, empty_delta)
+ ],
+ self.hook_calls)
+ tree.unlock()
+
+ def test_pre_commit_fails(self):
+ empty_delta = TreeDelta()
+ root_delta = TreeDelta()
+ root_delta.added = [('', '', 'directory')]
+ tree = self.make_branch_and_memory_tree('branch')
+ tree.lock_write()
+ tree.add('', '')
+ class PreCommitException(Exception): pass
+ def hook_func(local, master,
+ old_revno, old_revid, new_revno, new_revid,
+ tree_delta, future_tree):
+ raise PreCommitException(new_revid)
+ Branch.hooks.install_hook("pre_commit", self.capture_pre_commit_hook)
+ Branch.hooks.install_hook("pre_commit", hook_func)
+ revids = [None, None, None]
+ # this commit will raise an exception
+ # so the commit is rolled back and revno unchanged
+ err = self.assertRaises(PreCommitException, tree.commit, 'message')
+ # we have to record the revid to use in assertEqual later
+ revids[0] = str(err)
+ # unregister all pre_commit hooks
+ Branch.hooks["pre_commit"] = []
+ # and re-register the capture hook
+ Branch.hooks.install_hook("pre_commit", self.capture_pre_commit_hook)
+ # now these commits should go through
+ for i in range(1, 3):
+ revids[i] = tree.commit('message')
+ self.assertEqual([
+ ('pre_commit', 0, NULL_REVISION, 1, revids[0], root_delta),
+ ('pre_commit', 0, NULL_REVISION, 1, revids[1], root_delta),
+ ('pre_commit', 1, revids[1], 2, revids[2], empty_delta)
+ ],
+ self.hook_calls)
+ tree.unlock()
+
+ def test_pre_commit_delta(self):
+ # This tests the TreeDelta object passed to pre_commit hook.
+ # This does not try to validate data correctness in the delta.
+ self.build_tree(['rootfile', 'dir/', 'dir/subfile'])
+ tree = self.make_branch_and_tree('.')
+ tree.lock_write()
+ try:
+ # setting up a playground
+ tree.set_root_id('root_id')
+ tree.add('rootfile', 'rootfile_id')
+ tree.put_file_bytes_non_atomic('rootfile_id', 'abc')
+ tree.add('dir', 'dir_id')
+ tree.add('dir/subfile', 'dir_subfile_id')
+ tree.mkdir('to_be_unversioned', 'to_be_unversioned_id')
+ tree.put_file_bytes_non_atomic('dir_subfile_id', 'def')
+ revid1 = tree.commit('first revision')
+ finally:
+ tree.unlock()
+
+ tree.lock_write()
+ try:
+ # making changes
+ tree.put_file_bytes_non_atomic('rootfile_id', 'jkl')
+ tree.rename_one('dir/subfile', 'dir/subfile_renamed')
+ tree.unversion(['to_be_unversioned_id'])
+ tree.mkdir('added_dir', 'added_dir_id')
+ # start to capture pre_commit delta
+ Branch.hooks.install_hook("pre_commit", self.capture_pre_commit_hook)
+ revid2 = tree.commit('second revision')
+ finally:
+ tree.unlock()
+
+ expected_delta = TreeDelta()
+ expected_delta.added = [('added_dir', 'added_dir_id', 'directory')]
+ expected_delta.removed = [('to_be_unversioned',
+ 'to_be_unversioned_id', 'directory')]
+ expected_delta.renamed = [('dir/subfile', 'dir/subfile_renamed',
+ 'dir_subfile_id', 'file', False, False)]
+ expected_delta.modified=[('rootfile', 'rootfile_id', 'file', True,
+ False)]
+ self.assertEqual([('pre_commit', 1, revid1, 2, revid2,
+ expected_delta)], self.hook_calls)
=== modified file 'bzrlib/tests/test_branch.py'
--- a/bzrlib/tests/test_branch.py 2007-08-14 11:53:00 +0000
+++ b/bzrlib/tests/test_branch.py 2007-08-27 03:21:16 +0000
@@ -321,6 +321,7 @@
self.assertTrue("set_rh" in hooks, "set_rh not in %s" % hooks)
self.assertTrue("post_push" in hooks, "post_push not in %s" % hooks)
self.assertTrue("post_commit" in hooks, "post_commit not in %s" % hooks)
+ self.assertTrue("pre_commit" in hooks, "pre_commit not in %s" % hooks)
self.assertTrue("post_pull" in hooks, "post_pull not in %s" % hooks)
self.assertTrue("post_uncommit" in hooks, "post_uncommit not in %s" % hooks)
=== modified file 'bzrlib/tests/workingtree_implementations/test_commit.py'
--- a/bzrlib/tests/workingtree_implementations/test_commit.py 2007-07-26 00:26:25 +0000
+++ b/bzrlib/tests/workingtree_implementations/test_commit.py 2007-08-27 08:38:37 +0000
@@ -354,17 +354,18 @@
# into the factory for this test - just make the test ui factory
# pun as a reporter. Then we can check the ordering is right.
tree.commit('second post', specific_files=['b'])
- # 4 steps, the first of which is reported 2 times, once per dir
+ # 5 steps, the first of which is reported 2 times, once per dir
self.assertEqual(
- [('update', 1, 4, 'Collecting changes [Directory 0] - Stage'),
- ('update', 1, 4, 'Collecting changes [Directory 1] - Stage'),
- ('update', 2, 4, 'Saving data locally - Stage'),
- ('update', 3, 4, 'Updating the working tree - Stage'),
- ('update', 4, 4, 'Running post commit hooks - Stage')],
+ [('update', 1, 5, 'Collecting changes [Directory 0] - Stage'),
+ ('update', 1, 5, 'Collecting changes [Directory 1] - Stage'),
+ ('update', 2, 5, 'Saving data locally - Stage'),
+ ('update', 3, 5, 'Running pre_commit hooks - Stage'),
+ ('update', 4, 5, 'Updating the working tree - Stage'),
+ ('update', 5, 5, 'Running post_commit hooks - Stage')],
factory._calls
)
- def test_commit_progress_shows_hook_names(self):
+ def test_commit_progress_shows_post_hook_names(self):
tree = self.make_branch_and_tree('.')
# set a progress bar that captures the calls so we can see what is
# emitted
@@ -378,15 +379,38 @@
branch.Branch.hooks.name_hook(a_hook, 'hook name')
tree.commit('first post')
self.assertEqual(
- [('update', 1, 4, 'Collecting changes [Directory 0] - Stage'),
- ('update', 1, 4, 'Collecting changes [Directory 1] - Stage'),
- ('update', 2, 4, 'Saving data locally - Stage'),
- ('update', 3, 4, 'Updating the working tree - Stage'),
- ('update', 4, 4, 'Running post commit hooks - Stage'),
- ('update', 4, 4, 'Running post commit hooks [hook name] - Stage'),
- ],
- factory._calls
- )
-
-
-
+ [('update', 1, 5, 'Collecting changes [Directory 0] - Stage'),
+ ('update', 1, 5, 'Collecting changes [Directory 1] - Stage'),
+ ('update', 2, 5, 'Saving data locally - Stage'),
+ ('update', 3, 5, 'Running pre_commit hooks - Stage'),
+ ('update', 4, 5, 'Updating the working tree - Stage'),
+ ('update', 5, 5, 'Running post_commit hooks - Stage'),
+ ('update', 5, 5, 'Running post_commit hooks [hook name] - Stage'),
+ ],
+ factory._calls
+ )
+
+ def test_commit_progress_shows_pre_hook_names(self):
+ tree = self.make_branch_and_tree('.')
+ # set a progress bar that captures the calls so we can see what is
+ # emitted
+ self.old_ui_factory = ui.ui_factory
+ self.addCleanup(self.restoreDefaults)
+ factory = CapturingUIFactory()
+ ui.ui_factory = factory
+ def a_hook(_, _2, _3, _4, _5, _6, _7, _8):
+ pass
+ branch.Branch.hooks.install_hook('pre_commit', a_hook)
+ branch.Branch.hooks.name_hook(a_hook, 'hook name')
+ tree.commit('first post')
+ self.assertEqual(
+ [('update', 1, 5, 'Collecting changes [Directory 0] - Stage'),
+ ('update', 1, 5, 'Collecting changes [Directory 1] - Stage'),
+ ('update', 2, 5, 'Saving data locally - Stage'),
+ ('update', 3, 5, 'Running pre_commit hooks - Stage'),
+ ('update', 3, 5, 'Running pre_commit hooks [hook name] - Stage'),
+ ('update', 4, 5, 'Updating the working tree - Stage'),
+ ('update', 5, 5, 'Running post_commit hooks - Stage'),
+ ],
+ factory._calls
+ )
=== modified file 'doc/en/user-reference/hooks.txt'
--- a/doc/en/user-reference/hooks.txt 2007-08-30 15:55:36 +0000
+++ b/doc/en/user-reference/hooks.txt 2007-09-02 05:37:08 +0000
@@ -26,6 +26,17 @@
is read-locked and the target branches are write-locked. Source will
be the local low-latency branch.
+pre_commit
+##########
+Run prefore ``commit`` has completed.
+
+The hook signature is (local, master, old_revno, old_revid, future_revno,
+future_revid, tree_delta, future_tree) where old_revno is NULL_REVISION for
+the first commit to a branch, tree_delta is a TreeDelta object describing
+changes from the basis revision, and future_tree is an in-memory tree
+obtained from CommitBuilder.revision_tree(). Hooks MUST NOT modify tree_delta
+and future_tree.
+
post_commit
###########
Run after ``commit`` has completed.
More information about the bazaar-commits
mailing list