Rev 5193: (andrew) Add bzrlib.merge.PerFileMerger to make it easier to write in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Thu Apr 29 08:30:14 BST 2010
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 5193 [merge]
revision-id: pqm at pqm.ubuntu.com-20100429073011-5f4kzm2wpojq9we1
parent: pqm at pqm.ubuntu.com-20100428220257-fwkbybtzi147j8re
parent: andrew.bennetts at canonical.com-20100429055235-24e81jfdse3h3ugt
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2010-04-29 08:30:11 +0100
message:
(andrew) Add bzrlib.merge.PerFileMerger to make it easier to write
simple merge_file_content hooks.
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/merge.py merge.py-20050513021216-953b65a438527106
doc/en/user-guide/hooks.txt hooks.txt-20070829200551-7nr6e5a1io6x78uf-1
=== modified file 'NEWS'
--- a/NEWS 2010-04-28 22:02:57 +0000
+++ b/NEWS 2010-04-29 05:52:35 +0000
@@ -76,6 +76,10 @@
API Changes
***********
+* Added ``bzrlib.merge.PerFileMerger``, a more convenient way to write
+ some kinds of ``merge_file_content`` hook functions.
+ (Andrew Bennetts)
+
* `BzrDir`, `Branch`, `Repository` and `WorkingTree` now all support `user_url`,
`user_transport`, `control_url` and `control_transport` members pointing
respectively to the directory containing the ``.bzr`` control directory,
=== modified file 'bzrlib/merge.py'
--- a/bzrlib/merge.py 2010-04-26 23:36:26 +0000
+++ b/bzrlib/merge.py 2010-04-29 05:52:35 +0000
@@ -93,7 +93,60 @@
return ('not applicable', None)
-class ConfigurableFileMerger(AbstractPerFileMerger):
+class PerFileMerger(AbstractPerFileMerger):
+ """Merge individual files when self.file_matches returns True.
+
+ This class is intended to be subclassed. The file_matches and
+ merge_matching methods should be overridden with concrete implementations.
+ """
+
+ def file_matches(self, params):
+ """Return True if merge_matching should be called on this file.
+
+ Only called with merges of plain files with no clear winner.
+
+ Subclasses must override this.
+ """
+ raise NotImplementedError(self.file_matches)
+
+ 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.
+ """
+ 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 tree: a Tree, e.g. self.merger.this_tree.
+ """
+ return tree.id2path(params.file_id)
+
+ def merge_contents(self, params):
+ """Merge the contents of a single file."""
+ # Check whether this custom merge logic should be used.
+ if (
+ # OTHER is a straight winner, rely on default merge.
+ params.winner == 'other' or
+ # THIS and OTHER aren't both files.
+ not params.is_file_merge() or
+ # The filename doesn't match *.xml
+ not self.file_matches(params)):
+ return 'not_applicable', None
+ return self.merge_matching(params)
+
+ def merge_matching(self, params):
+ """Merge the contents of a single file that has matched the criteria
+ in PerFileMerger.merge_contents (is a conflict, is a file,
+ self.file_matches is True).
+
+ Subclasses must override this.
+ """
+ raise NotImplementedError(self.merge_matching)
+
+
+class ConfigurableFileMerger(PerFileMerger):
"""Merge individual files when configured via a .conf file.
This is a base class for concrete custom file merging logic. Concrete
@@ -122,7 +175,7 @@
if self.name_prefix is None:
raise ValueError("name_prefix must be set.")
- def filename_matches_config(self, params):
+ def file_matches(self, params):
"""Check whether the file should call the merge hook.
<name_prefix>_merge_files configuration variable is a list of files
@@ -142,24 +195,12 @@
affected_files = self.default_files
self.affected_files = affected_files
if affected_files:
- filename = self.merger.this_tree.id2path(params.file_id)
- if filename in affected_files:
+ filepath = self.get_filepath(params, self.merger.this_tree)
+ if filepath in affected_files:
return True
return False
- def merge_contents(self, params):
- """Merge the contents of a single file."""
- # First, check whether this custom merge logic should be used. We
- # expect most files should not be merged by this handler.
- if (
- # OTHER is a straight winner, rely on default merge.
- params.winner == 'other' or
- # THIS and OTHER aren't both files.
- not params.is_file_merge() or
- # The filename isn't listed in the 'NAME_merge_files' config
- # option.
- not self.filename_matches_config(params)):
- return 'not_applicable', None
+ def merge_matching(self, params):
return self.merge_text(params)
def merge_text(self, params):
=== modified file 'doc/en/user-guide/hooks.txt'
--- a/doc/en/user-guide/hooks.txt 2010-04-21 07:52:31 +0000
+++ b/doc/en/user-guide/hooks.txt 2010-04-22 07:35:06 +0000
@@ -77,32 +77,19 @@
Always conflicts if both branches have changed the file.
"""
- from bzrlib.merge import AbstractPerFileMerger, Merger
+ from bzrlib.merge import PerFileMerger, Merger
def merge_xml_files_hook(merger):
"""Hook to merge *.xml files"""
return MergeXMLFiles(merger)
- class MergeXMLFiles(AbstractPerFileMerger):
-
- def filename_matches(self, params):
- inventory = self.merger.this_tree.inventory
- filename = inventory[params.file_id].name
- if filename.endswith('.xml'):
- return filename
-
- def merge_contents(self, params):
- """Merge the contents of a single file."""
- # First, check whether this custom merge logic should be used. We
- # expect most files should not be merged by this handler.
- if (
- # OTHER is a straight winner, rely on default merge.
- params.winner == 'other' or
- # THIS and OTHER aren't both files.
- not params.is_file_merge() or
- # The filename doesn't match *.xml
- not self.filename_matches(params)):
- return 'not_applicable', None
+ class AlwaysConflictXMLMerger(PerFileMerger):
+
+ def file_matches(self, params):
+ filename = self.get_filename(params, self.merger.this_tree)
+ return filename.endswith('.xml')
+
+ def merge_matching(self, params):
return 'conflicted', params.this_lines
Merger.hooks.install_named_hook(
More information about the bazaar-commits
mailing list