Rev 5174: (vila) Add 'post_repo_init', 'post_branch_init' and 'post_switch' hooks. (Marco Pantaleoni) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Thu Apr 22 18:08:48 BST 2010
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 5174 [merge]
revision-id: pqm at pqm.ubuntu.com-20100422170827-h0bb41yq5nkosu6t
parent: pqm at pqm.ubuntu.com-20100422154421-eeit8sxsvtxxherb
parent: panta at elasticworld.org-20100326071129-fzwihjpyb43wn2j5
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2010-04-22 18:08:27 +0100
message:
(vila) Add 'post_repo_init', 'post_branch_init' and 'post_switch' hooks. (Marco Pantaleoni)
modified:
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/bzrdir.py bzrdir.py-20060131065624-156dfea39c4387cb
bzrlib/repofmt/knitrepo.py knitrepo.py-20070206081537-pyy4a00xdas0j4pf-1
bzrlib/repofmt/pack_repo.py pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
bzrlib/repofmt/weaverepo.py presplitout.py-20070125045333-wfav3tsh73oxu3zk-1
bzrlib/repository.py rev_storage.py-20051111201905-119e9401e46257e3
bzrlib/switch.py switch.py-20071116011000-v5lnw7d2wkng9eux-1
bzrlib/tests/blackbox/test_branch.py test_branch.py-20060524161337-noms9gmcwqqrfi8y-1
bzrlib/tests/blackbox/test_shared_repository.py test_shared_repository.py-20060317053531-ed30c0d79325e483
bzrlib/tests/blackbox/test_switch.py test_switch.py-20071122111948-0c5en6uz92bwl76h-1
bzrlib/tests/test_branch.py test_branch.py-20060116013032-97819aa07b8ab3b5
bzrlib/tests/test_bzrdir.py test_bzrdir.py-20060131065654-deba40eef51cf220
=== modified file 'bzrlib/branch.py'
--- a/bzrlib/branch.py 2010-04-10 18:03:54 +0000
+++ b/bzrlib/branch.py 2010-04-22 17:08:27 +0000
@@ -1543,6 +1543,14 @@
"""Return the short format description for this format."""
raise NotImplementedError(self.get_format_description)
+ def _run_post_branch_init_hooks(self, a_bzrdir, name, branch):
+ hooks = Branch.hooks['post_branch_init']
+ if not hooks:
+ return
+ params = BranchInitHookParams(self, a_bzrdir, name, branch)
+ for hook in hooks:
+ hook(params)
+
def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
lock_type='metadir', set_format=True):
"""Initialize a branch in a bzrdir, with specified files
@@ -1584,7 +1592,9 @@
finally:
if lock_taken:
control_files.unlock()
- return self.open(a_bzrdir, name, _found=True)
+ branch = self.open(a_bzrdir, name, _found=True)
+ self._run_post_branch_init_hooks(a_bzrdir, name, branch)
+ return branch
def initialize(self, a_bzrdir, name=None):
"""Create a branch of this format in a_bzrdir.
@@ -1750,6 +1760,16 @@
"should return a tag name or None if no tag name could be "
"determined. The first non-None tag name returned will be used.",
(2, 2), None))
+ self.create_hook(HookPoint('post_branch_init',
+ "Called after new branch initialization completes. "
+ "post_branch_init is called with a "
+ "bzrlib.branch.BranchInitHookParams. "
+ "Note that init, branch and checkout (both heavyweight and "
+ "lightweight) will all trigger this hook.", (2, 2), None))
+ self.create_hook(HookPoint('post_switch',
+ "Called after a checkout switches branch. "
+ "post_switch is called with a "
+ "bzrlib.branch.SwitchHookParams.", (2, 2), None))
@@ -1795,6 +1815,84 @@
self.old_revno, self.old_revid, self.new_revno, self.new_revid)
+class BranchInitHookParams(object):
+ """Object holding parameters passed to *_branch_init hooks.
+
+ There are 4 fields that hooks may wish to access:
+
+ :ivar format: the branch format
+ :ivar bzrdir: the BzrDir where the branch will be/has been initialized
+ :ivar name: name of colocated branch, if any (or None)
+ :ivar branch: the branch created
+
+ Note that for lightweight checkouts, the bzrdir and format fields refer to
+ the checkout, hence they are different from the corresponding fields in
+ branch, which refer to the original branch.
+ """
+
+ def __init__(self, format, a_bzrdir, name, branch):
+ """Create a group of BranchInitHook parameters.
+
+ :param format: the branch format
+ :param a_bzrdir: the BzrDir where the branch will be/has been
+ initialized
+ :param name: name of colocated branch, if any (or None)
+ :param branch: the branch created
+
+ Note that for lightweight checkouts, the bzrdir and format fields refer
+ to the checkout, hence they are different from the corresponding fields
+ in branch, which refer to the original branch.
+ """
+ self.format = format
+ self.bzrdir = a_bzrdir
+ self.name = name
+ self.branch = branch
+
+ def __eq__(self, other):
+ return self.__dict__ == other.__dict__
+
+ def __repr__(self):
+ if self.branch:
+ return "<%s of %s>" % (self.__class__.__name__, self.branch)
+ else:
+ return "<%s of format:%s bzrdir:%s>" % (
+ self.__class__.__name__, self.branch,
+ self.format, self.bzrdir)
+
+
+class SwitchHookParams(object):
+ """Object holding parameters passed to *_switch hooks.
+
+ There are 4 fields that hooks may wish to access:
+
+ :ivar control_dir: BzrDir of the checkout to change
+ :ivar to_branch: branch that the checkout is to reference
+ :ivar force: skip the check for local commits in a heavy checkout
+ :ivar revision_id: revision ID to switch to (or None)
+ """
+
+ def __init__(self, control_dir, to_branch, force, revision_id):
+ """Create a group of SwitchHook parameters.
+
+ :param control_dir: BzrDir of the checkout to change
+ :param to_branch: branch that the checkout is to reference
+ :param force: skip the check for local commits in a heavy checkout
+ :param revision_id: revision ID to switch to (or None)
+ """
+ self.control_dir = control_dir
+ self.to_branch = to_branch
+ self.force = force
+ self.revision_id = revision_id
+
+ def __eq__(self, other):
+ return self.__dict__ == other.__dict__
+
+ def __repr__(self):
+ return "<%s for %s to (%s, %s)>" % (self.__class__.__name__,
+ self.control_dir, self.to_branch,
+ self.revision_id)
+
+
class BzrBranchFormat4(BranchFormat):
"""Bzr branch format 4.
@@ -2069,9 +2167,11 @@
branch_transport.put_bytes('location',
target_branch.bzrdir.root_transport.base)
branch_transport.put_bytes('format', self.get_format_string())
- return self.open(
+ branch = self.open(
a_bzrdir, name, _found=True,
possible_transports=[target_branch.bzrdir.root_transport])
+ self._run_post_branch_init_hooks(a_bzrdir, name, branch)
+ return branch
def __init__(self):
super(BranchReferenceFormat, self).__init__()
=== modified file 'bzrlib/bzrdir.py'
--- a/bzrlib/bzrdir.py 2010-04-16 07:56:51 +0000
+++ b/bzrlib/bzrdir.py 2010-04-22 17:08:27 +0000
@@ -1330,11 +1330,52 @@
self.create_hook(hooks.HookPoint('pre_open',
"Invoked before attempting to open a BzrDir with the transport "
"that the open will use.", (1, 14), None))
+ self.create_hook(hooks.HookPoint('post_repo_init',
+ "Invoked after a repository has been initialized. "
+ "post_repo_init is called with a "
+ "bzrlib.bzrdir.RepoInitHookParams.",
+ (2, 2), None))
# install the default hooks
BzrDir.hooks = BzrDirHooks()
+class RepoInitHookParams(object):
+ """Object holding parameters passed to *_repo_init hooks.
+
+ There are 4 fields that hooks may wish to access:
+
+ :ivar repository: Repository created
+ :ivar format: Repository format
+ :ivar bzrdir: The bzrdir for the repository
+ :ivar shared: The repository is shared
+ """
+
+ def __init__(self, repository, format, a_bzrdir, shared):
+ """Create a group of RepoInitHook parameters.
+
+ :param repository: Repository created
+ :param format: Repository format
+ :param bzrdir: The bzrdir for the repository
+ :param shared: The repository is shared
+ """
+ self.repository = repository
+ self.format = format
+ self.bzrdir = a_bzrdir
+ self.shared = shared
+
+ def __eq__(self, other):
+ return self.__dict__ == other.__dict__
+
+ def __repr__(self):
+ if self.repository:
+ return "<%s for %s>" % (self.__class__.__name__,
+ self.repository)
+ else:
+ return "<%s for %s>" % (self.__class__.__name__,
+ self.bzrdir)
+
+
class BzrDirPreSplitOut(BzrDir):
"""A common class for the all-in-one formats."""
=== modified file 'bzrlib/repofmt/knitrepo.py'
--- a/bzrlib/repofmt/knitrepo.py 2010-01-29 10:59:12 +0000
+++ b/bzrlib/repofmt/knitrepo.py 2010-03-24 14:35:25 +0000
@@ -360,6 +360,7 @@
result.revisions.get_parent_map([('A',)])
result.signatures.get_parent_map([('A',)])
result.unlock()
+ self._run_post_repo_init_hooks(result, a_bzrdir, shared)
return result
def open(self, a_bzrdir, _found=False, _override_transport=None):
=== modified file 'bzrlib/repofmt/pack_repo.py'
--- a/bzrlib/repofmt/pack_repo.py 2010-04-19 13:04:30 +0000
+++ b/bzrlib/repofmt/pack_repo.py 2010-04-22 17:08:27 +0000
@@ -2546,7 +2546,9 @@
utf8_files = [('format', self.get_format_string())]
self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
- return self.open(a_bzrdir=a_bzrdir, _found=True)
+ repository = self.open(a_bzrdir=a_bzrdir, _found=True)
+ self._run_post_repo_init_hooks(repository, a_bzrdir, shared)
+ return repository
def open(self, a_bzrdir, _found=False, _override_transport=None):
"""See RepositoryFormat.open().
=== modified file 'bzrlib/repofmt/weaverepo.py'
--- a/bzrlib/repofmt/weaverepo.py 2009-09-16 17:19:07 +0000
+++ b/bzrlib/repofmt/weaverepo.py 2010-03-24 14:35:25 +0000
@@ -302,7 +302,9 @@
mode=a_bzrdir._get_file_mode())
finally:
control_files.unlock()
- return self.open(a_bzrdir, _found=True)
+ repository = self.open(a_bzrdir, _found=True)
+ self._run_post_repo_init_hooks(repository, a_bzrdir, shared)
+ return repository
def open(self, a_bzrdir, _found=False):
"""See RepositoryFormat.open()."""
=== modified file 'bzrlib/repository.py'
--- a/bzrlib/repository.py 2010-04-19 13:04:30 +0000
+++ b/bzrlib/repository.py 2010-04-22 17:08:27 +0000
@@ -3171,6 +3171,15 @@
"""
raise NotImplementedError(self.open)
+ def _run_post_repo_init_hooks(self, repository, a_bzrdir, shared):
+ from bzrlib.bzrdir import BzrDir, RepoInitHookParams
+ hooks = BzrDir.hooks['post_repo_init']
+ if not hooks:
+ return
+ params = RepoInitHookParams(repository, self, a_bzrdir, shared)
+ for hook in hooks:
+ hook(params)
+
class MetaDirRepositoryFormat(RepositoryFormat):
"""Common base class for the new repositories using the metadir layout."""
=== modified file 'bzrlib/switch.py'
--- a/bzrlib/switch.py 2010-02-17 17:11:16 +0000
+++ b/bzrlib/switch.py 2010-03-25 14:22:41 +0000
@@ -22,6 +22,15 @@
from bzrlib.trace import note
+def _run_post_switch_hooks(control_dir, to_branch, force, revision_id):
+ from bzrlib.branch import SwitchHookParams
+ hooks = Branch.hooks['post_switch']
+ if not hooks:
+ return
+ params = SwitchHookParams(control_dir, to_branch, force, revision_id)
+ for hook in hooks:
+ hook(params)
+
def switch(control_dir, to_branch, force=False, quiet=False, revision_id=None):
"""Switch the branch associated with a checkout.
@@ -38,7 +47,7 @@
_set_branch_location(control_dir, to_branch, force)
tree = control_dir.open_workingtree()
_update(tree, source_repository, quiet, revision_id)
-
+ _run_post_switch_hooks(control_dir, to_branch, force, revision_id)
def _check_pending_merges(control, force=False):
"""Check that there are no outstanding pending merges before switching.
=== modified file 'bzrlib/tests/blackbox/test_branch.py'
--- a/bzrlib/tests/blackbox/test_branch.py 2010-03-25 07:34:15 +0000
+++ b/bzrlib/tests/blackbox/test_branch.py 2010-04-22 17:08:27 +0000
@@ -217,6 +217,36 @@
b = branch.Branch.open('b')
self.assertEndsWith(b.get_bound_location(), '/a/')
+ def test_branch_with_post_branch_init_hook(self):
+ calls = []
+ branch.Branch.hooks.install_named_hook('post_branch_init',
+ calls.append, None)
+ self.assertLength(0, calls)
+ self.example_branch('a')
+ self.assertLength(1, calls)
+ self.run_bzr('branch a b')
+ self.assertLength(2, calls)
+
+ def test_checkout_with_post_branch_init_hook(self):
+ calls = []
+ branch.Branch.hooks.install_named_hook('post_branch_init',
+ calls.append, None)
+ self.assertLength(0, calls)
+ self.example_branch('a')
+ self.assertLength(1, calls)
+ self.run_bzr('checkout a b')
+ self.assertLength(2, calls)
+
+ def test_lightweight_checkout_with_post_branch_init_hook(self):
+ calls = []
+ branch.Branch.hooks.install_named_hook('post_branch_init',
+ calls.append, None)
+ self.assertLength(0, calls)
+ self.example_branch('a')
+ self.assertLength(1, calls)
+ self.run_bzr('checkout --lightweight a b')
+ self.assertLength(2, calls)
+
class TestBranchStacked(ExternalBase):
"""Tests for branch --stacked"""
=== modified file 'bzrlib/tests/blackbox/test_shared_repository.py'
--- a/bzrlib/tests/blackbox/test_shared_repository.py 2010-02-17 17:11:16 +0000
+++ b/bzrlib/tests/blackbox/test_shared_repository.py 2010-03-25 18:02:45 +0000
@@ -138,3 +138,10 @@
self.assertRaises(errors.NoRepositoryPresent, dir.open_repository)
e = self.assertRaises(errors.NotBranchError, dir.open_branch)
self.assertNotContainsRe(str(e), "location is a repository")
+
+ def test_init_repo_with_post_repo_init_hook(self):
+ calls = []
+ BzrDir.hooks.install_named_hook('post_repo_init', calls.append, None)
+ self.assertLength(0, calls)
+ self.run_bzr("init-repository a")
+ self.assertLength(1, calls)
=== modified file 'bzrlib/tests/blackbox/test_switch.py'
--- a/bzrlib/tests/blackbox/test_switch.py 2010-02-17 17:11:16 +0000
+++ b/bzrlib/tests/blackbox/test_switch.py 2010-03-26 07:08:56 +0000
@@ -225,3 +225,29 @@
self.run_bzr('switch -b foo:branch2', working_dir='tree')
tree = WorkingTree.open('tree')
self.assertEndsWith(tree.branch.base, 'foo-branch2/')
+
+ def test_switch_with_post_switch_hook(self):
+ from bzrlib import branch as _mod_branch
+ calls = []
+ _mod_branch.Branch.hooks.install_named_hook('post_switch',
+ calls.append, None)
+ self.make_branch_and_tree('branch')
+ self.run_bzr('branch branch branch2')
+ self.run_bzr('checkout branch checkout')
+ os.chdir('checkout')
+ self.assertLength(0, calls)
+ out, err = self.run_bzr('switch ../branch2')
+ self.assertLength(1, calls)
+
+ def test_switch_lightweight_co_with_post_switch_hook(self):
+ from bzrlib import branch as _mod_branch
+ calls = []
+ _mod_branch.Branch.hooks.install_named_hook('post_switch',
+ calls.append, None)
+ self.make_branch_and_tree('branch')
+ self.run_bzr('branch branch branch2')
+ self.run_bzr('checkout --lightweight branch checkout')
+ os.chdir('checkout')
+ self.assertLength(0, calls)
+ out, err = self.run_bzr('switch ../branch2')
+ self.assertLength(1, calls)
=== modified file 'bzrlib/tests/test_branch.py'
--- a/bzrlib/tests/test_branch.py 2010-03-11 13:14:37 +0000
+++ b/bzrlib/tests/test_branch.py 2010-03-25 14:22:41 +0000
@@ -455,7 +455,7 @@
_mod_branch.BranchReferenceFormat().get_reference(checkout.bzrdir))
-class TestHooks(tests.TestCase):
+class TestHooks(tests.TestCaseWithTransport):
def test_constructor(self):
"""Check that creating a BranchHooks instance has the right defaults."""
@@ -469,6 +469,10 @@
"post_uncommit not in %s" % hooks)
self.assertTrue("post_change_branch_tip" in hooks,
"post_change_branch_tip not in %s" % hooks)
+ self.assertTrue("post_branch_init" in hooks,
+ "post_branch_init not in %s" % hooks)
+ self.assertTrue("post_switch" in hooks,
+ "post_switch not in %s" % hooks)
def test_installed_hooks_are_BranchHooks(self):
"""The installed hooks object should be a BranchHooks."""
@@ -476,6 +480,40 @@
self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch][1],
_mod_branch.BranchHooks)
+ def test_post_branch_init_hook(self):
+ calls = []
+ _mod_branch.Branch.hooks.install_named_hook('post_branch_init',
+ calls.append, None)
+ self.assertLength(0, calls)
+ branch = self.make_branch('a')
+ self.assertLength(1, calls)
+ params = calls[0]
+ self.assertIsInstance(params, _mod_branch.BranchInitHookParams)
+ self.assertTrue(hasattr(params, 'bzrdir'))
+ self.assertTrue(hasattr(params, 'branch'))
+
+ def test_post_switch_hook(self):
+ from bzrlib import switch
+ calls = []
+ _mod_branch.Branch.hooks.install_named_hook('post_switch',
+ calls.append, None)
+ tree = self.make_branch_and_tree('branch-1')
+ self.build_tree(['branch-1/file-1'])
+ tree.add('file-1')
+ tree.commit('rev1')
+ to_branch = tree.bzrdir.sprout('branch-2').open_branch()
+ self.build_tree(['branch-1/file-2'])
+ tree.add('file-2')
+ tree.remove('file-1')
+ tree.commit('rev2')
+ checkout = tree.branch.create_checkout('checkout')
+ self.assertLength(0, calls)
+ switch.switch(checkout.bzrdir, to_branch)
+ self.assertLength(1, calls)
+ params = calls[0]
+ self.assertIsInstance(params, _mod_branch.SwitchHookParams)
+ self.assertTrue(hasattr(params, 'to_branch'))
+ self.assertTrue(hasattr(params, 'revision_id'))
class TestPullResult(tests.TestCase):
=== modified file 'bzrlib/tests/test_bzrdir.py'
--- a/bzrlib/tests/test_bzrdir.py 2010-03-02 22:25:58 +0000
+++ b/bzrlib/tests/test_bzrdir.py 2010-03-25 14:22:41 +0000
@@ -1339,3 +1339,15 @@
url = transport.base
err = self.assertRaises(errors.BzrError, bzrdir.BzrDir.open, url)
self.assertEqual('fail', err._preformatted_string)
+
+ def test_post_repo_init(self):
+ from bzrlib.bzrdir import RepoInitHookParams
+ calls = []
+ bzrdir.BzrDir.hooks.install_named_hook('post_repo_init',
+ calls.append, None)
+ self.make_repository('foo')
+ self.assertLength(1, calls)
+ params = calls[0]
+ self.assertIsInstance(params, RepoInitHookParams)
+ self.assertTrue(hasattr(params, 'bzrdir'))
+ self.assertTrue(hasattr(params, 'repository'))
More information about the bazaar-commits
mailing list