/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 = []
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
54
            builder.record_entry_contents(ie, parent_invs, '', tree)
1731.1.33 by Aaron Bentley
Revert no-special-root changes
55
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
56
    def test_finish_inventory(self):
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
57
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
58
        tree.lock_write()
2617.6.8 by Robert Collins
Review feedback and documentation.
59
        try:
60
            builder = tree.branch.get_commit_builder([])
61
            self.record_root(builder, tree)
62
            builder.finish_inventory()
63
            tree.branch.repository.commit_write_group()
64
        finally:
65
            tree.unlock()
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
66
2749.3.1 by Jelmer Vernooij
Add CommitBuilder.abort().
67
    def test_abort(self):
68
        tree = self.make_branch_and_tree(".")
69
        tree.lock_write()
70
        try:
71
            builder = tree.branch.get_commit_builder([])
72
            self.record_root(builder, tree)
73
            builder.finish_inventory()
74
            builder.abort()
75
        finally:
76
            tree.unlock()
77
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
78
    def test_commit_message(self):
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
79
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
80
        tree.lock_write()
2617.6.8 by Robert Collins
Review feedback and documentation.
81
        try:
82
            builder = tree.branch.get_commit_builder([])
83
            self.record_root(builder, tree)
84
            builder.finish_inventory()
85
            rev_id = builder.commit('foo bar blah')
86
        finally:
87
            tree.unlock()
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
88
        rev = tree.branch.repository.get_revision(rev_id)
89
        self.assertEqual('foo bar blah', rev.message)
90
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
91
    def test_commit_with_revision_id(self):
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
92
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
93
        tree.lock_write()
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
94
        try:
2617.6.8 by Robert Collins
Review feedback and documentation.
95
            # use a unicode revision id to test more corner cases.
96
            # The repository layer is meant to handle this.
97
            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.
98
            try:
2617.6.8 by Robert Collins
Review feedback and documentation.
99
                try:
100
                    builder = tree.branch.get_commit_builder([],
101
                        revision_id=revision_id)
2831.5.1 by Vincent Ladeuil
Portability fix in TestCommitBuilder for unlink.
102
                except errors.NonAsciiRevisionId:
2617.6.8 by Robert Collins
Review feedback and documentation.
103
                    revision_id = 'abc'
104
                    builder = tree.branch.get_commit_builder([],
105
                        revision_id=revision_id)
2831.5.1 by Vincent Ladeuil
Portability fix in TestCommitBuilder for unlink.
106
            except errors.CannotSetRevisionId:
2617.6.8 by Robert Collins
Review feedback and documentation.
107
                # This format doesn't support supplied revision ids
108
                return
2805.6.1 by Robert Collins
Set random_revid on CommitBuilder when a commit generated its own revision id.
109
            self.assertFalse(builder.random_revid)
2617.6.8 by Robert Collins
Review feedback and documentation.
110
            self.record_root(builder, tree)
111
            builder.finish_inventory()
112
            self.assertEqual(revision_id, builder.commit('foo bar'))
113
        finally:
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
114
            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.
115
        self.assertTrue(tree.branch.repository.has_revision(revision_id))
116
        # the revision id must be set on the inventory when saving it. This
117
        # does not precisely test that - a repository that wants to can add it
118
        # on deserialisation, but thats all the current contract guarantees
119
        # anyway.
120
        self.assertEqual(revision_id,
121
            tree.branch.repository.get_inventory(revision_id).revision_id)
1740.3.8 by Jelmer Vernooij
Move make_revision() to commit builder.
122
1910.2.8 by Aaron Bentley
Fix commit_builder when root not passed to record_entry_contents
123
    def test_commit_without_root(self):
124
        """This should cause a deprecation warning, not an assertion failure"""
125
        tree = self.make_branch_and_tree(".")
2255.7.8 by John Arbash Meinel
Lock the tree when using a commit builder.
126
        tree.lock_write()
127
        try:
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
128
            if tree.branch.repository.supports_rich_root():
129
                raise tests.TestSkipped('Format requires root')
130
            self.build_tree(['foo'])
131
            tree.add('foo', 'foo-id')
2255.7.8 by John Arbash Meinel
Lock the tree when using a commit builder.
132
            entry = tree.inventory['foo-id']
133
            builder = tree.branch.get_commit_builder([])
134
            self.callDeprecated(['Root entry should be supplied to'
135
                ' record_entry_contents, as of bzr 0.10.'],
136
                builder.record_entry_contents, entry, [], 'foo', tree)
137
            builder.finish_inventory()
138
            rev_id = builder.commit('foo bar')
139
        finally:
140
            tree.unlock()
1910.2.8 by Aaron Bentley
Fix commit_builder when root not passed to record_entry_contents
141
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
142
    def test_commit(self):
1740.3.8 by Jelmer Vernooij
Move make_revision() to commit builder.
143
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
144
        tree.lock_write()
2617.6.8 by Robert Collins
Review feedback and documentation.
145
        try:
146
            builder = tree.branch.get_commit_builder([])
147
            self.record_root(builder, tree)
148
            builder.finish_inventory()
149
            rev_id = builder.commit('foo bar')
150
        finally:
151
            tree.unlock()
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
152
        self.assertNotEqual(None, rev_id)
153
        self.assertTrue(tree.branch.repository.has_revision(rev_id))
1757.1.2 by Robert Collins
Bugfix CommitBuilders recording of the inventory revision id.
154
        # the revision id must be set on the inventory when saving it. This does not
155
        # precisely test that - a repository that wants to can add it on deserialisation,
156
        # but thats all the current contract guarantees anyway.
157
        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
158
2041.1.5 by John Arbash Meinel
CommitBuilder.get_tree => CommitBuilder.revision_tree
159
    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
160
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
161
        tree.lock_write()
2617.6.8 by Robert Collins
Review feedback and documentation.
162
        try:
163
            builder = tree.branch.get_commit_builder([])
164
            self.record_root(builder, tree)
165
            builder.finish_inventory()
166
            rev_id = builder.commit('foo bar')
167
        finally:
168
            tree.unlock()
2041.1.5 by John Arbash Meinel
CommitBuilder.get_tree => CommitBuilder.revision_tree
169
        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
170
        # Just a couple simple tests to ensure that it actually follows
171
        # the RevisionTree api.
172
        self.assertEqual(rev_id, rev_tree.get_revision_id())
173
        self.assertEqual([], rev_tree.get_parent_ids())
2255.7.65 by Robert Collins
Split test_root_revision_entry into tree and repository portions.
174
175
    def test_root_entry_has_revision(self):
176
        # test the root revision created and put in the basis
177
        # has the right rev id.
178
        tree = self.make_branch_and_tree('.')
179
        rev_id = tree.commit('message')
180
        basis_tree = tree.basis_tree()
181
        basis_tree.lock_read()
182
        self.addCleanup(basis_tree.unlock)
183
        self.assertEqual(rev_id, basis_tree.inventory.root.revision)
184
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
185
    def _get_revtrees(self, tree, revision_ids):
186
        trees = list(tree.branch.repository.revision_trees(revision_ids))
187
        for tree in trees:
188
            tree.lock_read()
189
            self.addCleanup(tree.unlock)
190
        return trees
191
192
    def test_last_modified_revision_after_commit_root_unchanged(self):
193
        # commiting without changing the root does not change the 
194
        # last modified except on non-rich-root-repositories.
195
        tree = self.make_branch_and_tree('.')
196
        rev1 = tree.commit('')
197
        rev2 = tree.commit('')
198
        tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
199
        self.assertEqual(rev1, tree1.inventory.root.revision)
200
        if tree.branch.repository.supports_rich_root():
201
            self.assertEqual(rev1, tree2.inventory.root.revision)
202
        else:
203
            self.assertEqual(rev2, tree2.inventory.root.revision)
204
205
    def _add_commit_check_unchanged(self, tree, name):
206
        tree.add([name], [name + 'id'])
207
        rev1 = tree.commit('')
208
        rev2 = tree.commit('')
209
        tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
210
        self.assertEqual(rev1, tree1.inventory[name + 'id'].revision)
211
        self.assertEqual(rev1, tree2.inventory[name + 'id'].revision)
212
        self.assertFileAncestry([rev1], tree, name)
213
214
    def test_last_modified_revision_after_commit_dir_unchanged(self):
215
        # committing without changing a dir does not change the last modified.
216
        tree = self.make_branch_and_tree('.')
217
        self.build_tree(['dir/'])
218
        self._add_commit_check_unchanged(tree, 'dir')
219
220
    def test_last_modified_revision_after_commit_dir_contents_unchanged(self):
221
        # committing without changing a dir does not change the last modified
222
        # of the dir even the dirs contents are changed.
223
        tree = self.make_branch_and_tree('.')
224
        self.build_tree(['dir/'])
225
        tree.add(['dir'], ['dirid'])
226
        rev1 = tree.commit('')
227
        self.build_tree(['dir/content'])
228
        tree.add(['dir/content'], ['contentid'])
229
        rev2 = tree.commit('')
230
        tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
231
        self.assertEqual(rev1, tree1.inventory['dirid'].revision)
232
        self.assertEqual(rev1, tree2.inventory['dirid'].revision)
233
        self.assertFileAncestry([rev1], tree, 'dir')
234
235
    def test_last_modified_revision_after_commit_file_unchanged(self):
236
        # committing without changing a file does not change the last modified.
237
        tree = self.make_branch_and_tree('.')
238
        self.build_tree(['file'])
239
        self._add_commit_check_unchanged(tree, 'file')
240
241
    def test_last_modified_revision_after_commit_link_unchanged(self):
242
        # committing without changing a link does not change the last modified.
243
        self.requireFeature(tests.SymlinkFeature)
244
        tree = self.make_branch_and_tree('.')
245
        os.symlink('target', 'link')
246
        self._add_commit_check_unchanged(tree, 'link')
247
248
    def _add_commit_renamed_check_changed(self, tree, name):
249
        def rename():
250
            tree.rename_one(name, 'new_' + name)
251
        self._add_commit_change_check_changed(tree, name, rename)
252
253
    def test_last_modified_revision_after_rename_dir_changes(self):
254
        # renaming a dir changes the last modified.
255
        tree = self.make_branch_and_tree('.')
256
        self.build_tree(['dir/'])
257
        self._add_commit_renamed_check_changed(tree, 'dir')
258
259
    def test_last_modified_revision_after_rename_file_changes(self):
260
        # renaming a file changes the last modified.
261
        tree = self.make_branch_and_tree('.')
262
        self.build_tree(['file'])
263
        self._add_commit_renamed_check_changed(tree, 'file')
264
265
    def test_last_modified_revision_after_rename_link_changes(self):
266
        # renaming a link changes the last modified.
267
        self.requireFeature(tests.SymlinkFeature)
268
        tree = self.make_branch_and_tree('.')
269
        os.symlink('target', 'link')
270
        self._add_commit_renamed_check_changed(tree, 'link')
271
272
    def _add_commit_reparent_check_changed(self, tree, name):
273
        self.build_tree(['newparent/'])
274
        tree.add(['newparent'])
275
        def reparent():
276
            tree.rename_one(name, 'newparent/new_' + name)
277
        self._add_commit_change_check_changed(tree, name, reparent)
278
279
    def test_last_modified_revision_after_reparent_dir_changes(self):
280
        # reparenting a dir changes the last modified.
281
        tree = self.make_branch_and_tree('.')
282
        self.build_tree(['dir/'])
283
        self._add_commit_reparent_check_changed(tree, 'dir')
284
285
    def test_last_modified_revision_after_reparent_file_changes(self):
286
        # reparenting a file changes the last modified.
287
        tree = self.make_branch_and_tree('.')
288
        self.build_tree(['file'])
289
        self._add_commit_reparent_check_changed(tree, 'file')
290
291
    def test_last_modified_revision_after_reparent_link_changes(self):
292
        # reparenting a link changes the last modified.
293
        self.requireFeature(tests.SymlinkFeature)
294
        tree = self.make_branch_and_tree('.')
295
        os.symlink('target', 'link')
296
        self._add_commit_reparent_check_changed(tree, 'link')
297
298
    def _add_commit_change_check_changed(self, tree, name, changer):
299
        tree.add([name], [name + 'id'])
300
        rev1 = tree.commit('')
301
        changer()
302
        rev2 = tree.commit('')
303
        tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
304
        self.assertEqual(rev1, tree1.inventory[name + 'id'].revision)
305
        self.assertEqual(rev2, tree2.inventory[name + 'id'].revision)
306
        self.assertFileAncestry([rev1, rev2], tree, name)
307
308
    def assertFileAncestry(self, ancestry, tree, name, alt_ancestry=None):
309
        # all the changes that have occured should be in the ancestry
310
        # (closest to a public per-file graph API we have today)
311
        tree.lock_read()
312
        self.addCleanup(tree.unlock)
313
        vw = tree.branch.repository.weave_store.get_weave(name + 'id',
314
            tree.branch.repository.get_transaction())
315
        result = vw.get_ancestry([ancestry[-1]])
316
        if alt_ancestry is None:
317
            self.assertEqual(ancestry, result)
318
        else:
319
            self.assertSubset([tuple(result)],
320
                [tuple(ancestry), tuple(alt_ancestry)])
321
322
    def test_last_modified_revision_after_content_file_changes(self):
323
        # altering a file changes the last modified.
324
        tree = self.make_branch_and_tree('.')
325
        self.build_tree(['file'])
326
        def change_file():
327
            tree.put_file_bytes_non_atomic('fileid', 'new content')
328
        self._add_commit_change_check_changed(tree, 'file', change_file)
329
330
    def test_last_modified_revision_after_content_link_changes(self):
331
        # changing a link changes the last modified.
332
        self.requireFeature(tests.SymlinkFeature)
333
        tree = self.make_branch_and_tree('.')
334
        os.symlink('target', 'link')
335
        def change_link():
336
            os.unlink('link')
337
            os.symlink('newtarget', 'link')
338
        self._add_commit_change_check_changed(tree, 'link', change_link)
339
340
    def _commit_sprout(self, tree, name):
341
        tree.add([name], [name + 'id'])
342
        rev_id = tree.commit('')
343
        return rev_id, tree.bzrdir.sprout('t2').open_workingtree()
344
345
    def _rename_in_tree(self, tree, name):
346
        tree.rename_one(name, 'new_' + name)
347
        return tree.commit('')
348
349
    def _commit_sprout_rename_merge(self, tree1, name):
350
        rev1, tree2 = self._commit_sprout(tree1, name)
351
        # change both sides equally
352
        rev2 = self._rename_in_tree(tree1, name)
353
        rev3 = self._rename_in_tree(tree2, name)
354
        tree1.merge_from_branch(tree2.branch)
355
        rev4 = tree1.commit('')
356
        tree3, = self._get_revtrees(tree1, [rev4])
357
        self.assertEqual(rev4, tree3.inventory[name + 'id'].revision)
358
        self.assertFileAncestry([rev1, rev2, rev3, rev4], tree1, name,
359
            [rev1, rev3, rev2, rev4])
360
361
    def test_last_modified_revision_after_merge_dir_changes(self):
362
        # merge a dir changes the last modified.
363
        tree1 = self.make_branch_and_tree('t1')
364
        self.build_tree(['t1/dir/'])
365
        self._commit_sprout_rename_merge(tree1, 'dir')
366
367
    def test_last_modified_revision_after_merge_file_changes(self):
368
        # merge a file changes the last modified.
369
        tree1 = self.make_branch_and_tree('t1')
370
        self.build_tree(['t1/file'])
371
        self._commit_sprout_rename_merge(tree1, 'file')
372
373
    def test_last_modified_revision_after_merge_link_changes(self):
374
        # merge a link changes the last modified.
375
        self.requireFeature(tests.SymlinkFeature)
376
        tree1 = self.make_branch_and_tree('t1')
377
        os.symlink('target', 't1/link')
378
        self._commit_sprout_rename_merge(tree1, 'link')
379
380
    def _commit_sprout_rename_merge_converged(self, tree1, name):
381
        rev1, tree2 = self._commit_sprout(tree1, name)
382
        # change on the other side to merge back
383
        rev2 = self._rename_in_tree(tree2, name)
384
        tree1.merge_from_branch(tree2.branch)
385
        rev3 = tree1.commit('')
386
        tree3, = self._get_revtrees(tree1, [rev2])
387
        self.assertEqual(rev2, tree3.inventory[name + 'id'].revision)
388
        self.assertFileAncestry([rev1, rev2], tree1, name)
389
390
    def test_last_modified_revision_after_converged_merge_dir_changes(self):
391
        # merge a dir changes the last modified.
392
        tree1 = self.make_branch_and_tree('t1')
393
        self.build_tree(['t1/dir/'])
394
        self._commit_sprout_rename_merge_converged(tree1, 'dir')
395
396
    def test_last_modified_revision_after_converged_merge_file_changes(self):
397
        # merge a file changes the last modified.
398
        tree1 = self.make_branch_and_tree('t1')
399
        self.build_tree(['t1/file'])
400
        self._commit_sprout_rename_merge_converged(tree1, 'file')
401
402
    def test_last_modified_revision_after_converged_merge_link_changes(self):
403
        # merge a link changes the last modified.
404
        self.requireFeature(tests.SymlinkFeature)
405
        tree1 = self.make_branch_and_tree('t1')
406
        os.symlink('target', 't1/link')
407
        self._commit_sprout_rename_merge_converged(tree1, 'link')
408
409
    def make_dir(self, name):
410
        self.build_tree([name + '/'])
411
412
    def make_file(self, name):
413
        self.build_tree([name])
414
415
    def make_link(self, name):
416
        self.requireFeature(tests.SymlinkFeature)
417
        os.symlink('target', name)
418
419
    def _check_kind_change(self, make_before, make_after):
420
        tree = self.make_branch_and_tree('.')
421
        path = 'name'
422
        make_before(path)
2831.5.2 by Vincent Ladeuil
Review feedback.
423
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
424
        def change_kind():
2831.5.2 by Vincent Ladeuil
Review feedback.
425
            osutils.delete_any(path)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
426
            make_after(path)
2831.5.2 by Vincent Ladeuil
Review feedback.
427
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
428
        self._add_commit_change_check_changed(tree, path, change_kind)
429
430
    def test_last_modified_dir_file(self):
431
        self._check_kind_change(self.make_dir, self.make_file)
432
433
    def test_last_modified_dir_link(self):
434
        self._check_kind_change(self.make_dir, self.make_link)
435
436
    def test_last_modified_link_file(self):
437
        self._check_kind_change(self.make_link, self.make_file)
438
439
    def test_last_modified_link_dir(self):
440
        self._check_kind_change(self.make_link, self.make_dir)
441
442
    def test_last_modified_file_dir(self):
443
        self._check_kind_change(self.make_file, self.make_dir)
444
445
    def test_last_modified_file_link(self):
446
        self._check_kind_change(self.make_file, self.make_link)