~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/merge.py

  • Committer: Andrew Bennetts
  • Date: 2010-04-22 07:35:06 UTC
  • mto: This revision was merged to the branch mainline in revision 5193.
  • Revision ID: andrew.bennetts@canonical.com-20100422073506-7i5pqyhzdj5pcelx
Create a PerFileMerger helper class that is midway between AbstractPerFileMerger and ConfigurableFileMerger.  It allows the example merge plugin in the docs (the always conflict *.xml files) to be much, much simpler.

Show diffs side-by-side

added added

removed removed

Lines of Context:
93
93
        return ('not applicable', None)
94
94
 
95
95
 
96
 
class ConfigurableFileMerger(AbstractPerFileMerger):
 
96
class PerFileMerger(AbstractPerFileMerger):
 
97
    """Merge individual files when self.file_matches returns True.
 
98
 
 
99
    This class is intended to be subclassed.  The file_matches and
 
100
    merge_matching methods should be overridden with concrete implementations.
 
101
    """
 
102
 
 
103
    def file_matches(self, params):
 
104
        """Return True if merge_matching should be called on this file.
 
105
 
 
106
        Only called with merges of plain files with no clear winner.
 
107
 
 
108
        Subclasses must override this.
 
109
        """
 
110
        raise NotImplementedError(self.file_matches)
 
111
 
 
112
    def get_filename(self, params, tree):
 
113
        """Lookup the filename (i.e. basename, not path), given a Tree (e.g.
 
114
        self.merger.this_tree) and a MergeHookParams.
 
115
        """
 
116
        return tree.inventory[params.file_id].name
 
117
 
 
118
    def get_filepath(self, params, tree):
 
119
        """Calculate the path to the file in a tree.
 
120
 
 
121
        :param params: A MergeHookParams describing the file to merge
 
122
        :param tree: a Tree, e.g. self.merger.this_tree.
 
123
        """
 
124
        return tree.id2path(params.file_id)
 
125
 
 
126
    def merge_contents(self, params):
 
127
        """Merge the contents of a single file."""
 
128
        # Check whether this custom merge logic should be used.
 
129
        if (
 
130
            # OTHER is a straight winner, rely on default merge.
 
131
            params.winner == 'other' or
 
132
            # THIS and OTHER aren't both files.
 
133
            not params.is_file_merge() or
 
134
            # The filename doesn't match *.xml
 
135
            not self.file_matches(params)):
 
136
            return 'not_applicable', None
 
137
        return self.merge_matching(self, params)
 
138
 
 
139
    def merge_matching(self, params):
 
140
        """Merge the contents of a single file that has matched the criteria
 
141
        in PerFileMerger.merge_contents (is a conflict, is a file,
 
142
        self.file_matches is True).
 
143
 
 
144
        Subclasses must override this.
 
145
        """
 
146
        raise NotImplementedError(self.merge_matching)
 
147
 
 
148
 
 
149
class ConfigurableFileMerger(PerFileMerger):
97
150
    """Merge individual files when configured via a .conf file.
98
151
 
99
152
    This is a base class for concrete custom file merging logic. Concrete
122
175
        if self.name_prefix is None:
123
176
            raise ValueError("name_prefix must be set.")
124
177
 
125
 
    def filename_matches_config(self, params):
 
178
    def file_matches(self, params):
126
179
        """Check whether the file should call the merge hook.
127
180
 
128
181
        <name_prefix>_merge_files configuration variable is a list of files
142
195
                affected_files = self.default_files
143
196
            self.affected_files = affected_files
144
197
        if affected_files:
145
 
            filename = self.merger.this_tree.id2path(params.file_id)
146
 
            if filename in affected_files:
 
198
            filepath = self.get_filepath(params, self.merger.this_tree)
 
199
            if filepath in affected_files:
147
200
                return True
148
201
        return False
149
202
 
150
 
    def merge_contents(self, params):
151
 
        """Merge the contents of a single file."""
152
 
        # First, check whether this custom merge logic should be used.  We
153
 
        # expect most files should not be merged by this handler.
154
 
        if (
155
 
            # OTHER is a straight winner, rely on default merge.
156
 
            params.winner == 'other' or
157
 
            # THIS and OTHER aren't both files.
158
 
            not params.is_file_merge() or
159
 
            # The filename isn't listed in the 'NAME_merge_files' config
160
 
            # option.
161
 
            not self.filename_matches_config(params)):
162
 
            return 'not_applicable', None
 
203
    def merge_matching(self, params):
163
204
        return self.merge_text(params)
164
205
 
165
206
    def merge_text(self, params):