/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2006 Canonical Ltd
1740.3.1 by Jelmer Vernooij
Introduce and use CommitBuilder objects.
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Tests for repository commit builder."""
18
2831.5.1 by Vincent Ladeuil
Portability fix in TestCommitBuilder for unlink.
19
import errno
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
20
import os
2831.5.1 by Vincent Ladeuil
Portability fix in TestCommitBuilder for unlink.
21
import sys
22
23
from bzrlib import (
24
    errors,
25
    inventory,
26
    osutils,
27
    repository,
28
    tests,
29
    )
30
from bzrlib.tests.repository_implementations import test_repository
31
32
33
class TestCommitBuilder(test_repository.TestCaseWithRepository):
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
34
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
35
    def test_get_commit_builder(self):
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
36
        branch = self.make_branch('.')
37
        branch.repository.lock_write()
38
        builder = branch.repository.get_commit_builder(
39
            branch, [], branch.get_config())
2831.5.1 by Vincent Ladeuil
Portability fix in TestCommitBuilder for unlink.
40
        self.assertIsInstance(builder, repository.CommitBuilder)
2805.6.1 by Robert Collins
Set random_revid on CommitBuilder when a commit generated its own revision id.
41
        self.assertTrue(builder.random_revid)
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
42
        branch.repository.commit_write_group()
43
        branch.repository.unlock()
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
44
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
45
    def record_root(self, builder, tree):
46
        if builder.record_root_entry is True:
2255.7.8 by John Arbash Meinel
Lock the tree when using a commit builder.
47
            tree.lock_read()
48
            try:
49
                ie = tree.inventory.root
50
            finally:
51
                tree.unlock()
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
52
            parent_tree = tree.branch.repository.revision_tree(None)
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
53
            parent_invs = []
2776.4.4 by Robert Collins
Move content summary generation outside of record_entry_contents.
54
            builder.record_entry_contents(ie, parent_invs, '', tree,
55
                tree.path_content_summary(''))
1731.1.33 by Aaron Bentley
Revert no-special-root changes
56
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
57
    def test_finish_inventory(self):
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
58
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
59
        tree.lock_write()
2617.6.8 by Robert Collins
Review feedback and documentation.
60
        try:
61
            builder = tree.branch.get_commit_builder([])
62
            self.record_root(builder, tree)
63
            builder.finish_inventory()
64
            tree.branch.repository.commit_write_group()
65
        finally:
66
            tree.unlock()
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
67
2749.3.1 by Jelmer Vernooij
Add CommitBuilder.abort().
68
    def test_abort(self):
69
        tree = self.make_branch_and_tree(".")
70
        tree.lock_write()
71
        try:
72
            builder = tree.branch.get_commit_builder([])
73
            self.record_root(builder, tree)
74
            builder.finish_inventory()
75
            builder.abort()
76
        finally:
77
            tree.unlock()
78
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
79
    def test_commit_message(self):
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
80
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
81
        tree.lock_write()
2617.6.8 by Robert Collins
Review feedback and documentation.
82
        try:
83
            builder = tree.branch.get_commit_builder([])
84
            self.record_root(builder, tree)
85
            builder.finish_inventory()
86
            rev_id = builder.commit('foo bar blah')
87
        finally:
88
            tree.unlock()
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
89
        rev = tree.branch.repository.get_revision(rev_id)
90
        self.assertEqual('foo bar blah', rev.message)
91
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
92
    def test_commit_with_revision_id(self):
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
93
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
94
        tree.lock_write()
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
95
        try:
2617.6.8 by Robert Collins
Review feedback and documentation.
96
            # use a unicode revision id to test more corner cases.
97
            # The repository layer is meant to handle this.
98
            revision_id = u'\xc8abc'.encode('utf8')
2150.2.2 by Robert Collins
Change the commit builder selected-revision-id test to use a unicode revision id where possible, leading to stricter testing of the hypothetical unicode revision id support in bzr.
99
            try:
2617.6.8 by Robert Collins
Review feedback and documentation.
100
                try:
101
                    builder = tree.branch.get_commit_builder([],
102
                        revision_id=revision_id)
2831.5.1 by Vincent Ladeuil
Portability fix in TestCommitBuilder for unlink.
103
                except errors.NonAsciiRevisionId:
2617.6.8 by Robert Collins
Review feedback and documentation.
104
                    revision_id = 'abc'
105
                    builder = tree.branch.get_commit_builder([],
106
                        revision_id=revision_id)
2831.5.1 by Vincent Ladeuil
Portability fix in TestCommitBuilder for unlink.
107
            except errors.CannotSetRevisionId:
2617.6.8 by Robert Collins
Review feedback and documentation.
108
                # This format doesn't support supplied revision ids
109
                return
2805.6.1 by Robert Collins
Set random_revid on CommitBuilder when a commit generated its own revision id.
110
            self.assertFalse(builder.random_revid)
2617.6.8 by Robert Collins
Review feedback and documentation.
111
            self.record_root(builder, tree)
112
            builder.finish_inventory()
113
            self.assertEqual(revision_id, builder.commit('foo bar'))
114
        finally:
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
115
            tree.unlock()
2150.2.2 by Robert Collins
Change the commit builder selected-revision-id test to use a unicode revision id where possible, leading to stricter testing of the hypothetical unicode revision id support in bzr.
116
        self.assertTrue(tree.branch.repository.has_revision(revision_id))
117
        # the revision id must be set on the inventory when saving it. This
118
        # does not precisely test that - a repository that wants to can add it
119
        # on deserialisation, but thats all the current contract guarantees
120
        # anyway.
121
        self.assertEqual(revision_id,
122
            tree.branch.repository.get_inventory(revision_id).revision_id)
1740.3.8 by Jelmer Vernooij
Move make_revision() to commit builder.
123
1910.2.8 by Aaron Bentley
Fix commit_builder when root not passed to record_entry_contents
124
    def test_commit_without_root(self):
125
        """This should cause a deprecation warning, not an assertion failure"""
126
        tree = self.make_branch_and_tree(".")
2255.7.8 by John Arbash Meinel
Lock the tree when using a commit builder.
127
        tree.lock_write()
128
        try:
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
129
            if tree.branch.repository.supports_rich_root():
130
                raise tests.TestSkipped('Format requires root')
131
            self.build_tree(['foo'])
132
            tree.add('foo', 'foo-id')
2255.7.8 by John Arbash Meinel
Lock the tree when using a commit builder.
133
            entry = tree.inventory['foo-id']
134
            builder = tree.branch.get_commit_builder([])
135
            self.callDeprecated(['Root entry should be supplied to'
136
                ' record_entry_contents, as of bzr 0.10.'],
2776.4.4 by Robert Collins
Move content summary generation outside of record_entry_contents.
137
                builder.record_entry_contents, entry, [], 'foo', tree,
138
                    tree.path_content_summary('foo'))
2255.7.8 by John Arbash Meinel
Lock the tree when using a commit builder.
139
            builder.finish_inventory()
140
            rev_id = builder.commit('foo bar')
141
        finally:
142
            tree.unlock()
2825.5.1 by Robert Collins
* Committing a change which is not a merge and does not change the number of
143
    
144
    def test_commit_unchanged_root(self):
145
        tree = self.make_branch_and_tree(".")
146
        tree.commit('')
147
        tree.lock_write()
148
        parent_tree = tree.basis_tree()
149
        parent_tree.lock_read()
150
        self.addCleanup(parent_tree.unlock)
151
        builder = tree.branch.get_commit_builder([parent_tree.inventory])
152
        try:
153
            ie = inventory.make_entry('directory', '', None,
154
                    tree.inventory.root.file_id)
155
            self.assertFalse(builder.record_entry_contents(
2776.4.13 by Robert Collins
Merge bzr.dev.
156
                ie, [parent_tree.inventory], '', tree,
157
                tree.path_content_summary('')))
2825.5.1 by Robert Collins
* Committing a change which is not a merge and does not change the number of
158
            builder.abort()
159
        except:
160
            builder.abort()
161
            tree.unlock()
162
            raise
163
        else:
164
            tree.unlock()
1910.2.8 by Aaron Bentley
Fix commit_builder when root not passed to record_entry_contents
165
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
166
    def test_commit(self):
1740.3.8 by Jelmer Vernooij
Move make_revision() to commit builder.
167
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
168
        tree.lock_write()
2617.6.8 by Robert Collins
Review feedback and documentation.
169
        try:
170
            builder = tree.branch.get_commit_builder([])
171
            self.record_root(builder, tree)
172
            builder.finish_inventory()
173
            rev_id = builder.commit('foo bar')
174
        finally:
175
            tree.unlock()
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
176
        self.assertNotEqual(None, rev_id)
177
        self.assertTrue(tree.branch.repository.has_revision(rev_id))
1757.1.2 by Robert Collins
Bugfix CommitBuilders recording of the inventory revision id.
178
        # the revision id must be set on the inventory when saving it. This does not
179
        # precisely test that - a repository that wants to can add it on deserialisation,
180
        # but thats all the current contract guarantees anyway.
181
        self.assertEqual(rev_id, tree.branch.repository.get_inventory(rev_id).revision_id)
2041.1.1 by John Arbash Meinel
Add a 'get_tree()' call that returns a RevisionTree for the newly committed tree
182
2041.1.5 by John Arbash Meinel
CommitBuilder.get_tree => CommitBuilder.revision_tree
183
    def test_revision_tree(self):
2041.1.1 by John Arbash Meinel
Add a 'get_tree()' call that returns a RevisionTree for the newly committed tree
184
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
185
        tree.lock_write()
2617.6.8 by Robert Collins
Review feedback and documentation.
186
        try:
187
            builder = tree.branch.get_commit_builder([])
188
            self.record_root(builder, tree)
189
            builder.finish_inventory()
190
            rev_id = builder.commit('foo bar')
191
        finally:
192
            tree.unlock()
2041.1.5 by John Arbash Meinel
CommitBuilder.get_tree => CommitBuilder.revision_tree
193
        rev_tree = builder.revision_tree()
2041.1.1 by John Arbash Meinel
Add a 'get_tree()' call that returns a RevisionTree for the newly committed tree
194
        # Just a couple simple tests to ensure that it actually follows
195
        # the RevisionTree api.
196
        self.assertEqual(rev_id, rev_tree.get_revision_id())
197
        self.assertEqual([], rev_tree.get_parent_ids())
2255.7.65 by Robert Collins
Split test_root_revision_entry into tree and repository portions.
198
199
    def test_root_entry_has_revision(self):
200
        # test the root revision created and put in the basis
201
        # has the right rev id.
202
        tree = self.make_branch_and_tree('.')
203
        rev_id = tree.commit('message')
204
        basis_tree = tree.basis_tree()
205
        basis_tree.lock_read()
206
        self.addCleanup(basis_tree.unlock)
207
        self.assertEqual(rev_id, basis_tree.inventory.root.revision)
208
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
209
    def _get_revtrees(self, tree, revision_ids):
210
        trees = list(tree.branch.repository.revision_trees(revision_ids))
211
        for tree in trees:
212
            tree.lock_read()
213
            self.addCleanup(tree.unlock)
214
        return trees
215
216
    def test_last_modified_revision_after_commit_root_unchanged(self):
217
        # commiting without changing the root does not change the 
218
        # last modified except on non-rich-root-repositories.
219
        tree = self.make_branch_and_tree('.')
220
        rev1 = tree.commit('')
221
        rev2 = tree.commit('')
222
        tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
223
        self.assertEqual(rev1, tree1.inventory.root.revision)
224
        if tree.branch.repository.supports_rich_root():
225
            self.assertEqual(rev1, tree2.inventory.root.revision)
226
        else:
227
            self.assertEqual(rev2, tree2.inventory.root.revision)
228
229
    def _add_commit_check_unchanged(self, tree, name):
230
        tree.add([name], [name + 'id'])
231
        rev1 = tree.commit('')
232
        rev2 = tree.commit('')
233
        tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
234
        self.assertEqual(rev1, tree1.inventory[name + 'id'].revision)
235
        self.assertEqual(rev1, tree2.inventory[name + 'id'].revision)
236
        self.assertFileAncestry([rev1], tree, name)
237
238
    def test_last_modified_revision_after_commit_dir_unchanged(self):
239
        # committing without changing a dir does not change the last modified.
240
        tree = self.make_branch_and_tree('.')
241
        self.build_tree(['dir/'])
242
        self._add_commit_check_unchanged(tree, 'dir')
243
244
    def test_last_modified_revision_after_commit_dir_contents_unchanged(self):
245
        # committing without changing a dir does not change the last modified
246
        # of the dir even the dirs contents are changed.
247
        tree = self.make_branch_and_tree('.')
248
        self.build_tree(['dir/'])
249
        tree.add(['dir'], ['dirid'])
250
        rev1 = tree.commit('')
251
        self.build_tree(['dir/content'])
252
        tree.add(['dir/content'], ['contentid'])
253
        rev2 = tree.commit('')
254
        tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
255
        self.assertEqual(rev1, tree1.inventory['dirid'].revision)
256
        self.assertEqual(rev1, tree2.inventory['dirid'].revision)
257
        self.assertFileAncestry([rev1], tree, 'dir')
258
259
    def test_last_modified_revision_after_commit_file_unchanged(self):
260
        # committing without changing a file does not change the last modified.
261
        tree = self.make_branch_and_tree('.')
262
        self.build_tree(['file'])
263
        self._add_commit_check_unchanged(tree, 'file')
264
265
    def test_last_modified_revision_after_commit_link_unchanged(self):
266
        # committing without changing a link does not change the last modified.
267
        self.requireFeature(tests.SymlinkFeature)
268
        tree = self.make_branch_and_tree('.')
269
        os.symlink('target', 'link')
270
        self._add_commit_check_unchanged(tree, 'link')
271
272
    def _add_commit_renamed_check_changed(self, tree, name):
273
        def rename():
274
            tree.rename_one(name, 'new_' + name)
275
        self._add_commit_change_check_changed(tree, name, rename)
276
277
    def test_last_modified_revision_after_rename_dir_changes(self):
278
        # renaming a dir changes the last modified.
279
        tree = self.make_branch_and_tree('.')
280
        self.build_tree(['dir/'])
281
        self._add_commit_renamed_check_changed(tree, 'dir')
282
283
    def test_last_modified_revision_after_rename_file_changes(self):
284
        # renaming a file changes the last modified.
285
        tree = self.make_branch_and_tree('.')
286
        self.build_tree(['file'])
287
        self._add_commit_renamed_check_changed(tree, 'file')
288
289
    def test_last_modified_revision_after_rename_link_changes(self):
290
        # renaming a link changes the last modified.
291
        self.requireFeature(tests.SymlinkFeature)
292
        tree = self.make_branch_and_tree('.')
293
        os.symlink('target', 'link')
294
        self._add_commit_renamed_check_changed(tree, 'link')
295
296
    def _add_commit_reparent_check_changed(self, tree, name):
297
        self.build_tree(['newparent/'])
298
        tree.add(['newparent'])
299
        def reparent():
300
            tree.rename_one(name, 'newparent/new_' + name)
301
        self._add_commit_change_check_changed(tree, name, reparent)
302
303
    def test_last_modified_revision_after_reparent_dir_changes(self):
304
        # reparenting a dir changes the last modified.
305
        tree = self.make_branch_and_tree('.')
306
        self.build_tree(['dir/'])
307
        self._add_commit_reparent_check_changed(tree, 'dir')
308
309
    def test_last_modified_revision_after_reparent_file_changes(self):
310
        # reparenting a file changes the last modified.
311
        tree = self.make_branch_and_tree('.')
312
        self.build_tree(['file'])
313
        self._add_commit_reparent_check_changed(tree, 'file')
314
315
    def test_last_modified_revision_after_reparent_link_changes(self):
316
        # reparenting a link changes the last modified.
317
        self.requireFeature(tests.SymlinkFeature)
318
        tree = self.make_branch_and_tree('.')
319
        os.symlink('target', 'link')
320
        self._add_commit_reparent_check_changed(tree, 'link')
321
322
    def _add_commit_change_check_changed(self, tree, name, changer):
323
        tree.add([name], [name + 'id'])
324
        rev1 = tree.commit('')
325
        changer()
2825.5.1 by Robert Collins
* Committing a change which is not a merge and does not change the number of
326
        tree.lock_write()
327
        try:
328
            # mini manual commit here so we can check the return of
329
            # record_entry_contents.
330
            builder = tree.branch.get_commit_builder([tree.last_revision()])
331
            parent_tree = tree.basis_tree()
332
            parent_tree.lock_read()
333
            self.addCleanup(parent_tree.unlock)
334
            parent_invs = [parent_tree.inventory]
335
            # root
336
            builder.record_entry_contents(
337
                inventory.make_entry('directory', '', None,
2776.4.13 by Robert Collins
Merge bzr.dev.
338
                    tree.inventory.root.file_id), parent_invs, '', tree,
339
                    tree.path_content_summary(''))
2825.5.1 by Robert Collins
* Committing a change which is not a merge and does not change the number of
340
            def commit_id(file_id):
341
                old_ie = tree.inventory[file_id]
342
                path = tree.id2path(file_id)
343
                ie = inventory.make_entry(tree.kind(file_id), old_ie.name,
344
                    old_ie.parent_id, file_id)
2776.4.13 by Robert Collins
Merge bzr.dev.
345
                return builder.record_entry_contents(ie, parent_invs, path,
346
                    tree, tree.path_content_summary(path))
2825.5.1 by Robert Collins
* Committing a change which is not a merge and does not change the number of
347
348
            file_id = name + 'id'
349
            parent_id = tree.inventory[file_id].parent_id
350
            if parent_id != tree.inventory.root.file_id:
351
                commit_id(parent_id)
352
            # because a change of some sort is meant to have occurred,
353
            # recording the entry must return True.
354
            self.assertTrue(commit_id(file_id))
355
            builder.finish_inventory()
356
            rev2 = builder.commit('')
357
            tree.set_parent_ids([rev2])
358
        except:
359
            builder.abort()
360
            tree.unlock()
361
            raise
362
        else:
363
            tree.unlock()
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
364
        tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
365
        self.assertEqual(rev1, tree1.inventory[name + 'id'].revision)
366
        self.assertEqual(rev2, tree2.inventory[name + 'id'].revision)
367
        self.assertFileAncestry([rev1, rev2], tree, name)
368
369
    def assertFileAncestry(self, ancestry, tree, name, alt_ancestry=None):
370
        # all the changes that have occured should be in the ancestry
371
        # (closest to a public per-file graph API we have today)
372
        tree.lock_read()
373
        self.addCleanup(tree.unlock)
374
        vw = tree.branch.repository.weave_store.get_weave(name + 'id',
375
            tree.branch.repository.get_transaction())
376
        result = vw.get_ancestry([ancestry[-1]])
377
        if alt_ancestry is None:
378
            self.assertEqual(ancestry, result)
379
        else:
380
            self.assertSubset([tuple(result)],
381
                [tuple(ancestry), tuple(alt_ancestry)])
382
383
    def test_last_modified_revision_after_content_file_changes(self):
384
        # altering a file changes the last modified.
385
        tree = self.make_branch_and_tree('.')
386
        self.build_tree(['file'])
387
        def change_file():
388
            tree.put_file_bytes_non_atomic('fileid', 'new content')
389
        self._add_commit_change_check_changed(tree, 'file', change_file)
390
391
    def test_last_modified_revision_after_content_link_changes(self):
392
        # changing a link changes the last modified.
393
        self.requireFeature(tests.SymlinkFeature)
394
        tree = self.make_branch_and_tree('.')
395
        os.symlink('target', 'link')
396
        def change_link():
397
            os.unlink('link')
398
            os.symlink('newtarget', 'link')
399
        self._add_commit_change_check_changed(tree, 'link', change_link)
400
401
    def _commit_sprout(self, tree, name):
402
        tree.add([name], [name + 'id'])
403
        rev_id = tree.commit('')
404
        return rev_id, tree.bzrdir.sprout('t2').open_workingtree()
405
406
    def _rename_in_tree(self, tree, name):
407
        tree.rename_one(name, 'new_' + name)
408
        return tree.commit('')
409
410
    def _commit_sprout_rename_merge(self, tree1, name):
411
        rev1, tree2 = self._commit_sprout(tree1, name)
412
        # change both sides equally
413
        rev2 = self._rename_in_tree(tree1, name)
414
        rev3 = self._rename_in_tree(tree2, name)
415
        tree1.merge_from_branch(tree2.branch)
416
        rev4 = tree1.commit('')
417
        tree3, = self._get_revtrees(tree1, [rev4])
418
        self.assertEqual(rev4, tree3.inventory[name + 'id'].revision)
2776.4.2 by Robert Collins
nuke _read_tree_state and snapshot from inventory, moving responsibility into the commit builder.
419
        # TODO: change this to an assertFileGraph call to check the
420
        # parent order of rev4: it should be rev2, rev3
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
421
        self.assertFileAncestry([rev1, rev2, rev3, rev4], tree1, name,
422
            [rev1, rev3, rev2, rev4])
423
424
    def test_last_modified_revision_after_merge_dir_changes(self):
425
        # merge a dir changes the last modified.
426
        tree1 = self.make_branch_and_tree('t1')
427
        self.build_tree(['t1/dir/'])
428
        self._commit_sprout_rename_merge(tree1, 'dir')
429
430
    def test_last_modified_revision_after_merge_file_changes(self):
431
        # merge a file changes the last modified.
432
        tree1 = self.make_branch_and_tree('t1')
433
        self.build_tree(['t1/file'])
434
        self._commit_sprout_rename_merge(tree1, 'file')
435
436
    def test_last_modified_revision_after_merge_link_changes(self):
437
        # merge a link changes the last modified.
438
        self.requireFeature(tests.SymlinkFeature)
439
        tree1 = self.make_branch_and_tree('t1')
440
        os.symlink('target', 't1/link')
441
        self._commit_sprout_rename_merge(tree1, 'link')
442
443
    def _commit_sprout_rename_merge_converged(self, tree1, name):
444
        rev1, tree2 = self._commit_sprout(tree1, name)
445
        # change on the other side to merge back
446
        rev2 = self._rename_in_tree(tree2, name)
447
        tree1.merge_from_branch(tree2.branch)
448
        rev3 = tree1.commit('')
449
        tree3, = self._get_revtrees(tree1, [rev2])
450
        self.assertEqual(rev2, tree3.inventory[name + 'id'].revision)
451
        self.assertFileAncestry([rev1, rev2], tree1, name)
452
453
    def test_last_modified_revision_after_converged_merge_dir_changes(self):
454
        # merge a dir changes the last modified.
455
        tree1 = self.make_branch_and_tree('t1')
456
        self.build_tree(['t1/dir/'])
457
        self._commit_sprout_rename_merge_converged(tree1, 'dir')
458
459
    def test_last_modified_revision_after_converged_merge_file_changes(self):
460
        # merge a file changes the last modified.
461
        tree1 = self.make_branch_and_tree('t1')
462
        self.build_tree(['t1/file'])
463
        self._commit_sprout_rename_merge_converged(tree1, 'file')
464
465
    def test_last_modified_revision_after_converged_merge_link_changes(self):
466
        # merge a link changes the last modified.
467
        self.requireFeature(tests.SymlinkFeature)
468
        tree1 = self.make_branch_and_tree('t1')
469
        os.symlink('target', 't1/link')
470
        self._commit_sprout_rename_merge_converged(tree1, 'link')
471
472
    def make_dir(self, name):
473
        self.build_tree([name + '/'])
474
475
    def make_file(self, name):
476
        self.build_tree([name])
477
478
    def make_link(self, name):
479
        self.requireFeature(tests.SymlinkFeature)
480
        os.symlink('target', name)
481
482
    def _check_kind_change(self, make_before, make_after):
483
        tree = self.make_branch_and_tree('.')
484
        path = 'name'
485
        make_before(path)
2831.5.2 by Vincent Ladeuil
Review feedback.
486
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
487
        def change_kind():
2831.5.2 by Vincent Ladeuil
Review feedback.
488
            osutils.delete_any(path)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
489
            make_after(path)
2831.5.2 by Vincent Ladeuil
Review feedback.
490
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
491
        self._add_commit_change_check_changed(tree, path, change_kind)
492
493
    def test_last_modified_dir_file(self):
494
        self._check_kind_change(self.make_dir, self.make_file)
495
496
    def test_last_modified_dir_link(self):
497
        self._check_kind_change(self.make_dir, self.make_link)
498
499
    def test_last_modified_link_file(self):
500
        self._check_kind_change(self.make_link, self.make_file)
501
502
    def test_last_modified_link_dir(self):
503
        self._check_kind_change(self.make_link, self.make_dir)
504
505
    def test_last_modified_file_dir(self):
506
        self._check_kind_change(self.make_file, self.make_dir)
507
508
    def test_last_modified_file_link(self):
509
        self._check_kind_change(self.make_file, self.make_link)