Rev 6395: (jelmer) Add pre_merge and post_merge hooks in Merger.hooks. (Jelmer in file:///srv/pqm.bazaar-vcs.org/archives/thelove/bzr/%2Btrunk/

Patch Queue Manager pqm at pqm.ubuntu.com
Wed Dec 21 15:32:36 UTC 2011


At file:///srv/pqm.bazaar-vcs.org/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 6395 [merge]
revision-id: pqm at pqm.ubuntu.com-20111221153234-kbq1axff8pe224vt
parent: pqm at pqm.ubuntu.com-20111221141733-gmep8iobns97q3eo
parent: jelmer at samba.org-20111221144339-8j56mzd82yekrm0i
committer: Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Wed 2011-12-21 15:32:34 +0000
message:
  (jelmer) Add pre_merge and post_merge hooks in Merger.hooks. (Jelmer
   Vernooij)
modified:
  bzrlib/merge.py                merge.py-20050513021216-953b65a438527106
  bzrlib/plugins/changelog_merge/tests/test_changelog_merge.py test_changelog_merge-20110310080015-9c3muqni567c1qux-3
  bzrlib/tests/test_merge.py     testmerge.py-20050905070950-c1b5aa49ff911024
  doc/en/release-notes/bzr-2.5.txt bzr2.5.txt-20110708125756-587p0hpw7oke4h05-1
=== modified file 'bzrlib/merge.py'
--- a/bzrlib/merge.py	2011-12-20 11:45:12 +0000
+++ b/bzrlib/merge.py	2011-12-20 13:13:25 +0000
@@ -78,6 +78,15 @@
             "See the AbstractPerFileMerger API docs for details on how it is "
             "used by merge.",
             (2, 1))
+        self.add_hook('pre_merge',
+            'Called before a merge. '
+            'Receives a Merger object as the single argument.',
+            (2, 5))
+        self.add_hook('post_merge',
+            'Called after a merge. '
+            'Receives a Merger object as the single argument. '
+            'The return value is ignored.',
+            (2, 5))
 
 
 class AbstractPerFileMerger(object):
@@ -95,7 +104,7 @@
     def merge_contents(self, merge_params):
         """Attempt to merge the contents of a single file.
         
-        :param merge_params: A bzrlib.merge.MergeHookParams
+        :param merge_params: A bzrlib.merge.MergeFileHookParams
         :return: A tuple of (status, chunks), where status is one of
             'not_applicable', 'success', 'conflicted', or 'delete'.  If status
             is 'success' or 'conflicted', then chunks should be an iterable of
@@ -122,14 +131,14 @@
 
     def get_filename(self, params, tree):
         """Lookup the filename (i.e. basename, not path), given a Tree (e.g.
-        self.merger.this_tree) and a MergeHookParams.
+        self.merger.this_tree) and a MergeFileHookParams.
         """
         return osutils.basename(tree.id2path(params.file_id))
 
     def get_filepath(self, params, tree):
         """Calculate the path to the file in a tree.
 
-        :param params: A MergeHookParams describing the file to merge
+        :param params: A MergeFileHookParams describing the file to merge
         :param tree: a Tree, e.g. self.merger.this_tree.
         """
         return tree.id2path(params.file_id)
@@ -224,7 +233,7 @@
         raise NotImplementedError(self.merge_text)
 
 
-class MergeHookParams(object):
+class MergeFileHookParams(object):
     """Object holding parameters passed to merge_file_content hooks.
 
     There are some fields hooks can access:
@@ -603,7 +612,7 @@
             self._maybe_fetch(base_branch, self.this_branch, self.base_rev_id)
 
     def make_merger(self):
-        kwargs = {'working_tree':self.this_tree, 'this_tree': self.this_tree,
+        kwargs = {'working_tree': self.this_tree, 'this_tree': self.this_tree,
                   'other_tree': self.other_tree,
                   'interesting_ids': self.interesting_ids,
                   'interesting_files': self.interesting_files,
@@ -639,7 +648,11 @@
         merge = self.make_merger()
         if self.other_branch is not None:
             self.other_branch.update_references(self.this_branch)
+        for hook in Merger.hooks['pre_merge']:
+            hook(merge)
         merge.do_merge()
+        for hook in Merger.hooks['post_merge']:
+            hook(merge)
         if self.recurse == 'down':
             for relpath, file_id in self.this_tree.iter_references():
                 sub_tree = self.this_tree.get_nested_tree(file_id, relpath)
@@ -1343,7 +1356,7 @@
         # We have a hypothetical conflict, but if we have files, then we
         # can try to merge the content
         trans_id = self.tt.trans_id_file_id(file_id)
-        params = MergeHookParams(self, file_id, trans_id, this_pair[0],
+        params = MergeFileHookParams(self, file_id, trans_id, this_pair[0],
             other_pair[0], winner)
         hooks = self.active_hooks
         hook_status = 'not_applicable'

=== modified file 'bzrlib/plugins/changelog_merge/tests/test_changelog_merge.py'
--- a/bzrlib/plugins/changelog_merge/tests/test_changelog_merge.py	2011-05-13 06:34:55 +0000
+++ b/bzrlib/plugins/changelog_merge/tests/test_changelog_merge.py	2011-12-21 14:43:39 +0000
@@ -188,7 +188,7 @@
         merger = builder.make_merger(merge.Merge3Merger, ['clog-id'])
         merger.this_branch.get_config().set_user_option(
             'changelog_merge_files', 'ChangeLog')
-        merge_hook_params = merge.MergeHookParams(merger, 'clog-id', None,
+        merge_hook_params = merge.MergeFileHookParams(merger, 'clog-id', None,
             'file', 'file', 'conflict')
         changelog_merger = changelog_merge.ChangeLogMerger(merger)
         return changelog_merger, merge_hook_params

=== modified file 'bzrlib/tests/test_merge.py'
--- a/bzrlib/tests/test_merge.py	2011-10-14 13:56:45 +0000
+++ b/bzrlib/tests/test_merge.py	2011-12-21 12:34:21 +0000
@@ -3242,3 +3242,46 @@
         # The dest tree is unmodified.
         self.assertEqual(['r1-dest'], dest_wt.get_parent_ids())
         self.assertTreeEntriesEqual([('', 'dest-root-id')], dest_wt)
+
+
+class TestMergeHooks(TestCaseWithTransport):
+
+    def setUp(self):
+        super(TestMergeHooks, self).setUp()
+        self.tree_a = self.make_branch_and_tree('tree_a')
+        self.build_tree_contents([('tree_a/file', 'content_1')])
+        self.tree_a.add('file', 'file-id')
+        self.tree_a.commit('added file')
+
+        self.tree_b = self.tree_a.bzrdir.sprout('tree_b').open_workingtree()
+        self.build_tree_contents([('tree_b/file', 'content_2')])
+        self.tree_b.commit('modify file')
+
+    def test_pre_merge_hook_inject_different_tree(self):
+        tree_c = self.tree_b.bzrdir.sprout('tree_c').open_workingtree()
+        self.build_tree_contents([('tree_c/file', 'content_3')])
+        tree_c.commit("more content")
+        calls = []
+        def factory(merger):
+            self.assertIsInstance(merger, _mod_merge.Merge3Merger)
+            merger.other_tree = tree_c
+            calls.append(merger)
+        _mod_merge.Merger.hooks.install_named_hook('pre_merge',
+                                                   factory, 'test factory')
+        self.tree_a.merge_from_branch(self.tree_b.branch)
+
+        self.assertFileEqual("content_3", 'tree_a/file')
+        self.assertLength(1, calls)
+
+    def test_post_merge_hook_called(self):
+        calls = []
+        def factory(merger):
+            self.assertIsInstance(merger, _mod_merge.Merge3Merger)
+            calls.append(merger)
+        _mod_merge.Merger.hooks.install_named_hook('post_merge',
+                                                   factory, 'test factory')
+
+        self.tree_a.merge_from_branch(self.tree_b.branch)
+
+        self.assertFileEqual("content_2", 'tree_a/file')
+        self.assertLength(1, calls)

=== modified file 'doc/en/release-notes/bzr-2.5.txt'
--- a/doc/en/release-notes/bzr-2.5.txt	2011-12-21 00:07:49 +0000
+++ b/doc/en/release-notes/bzr-2.5.txt	2011-12-21 15:32:34 +0000
@@ -36,6 +36,11 @@
 
 * New HPSS call for ``Repository.reconcile``. (Jelmer Vernooij, #894455)
 
+* Merge now has two new hooks ``pre_merge`` and ``post_merge``
+  that are called before and after a merge and can make
+  additional modifications to the trees involved.
+  (Jelmer Vernooij, #906877)
+
 * Override the value returned by ``sys.getfilesystemencoding()`` for the bzr
   script to utf-8 when it would otherwise be ascii on a posix system. This
   will mean bzr works with non-ascii files when no locale or an incorrect




More information about the bazaar-commits mailing list