/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5557.1.15 by John Arbash Meinel
Merge bzr.dev 5597 to resolve NEWS, aka bzr-2.3.txt
1
# Copyright (C) 2009, 2010, 2011 Canonical Ltd
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
17
"""Implementation tests for breezy.merge.Merger."""
4869.2.8 by Andrew Bennetts
Use _merge_type_registry for per_merger tests.
18
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
19
import os
20
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
21
from ..conflicts import TextConflict
22
from .. import (
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
23
    errors,
24
    merge as _mod_merge,
25
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
26
from . import (
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
27
    multiply_tests,
28
    TestCaseWithTransport,
29
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
30
from .test_merge_core import MergeBuilder
31
from ..transform import TreeTransform
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
32
33
34
6625.1.5 by Martin
Drop custom load_tests implementation and use unittest signature
35
def load_tests(loader, standard_tests, pattern):
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
36
    """Multiply tests for tranport implementations."""
37
    result = loader.suiteClass()
38
    scenarios = [
4869.2.8 by Andrew Bennetts
Use _merge_type_registry for per_merger tests.
39
        (name, {'merge_type': merger})
6259.3.5 by Martin Packman
Update bt.per_merger parametrisation to new registry location
40
        for name, merger in _mod_merge.merge_type_registry.items()]
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
41
    return multiply_tests(standard_tests, scenarios, result)
42
43
44
class TestMergeImplementation(TestCaseWithTransport):
45
46
    def do_merge(self, target_tree, source_tree, **kwargs):
6719.1.2 by Jelmer Vernooij
Fix some tests.
47
        merger = _mod_merge.Merger.from_revision_ids(
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
48
            target_tree, source_tree.last_revision(),
49
            other_branch=source_tree.branch)
50
        merger.merge_type=self.merge_type
51
        for name, value in kwargs.items():
52
            setattr(merger, name, value)
53
        merger.do_merge()
54
55
    def test_merge_specific_file(self):
56
        this_tree = self.make_branch_and_tree('this')
57
        this_tree.lock_write()
58
        self.addCleanup(this_tree.unlock)
59
        self.build_tree_contents([
6855.4.1 by Jelmer Vernooij
Yet more bees.
60
            ('this/file1', b'a\nb\n'),
61
            ('this/file2', b'a\nb\n')
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
62
        ])
63
        this_tree.add(['file1', 'file2'])
64
        this_tree.commit('Added files')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
65
        other_tree = this_tree.controldir.sprout('other').open_workingtree()
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
66
        self.build_tree_contents([
6855.4.1 by Jelmer Vernooij
Yet more bees.
67
            ('other/file1', b'a\nb\nc\n'),
68
            ('other/file2', b'a\nb\nc\n')
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
69
        ])
70
        other_tree.commit('modified both')
71
        self.build_tree_contents([
6855.4.1 by Jelmer Vernooij
Yet more bees.
72
            ('this/file1', b'd\na\nb\n'),
73
            ('this/file2', b'd\na\nb\n')
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
74
        ])
75
        this_tree.commit('modified both')
76
        self.do_merge(this_tree, other_tree, interesting_files=['file1'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
77
        self.assertFileEqual(b'd\na\nb\nc\n', 'this/file1')
78
        self.assertFileEqual(b'd\na\nb\n', 'this/file2')
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
79
80
    def test_merge_move_and_change(self):
81
        this_tree = self.make_branch_and_tree('this')
82
        this_tree.lock_write()
83
        self.addCleanup(this_tree.unlock)
84
        self.build_tree_contents([
6855.4.1 by Jelmer Vernooij
Yet more bees.
85
            ('this/file1', b'line 1\nline 2\nline 3\nline 4\n'),
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
86
        ])
87
        this_tree.add('file1',)
88
        this_tree.commit('Added file')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
89
        other_tree = this_tree.controldir.sprout('other').open_workingtree()
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
90
        self.build_tree_contents([
6855.4.1 by Jelmer Vernooij
Yet more bees.
91
            ('other/file1', b'line 1\nline 2 to 2.1\nline 3\nline 4\n'),
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
92
        ])
93
        other_tree.commit('Changed 2 to 2.1')
94
        self.build_tree_contents([
6855.4.1 by Jelmer Vernooij
Yet more bees.
95
            ('this/file1', b'line 1\nline 3\nline 2\nline 4\n'),
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
96
        ])
97
        this_tree.commit('Swapped 2 & 3')
98
        self.do_merge(this_tree, other_tree)
99
        if self.merge_type is _mod_merge.LCAMerger:
4869.2.6 by Andrew Bennetts
test_merge_move_and_change should still be an expected fail for LCA merge.
100
            self.expectFailure(
101
                "lca merge doesn't conflict for move and change",
102
                self.assertFileEqual,
6855.4.1 by Jelmer Vernooij
Yet more bees.
103
                b'line 1\n'
104
                b'<<<<<<< TREE\n'
105
                b'line 3\n'
106
                b'line 2\n'
107
                b'=======\n'
108
                b'line 2 to 2.1\n'
109
                b'line 3\n'
110
                b'>>>>>>> MERGE-SOURCE\n'
111
                b'line 4\n', 'this/file1')
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
112
        else:
6855.4.1 by Jelmer Vernooij
Yet more bees.
113
            self.assertFileEqual(b'line 1\n'
114
                b'<<<<<<< TREE\n'
115
                b'line 3\n'
116
                b'line 2\n'
117
                b'=======\n'
118
                b'line 2 to 2.1\n'
119
                b'line 3\n'
120
                b'>>>>>>> MERGE-SOURCE\n'
121
                b'line 4\n', 'this/file1')
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
122
123
    def test_modify_conflicts_with_delete(self):
124
        # If one side deletes a line, and the other modifies that line, then
125
        # the modification should be considered a conflict
126
        builder = self.make_branch_builder('test')
127
        builder.start_series()
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
128
        builder.build_snapshot(None,
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
129
            [('add', ('', None, 'directory', None)),
6855.4.1 by Jelmer Vernooij
Yet more bees.
130
             ('add', ('foo', b'foo-id', 'file', b'a\nb\nc\nd\ne\n')),
131
            ], revision_id=b'BASE-id')
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
132
        # Delete 'b\n'
6855.4.1 by Jelmer Vernooij
Yet more bees.
133
        builder.build_snapshot([b'BASE-id'],
6883.22.11 by Jelmer Vernooij
merge trunk
134
            [('modify', ('foo', b'a\nc\nd\ne\n'))],
6855.4.1 by Jelmer Vernooij
Yet more bees.
135
            revision_id=b'OTHER-id')
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
136
        # Modify 'b\n', add 'X\n'
6855.4.1 by Jelmer Vernooij
Yet more bees.
137
        builder.build_snapshot([b'BASE-id'],
6883.22.11 by Jelmer Vernooij
merge trunk
138
            [('modify', ('foo', b'a\nb2\nc\nd\nX\ne\n'))],
6855.4.1 by Jelmer Vernooij
Yet more bees.
139
            revision_id=b'THIS-id')
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
140
        builder.finish_series()
141
        branch = builder.get_branch()
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
142
        this_tree = branch.controldir.create_workingtree()
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
143
        this_tree.lock_write()
144
        self.addCleanup(this_tree.unlock)
6855.4.1 by Jelmer Vernooij
Yet more bees.
145
        other_tree = this_tree.controldir.sprout('other', b'OTHER-id').open_workingtree()
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
146
        self.do_merge(this_tree, other_tree)
147
        if self.merge_type is _mod_merge.LCAMerger:
148
            self.expectFailure("lca merge doesn't track deleted lines",
149
                self.assertFileEqual,
6855.4.1 by Jelmer Vernooij
Yet more bees.
150
                    b'a\n'
151
                    b'<<<<<<< TREE\n'
152
                    b'b2\n'
153
                    b'=======\n'
154
                    b'>>>>>>> MERGE-SOURCE\n'
155
                    b'c\n'
156
                    b'd\n'
157
                    b'X\n'
158
                    b'e\n', 'test/foo')
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
159
        else:
160
            self.assertFileEqual(
6855.4.1 by Jelmer Vernooij
Yet more bees.
161
                b'a\n'
162
                b'<<<<<<< TREE\n'
163
                b'b2\n'
164
                b'=======\n'
165
                b'>>>>>>> MERGE-SOURCE\n'
166
                b'c\n'
167
                b'd\n'
168
                b'X\n'
169
                b'e\n', 'test/foo')
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
170
171
    def get_limbodir_deletiondir(self, wt):
172
        transform = TreeTransform(wt)
173
        limbodir = transform._limbodir
174
        deletiondir = transform._deletiondir
175
        transform.finalize()
176
        return (limbodir, deletiondir)
4869.3.34 by Vincent Ladeuil
Finish the patch based on reviews.
177
6015.51.1 by Martin Pool
Tolerate empty limbo and pending-deletion directories
178
    def test_merge_with_existing_limbo_empty(self):
179
        """Empty limbo dir is just cleaned up - see bug 427773"""
180
        wt = self.make_branch_and_tree('this')
181
        (limbodir, deletiondir) =  self.get_limbodir_deletiondir(wt)
182
        os.mkdir(limbodir)
183
        self.do_merge(wt, wt)
184
185
    def test_merge_with_existing_limbo_non_empty(self):
186
        wt = self.make_branch_and_tree('this')
187
        (limbodir, deletiondir) =  self.get_limbodir_deletiondir(wt)
188
        os.mkdir(limbodir)
189
        os.mkdir(os.path.join(limbodir, 'something'))
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
190
        self.assertRaises(errors.ExistingLimbo, self.do_merge, wt, wt)
191
        self.assertRaises(errors.LockError, wt.unlock)
192
6015.51.1 by Martin Pool
Tolerate empty limbo and pending-deletion directories
193
    def test_merge_with_pending_deletion_empty(self):
6015.51.2 by Martin Pool
Get the test names right
194
        wt = self.make_branch_and_tree('this')
195
        (limbodir, deletiondir) =  self.get_limbodir_deletiondir(wt)
196
        os.mkdir(deletiondir)
6015.51.3 by Martin Pool
test_merge_with_pending_deletion_empty: correct the assertions
197
        self.do_merge(wt, wt)
6015.51.2 by Martin Pool
Get the test names right
198
199
    def test_merge_with_pending_deletion_non_empty(self):
6015.51.1 by Martin Pool
Tolerate empty limbo and pending-deletion directories
200
        """Also see bug 427773"""
201
        wt = self.make_branch_and_tree('this')
202
        (limbodir, deletiondir) =  self.get_limbodir_deletiondir(wt)
203
        os.mkdir(deletiondir)
204
        os.mkdir(os.path.join(deletiondir, 'something'))
205
        self.assertRaises(errors.ExistingPendingDeletion, self.do_merge, wt, wt)
206
        self.assertRaises(errors.LockError, wt.unlock)
207
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
208
4869.3.3 by Andrew Bennetts
Move test_hook_merge_file_content to per_merger.
209
class TestHookMergeFileContent(TestCaseWithTransport):
210
    """Tests that the 'merge_file_content' hook is invoked."""
211
4869.3.10 by Andrew Bennetts
Add more tests.
212
    def setUp(self):
6552.1.4 by Vincent Ladeuil
Remaining tests matching setup(self) that can be rewritten with super().
213
        super(TestHookMergeFileContent, self).setUp()
4869.3.10 by Andrew Bennetts
Add more tests.
214
        self.hook_log = []
4869.3.34 by Vincent Ladeuil
Finish the patch based on reviews.
215
4797.5.1 by Robert Collins
Support state on per-file merging to permit more efficient use of configuration data.
216
    def install_hook_inactive(self):
217
        def inactive_factory(merger):
218
            # This hook is never active
219
            self.hook_log.append(('inactive',))
220
            return None
221
        _mod_merge.Merger.hooks.install_named_hook(
222
            'merge_file_content', inactive_factory, 'test hook (inactive)')
223
4869.3.5 by Andrew Bennetts
Hook is invoked for delete vs. change conflicts, and may choose to result in deleting the file.
224
    def install_hook_noop(self):
4797.5.1 by Robert Collins
Support state on per-file merging to permit more efficient use of configuration data.
225
        test = self
226
        class HookNA(_mod_merge.AbstractPerFileMerger):
227
            def merge_contents(self, merge_params):
228
                # This hook unconditionally does nothing.
229
                test.hook_log.append(('no-op',))
230
                return 'not_applicable', None
231
        def hook_na_factory(merger):
232
            return HookNA(merger)
4869.3.3 by Andrew Bennetts
Move test_hook_merge_file_content to per_merger.
233
        _mod_merge.Merger.hooks.install_named_hook(
4797.5.1 by Robert Collins
Support state on per-file merging to permit more efficient use of configuration data.
234
            'merge_file_content', hook_na_factory, 'test hook (no-op)')
4869.3.5 by Andrew Bennetts
Hook is invoked for delete vs. change conflicts, and may choose to result in deleting the file.
235
236
    def install_hook_success(self):
4797.5.1 by Robert Collins
Support state on per-file merging to permit more efficient use of configuration data.
237
        test = self
238
        class HookSuccess(_mod_merge.AbstractPerFileMerger):
239
            def merge_contents(self, merge_params):
240
                test.hook_log.append(('success',))
241
                if merge_params.file_id == '1':
6973.12.3 by Jelmer Vernooij
Fixes.
242
                    return 'success', [b'text-merged-by-hook']
4797.5.1 by Robert Collins
Support state on per-file merging to permit more efficient use of configuration data.
243
                return 'not_applicable', None
244
        def hook_success_factory(merger):
245
            return HookSuccess(merger)
4869.3.3 by Andrew Bennetts
Move test_hook_merge_file_content to per_merger.
246
        _mod_merge.Merger.hooks.install_named_hook(
4797.5.1 by Robert Collins
Support state on per-file merging to permit more efficient use of configuration data.
247
            'merge_file_content', hook_success_factory, 'test hook (success)')
4869.3.34 by Vincent Ladeuil
Finish the patch based on reviews.
248
4869.3.6 by Andrew Bennetts
Add more tests.
249
    def install_hook_conflict(self):
4797.5.1 by Robert Collins
Support state on per-file merging to permit more efficient use of configuration data.
250
        test = self
251
        class HookConflict(_mod_merge.AbstractPerFileMerger):
252
            def merge_contents(self, merge_params):
253
                test.hook_log.append(('conflict',))
254
                if merge_params.file_id == '1':
255
                    return ('conflicted',
6973.12.3 by Jelmer Vernooij
Fixes.
256
                        [b'text-with-conflict-markers-from-hook'])
4797.5.1 by Robert Collins
Support state on per-file merging to permit more efficient use of configuration data.
257
                return 'not_applicable', None
258
        def hook_conflict_factory(merger):
259
            return HookConflict(merger)
4869.3.6 by Andrew Bennetts
Add more tests.
260
        _mod_merge.Merger.hooks.install_named_hook(
4797.5.1 by Robert Collins
Support state on per-file merging to permit more efficient use of configuration data.
261
            'merge_file_content', hook_conflict_factory, 'test hook (delete)')
4869.3.34 by Vincent Ladeuil
Finish the patch based on reviews.
262
4869.3.5 by Andrew Bennetts
Hook is invoked for delete vs. change conflicts, and may choose to result in deleting the file.
263
    def install_hook_delete(self):
4797.5.1 by Robert Collins
Support state on per-file merging to permit more efficient use of configuration data.
264
        test = self
265
        class HookDelete(_mod_merge.AbstractPerFileMerger):
266
            def merge_contents(self, merge_params):
267
                test.hook_log.append(('delete',))
268
                if merge_params.file_id == '1':
269
                    return 'delete', None
270
                return 'not_applicable', None
271
        def hook_delete_factory(merger):
272
            return HookDelete(merger)
4869.3.5 by Andrew Bennetts
Hook is invoked for delete vs. change conflicts, and may choose to result in deleting the file.
273
        _mod_merge.Merger.hooks.install_named_hook(
4797.5.1 by Robert Collins
Support state on per-file merging to permit more efficient use of configuration data.
274
            'merge_file_content', hook_delete_factory, 'test hook (delete)')
4869.3.34 by Vincent Ladeuil
Finish the patch based on reviews.
275
4869.3.6 by Andrew Bennetts
Add more tests.
276
    def install_hook_log_lines(self):
277
        """Install a hook that saves the get_lines for the this, base and other
278
        versions of the file.
279
        """
4797.5.1 by Robert Collins
Support state on per-file merging to permit more efficient use of configuration data.
280
        test = self
281
        class HookLogLines(_mod_merge.AbstractPerFileMerger):
282
            def merge_contents(self, merge_params):
283
                test.hook_log.append((
284
                    'log_lines',
285
                    merge_params.this_lines,
286
                    merge_params.other_lines,
287
                    merge_params.base_lines,
288
                    ))
289
                return 'not_applicable', None
290
        def hook_log_lines_factory(merger):
291
            return HookLogLines(merger)
4869.3.6 by Andrew Bennetts
Add more tests.
292
        _mod_merge.Merger.hooks.install_named_hook(
4797.5.1 by Robert Collins
Support state on per-file merging to permit more efficient use of configuration data.
293
            'merge_file_content', hook_log_lines_factory,
294
            'test hook (log_lines)')
4869.3.6 by Andrew Bennetts
Add more tests.
295
4869.3.3 by Andrew Bennetts
Move test_hook_merge_file_content to per_merger.
296
    def make_merge_builder(self):
297
        builder = MergeBuilder(self.test_base_dir)
298
        self.addCleanup(builder.cleanup)
299
        return builder
300
4869.3.10 by Andrew Bennetts
Add more tests.
301
    def create_file_needing_contents_merge(self, builder, file_id):
6855.3.1 by Jelmer Vernooij
Several more fixes.
302
        builder.add_file(file_id, builder.tree_root, "name1", b"text1", True)
6973.12.3 by Jelmer Vernooij
Fixes.
303
        builder.change_contents(file_id, other=b"text4", this=b"text3")
4869.3.34 by Vincent Ladeuil
Finish the patch based on reviews.
304
4869.3.5 by Andrew Bennetts
Hook is invoked for delete vs. change conflicts, and may choose to result in deleting the file.
305
    def test_change_vs_change(self):
306
        """Hook is used for (changed, changed)"""
307
        self.install_hook_success()
4869.3.3 by Andrew Bennetts
Move test_hook_merge_file_content to per_merger.
308
        builder = self.make_merge_builder()
6973.12.3 by Jelmer Vernooij
Fixes.
309
        builder.add_file(b"1", builder.tree_root, "name1", b"text1", True)
310
        builder.change_contents(b"1", other=b"text4", this=b"text3")
4869.3.3 by Andrew Bennetts
Move test_hook_merge_file_content to per_merger.
311
        conflicts = builder.merge(self.merge_type)
312
        self.assertEqual(conflicts, [])
313
        self.assertEqual(
6973.12.3 by Jelmer Vernooij
Fixes.
314
            builder.this.get_file('name1').read(), b'text-merged-by-hook')
4869.2.5 by Andrew Bennetts
Move per-merger tests into a per_merger test module.
315
4869.3.5 by Andrew Bennetts
Hook is invoked for delete vs. change conflicts, and may choose to result in deleting the file.
316
    def test_change_vs_deleted(self):
317
        """Hook is used for (changed, deleted)"""
318
        self.install_hook_success()
319
        builder = self.make_merge_builder()
6973.12.3 by Jelmer Vernooij
Fixes.
320
        builder.add_file(b"1", builder.tree_root, "name1", b"text1", True)
321
        builder.change_contents(b"1", this=b"text2")
322
        builder.remove_file(b"1", other=True)
4869.3.5 by Andrew Bennetts
Hook is invoked for delete vs. change conflicts, and may choose to result in deleting the file.
323
        conflicts = builder.merge(self.merge_type)
324
        self.assertEqual(conflicts, [])
325
        self.assertEqual(
6973.12.3 by Jelmer Vernooij
Fixes.
326
            builder.this.get_file('name1').read(), b'text-merged-by-hook')
4869.3.5 by Andrew Bennetts
Hook is invoked for delete vs. change conflicts, and may choose to result in deleting the file.
327
328
    def test_result_can_be_delete(self):
329
        """A hook's result can be the deletion of a file."""
330
        self.install_hook_delete()
331
        builder = self.make_merge_builder()
6973.12.3 by Jelmer Vernooij
Fixes.
332
        self.create_file_needing_contents_merge(builder, b"1")
4869.3.5 by Andrew Bennetts
Hook is invoked for delete vs. change conflicts, and may choose to result in deleting the file.
333
        conflicts = builder.merge(self.merge_type)
334
        self.assertEqual(conflicts, [])
6973.12.3 by Jelmer Vernooij
Fixes.
335
        self.assertRaises(errors.NoSuchId, builder.this.id2path, b'1')
4869.3.14 by Andrew Bennetts
Fix bug that would leave an unversioned file behind when a hook asks for a deletion.
336
        self.assertEqual([], list(builder.this.list_files()))
4869.3.5 by Andrew Bennetts
Hook is invoked for delete vs. change conflicts, and may choose to result in deleting the file.
337
4869.3.6 by Andrew Bennetts
Add more tests.
338
    def test_result_can_be_conflict(self):
339
        """A hook's result can be a conflict."""
340
        self.install_hook_conflict()
341
        builder = self.make_merge_builder()
6973.12.3 by Jelmer Vernooij
Fixes.
342
        self.create_file_needing_contents_merge(builder, b"1")
4869.3.6 by Andrew Bennetts
Add more tests.
343
        conflicts = builder.merge(self.merge_type)
6973.12.3 by Jelmer Vernooij
Fixes.
344
        self.assertEqual(conflicts, [TextConflict('name1', file_id=b'1')])
4869.3.6 by Andrew Bennetts
Add more tests.
345
        # The hook still gets to set the file contents in this case, so that it
346
        # can insert custom conflict markers.
347
        self.assertEqual(
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
348
            builder.this.get_file('name1').read(),
6973.12.3 by Jelmer Vernooij
Fixes.
349
            b'text-with-conflict-markers-from-hook')
4869.3.6 by Andrew Bennetts
Add more tests.
350
351
    def test_can_access_this_other_and_base_versions(self):
352
        """The hook function can call params.merger.get_lines to access the
353
        THIS/OTHER/BASE versions of the file.
354
        """
355
        self.install_hook_log_lines()
356
        builder = self.make_merge_builder()
6973.12.3 by Jelmer Vernooij
Fixes.
357
        builder.add_file(b"1", builder.tree_root, "name1", b"text1", True)
358
        builder.change_contents(b"1", this=b"text2", other=b"text3")
4869.3.6 by Andrew Bennetts
Add more tests.
359
        conflicts = builder.merge(self.merge_type)
360
        self.assertEqual(
6973.12.3 by Jelmer Vernooij
Fixes.
361
            [('log_lines', [b'text2'], [b'text3'], [b'text1'])], self.hook_log)
4869.3.10 by Andrew Bennetts
Add more tests.
362
4797.5.1 by Robert Collins
Support state on per-file merging to permit more efficient use of configuration data.
363
    def test_chain_when_not_active(self):
364
        """When a hook function returns None, merging still works."""
365
        self.install_hook_inactive()
366
        self.install_hook_success()
367
        builder = self.make_merge_builder()
6973.12.3 by Jelmer Vernooij
Fixes.
368
        self.create_file_needing_contents_merge(builder, b"1")
4797.5.1 by Robert Collins
Support state on per-file merging to permit more efficient use of configuration data.
369
        conflicts = builder.merge(self.merge_type)
370
        self.assertEqual(conflicts, [])
371
        self.assertEqual(
6973.12.3 by Jelmer Vernooij
Fixes.
372
            builder.this.get_file('name1').read(), b'text-merged-by-hook')
4797.5.1 by Robert Collins
Support state on per-file merging to permit more efficient use of configuration data.
373
        self.assertEqual([('inactive',), ('success',)], self.hook_log)
374
4869.3.10 by Andrew Bennetts
Add more tests.
375
    def test_chain_when_not_applicable(self):
376
        """When a hook function returns not_applicable, the next function is
377
        tried (when one exists).
378
        """
379
        self.install_hook_noop()
380
        self.install_hook_success()
381
        builder = self.make_merge_builder()
6973.12.3 by Jelmer Vernooij
Fixes.
382
        self.create_file_needing_contents_merge(builder, b"1")
4869.3.10 by Andrew Bennetts
Add more tests.
383
        conflicts = builder.merge(self.merge_type)
384
        self.assertEqual(conflicts, [])
385
        self.assertEqual(
6973.12.3 by Jelmer Vernooij
Fixes.
386
            builder.this.get_file('name1').read(), b'text-merged-by-hook')
4869.3.10 by Andrew Bennetts
Add more tests.
387
        self.assertEqual([('no-op',), ('success',)], self.hook_log)
388
389
    def test_chain_stops_after_success(self):
390
        """When a hook function returns success, no later functions are tried.
391
        """
392
        self.install_hook_success()
393
        self.install_hook_noop()
394
        builder = self.make_merge_builder()
6973.12.3 by Jelmer Vernooij
Fixes.
395
        self.create_file_needing_contents_merge(builder, b"1")
4869.3.10 by Andrew Bennetts
Add more tests.
396
        conflicts = builder.merge(self.merge_type)
397
        self.assertEqual([('success',)], self.hook_log)
398
399
    def test_chain_stops_after_conflict(self):
400
        """When a hook function returns conflict, no later functions are tried.
401
        """
402
        self.install_hook_conflict()
403
        self.install_hook_noop()
404
        builder = self.make_merge_builder()
6973.12.3 by Jelmer Vernooij
Fixes.
405
        self.create_file_needing_contents_merge(builder, b"1")
4869.3.10 by Andrew Bennetts
Add more tests.
406
        conflicts = builder.merge(self.merge_type)
407
        self.assertEqual([('conflict',)], self.hook_log)
408
409
    def test_chain_stops_after_delete(self):
410
        """When a hook function returns delete, no later functions are tried.
411
        """
412
        self.install_hook_delete()
413
        self.install_hook_noop()
414
        builder = self.make_merge_builder()
6973.12.3 by Jelmer Vernooij
Fixes.
415
        self.create_file_needing_contents_merge(builder, b"1")
4869.3.10 by Andrew Bennetts
Add more tests.
416
        conflicts = builder.merge(self.merge_type)
417
        self.assertEqual([('delete',)], self.hook_log)
4869.3.6 by Andrew Bennetts
Add more tests.
418