/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1
# Copyright (C) 2006-2012, 2016 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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1740.3.1 by Jelmer Vernooij
Introduce and use CommitBuilder objects.
16
17
"""Tests for repository commit builder."""
18
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
19
import os
2831.5.1 by Vincent Ladeuil
Portability fix in TestCommitBuilder for unlink.
20
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
21
from breezy import (
5609.31.2 by mbp at sourcefrog
Also turn off whoami inference in per_repository tests
22
    config,
2831.5.1 by Vincent Ladeuil
Portability fix in TestCommitBuilder for unlink.
23
    errors,
24
    osutils,
25
    repository,
3668.5.1 by Jelmer Vernooij
Use NULL_REVISION rather than None for Repository.revision_tree().
26
    revision as _mod_revision,
2831.5.1 by Vincent Ladeuil
Portability fix in TestCommitBuilder for unlink.
27
    tests,
28
    )
6670.4.3 by Jelmer Vernooij
Fix more imports.
29
from breezy.bzr import (
30
    inventory,
31
    )
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
32
from breezy.tests import per_repository
33
from breezy.tests import (
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
34
    features,
35
    )
5010.2.24 by Vincent Ladeuil
Fix imports in per_repository/test_commit_builder.py.
36
37
38
class TestCommitBuilder(per_repository.TestCaseWithRepository):
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
39
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
40
    def test_get_commit_builder(self):
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
41
        branch = self.make_branch('.')
42
        branch.repository.lock_write()
43
        builder = branch.repository.get_commit_builder(
6351.3.3 by Jelmer Vernooij
Convert more stuff to use config stacks.
44
            branch, [], branch.get_config_stack())
2831.5.1 by Vincent Ladeuil
Portability fix in TestCommitBuilder for unlink.
45
        self.assertIsInstance(builder, repository.CommitBuilder)
2805.6.1 by Robert Collins
Set random_revid on CommitBuilder when a commit generated its own revision id.
46
        self.assertTrue(builder.random_revid)
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
47
        branch.repository.commit_write_group()
48
        branch.repository.unlock()
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
49
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
50
    def record_root(self, builder, tree):
51
        if builder.record_root_entry is True:
2255.7.8 by John Arbash Meinel
Lock the tree when using a commit builder.
52
            tree.lock_read()
53
            try:
6405.2.5 by Jelmer Vernooij
Add root_inventory.
54
                ie = tree.root_inventory.root
2255.7.8 by John Arbash Meinel
Lock the tree when using a commit builder.
55
            finally:
56
                tree.unlock()
3668.5.1 by Jelmer Vernooij
Use NULL_REVISION rather than None for Repository.revision_tree().
57
            parent_tree = tree.branch.repository.revision_tree(
58
                              _mod_revision.NULL_REVISION)
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
59
            parent_invs = []
2776.4.4 by Robert Collins
Move content summary generation outside of record_entry_contents.
60
            builder.record_entry_contents(ie, parent_invs, '', tree,
61
                tree.path_content_summary(''))
1731.1.33 by Aaron Bentley
Revert no-special-root changes
62
3775.2.4 by Robert Collins
Start on a CommitBuilder.record_iter_changes method.
63
    def test_finish_inventory_with_record_root(self):
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
64
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
65
        tree.lock_write()
2617.6.8 by Robert Collins
Review feedback and documentation.
66
        try:
67
            builder = tree.branch.get_commit_builder([])
5718.4.3 by Jelmer Vernooij
Skip record_entry_contents-using tests for commit builders that don't support it.
68
            if not builder.supports_record_entry_contents:
69
                raise tests.TestNotApplicable("CommitBuilder doesn't support "
70
                    "record_entry_contents")
3775.2.4 by Robert Collins
Start on a CommitBuilder.record_iter_changes method.
71
            repo = tree.branch.repository
2617.6.8 by Robert Collins
Review feedback and documentation.
72
            self.record_root(builder, tree)
73
            builder.finish_inventory()
3775.2.4 by Robert Collins
Start on a CommitBuilder.record_iter_changes method.
74
            repo.commit_write_group()
75
        finally:
76
            tree.unlock()
77
78
    def test_finish_inventory_record_iter_changes(self):
79
        tree = self.make_branch_and_tree(".")
80
        tree.lock_write()
81
        try:
82
            builder = tree.branch.get_commit_builder([])
83
            try:
4183.5.4 by Robert Collins
Turn record_iter_changes into a generator to emit file system hashes.
84
                list(builder.record_iter_changes(tree, tree.last_revision(),
85
                    tree.iter_changes(tree.basis_tree())))
3775.2.4 by Robert Collins
Start on a CommitBuilder.record_iter_changes method.
86
                builder.finish_inventory()
87
            except:
88
                builder.abort()
89
                raise
90
            repo = tree.branch.repository
91
            repo.commit_write_group()
2617.6.8 by Robert Collins
Review feedback and documentation.
92
        finally:
93
            tree.unlock()
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
94
5718.4.3 by Jelmer Vernooij
Skip record_entry_contents-using tests for commit builders that don't support it.
95
    def test_abort_record_entry_contents(self):
2749.3.1 by Jelmer Vernooij
Add CommitBuilder.abort().
96
        tree = self.make_branch_and_tree(".")
97
        tree.lock_write()
98
        try:
99
            builder = tree.branch.get_commit_builder([])
5718.4.3 by Jelmer Vernooij
Skip record_entry_contents-using tests for commit builders that don't support it.
100
            if not builder.supports_record_entry_contents:
101
                raise tests.TestNotApplicable("CommitBuilder doesn't support "
102
                    "record_entry_contents")
2749.3.1 by Jelmer Vernooij
Add CommitBuilder.abort().
103
            self.record_root(builder, tree)
104
            builder.finish_inventory()
105
            builder.abort()
106
        finally:
107
            tree.unlock()
108
3775.2.5 by Robert Collins
CommitBuilder.abort() is callable after record_iter_changes.
109
    def test_abort_record_iter_changes(self):
110
        tree = self.make_branch_and_tree(".")
111
        tree.lock_write()
112
        try:
113
            builder = tree.branch.get_commit_builder([])
114
            try:
3775.2.29 by Robert Collins
Updates to the form of add_inventory_by_delta that landed in trunk.
115
                basis = tree.basis_tree()
116
                last_rev = tree.last_revision()
117
                changes = tree.iter_changes(basis)
4183.5.4 by Robert Collins
Turn record_iter_changes into a generator to emit file system hashes.
118
                list(builder.record_iter_changes(tree, last_rev, changes))
3775.2.5 by Robert Collins
CommitBuilder.abort() is callable after record_iter_changes.
119
                builder.finish_inventory()
3775.2.29 by Robert Collins
Updates to the form of add_inventory_by_delta that landed in trunk.
120
            finally:
3775.2.5 by Robert Collins
CommitBuilder.abort() is callable after record_iter_changes.
121
                builder.abort()
122
        finally:
123
            tree.unlock()
124
5777.6.8 by Jelmer Vernooij
Add test for get_commit_builder(lossy=True).
125
    def test_commit_lossy(self):
126
        tree = self.make_branch_and_tree(".")
127
        tree.lock_write()
128
        try:
129
            builder = tree.branch.get_commit_builder([], lossy=True)
130
            list(builder.record_iter_changes(tree, tree.last_revision(),
131
                tree.iter_changes(tree.basis_tree())))
132
            builder.finish_inventory()
133
            rev_id = builder.commit('foo bar blah')
134
        finally:
135
            tree.unlock()
136
        rev = tree.branch.repository.get_revision(rev_id)
137
        self.assertEqual('foo bar blah', rev.message)
138
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
139
    def test_commit_message(self):
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
140
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
141
        tree.lock_write()
2617.6.8 by Robert Collins
Review feedback and documentation.
142
        try:
143
            builder = tree.branch.get_commit_builder([])
5718.4.6 by Jelmer Vernooij
inline function only used once.
144
            list(builder.record_iter_changes(tree, tree.last_revision(),
145
                tree.iter_changes(tree.basis_tree())))
146
            builder.finish_inventory()
2617.6.8 by Robert Collins
Review feedback and documentation.
147
            rev_id = builder.commit('foo bar blah')
148
        finally:
149
            tree.unlock()
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
150
        rev = tree.branch.repository.get_revision(rev_id)
151
        self.assertEqual('foo bar blah', rev.message)
152
6217.5.1 by Jelmer Vernooij
Add CommitBuilder.updates_branch.
153
    def test_updates_branch(self):
154
        tree = self.make_branch_and_tree(".")
155
        tree.lock_write()
156
        try:
157
            builder = tree.branch.get_commit_builder([])
158
            list(builder.record_iter_changes(tree, tree.last_revision(),
159
                tree.iter_changes(tree.basis_tree())))
160
            builder.finish_inventory()
161
            will_update_branch = builder.updates_branch
162
            rev_id = builder.commit('might update the branch')
163
        finally:
164
            tree.unlock()
165
        actually_updated_branch = (tree.branch.last_revision() == rev_id)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
166
        self.assertEqual(actually_updated_branch, will_update_branch)
6217.5.1 by Jelmer Vernooij
Add CommitBuilder.updates_branch.
167
5718.4.3 by Jelmer Vernooij
Skip record_entry_contents-using tests for commit builders that don't support it.
168
    def test_commit_with_revision_id_record_entry_contents(self):
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
169
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
170
        tree.lock_write()
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
171
        try:
2617.6.8 by Robert Collins
Review feedback and documentation.
172
            # use a unicode revision id to test more corner cases.
173
            # The repository layer is meant to handle this.
174
            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.
175
            try:
2617.6.8 by Robert Collins
Review feedback and documentation.
176
                try:
177
                    builder = tree.branch.get_commit_builder([],
178
                        revision_id=revision_id)
2831.5.1 by Vincent Ladeuil
Portability fix in TestCommitBuilder for unlink.
179
                except errors.NonAsciiRevisionId:
2617.6.8 by Robert Collins
Review feedback and documentation.
180
                    revision_id = 'abc'
181
                    builder = tree.branch.get_commit_builder([],
182
                        revision_id=revision_id)
2831.5.1 by Vincent Ladeuil
Portability fix in TestCommitBuilder for unlink.
183
            except errors.CannotSetRevisionId:
2617.6.8 by Robert Collins
Review feedback and documentation.
184
                # This format doesn't support supplied revision ids
185
                return
5718.4.3 by Jelmer Vernooij
Skip record_entry_contents-using tests for commit builders that don't support it.
186
            if not builder.supports_record_entry_contents:
187
                raise tests.TestNotApplicable("CommitBuilder doesn't support "
188
                    "record_entry_contents")
2805.6.1 by Robert Collins
Set random_revid on CommitBuilder when a commit generated its own revision id.
189
            self.assertFalse(builder.random_revid)
2617.6.8 by Robert Collins
Review feedback and documentation.
190
            self.record_root(builder, tree)
191
            builder.finish_inventory()
192
            self.assertEqual(revision_id, builder.commit('foo bar'))
193
        finally:
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
194
            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.
195
        self.assertTrue(tree.branch.repository.has_revision(revision_id))
196
        # the revision id must be set on the inventory when saving it. This
197
        # does not precisely test that - a repository that wants to can add it
198
        # on deserialisation, but thats all the current contract guarantees
199
        # anyway.
200
        self.assertEqual(revision_id,
201
            tree.branch.repository.get_inventory(revision_id).revision_id)
1740.3.8 by Jelmer Vernooij
Move make_revision() to commit builder.
202
3775.2.6 by Robert Collins
CommitBuilder can specify a revision_id with record_iter_changes.
203
    def test_commit_with_revision_id_record_iter_changes(self):
204
        tree = self.make_branch_and_tree(".")
205
        tree.lock_write()
206
        try:
207
            # use a unicode revision id to test more corner cases.
208
            # The repository layer is meant to handle this.
209
            revision_id = u'\xc8abc'.encode('utf8')
210
            try:
211
                try:
212
                    builder = tree.branch.get_commit_builder([],
213
                        revision_id=revision_id)
214
                except errors.NonAsciiRevisionId:
215
                    revision_id = 'abc'
216
                    builder = tree.branch.get_commit_builder([],
217
                        revision_id=revision_id)
218
            except errors.CannotSetRevisionId:
219
                # This format doesn't support supplied revision ids
220
                return
221
            self.assertFalse(builder.random_revid)
222
            try:
4183.5.4 by Robert Collins
Turn record_iter_changes into a generator to emit file system hashes.
223
                list(builder.record_iter_changes(tree, tree.last_revision(),
224
                    tree.iter_changes(tree.basis_tree())))
3775.2.6 by Robert Collins
CommitBuilder can specify a revision_id with record_iter_changes.
225
                builder.finish_inventory()
226
            except:
227
                builder.abort()
228
                raise
229
            self.assertEqual(revision_id, builder.commit('foo bar'))
230
        finally:
231
            tree.unlock()
232
        self.assertTrue(tree.branch.repository.has_revision(revision_id))
233
        # the revision id must be set on the inventory when saving it. This
234
        # does not precisely test that - a repository that wants to can add it
235
        # on deserialisation, but thats all the current contract guarantees
236
        # anyway.
237
        self.assertEqual(revision_id,
6113.1.4 by Jelmer Vernooij
Use revision_tree for testing, it's always present.
238
            tree.branch.repository.revision_tree(revision_id).get_revision_id())
3775.2.6 by Robert Collins
CommitBuilder can specify a revision_id with record_iter_changes.
239
5222.1.1 by Aaron Bentley
Refuse to commit trees with no root.
240
    def test_commit_without_root_errors(self):
241
        tree = self.make_branch_and_tree(".")
242
        tree.lock_write()
243
        try:
244
            builder = tree.branch.get_commit_builder([])
245
            def do_commit():
246
                try:
247
                    list(builder.record_iter_changes(
248
                        tree, tree.last_revision(), []))
249
                    builder.finish_inventory()
250
                except:
251
                    builder.abort()
252
                    raise
6202.2.1 by Jelmer Vernooij
Commit in commit builder test to prevent masking errors.
253
                else:
254
                    builder.commit("msg")
5222.1.1 by Aaron Bentley
Refuse to commit trees with no root.
255
            self.assertRaises(errors.RootMissing, do_commit)
256
        finally:
257
            tree.unlock()
258
3775.2.7 by Robert Collins
CommitBuilder handles no-change commits to roots properly with record_iter_changes.
259
    def test_commit_without_root_or_record_iter_changes_errors(self):
1910.2.8 by Aaron Bentley
Fix commit_builder when root not passed to record_entry_contents
260
        tree = self.make_branch_and_tree(".")
2255.7.8 by John Arbash Meinel
Lock the tree when using a commit builder.
261
        tree.lock_write()
262
        try:
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
263
            self.build_tree(['foo'])
264
            tree.add('foo', 'foo-id')
5856.1.2 by Jelmer Vernooij
Delay accessing inventory in tests until necessary.
265
            builder = tree.branch.get_commit_builder([])
266
            if not builder.supports_record_entry_contents:
267
                raise tests.TestNotApplicable("CommitBuilder doesn't support "
268
                    "record_entry_contents")
6405.2.6 by Jelmer Vernooij
Lots of test fixes.
269
            entry = tree.root_inventory['foo-id']
2871.1.2 by Robert Collins
* ``CommitBuilder.record_entry_contents`` now requires the root entry of a
270
            self.assertRaises(errors.RootMissing,
2776.4.4 by Robert Collins
Move content summary generation outside of record_entry_contents.
271
                builder.record_entry_contents, entry, [], 'foo', tree,
272
                    tree.path_content_summary('foo'))
2871.1.2 by Robert Collins
* ``CommitBuilder.record_entry_contents`` now requires the root entry of a
273
            builder.abort()
2255.7.8 by John Arbash Meinel
Lock the tree when using a commit builder.
274
        finally:
275
            tree.unlock()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
276
5718.4.3 by Jelmer Vernooij
Skip record_entry_contents-using tests for commit builders that don't support it.
277
    def test_commit_unchanged_root_record_entry_contents(self):
2825.5.1 by Robert Collins
* Committing a change which is not a merge and does not change the number of
278
        tree = self.make_branch_and_tree(".")
2903.2.3 by Martin Pool
CommitBuilder tests should expect the root to be in the delta iff it's changed in the commit
279
        old_revision_id = tree.commit('')
2825.5.1 by Robert Collins
* Committing a change which is not a merge and does not change the number of
280
        tree.lock_write()
281
        parent_tree = tree.basis_tree()
282
        parent_tree.lock_read()
283
        self.addCleanup(parent_tree.unlock)
3879.2.5 by John Arbash Meinel
Change record_delete() to return the delta.
284
        builder = tree.branch.get_commit_builder([old_revision_id])
2825.5.1 by Robert Collins
* Committing a change which is not a merge and does not change the number of
285
        try:
5718.4.3 by Jelmer Vernooij
Skip record_entry_contents-using tests for commit builders that don't support it.
286
            if not builder.supports_record_entry_contents:
287
                raise tests.TestNotApplicable("CommitBuilder doesn't support "
288
                    "record_entry_contents")
6437.12.2 by Jelmer Vernooij
Remove more uses of CommitBuilder._basis_delta.
289
            builder.will_record_deletes()
2825.5.1 by Robert Collins
* Committing a change which is not a merge and does not change the number of
290
            ie = inventory.make_entry('directory', '', None,
2946.3.3 by John Arbash Meinel
Prefer tree.get_root_id() as more explicit than tree.path2id('')
291
                    tree.get_root_id())
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
292
            delta, version_recorded, fs_hash = builder.record_entry_contents(
6405.2.6 by Jelmer Vernooij
Lots of test fixes.
293
                ie, [parent_tree.root_inventory], '', tree,
2871.1.4 by Robert Collins
Merge bzr.dev.
294
                tree.path_content_summary(''))
3775.2.7 by Robert Collins
CommitBuilder handles no-change commits to roots properly with record_iter_changes.
295
            # Regardless of repository root behaviour we should consider this a
296
            # pointless commit.
3775.2.9 by Robert Collins
CommitBuilder handles deletes via record_iter_entries.
297
            self.assertFalse(builder.any_changes())
2871.1.3 by Robert Collins
* The CommitBuilder method ``record_entry_contents`` now returns summary
298
            self.assertFalse(version_recorded)
2903.2.3 by Martin Pool
CommitBuilder tests should expect the root to be in the delta iff it's changed in the commit
299
            # if the repository format recorded a new root revision, that
300
            # should be in the delta
301
            got_new_revision = ie.revision != old_revision_id
302
            if got_new_revision:
3879.2.5 by John Arbash Meinel
Change record_delete() to return the delta.
303
                self.assertEqual(('', '', ie.file_id, ie), delta)
304
                # The delta should be tracked
6437.12.2 by Jelmer Vernooij
Remove more uses of CommitBuilder._basis_delta.
305
                self.assertEqual(delta, builder.get_basis_delta()[-1])
2903.2.3 by Martin Pool
CommitBuilder tests should expect the root to be in the delta iff it's changed in the commit
306
            else:
307
                self.assertEqual(None, delta)
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
308
            # Directories do not get hashed.
309
            self.assertEqual(None, fs_hash)
2825.5.1 by Robert Collins
* Committing a change which is not a merge and does not change the number of
310
            builder.abort()
311
        except:
312
            builder.abort()
313
            tree.unlock()
314
            raise
315
        else:
316
            tree.unlock()
1910.2.8 by Aaron Bentley
Fix commit_builder when root not passed to record_entry_contents
317
3775.2.7 by Robert Collins
CommitBuilder handles no-change commits to roots properly with record_iter_changes.
318
    def test_commit_unchanged_root_record_iter_changes(self):
319
        tree = self.make_branch_and_tree(".")
320
        old_revision_id = tree.commit('')
321
        tree.lock_write()
3775.2.9 by Robert Collins
CommitBuilder handles deletes via record_iter_entries.
322
        builder = tree.branch.get_commit_builder([old_revision_id])
3775.2.7 by Robert Collins
CommitBuilder handles no-change commits to roots properly with record_iter_changes.
323
        try:
4183.5.4 by Robert Collins
Turn record_iter_changes into a generator to emit file system hashes.
324
            list(builder.record_iter_changes(tree, old_revision_id, []))
3775.2.7 by Robert Collins
CommitBuilder handles no-change commits to roots properly with record_iter_changes.
325
            # Regardless of repository root behaviour we should consider this a
326
            # pointless commit.
3775.2.9 by Robert Collins
CommitBuilder handles deletes via record_iter_entries.
327
            self.assertFalse(builder.any_changes())
3775.2.7 by Robert Collins
CommitBuilder handles no-change commits to roots properly with record_iter_changes.
328
            builder.finish_inventory()
6362.5.5 by Jelmer Vernooij
Don't access revision tree before commit.
329
            builder.commit('')
5878.1.1 by Jelmer Vernooij
Avoid inventory usage in a commit builder test.
330
            builder_tree = builder.revision_tree()
331
            new_root_id = builder_tree.get_root_id()
332
            new_root_revision = builder_tree.get_file_revision(new_root_id)
3775.2.7 by Robert Collins
CommitBuilder handles no-change commits to roots properly with record_iter_changes.
333
            if tree.branch.repository.supports_rich_root():
334
                # We should not have seen a new root revision
5878.1.1 by Jelmer Vernooij
Avoid inventory usage in a commit builder test.
335
                self.assertEqual(old_revision_id, new_root_revision)
3775.2.7 by Robert Collins
CommitBuilder handles no-change commits to roots properly with record_iter_changes.
336
            else:
337
                # We should see a new root revision
5878.1.1 by Jelmer Vernooij
Avoid inventory usage in a commit builder test.
338
                self.assertNotEqual(old_revision_id, new_root_revision)
3775.2.7 by Robert Collins
CommitBuilder handles no-change commits to roots properly with record_iter_changes.
339
        finally:
340
            tree.unlock()
341
5718.4.3 by Jelmer Vernooij
Skip record_entry_contents-using tests for commit builders that don't support it.
342
    def test_commit_record_entry_contents(self):
1740.3.8 by Jelmer Vernooij
Move make_revision() to commit builder.
343
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
344
        tree.lock_write()
2617.6.8 by Robert Collins
Review feedback and documentation.
345
        try:
346
            builder = tree.branch.get_commit_builder([])
5718.4.3 by Jelmer Vernooij
Skip record_entry_contents-using tests for commit builders that don't support it.
347
            if not builder.supports_record_entry_contents:
348
                raise tests.TestNotApplicable("CommitBuilder doesn't "
349
                    "support record_entry_contents")
2617.6.8 by Robert Collins
Review feedback and documentation.
350
            self.record_root(builder, tree)
351
            builder.finish_inventory()
352
            rev_id = builder.commit('foo bar')
353
        finally:
354
            tree.unlock()
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
355
        self.assertNotEqual(None, rev_id)
356
        self.assertTrue(tree.branch.repository.has_revision(rev_id))
1757.1.2 by Robert Collins
Bugfix CommitBuilders recording of the inventory revision id.
357
        # the revision id must be set on the inventory when saving it. This does not
358
        # precisely test that - a repository that wants to can add it on deserialisation,
359
        # but thats all the current contract guarantees anyway.
360
        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
361
3879.2.5 by John Arbash Meinel
Change record_delete() to return the delta.
362
    def test_get_basis_delta(self):
363
        tree = self.make_branch_and_tree(".")
364
        self.build_tree(["foo"])
365
        tree.add(["foo"], ["foo-id"])
366
        old_revision_id = tree.commit("added foo")
367
        tree.lock_write()
368
        try:
369
            self.build_tree(['bar'])
370
            tree.add(['bar'], ['bar-id'])
371
            basis = tree.branch.repository.revision_tree(old_revision_id)
372
            basis.lock_read()
373
            self.addCleanup(basis.unlock)
374
            builder = tree.branch.get_commit_builder([old_revision_id])
375
            total_delta = []
376
            try:
5718.4.3 by Jelmer Vernooij
Skip record_entry_contents-using tests for commit builders that don't support it.
377
                if not builder.supports_record_entry_contents:
378
                    raise tests.TestNotApplicable("CommitBuilder doesn't "
379
                        "support record_entry_contents")
6405.2.6 by Jelmer Vernooij
Lots of test fixes.
380
                parent_invs = [basis.root_inventory]
3879.2.5 by John Arbash Meinel
Change record_delete() to return the delta.
381
                builder.will_record_deletes()
382
                if builder.record_root_entry:
6405.2.6 by Jelmer Vernooij
Lots of test fixes.
383
                    ie = basis.root_inventory.root.copy()
3879.2.5 by John Arbash Meinel
Change record_delete() to return the delta.
384
                    delta, _, _ = builder.record_entry_contents(ie, parent_invs,
385
                        '', tree, tree.path_content_summary(''))
386
                    if delta is not None:
387
                        total_delta.append(delta)
388
                delta = builder.record_delete("foo", "foo-id")
389
                total_delta.append(delta)
390
                new_bar = inventory.make_entry('file', 'bar',
391
                    parent_id=tree.get_root_id(), file_id='bar-id')
392
                delta, _, _ = builder.record_entry_contents(new_bar, parent_invs,
393
                    'bar', tree, tree.path_content_summary('bar'))
394
                total_delta.append(delta)
395
                # All actions should have been recorded in the basis_delta
396
                self.assertEqual(total_delta, builder.get_basis_delta())
397
                builder.finish_inventory()
398
                builder.commit('delete foo, add bar')
399
            except:
400
                tree.branch.repository.abort_write_group()
401
                raise
402
        finally:
403
            tree.unlock()
404
405
    def test_get_basis_delta_without_notification(self):
406
        tree = self.make_branch_and_tree(".")
407
        old_revision_id = tree.commit('')
408
        tree.lock_write()
409
        try:
410
            parent_tree = tree.basis_tree()
411
            parent_tree.lock_read()
412
            self.addCleanup(parent_tree.unlock)
413
            builder = tree.branch.get_commit_builder([old_revision_id])
414
            # It is an error to expect builder.get_basis_delta() to be correct,
415
            # if you have not also called will_record_deletes() to indicate you
416
            # will be calling record_delete() when appropriate
417
            self.assertRaises(AssertionError, builder.get_basis_delta)
418
            tree.branch.repository.abort_write_group()
419
        finally:
420
            tree.unlock()
421
3775.2.2 by Robert Collins
Teach CommitBuilder to accumulate inventory deltas.
422
    def test_record_delete(self):
423
        tree = self.make_branch_and_tree(".")
424
        self.build_tree(["foo"])
425
        tree.add(["foo"], ["foo-id"])
426
        rev_id = tree.commit("added foo")
427
        # Remove the inventory details for foo-id, because
428
        # record_entry_contents ends up copying root verbatim.
429
        tree.unversion(["foo-id"])
430
        tree.lock_write()
431
        try:
432
            basis = tree.branch.repository.revision_tree(rev_id)
433
            builder = tree.branch.get_commit_builder([rev_id])
434
            try:
5718.4.3 by Jelmer Vernooij
Skip record_entry_contents-using tests for commit builders that don't support it.
435
                if not builder.supports_record_entry_contents:
436
                    raise tests.TestNotApplicable("CommitBuilder doesn't "
437
                        "support record_entry_contents")
3879.2.5 by John Arbash Meinel
Change record_delete() to return the delta.
438
                builder.will_record_deletes()
3775.2.2 by Robert Collins
Teach CommitBuilder to accumulate inventory deltas.
439
                if builder.record_root_entry is True:
6405.2.6 by Jelmer Vernooij
Lots of test fixes.
440
                    parent_invs = [basis.root_inventory]
441
                    del basis.root_inventory.root.children['foo']
442
                    builder.record_entry_contents(basis.root_inventory.root,
3775.2.2 by Robert Collins
Teach CommitBuilder to accumulate inventory deltas.
443
                        parent_invs, '', tree, tree.path_content_summary(''))
3879.2.5 by John Arbash Meinel
Change record_delete() to return the delta.
444
                # the delta should be returned, and recorded in _basis_delta
445
                delta = builder.record_delete("foo", "foo-id")
446
                self.assertEqual(("foo", None, "foo-id", None), delta)
6437.12.2 by Jelmer Vernooij
Remove more uses of CommitBuilder._basis_delta.
447
                self.assertEqual(delta, builder.get_basis_delta()[-1])
3775.2.2 by Robert Collins
Teach CommitBuilder to accumulate inventory deltas.
448
                builder.finish_inventory()
449
                rev_id2 = builder.commit('delete foo')
450
            except:
451
                tree.branch.repository.abort_write_group()
452
                raise
453
        finally:
454
            tree.unlock()
455
        rev_tree = builder.revision_tree()
456
        rev_tree.lock_read()
457
        self.addCleanup(rev_tree.unlock)
458
        self.assertFalse(rev_tree.path2id('foo'))
459
3775.2.9 by Robert Collins
CommitBuilder handles deletes via record_iter_entries.
460
    def test_record_delete_record_iter_changes(self):
461
        tree = self.make_branch_and_tree(".")
462
        self.build_tree(["foo"])
463
        tree.add(["foo"], ["foo-id"])
464
        rev_id = tree.commit("added foo")
465
        tree.lock_write()
466
        try:
467
            builder = tree.branch.get_commit_builder([rev_id])
468
            try:
6437.12.2 by Jelmer Vernooij
Remove more uses of CommitBuilder._basis_delta.
469
                builder.will_record_deletes()
3775.2.9 by Robert Collins
CommitBuilder handles deletes via record_iter_entries.
470
                delete_change = ('foo-id', ('foo', None), True, (True, False),
471
                    (tree.path2id(''), None), ('foo', None), ('file', None),
472
                    (False, None))
4183.5.4 by Robert Collins
Turn record_iter_changes into a generator to emit file system hashes.
473
                list(builder.record_iter_changes(tree, rev_id,
474
                    [delete_change]))
3775.2.9 by Robert Collins
CommitBuilder handles deletes via record_iter_entries.
475
                self.assertEqual(("foo", None, "foo-id", None),
6437.12.2 by Jelmer Vernooij
Remove more uses of CommitBuilder._basis_delta.
476
                    builder.get_basis_delta()[0])
3775.2.9 by Robert Collins
CommitBuilder handles deletes via record_iter_entries.
477
                self.assertTrue(builder.any_changes())
478
                builder.finish_inventory()
479
                rev_id2 = builder.commit('delete foo')
480
            except:
481
                builder.abort()
482
                raise
483
        finally:
484
            tree.unlock()
485
        rev_tree = builder.revision_tree()
486
        rev_tree.lock_read()
487
        self.addCleanup(rev_tree.unlock)
488
        self.assertFalse(rev_tree.path2id('foo'))
489
3775.2.2 by Robert Collins
Teach CommitBuilder to accumulate inventory deltas.
490
    def test_record_delete_without_notification(self):
491
        tree = self.make_branch_and_tree(".")
492
        self.build_tree(["foo"])
493
        tree.add(["foo"], ["foo-id"])
494
        rev_id = tree.commit("added foo")
495
        tree.lock_write()
496
        try:
497
            builder = tree.branch.get_commit_builder([rev_id])
498
            try:
5718.4.3 by Jelmer Vernooij
Skip record_entry_contents-using tests for commit builders that don't support it.
499
                if not builder.supports_record_entry_contents:
500
                    raise tests.TestNotApplicable("CommitBuilder doesn't "
501
                        "support record_entry_contents")
3775.2.2 by Robert Collins
Teach CommitBuilder to accumulate inventory deltas.
502
                self.record_root(builder, tree)
503
                self.assertRaises(AssertionError,
504
                    builder.record_delete, "foo", "foo-id")
505
            finally:
506
                tree.branch.repository.abort_write_group()
507
        finally:
508
            tree.unlock()
509
5718.4.3 by Jelmer Vernooij
Skip record_entry_contents-using tests for commit builders that don't support it.
510
    def test_revision_tree_record_entry_contents(self):
2041.1.1 by John Arbash Meinel
Add a 'get_tree()' call that returns a RevisionTree for the newly committed tree
511
        tree = self.make_branch_and_tree(".")
2617.6.2 by Robert Collins
Add abort_write_group and wire write_groups into fetch and commit.
512
        tree.lock_write()
2617.6.8 by Robert Collins
Review feedback and documentation.
513
        try:
514
            builder = tree.branch.get_commit_builder([])
5718.4.3 by Jelmer Vernooij
Skip record_entry_contents-using tests for commit builders that don't support it.
515
            if not builder.supports_record_entry_contents:
516
                raise tests.TestNotApplicable("CommitBuilder doesn't "
517
                    "support record_entry_contents")
2617.6.8 by Robert Collins
Review feedback and documentation.
518
            self.record_root(builder, tree)
519
            builder.finish_inventory()
520
            rev_id = builder.commit('foo bar')
521
        finally:
522
            tree.unlock()
2041.1.5 by John Arbash Meinel
CommitBuilder.get_tree => CommitBuilder.revision_tree
523
        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
524
        # Just a couple simple tests to ensure that it actually follows
525
        # the RevisionTree api.
526
        self.assertEqual(rev_id, rev_tree.get_revision_id())
527
        self.assertEqual([], rev_tree.get_parent_ids())
2255.7.65 by Robert Collins
Split test_root_revision_entry into tree and repository portions.
528
3775.2.10 by Robert Collins
CommitBuilder gives a revision tree when used with record_iter_contents.
529
    def test_revision_tree_record_iter_changes(self):
530
        tree = self.make_branch_and_tree(".")
531
        tree.lock_write()
532
        try:
533
            builder = tree.branch.get_commit_builder([])
534
            try:
4183.5.4 by Robert Collins
Turn record_iter_changes into a generator to emit file system hashes.
535
                list(builder.record_iter_changes(tree,
536
                    _mod_revision.NULL_REVISION,
537
                    tree.iter_changes(tree.basis_tree())))
3775.2.10 by Robert Collins
CommitBuilder gives a revision tree when used with record_iter_contents.
538
                builder.finish_inventory()
539
                rev_id = builder.commit('foo bar')
540
            except:
541
                builder.abort()
542
                raise
543
            rev_tree = builder.revision_tree()
544
            # Just a couple simple tests to ensure that it actually follows
545
            # the RevisionTree api.
546
            self.assertEqual(rev_id, rev_tree.get_revision_id())
6072.1.1 by Jelmer Vernooij
Various fixes for tests of foreign plugins.
547
            self.assertEqual((), tuple(rev_tree.get_parent_ids()))
3775.2.10 by Robert Collins
CommitBuilder gives a revision tree when used with record_iter_contents.
548
        finally:
549
            tree.unlock()
550
2255.7.65 by Robert Collins
Split test_root_revision_entry into tree and repository portions.
551
    def test_root_entry_has_revision(self):
552
        # test the root revision created and put in the basis
553
        # has the right rev id.
3775.2.11 by Robert Collins
CommitBuilder handles renamed directory and unmodified entries with single parents, for record_iter_changes.
554
        # XXX: RBC 20081118 - this test is too big, it depends on the exact
555
        # behaviour of tree methods and so on; it should be written to the
556
        # commit builder interface directly.
2255.7.65 by Robert Collins
Split test_root_revision_entry into tree and repository portions.
557
        tree = self.make_branch_and_tree('.')
558
        rev_id = tree.commit('message')
559
        basis_tree = tree.basis_tree()
560
        basis_tree.lock_read()
561
        self.addCleanup(basis_tree.unlock)
5819.2.4 by Jelmer Vernooij
Avoid using inventory.
562
        self.assertEqual(rev_id,
563
            basis_tree.get_file_revision(basis_tree.get_root_id()))
2255.7.65 by Robert Collins
Split test_root_revision_entry into tree and repository portions.
564
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
565
    def _get_revtrees(self, tree, revision_ids):
2592.3.214 by Robert Collins
Merge bzr.dev.
566
        tree.lock_read()
567
        try:
568
            trees = list(tree.branch.repository.revision_trees(revision_ids))
569
            for _tree in trees:
570
                _tree.lock_read()
571
                self.addCleanup(_tree.unlock)
572
            return trees
573
        finally:
574
            tree.unlock()
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
575
576
    def test_last_modified_revision_after_commit_root_unchanged(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
577
        # commiting without changing the root does not change the
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
578
        # last modified except on non-rich-root-repositories.
579
        tree = self.make_branch_and_tree('.')
580
        rev1 = tree.commit('')
581
        rev2 = tree.commit('')
582
        tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
5819.2.4 by Jelmer Vernooij
Avoid using inventory.
583
        self.assertEqual(rev1, tree1.get_file_revision(tree1.get_root_id()))
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
584
        if tree.branch.repository.supports_rich_root():
5819.2.4 by Jelmer Vernooij
Avoid using inventory.
585
            self.assertEqual(rev1,
586
                tree2.get_file_revision(tree2.get_root_id()))
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
587
        else:
5819.2.4 by Jelmer Vernooij
Avoid using inventory.
588
            self.assertEqual(rev2,
589
                tree2.get_file_revision(tree2.get_root_id()))
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
590
3775.2.11 by Robert Collins
CommitBuilder handles renamed directory and unmodified entries with single parents, for record_iter_changes.
591
    def _add_commit_check_unchanged(self, tree, name, mini_commit=None):
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
592
        tree.add([name], [name + 'id'])
4183.5.3 by Robert Collins
Fix typo.
593
        self._commit_check_unchanged(tree, name, name + 'id',
4183.5.2 by Robert Collins
Support tree-reference in record_iter_changes.
594
            mini_commit=mini_commit)
595
596
    def _commit_check_unchanged(self, tree, name, file_id, mini_commit=None):
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
597
        rev1 = tree.commit('')
3775.2.11 by Robert Collins
CommitBuilder handles renamed directory and unmodified entries with single parents, for record_iter_changes.
598
        if mini_commit is None:
599
            mini_commit = self.mini_commit
600
        rev2 = mini_commit(tree, name, name, False, False)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
601
        tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
5793.2.3 by Jelmer Vernooij
Add a RevisionTree.get_file_revision() method.
602
        self.assertEqual(rev1, tree1.get_file_revision(file_id))
603
        self.assertEqual(rev1, tree2.get_file_revision(file_id))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
604
        expected_graph = {}
605
        expected_graph[(file_id, rev1)] = ()
606
        self.assertFileGraph(expected_graph, tree, (file_id, rev1))
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
607
608
    def test_last_modified_revision_after_commit_dir_unchanged(self):
609
        # committing without changing a dir does not change the last modified.
610
        tree = self.make_branch_and_tree('.')
611
        self.build_tree(['dir/'])
612
        self._add_commit_check_unchanged(tree, 'dir')
613
3775.2.11 by Robert Collins
CommitBuilder handles renamed directory and unmodified entries with single parents, for record_iter_changes.
614
    def test_last_modified_revision_after_commit_dir_unchanged_ric(self):
615
        # committing without changing a dir does not change the last modified.
616
        tree = self.make_branch_and_tree('.')
617
        self.build_tree(['dir/'])
618
        self._add_commit_check_unchanged(tree, 'dir',
619
            mini_commit=self.mini_commit_record_iter_changes)
620
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
621
    def test_last_modified_revision_after_commit_dir_contents_unchanged(self):
622
        # committing without changing a dir does not change the last modified
623
        # of the dir even the dirs contents are changed.
624
        tree = self.make_branch_and_tree('.')
625
        self.build_tree(['dir/'])
626
        tree.add(['dir'], ['dirid'])
627
        rev1 = tree.commit('')
628
        self.build_tree(['dir/content'])
629
        tree.add(['dir/content'], ['contentid'])
630
        rev2 = tree.commit('')
631
        tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
5793.2.3 by Jelmer Vernooij
Add a RevisionTree.get_file_revision() method.
632
        self.assertEqual(rev1, tree1.get_file_revision('dirid'))
633
        self.assertEqual(rev1, tree2.get_file_revision('dirid'))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
634
        file_id = 'dirid'
635
        expected_graph = {}
636
        expected_graph[(file_id, rev1)] = ()
637
        self.assertFileGraph(expected_graph, tree, (file_id, rev1))
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
638
639
    def test_last_modified_revision_after_commit_file_unchanged(self):
640
        # committing without changing a file does not change the last modified.
641
        tree = self.make_branch_and_tree('.')
642
        self.build_tree(['file'])
643
        self._add_commit_check_unchanged(tree, 'file')
644
3775.2.11 by Robert Collins
CommitBuilder handles renamed directory and unmodified entries with single parents, for record_iter_changes.
645
    def test_last_modified_revision_after_commit_file_unchanged_ric(self):
646
        # committing without changing a file does not change the last modified.
647
        tree = self.make_branch_and_tree('.')
648
        self.build_tree(['file'])
649
        self._add_commit_check_unchanged(tree, 'file',
650
            mini_commit=self.mini_commit_record_iter_changes)
651
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
652
    def test_last_modified_revision_after_commit_link_unchanged(self):
653
        # committing without changing a link does not change the last modified.
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
654
        self.requireFeature(features.SymlinkFeature)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
655
        tree = self.make_branch_and_tree('.')
656
        os.symlink('target', 'link')
657
        self._add_commit_check_unchanged(tree, 'link')
658
3775.2.11 by Robert Collins
CommitBuilder handles renamed directory and unmodified entries with single parents, for record_iter_changes.
659
    def test_last_modified_revision_after_commit_link_unchanged_ric(self):
4183.5.6 by Robert Collins
Review caught a bogus change to test_last_modified_revision_after_commit_link_unchanged_ric.
660
        # committing without changing a link does not change the last modified.
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
661
        self.requireFeature(features.SymlinkFeature)
3775.2.11 by Robert Collins
CommitBuilder handles renamed directory and unmodified entries with single parents, for record_iter_changes.
662
        tree = self.make_branch_and_tree('.')
663
        os.symlink('target', 'link')
664
        self._add_commit_check_unchanged(tree, 'link',
665
            mini_commit=self.mini_commit_record_iter_changes)
666
4183.5.2 by Robert Collins
Support tree-reference in record_iter_changes.
667
    def test_last_modified_revision_after_commit_reference_unchanged(self):
668
        # committing without changing a subtree does not change the last
669
        # modified.
670
        tree = self.make_branch_and_tree('.')
671
        subtree = self.make_reference('reference')
672
        try:
673
            tree.add_reference(subtree)
674
            self._commit_check_unchanged(tree, 'reference',
675
                subtree.get_root_id())
676
        except errors.UnsupportedOperation:
677
            return
678
679
    def test_last_modified_revision_after_commit_reference_unchanged_ric(self):
680
        # committing without changing a subtree does not change the last
681
        # modified.
682
        tree = self.make_branch_and_tree('.')
683
        subtree = self.make_reference('reference')
684
        try:
685
            tree.add_reference(subtree)
686
            self._commit_check_unchanged(tree, 'reference',
687
                subtree.get_root_id(),
688
                mini_commit=self.mini_commit_record_iter_changes)
689
        except errors.UnsupportedOperation:
690
            return
691
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
692
    def _add_commit_renamed_check_changed(self, tree, name,
3775.2.11 by Robert Collins
CommitBuilder handles renamed directory and unmodified entries with single parents, for record_iter_changes.
693
        expect_fs_hash=False, mini_commit=None):
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
694
        def rename():
695
            tree.rename_one(name, 'new_' + name)
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
696
        self._add_commit_change_check_changed(tree, name, rename,
3775.2.11 by Robert Collins
CommitBuilder handles renamed directory and unmodified entries with single parents, for record_iter_changes.
697
            expect_fs_hash=expect_fs_hash, mini_commit=mini_commit)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
698
4183.5.2 by Robert Collins
Support tree-reference in record_iter_changes.
699
    def _commit_renamed_check_changed(self, tree, name, file_id,
700
        expect_fs_hash=False, mini_commit=None):
701
        def rename():
702
            tree.rename_one(name, 'new_' + name)
703
        self._commit_change_check_changed(tree, name, file_id, rename,
704
            expect_fs_hash=expect_fs_hash, mini_commit=mini_commit)
705
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
706
    def test_last_modified_revision_after_rename_dir_changes(self):
707
        # renaming a dir changes the last modified.
708
        tree = self.make_branch_and_tree('.')
709
        self.build_tree(['dir/'])
710
        self._add_commit_renamed_check_changed(tree, 'dir')
711
3775.2.11 by Robert Collins
CommitBuilder handles renamed directory and unmodified entries with single parents, for record_iter_changes.
712
    def test_last_modified_revision_after_rename_dir_changes_ric(self):
713
        # renaming a dir changes the last modified.
714
        tree = self.make_branch_and_tree('.')
715
        self.build_tree(['dir/'])
716
        self._add_commit_renamed_check_changed(tree, 'dir',
717
            mini_commit=self.mini_commit_record_iter_changes)
718
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
719
    def test_last_modified_revision_after_rename_file_changes(self):
720
        # renaming a file changes the last modified.
721
        tree = self.make_branch_and_tree('.')
722
        self.build_tree(['file'])
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
723
        self._add_commit_renamed_check_changed(tree, 'file',
724
            expect_fs_hash=True)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
725
3775.2.12 by Robert Collins
CommitBuilder.record_iter_changes handles renamed files.
726
    def test_last_modified_revision_after_rename_file_changes_ric(self):
727
        # renaming a file changes the last modified.
728
        tree = self.make_branch_and_tree('.')
729
        self.build_tree(['file'])
730
        self._add_commit_renamed_check_changed(tree, 'file',
731
            expect_fs_hash=True,
732
            mini_commit=self.mini_commit_record_iter_changes)
733
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
734
    def test_last_modified_revision_after_rename_link_changes(self):
735
        # renaming a link changes the last modified.
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
736
        self.requireFeature(features.SymlinkFeature)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
737
        tree = self.make_branch_and_tree('.')
738
        os.symlink('target', 'link')
739
        self._add_commit_renamed_check_changed(tree, 'link')
740
3775.2.13 by Robert Collins
CommitBuilder.record_iter_changes handles renamed symlinks.
741
    def test_last_modified_revision_after_rename_link_changes_ric(self):
742
        # renaming a link changes the last modified.
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
743
        self.requireFeature(features.SymlinkFeature)
3775.2.13 by Robert Collins
CommitBuilder.record_iter_changes handles renamed symlinks.
744
        tree = self.make_branch_and_tree('.')
745
        os.symlink('target', 'link')
746
        self._add_commit_renamed_check_changed(tree, 'link',
747
            mini_commit=self.mini_commit_record_iter_changes)
748
4183.5.2 by Robert Collins
Support tree-reference in record_iter_changes.
749
    def test_last_modified_revision_after_rename_ref_changes(self):
750
        # renaming a reference changes the last modified.
751
        tree = self.make_branch_and_tree('.')
752
        subtree = self.make_reference('reference')
753
        try:
754
            tree.add_reference(subtree)
755
            self._commit_renamed_check_changed(tree, 'reference',
756
                subtree.get_root_id())
757
        except errors.UnsupportedOperation:
758
            return
759
760
    def test_last_modified_revision_after_rename_ref_changes_ric(self):
761
        # renaming a reference changes the last modified.
762
        tree = self.make_branch_and_tree('.')
763
        subtree = self.make_reference('reference')
764
        try:
765
            tree.add_reference(subtree)
766
            self._commit_renamed_check_changed(tree, 'reference',
767
                subtree.get_root_id(),
768
                mini_commit=self.mini_commit_record_iter_changes)
769
        except errors.UnsupportedOperation:
770
            return
771
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
772
    def _add_commit_reparent_check_changed(self, tree, name,
3775.2.14 by Robert Collins
CommitBuilder.record_iter_changes handles reparented directories.
773
        expect_fs_hash=False, mini_commit=None):
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
774
        self.build_tree(['newparent/'])
775
        tree.add(['newparent'])
776
        def reparent():
777
            tree.rename_one(name, 'newparent/new_' + name)
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
778
        self._add_commit_change_check_changed(tree, name, reparent,
3775.2.14 by Robert Collins
CommitBuilder.record_iter_changes handles reparented directories.
779
            expect_fs_hash=expect_fs_hash, mini_commit=mini_commit)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
780
781
    def test_last_modified_revision_after_reparent_dir_changes(self):
782
        # reparenting a dir changes the last modified.
783
        tree = self.make_branch_and_tree('.')
784
        self.build_tree(['dir/'])
785
        self._add_commit_reparent_check_changed(tree, 'dir')
786
3775.2.14 by Robert Collins
CommitBuilder.record_iter_changes handles reparented directories.
787
    def test_last_modified_revision_after_reparent_dir_changes_ric(self):
788
        # reparenting a dir changes the last modified.
789
        tree = self.make_branch_and_tree('.')
790
        self.build_tree(['dir/'])
791
        self._add_commit_reparent_check_changed(tree, 'dir',
792
            mini_commit=self.mini_commit_record_iter_changes)
793
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
794
    def test_last_modified_revision_after_reparent_file_changes(self):
795
        # reparenting a file changes the last modified.
796
        tree = self.make_branch_and_tree('.')
797
        self.build_tree(['file'])
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
798
        self._add_commit_reparent_check_changed(tree, 'file',
799
            expect_fs_hash=True)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
800
3775.2.15 by Robert Collins
CommitBuilder.record_iter_changes handles reparented files.
801
    def test_last_modified_revision_after_reparent_file_changes_ric(self):
802
        # reparenting a file changes the last modified.
803
        tree = self.make_branch_and_tree('.')
804
        self.build_tree(['file'])
805
        self._add_commit_reparent_check_changed(tree, 'file',
3775.2.17 by Robert Collins
CommitBuilder.record_iter_changes handles changed files.
806
            expect_fs_hash=True,
807
            mini_commit=self.mini_commit_record_iter_changes)
3775.2.15 by Robert Collins
CommitBuilder.record_iter_changes handles reparented files.
808
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
809
    def test_last_modified_revision_after_reparent_link_changes(self):
810
        # reparenting a link changes the last modified.
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
811
        self.requireFeature(features.SymlinkFeature)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
812
        tree = self.make_branch_and_tree('.')
813
        os.symlink('target', 'link')
814
        self._add_commit_reparent_check_changed(tree, 'link')
815
3775.2.16 by Robert Collins
CommitBuilder.record_iter_changes handles reparented symlinks.
816
    def test_last_modified_revision_after_reparent_link_changes_ric(self):
817
        # reparenting a link changes the last modified.
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
818
        self.requireFeature(features.SymlinkFeature)
3775.2.16 by Robert Collins
CommitBuilder.record_iter_changes handles reparented symlinks.
819
        tree = self.make_branch_and_tree('.')
820
        os.symlink('target', 'link')
821
        self._add_commit_reparent_check_changed(tree, 'link',
822
            mini_commit=self.mini_commit_record_iter_changes)
823
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
824
    def _add_commit_change_check_changed(self, tree, name, changer,
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
825
        expect_fs_hash=False, mini_commit=None, file_id=None):
826
        if file_id is None:
827
            file_id = name + 'id'
828
        tree.add([name], [file_id])
829
        self._commit_change_check_changed(
830
            tree, name, file_id,
4183.5.2 by Robert Collins
Support tree-reference in record_iter_changes.
831
            changer, expect_fs_hash=expect_fs_hash, mini_commit=mini_commit)
832
4183.5.3 by Robert Collins
Fix typo.
833
    def _commit_change_check_changed(self, tree, name, file_id, changer,
4183.5.2 by Robert Collins
Support tree-reference in record_iter_changes.
834
        expect_fs_hash=False, mini_commit=None):
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
835
        rev1 = tree.commit('')
836
        changer()
3775.2.11 by Robert Collins
CommitBuilder handles renamed directory and unmodified entries with single parents, for record_iter_changes.
837
        if mini_commit is None:
838
            mini_commit = self.mini_commit
4183.5.2 by Robert Collins
Support tree-reference in record_iter_changes.
839
        rev2 = mini_commit(tree, name, tree.id2path(file_id),
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
840
            expect_fs_hash=expect_fs_hash)
2871.1.3 by Robert Collins
* The CommitBuilder method ``record_entry_contents`` now returns summary
841
        tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
5793.2.3 by Jelmer Vernooij
Add a RevisionTree.get_file_revision() method.
842
        self.assertEqual(rev1, tree1.get_file_revision(file_id))
843
        self.assertEqual(rev2, tree2.get_file_revision(file_id))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
844
        expected_graph = {}
845
        expected_graph[(file_id, rev1)] = ()
846
        expected_graph[(file_id, rev2)] = ((file_id, rev1),)
847
        self.assertFileGraph(expected_graph, tree, (file_id, rev2))
2871.1.3 by Robert Collins
* The CommitBuilder method ``record_entry_contents`` now returns summary
848
849
    def mini_commit(self, tree, name, new_name, records_version=True,
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
850
        delta_against_basis=True, expect_fs_hash=False):
2871.1.3 by Robert Collins
* The CommitBuilder method ``record_entry_contents`` now returns summary
851
        """Perform a miniature commit looking for record entry results.
3879.2.5 by John Arbash Meinel
Change record_delete() to return the delta.
852
2871.1.3 by Robert Collins
* The CommitBuilder method ``record_entry_contents`` now returns summary
853
        :param tree: The tree to commit.
854
        :param name: The path in the basis tree of the tree being committed.
855
        :param new_name: The path in the tree being committed.
856
        :param records_version: True if the commit of new_name is expected to
857
            record a new version.
858
        :param delta_against_basis: True of the commit of new_name is expected
859
            to have a delta against the basis.
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
860
        :param expect_fs_hash: True or false to indicate whether we expect a
861
            file hash to be returned from the record_entry_contents call.
2871.1.3 by Robert Collins
* The CommitBuilder method ``record_entry_contents`` now returns summary
862
        """
2825.5.1 by Robert Collins
* Committing a change which is not a merge and does not change the number of
863
        tree.lock_write()
864
        try:
865
            # mini manual commit here so we can check the return of
866
            # record_entry_contents.
2871.1.3 by Robert Collins
* The CommitBuilder method ``record_entry_contents`` now returns summary
867
            parent_ids = tree.get_parent_ids()
868
            builder = tree.branch.get_commit_builder(parent_ids)
5707.1.1 by Jelmer Vernooij
Properly try/except.
869
            try:
5718.4.3 by Jelmer Vernooij
Skip record_entry_contents-using tests for commit builders that don't support it.
870
                if not builder.supports_record_entry_contents:
871
                    raise tests.TestNotApplicable("CommitBuilder doesn't "
872
                        "support record_entry_contents")
6437.12.2 by Jelmer Vernooij
Remove more uses of CommitBuilder._basis_delta.
873
                builder.will_record_deletes()
5707.1.1 by Jelmer Vernooij
Properly try/except.
874
                parent_tree = tree.basis_tree()
875
                parent_tree.lock_read()
876
                self.addCleanup(parent_tree.unlock)
6405.2.6 by Jelmer Vernooij
Lots of test fixes.
877
                parent_invs = [parent_tree.root_inventory]
5707.1.1 by Jelmer Vernooij
Properly try/except.
878
                for parent_id in parent_ids[1:]:
879
                    parent_invs.append(tree.branch.repository.revision_tree(
6405.2.6 by Jelmer Vernooij
Lots of test fixes.
880
                        parent_id).root_inventory)
5707.1.1 by Jelmer Vernooij
Properly try/except.
881
                # root
882
                builder.record_entry_contents(
883
                    inventory.make_entry('directory', '', None,
884
                        tree.get_root_id()), parent_invs, '', tree,
885
                        tree.path_content_summary(''))
886
                def commit_id(file_id):
6405.2.6 by Jelmer Vernooij
Lots of test fixes.
887
                    old_ie = tree.root_inventory[file_id]
5707.1.1 by Jelmer Vernooij
Properly try/except.
888
                    path = tree.id2path(file_id)
889
                    ie = inventory.make_entry(tree.kind(file_id), old_ie.name,
890
                        old_ie.parent_id, file_id)
891
                    content_summary = tree.path_content_summary(path)
892
                    if content_summary[0] == 'tree-reference':
893
                        content_summary = content_summary[:3] + (
894
                            tree.get_reference_revision(file_id),)
895
                    return builder.record_entry_contents(ie, parent_invs, path,
896
                        tree, content_summary)
2825.5.1 by Robert Collins
* Committing a change which is not a merge and does not change the number of
897
5707.1.1 by Jelmer Vernooij
Properly try/except.
898
                file_id = tree.path2id(new_name)
6405.2.6 by Jelmer Vernooij
Lots of test fixes.
899
                parent_id = tree.root_inventory[file_id].parent_id
5707.1.1 by Jelmer Vernooij
Properly try/except.
900
                if parent_id != tree.get_root_id():
901
                    commit_id(parent_id)
902
                # because a change of some sort is meant to have occurred,
903
                # recording the entry must return True.
904
                delta, version_recorded, fs_hash = commit_id(file_id)
905
                if records_version:
906
                    self.assertTrue(version_recorded)
907
                else:
908
                    self.assertFalse(version_recorded)
909
                if expect_fs_hash:
910
                    tree_file_stat = tree.get_file_with_stat(file_id)
911
                    tree_file_stat[0].close()
912
                    self.assertEqual(2, len(fs_hash))
913
                    self.assertEqual(tree.get_file_sha1(file_id), fs_hash[0])
914
                    self.assertEqualStat(tree_file_stat[1], fs_hash[1])
915
                else:
916
                    self.assertEqual(None, fs_hash)
917
                new_entry = builder.new_inventory[file_id]
918
                if delta_against_basis:
919
                    expected_delta = (name, new_name, file_id, new_entry)
920
                    # The delta should be recorded
6437.12.2 by Jelmer Vernooij
Remove more uses of CommitBuilder._basis_delta.
921
                    self.assertEqual(expected_delta,
922
                        builder.get_basis_delta()[-1])
5707.1.1 by Jelmer Vernooij
Properly try/except.
923
                else:
924
                    expected_delta = None
925
                self.assertEqual(expected_delta, delta)
926
                builder.finish_inventory()
927
            except:
928
                builder.abort()
929
                raise
930
            else:
931
                rev2 = builder.commit('')
3735.2.9 by Robert Collins
Get a working chk_map using inventory implementation bootstrapped.
932
        except:
933
            tree.unlock()
934
            raise
4245.1.1 by Ian Clatworthy
minor test clean-ups & _reconcile_pack API
935
        try:
936
            tree.set_parent_ids([rev2])
937
        finally:
2825.5.1 by Robert Collins
* Committing a change which is not a merge and does not change the number of
938
            tree.unlock()
2871.1.3 by Robert Collins
* The CommitBuilder method ``record_entry_contents`` now returns summary
939
        return rev2
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
940
3775.2.11 by Robert Collins
CommitBuilder handles renamed directory and unmodified entries with single parents, for record_iter_changes.
941
    def mini_commit_record_iter_changes(self, tree, name, new_name,
942
        records_version=True, delta_against_basis=True, expect_fs_hash=False):
943
        """Perform a miniature commit looking for record entry results.
944
945
        This version uses the record_iter_changes interface.
946
        
947
        :param tree: The tree to commit.
948
        :param name: The path in the basis tree of the tree being committed.
949
        :param new_name: The path in the tree being committed.
950
        :param records_version: True if the commit of new_name is expected to
951
            record a new version.
952
        :param delta_against_basis: True of the commit of new_name is expected
953
            to have a delta against the basis.
4183.5.4 by Robert Collins
Turn record_iter_changes into a generator to emit file system hashes.
954
        :param expect_fs_hash: If true, looks for a fs hash output from
955
            record_iter_changes.
3775.2.11 by Robert Collins
CommitBuilder handles renamed directory and unmodified entries with single parents, for record_iter_changes.
956
        """
957
        tree.lock_write()
958
        try:
959
            # mini manual commit here so we can check the return of
960
            # record_entry_contents.
961
            parent_ids = tree.get_parent_ids()
962
            builder = tree.branch.get_commit_builder(parent_ids)
6437.12.1 by Jelmer Vernooij
Use CommitBuilder.get_basis_delta rather than private CommitBuilder._basis_delta.
963
            builder.will_record_deletes()
3775.2.11 by Robert Collins
CommitBuilder handles renamed directory and unmodified entries with single parents, for record_iter_changes.
964
            parent_tree = tree.basis_tree()
965
            parent_tree.lock_read()
966
            self.addCleanup(parent_tree.unlock)
5856.1.2 by Jelmer Vernooij
Delay accessing inventory in tests until necessary.
967
            parent_trees = [parent_tree]
3775.2.11 by Robert Collins
CommitBuilder handles renamed directory and unmodified entries with single parents, for record_iter_changes.
968
            for parent_id in parent_ids[1:]:
5856.1.2 by Jelmer Vernooij
Delay accessing inventory in tests until necessary.
969
                parent_trees.append(tree.branch.repository.revision_tree(
970
                    parent_id))
3775.2.11 by Robert Collins
CommitBuilder handles renamed directory and unmodified entries with single parents, for record_iter_changes.
971
            changes = list(tree.iter_changes(parent_tree))
4183.5.4 by Robert Collins
Turn record_iter_changes into a generator to emit file system hashes.
972
            result = list(builder.record_iter_changes(tree, parent_ids[0],
973
                changes))
974
            file_id = tree.path2id(new_name)
975
            if expect_fs_hash:
976
                tree_file_stat = tree.get_file_with_stat(file_id)
977
                tree_file_stat[0].close()
978
                self.assertLength(1, result)
979
                result = result[0]
980
                self.assertEqual(result[:2], (file_id, new_name))
981
                self.assertEqual(result[2][0], tree.get_file_sha1(file_id))
982
                self.assertEqualStat(result[2][1], tree_file_stat[1])
983
            else:
984
                self.assertEqual([], result)
4789.27.2 by John Arbash Meinel
Add some tests that the record-iter-changes is setting inv_sha1 correctly.
985
            self.assertIs(None, builder.new_inventory)
3775.2.11 by Robert Collins
CommitBuilder handles renamed directory and unmodified entries with single parents, for record_iter_changes.
986
            builder.finish_inventory()
5718.4.4 by Jelmer Vernooij
Only check .inventories if present.
987
            if tree.branch.repository._format.supports_full_versioned_files:
988
                inv_key = (builder._new_revision_id,)
989
                inv_sha1 = tree.branch.repository.inventories.get_sha1s(
990
                                [inv_key])[inv_key]
991
                self.assertEqual(inv_sha1, builder.inv_sha1)
4789.27.4 by John Arbash Meinel
Robert says that self.new_inventory shouldn't be set.
992
            self.assertIs(None, builder.new_inventory)
6362.5.5 by Jelmer Vernooij
Don't access revision tree before commit.
993
            rev2 = builder.commit('')
6437.12.1 by Jelmer Vernooij
Use CommitBuilder.get_basis_delta rather than private CommitBuilder._basis_delta.
994
            delta = builder.get_basis_delta()
995
            delta_dict = dict((change[2], change) for change in delta)
996
            version_recorded = (file_id in delta_dict and
997
                delta_dict[file_id][3] is not None and
998
                delta_dict[file_id][3].revision == rev2)
999
            if records_version:
1000
                self.assertTrue(version_recorded)
1001
            else:
1002
                self.assertFalse(version_recorded)
1003
6405.2.6 by Jelmer Vernooij
Lots of test fixes.
1004
            new_inventory = builder.revision_tree().root_inventory
3775.2.11 by Robert Collins
CommitBuilder handles renamed directory and unmodified entries with single parents, for record_iter_changes.
1005
            new_entry = new_inventory[file_id]
1006
            if delta_against_basis:
1007
                expected_delta = (name, new_name, file_id, new_entry)
1008
                self.assertEqual(expected_delta, delta_dict[file_id])
1009
            else:
1010
                expected_delta = None
1011
                self.assertFalse(version_recorded)
1012
            tree.set_parent_ids([rev2])
1013
        except:
1014
            builder.abort()
1015
            tree.unlock()
1016
            raise
1017
        else:
1018
            tree.unlock()
1019
        return rev2
1020
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1021
    def assertFileGraph(self, expected_graph, tree, tip):
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1022
        # all the changes that have occured should be in the ancestry
1023
        # (closest to a public per-file graph API we have today)
1024
        tree.lock_read()
1025
        self.addCleanup(tree.unlock)
5815.5.9 by Jelmer Vernooij
Remove dependencies on texts.
1026
        g = dict(tree.branch.repository.get_file_graph().iter_ancestry([tip]))
5010.2.24 by Vincent Ladeuil
Fix imports in per_repository/test_commit_builder.py.
1027
        self.assertEqual(expected_graph, g)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1028
1029
    def test_last_modified_revision_after_content_file_changes(self):
1030
        # altering a file changes the last modified.
1031
        tree = self.make_branch_and_tree('.')
1032
        self.build_tree(['file'])
1033
        def change_file():
1034
            tree.put_file_bytes_non_atomic('fileid', 'new content')
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
1035
        self._add_commit_change_check_changed(tree, 'file', change_file,
1036
            expect_fs_hash=True)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1037
3775.2.17 by Robert Collins
CommitBuilder.record_iter_changes handles changed files.
1038
    def test_last_modified_revision_after_content_file_changes_ric(self):
1039
        # altering a file changes the last modified.
1040
        tree = self.make_branch_and_tree('.')
1041
        self.build_tree(['file'])
1042
        def change_file():
1043
            tree.put_file_bytes_non_atomic('fileid', 'new content')
1044
        self._add_commit_change_check_changed(tree, 'file', change_file,
1045
            expect_fs_hash=True,
1046
            mini_commit=self.mini_commit_record_iter_changes)
1047
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1048
    def test_last_modified_revision_after_content_link_changes(self):
1049
        # changing a link changes the last modified.
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
1050
        self.requireFeature(features.SymlinkFeature)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1051
        tree = self.make_branch_and_tree('.')
1052
        os.symlink('target', 'link')
1053
        def change_link():
1054
            os.unlink('link')
1055
            os.symlink('newtarget', 'link')
1056
        self._add_commit_change_check_changed(tree, 'link', change_link)
1057
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
1058
    def _test_last_mod_rev_after_content_link_changes_ric(
1059
        self, link, target, newtarget, file_id=None):
1060
        if file_id is None:
1061
            file_id = link
3775.2.18 by Robert Collins
CommitBuilder.record_iter_changes handles changed symlinks.
1062
        # changing a link changes the last modified.
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
1063
        self.requireFeature(features.SymlinkFeature)
3775.2.18 by Robert Collins
CommitBuilder.record_iter_changes handles changed symlinks.
1064
        tree = self.make_branch_and_tree('.')
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
1065
        os.symlink(target, link)
3775.2.18 by Robert Collins
CommitBuilder.record_iter_changes handles changed symlinks.
1066
        def change_link():
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
1067
            os.unlink(link)
1068
            os.symlink(newtarget, link)
1069
        self._add_commit_change_check_changed(
1070
            tree, link, change_link,
1071
            mini_commit=self.mini_commit_record_iter_changes,
1072
            file_id=file_id)
1073
1074
    def test_last_modified_rev_after_content_link_changes_ric(self):
1075
        self._test_last_mod_rev_after_content_link_changes_ric(
1076
            'link', 'target', 'newtarget')
1077
1078
    def test_last_modified_rev_after_content_unicode_link_changes_ric(self):
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
1079
        self.requireFeature(features.UnicodeFilenameFeature)
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
1080
        self._test_last_mod_rev_after_content_link_changes_ric(
1081
            u'li\u1234nk', u'targ\N{Euro Sign}t', u'n\N{Euro Sign}wtarget',
1082
1083
            file_id=u'li\u1234nk'.encode('UTF-8'))
3775.2.18 by Robert Collins
CommitBuilder.record_iter_changes handles changed symlinks.
1084
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1085
    def _commit_sprout(self, tree, name):
1086
        tree.add([name], [name + 'id'])
1087
        rev_id = tree.commit('')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
1088
        return rev_id, tree.controldir.sprout('t2').open_workingtree()
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1089
1090
    def _rename_in_tree(self, tree, name):
1091
        tree.rename_one(name, 'new_' + name)
1092
        return tree.commit('')
1093
3775.2.19 by Robert Collins
CommitBuilder.record_iter_changes handles merged directories.
1094
    def _commit_sprout_rename_merge(self, tree1, name, expect_fs_hash=False,
1095
        mini_commit=None):
3775.2.33 by Robert Collins
Fix bug with merges of new files, increasing test coverage to ensure its kept fixed.
1096
        """Do a rename in both trees."""
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1097
        rev1, tree2 = self._commit_sprout(tree1, name)
1098
        # change both sides equally
1099
        rev2 = self._rename_in_tree(tree1, name)
1100
        rev3 = self._rename_in_tree(tree2, name)
1101
        tree1.merge_from_branch(tree2.branch)
3775.2.19 by Robert Collins
CommitBuilder.record_iter_changes handles merged directories.
1102
        if mini_commit is None:
1103
            mini_commit = self.mini_commit
1104
        rev4 = mini_commit(tree1, 'new_' + name, 'new_' + name,
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
1105
            expect_fs_hash=expect_fs_hash)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1106
        tree3, = self._get_revtrees(tree1, [rev4])
5793.2.3 by Jelmer Vernooij
Add a RevisionTree.get_file_revision() method.
1107
        self.assertEqual(rev4, tree3.get_file_revision(name + 'id'))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1108
        file_id = name + 'id'
1109
        expected_graph = {}
1110
        expected_graph[(file_id, rev1)] = ()
1111
        expected_graph[(file_id, rev2)] = ((file_id, rev1),)
1112
        expected_graph[(file_id, rev3)] = ((file_id, rev1),)
1113
        expected_graph[(file_id, rev4)] = ((file_id, rev2), (file_id, rev3),)
1114
        self.assertFileGraph(expected_graph, tree1, (file_id, rev4))
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1115
1116
    def test_last_modified_revision_after_merge_dir_changes(self):
1117
        # merge a dir changes the last modified.
1118
        tree1 = self.make_branch_and_tree('t1')
1119
        self.build_tree(['t1/dir/'])
1120
        self._commit_sprout_rename_merge(tree1, 'dir')
1121
3775.2.19 by Robert Collins
CommitBuilder.record_iter_changes handles merged directories.
1122
    def test_last_modified_revision_after_merge_dir_changes_ric(self):
1123
        # merge a dir changes the last modified.
1124
        tree1 = self.make_branch_and_tree('t1')
1125
        self.build_tree(['t1/dir/'])
1126
        self._commit_sprout_rename_merge(tree1, 'dir',
1127
            mini_commit=self.mini_commit_record_iter_changes)
1128
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1129
    def test_last_modified_revision_after_merge_file_changes(self):
1130
        # merge a file changes the last modified.
1131
        tree1 = self.make_branch_and_tree('t1')
1132
        self.build_tree(['t1/file'])
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
1133
        self._commit_sprout_rename_merge(tree1, 'file', expect_fs_hash=True)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1134
3775.2.20 by Robert Collins
CommitBuilder.record_iter_changes handles merged files.
1135
    def test_last_modified_revision_after_merge_file_changes_ric(self):
1136
        # merge a file changes the last modified.
1137
        tree1 = self.make_branch_and_tree('t1')
1138
        self.build_tree(['t1/file'])
1139
        self._commit_sprout_rename_merge(tree1, 'file', expect_fs_hash=True,
1140
            mini_commit=self.mini_commit_record_iter_changes)
1141
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1142
    def test_last_modified_revision_after_merge_link_changes(self):
1143
        # merge a link changes the last modified.
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
1144
        self.requireFeature(features.SymlinkFeature)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1145
        tree1 = self.make_branch_and_tree('t1')
1146
        os.symlink('target', 't1/link')
1147
        self._commit_sprout_rename_merge(tree1, 'link')
1148
3775.2.21 by Robert Collins
CommitBuilder.record_iter_changes handles merged symlinks.
1149
    def test_last_modified_revision_after_merge_link_changes_ric(self):
1150
        # merge a link changes the last modified.
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
1151
        self.requireFeature(features.SymlinkFeature)
3775.2.21 by Robert Collins
CommitBuilder.record_iter_changes handles merged symlinks.
1152
        tree1 = self.make_branch_and_tree('t1')
1153
        os.symlink('target', 't1/link')
1154
        self._commit_sprout_rename_merge(tree1, 'link',
1155
            mini_commit=self.mini_commit_record_iter_changes)
1156
3775.2.22 by Robert Collins
CommitBuilder.record_iter_changes handles changed-in-branch directories.
1157
    def _commit_sprout_rename_merge_converged(self, tree1, name,
1158
        mini_commit=None):
1159
        # Make a merge which just incorporates a change from a branch:
1160
        # The per-file graph is straight line, and no alteration occurs
1161
        # in the inventory.
4183.5.9 by Robert Collins
Fix creating new revisions of files when merging.
1162
        # Part 1: change in the merged branch.
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1163
        rev1, tree2 = self._commit_sprout(tree1, name)
1164
        # change on the other side to merge back
1165
        rev2 = self._rename_in_tree(tree2, name)
1166
        tree1.merge_from_branch(tree2.branch)
3775.2.22 by Robert Collins
CommitBuilder.record_iter_changes handles changed-in-branch directories.
1167
        if mini_commit is None:
1168
            mini_commit = self.mini_commit
4183.5.9 by Robert Collins
Fix creating new revisions of files when merging.
1169
        def _check_graph(in_tree, changed_in_tree):
1170
            rev3 = mini_commit(in_tree, name, 'new_' + name, False,
1171
                delta_against_basis=changed_in_tree)
1172
            tree3, = self._get_revtrees(in_tree, [rev2])
5793.2.3 by Jelmer Vernooij
Add a RevisionTree.get_file_revision() method.
1173
            self.assertEqual(rev2, tree3.get_file_revision(name + 'id'))
4183.5.9 by Robert Collins
Fix creating new revisions of files when merging.
1174
            file_id = name + 'id'
1175
            expected_graph = {}
1176
            expected_graph[(file_id, rev1)] = ()
1177
            expected_graph[(file_id, rev2)] = ((file_id, rev1),)
1178
            self.assertFileGraph(expected_graph, in_tree, (file_id, rev2))
1179
        _check_graph(tree1, True)
1180
        # Part 2: change in the merged into branch - we use tree2 that has a
1181
        # change to name, branch tree1 and give it an unrelated change, then
1182
        # merge that to t2.
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
1183
        other_tree = tree1.controldir.sprout('t3').open_workingtree()
4183.5.9 by Robert Collins
Fix creating new revisions of files when merging.
1184
        other_rev = other_tree.commit('')
1185
        tree2.merge_from_branch(other_tree.branch)
1186
        _check_graph(tree2, False)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1187
3775.2.33 by Robert Collins
Fix bug with merges of new files, increasing test coverage to ensure its kept fixed.
1188
    def _commit_sprout_make_merge(self, tree1, make, mini_commit=None):
1189
        # Make a merge which incorporates the addition of a new object to
1190
        # another branch. The per-file graph shows no additional change
1191
        # in the merge because its a straight line.
1192
        rev1 = tree1.commit('')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
1193
        tree2 = tree1.controldir.sprout('t2').open_workingtree()
3775.2.33 by Robert Collins
Fix bug with merges of new files, increasing test coverage to ensure its kept fixed.
1194
        # make and commit on the other side to merge back
1195
        make('t2/name')
1196
        file_id = 'nameid'
1197
        tree2.add(['name'], [file_id])
1198
        rev2 = tree2.commit('')
1199
        tree1.merge_from_branch(tree2.branch)
1200
        if mini_commit is None:
1201
            mini_commit = self.mini_commit
1202
        rev3 = mini_commit(tree1, None, 'name', False)
1203
        tree3, = self._get_revtrees(tree1, [rev2])
1204
        # in rev2, name should be only changed in rev2
5793.2.3 by Jelmer Vernooij
Add a RevisionTree.get_file_revision() method.
1205
        self.assertEqual(rev2, tree3.get_file_revision(file_id))
3775.2.33 by Robert Collins
Fix bug with merges of new files, increasing test coverage to ensure its kept fixed.
1206
        expected_graph = {}
1207
        expected_graph[(file_id, rev2)] = ()
1208
        self.assertFileGraph(expected_graph, tree1, (file_id, rev2))
1209
1210
    def test_last_modified_revision_after_converged_merge_dir_unchanged(self):
1211
        # merge a dir that changed preserves the last modified.
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1212
        tree1 = self.make_branch_and_tree('t1')
1213
        self.build_tree(['t1/dir/'])
1214
        self._commit_sprout_rename_merge_converged(tree1, 'dir')
1215
3775.2.33 by Robert Collins
Fix bug with merges of new files, increasing test coverage to ensure its kept fixed.
1216
    def test_last_modified_revision_after_converged_merge_dir_unchanged_ric(self):
1217
        # merge a dir that changed preserves the last modified.
3775.2.22 by Robert Collins
CommitBuilder.record_iter_changes handles changed-in-branch directories.
1218
        tree1 = self.make_branch_and_tree('t1')
1219
        self.build_tree(['t1/dir/'])
1220
        self._commit_sprout_rename_merge_converged(tree1, 'dir',
1221
            mini_commit=self.mini_commit_record_iter_changes)
1222
3775.2.33 by Robert Collins
Fix bug with merges of new files, increasing test coverage to ensure its kept fixed.
1223
    def test_last_modified_revision_after_converged_merge_file_unchanged(self):
1224
        # merge a file that changed preserves the last modified.
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1225
        tree1 = self.make_branch_and_tree('t1')
1226
        self.build_tree(['t1/file'])
1227
        self._commit_sprout_rename_merge_converged(tree1, 'file')
1228
3775.2.33 by Robert Collins
Fix bug with merges of new files, increasing test coverage to ensure its kept fixed.
1229
    def test_last_modified_revision_after_converged_merge_file_unchanged_ric(self):
1230
        # merge a file that changed preserves the last modified.
3775.2.23 by Robert Collins
CommitBuilder.record_iter_changes handles changed-in-branch files.
1231
        tree1 = self.make_branch_and_tree('t1')
1232
        self.build_tree(['t1/file'])
1233
        self._commit_sprout_rename_merge_converged(tree1, 'file',
1234
            mini_commit=self.mini_commit_record_iter_changes)
1235
3775.2.33 by Robert Collins
Fix bug with merges of new files, increasing test coverage to ensure its kept fixed.
1236
    def test_last_modified_revision_after_converged_merge_link_unchanged(self):
1237
        # merge a link that changed preserves the last modified.
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
1238
        self.requireFeature(features.SymlinkFeature)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1239
        tree1 = self.make_branch_and_tree('t1')
1240
        os.symlink('target', 't1/link')
1241
        self._commit_sprout_rename_merge_converged(tree1, 'link')
1242
3775.2.33 by Robert Collins
Fix bug with merges of new files, increasing test coverage to ensure its kept fixed.
1243
    def test_last_modified_revision_after_converged_merge_link_unchanged_ric(self):
1244
        # merge a link that changed preserves the last modified.
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
1245
        self.requireFeature(features.SymlinkFeature)
3775.2.24 by Robert Collins
CommitBuilder.record_iter_changes handles changed-in-branch symlinks.
1246
        tree1 = self.make_branch_and_tree('t1')
1247
        os.symlink('target', 't1/link')
1248
        self._commit_sprout_rename_merge_converged(tree1, 'link',
1249
            mini_commit=self.mini_commit_record_iter_changes)
1250
3775.2.33 by Robert Collins
Fix bug with merges of new files, increasing test coverage to ensure its kept fixed.
1251
    def test_last_modified_revision_after_merge_new_dir_unchanged(self):
1252
        # merge a new dir does not change the last modified.
1253
        tree1 = self.make_branch_and_tree('t1')
1254
        self._commit_sprout_make_merge(tree1, self.make_dir)
1255
1256
    def test_last_modified_revision_after_merge_new_dir_unchanged_ric(self):
1257
        # merge a new dir does not change the last modified.
1258
        tree1 = self.make_branch_and_tree('t1')
1259
        self._commit_sprout_make_merge(tree1, self.make_dir,
1260
            mini_commit=self.mini_commit_record_iter_changes)
1261
1262
    def test_last_modified_revision_after_merge_new_file_unchanged(self):
1263
        # merge a new file does not change the last modified.
1264
        tree1 = self.make_branch_and_tree('t1')
1265
        self._commit_sprout_make_merge(tree1, self.make_file)
1266
1267
    def test_last_modified_revision_after_merge_new_file_unchanged_ric(self):
1268
        # merge a new file does not change the last modified.
1269
        tree1 = self.make_branch_and_tree('t1')
1270
        self._commit_sprout_make_merge(tree1, self.make_file,
1271
            mini_commit=self.mini_commit_record_iter_changes)
1272
1273
    def test_last_modified_revision_after_merge_new_link_unchanged(self):
1274
        # merge a new link does not change the last modified.
1275
        tree1 = self.make_branch_and_tree('t1')
1276
        self._commit_sprout_make_merge(tree1, self.make_link)
1277
1278
    def test_last_modified_revision_after_merge_new_link_unchanged_ric(self):
1279
        # merge a new link does not change the last modified.
1280
        tree1 = self.make_branch_and_tree('t1')
1281
        self._commit_sprout_make_merge(tree1, self.make_link,
1282
            mini_commit=self.mini_commit_record_iter_changes)
1283
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1284
    def make_dir(self, name):
1285
        self.build_tree([name + '/'])
1286
1287
    def make_file(self, name):
1288
        self.build_tree([name])
1289
1290
    def make_link(self, name):
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
1291
        self.requireFeature(features.SymlinkFeature)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1292
        os.symlink('target', name)
1293
4183.5.2 by Robert Collins
Support tree-reference in record_iter_changes.
1294
    def make_reference(self, name):
1295
        tree = self.make_branch_and_tree(name, format='1.9-rich-root')
1296
        tree.commit('foo')
1297
        return tree
1298
3775.2.25 by Robert Collins
CommitBuilder.record_iter_changes handles directories becoming files and links.
1299
    def _check_kind_change(self, make_before, make_after, expect_fs_hash=False,
1300
        mini_commit=None):
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1301
        tree = self.make_branch_and_tree('.')
1302
        path = 'name'
1303
        make_before(path)
2831.5.2 by Vincent Ladeuil
Review feedback.
1304
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1305
        def change_kind():
6164.2.3 by Jelmer Vernooij
Use rmtree, since some vcses include control directories in every directory.
1306
            if osutils.file_kind(path) == "directory":
1307
                osutils.rmtree(path)
1308
            else:
1309
                osutils.delete_any(path)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1310
            make_after(path)
2831.5.2 by Vincent Ladeuil
Review feedback.
1311
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
1312
        self._add_commit_change_check_changed(tree, path, change_kind,
3775.2.25 by Robert Collins
CommitBuilder.record_iter_changes handles directories becoming files and links.
1313
            expect_fs_hash=expect_fs_hash, mini_commit=mini_commit)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1314
1315
    def test_last_modified_dir_file(self):
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
1316
        self._check_kind_change(self.make_dir, self.make_file,
1317
            expect_fs_hash=True)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1318
3775.2.25 by Robert Collins
CommitBuilder.record_iter_changes handles directories becoming files and links.
1319
    def test_last_modified_dir_file_ric(self):
6217.2.1 by Jelmer Vernooij
Allow tree implementations to not support kind changes.
1320
        try:
1321
            self._check_kind_change(self.make_dir, self.make_file,
1322
                expect_fs_hash=True,
1323
                mini_commit=self.mini_commit_record_iter_changes)
1324
        except errors.UnsupportedKindChange:
1325
            raise tests.TestSkipped(
1326
                "tree does not support changing entry kind from "
1327
                "directory to file")
3775.2.25 by Robert Collins
CommitBuilder.record_iter_changes handles directories becoming files and links.
1328
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1329
    def test_last_modified_dir_link(self):
1330
        self._check_kind_change(self.make_dir, self.make_link)
1331
3775.2.25 by Robert Collins
CommitBuilder.record_iter_changes handles directories becoming files and links.
1332
    def test_last_modified_dir_link_ric(self):
6217.2.1 by Jelmer Vernooij
Allow tree implementations to not support kind changes.
1333
        try:
1334
            self._check_kind_change(self.make_dir, self.make_link,
1335
                mini_commit=self.mini_commit_record_iter_changes)
1336
        except errors.UnsupportedKindChange:
1337
            raise tests.TestSkipped(
1338
                "tree does not support changing entry kind from "
1339
                "directory to link")
3775.2.25 by Robert Collins
CommitBuilder.record_iter_changes handles directories becoming files and links.
1340
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1341
    def test_last_modified_link_file(self):
3709.3.1 by Robert Collins
First cut - make it work - at updating the tree stat cache during commit.
1342
        self._check_kind_change(self.make_link, self.make_file,
1343
            expect_fs_hash=True)
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1344
3775.2.26 by Robert Collins
CommitBuilder.record_iter_changes handles links becomes directories and files.
1345
    def test_last_modified_link_file_ric(self):
1346
        self._check_kind_change(self.make_link, self.make_file,
1347
            expect_fs_hash=True,
1348
            mini_commit=self.mini_commit_record_iter_changes)
1349
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1350
    def test_last_modified_link_dir(self):
1351
        self._check_kind_change(self.make_link, self.make_dir)
1352
3775.2.26 by Robert Collins
CommitBuilder.record_iter_changes handles links becomes directories and files.
1353
    def test_last_modified_link_dir_ric(self):
1354
        self._check_kind_change(self.make_link, self.make_dir,
1355
            mini_commit=self.mini_commit_record_iter_changes)
1356
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1357
    def test_last_modified_file_dir(self):
1358
        self._check_kind_change(self.make_file, self.make_dir)
1359
3775.2.27 by Robert Collins
CommitBuilder.record_iter_changes handles files becoming directories and links.
1360
    def test_last_modified_file_dir_ric(self):
1361
        self._check_kind_change(self.make_file, self.make_dir,
1362
            mini_commit=self.mini_commit_record_iter_changes)
1363
2776.1.5 by Robert Collins
Add reasonably comprehensive tests for path last modified and per file graph behaviour.
1364
    def test_last_modified_file_link(self):
1365
        self._check_kind_change(self.make_file, self.make_link)
3831.1.1 by John Arbash Meinel
Before allowing commit to succeed, verify the texts will be 'safe'.
1366
3775.2.27 by Robert Collins
CommitBuilder.record_iter_changes handles files becoming directories and links.
1367
    def test_last_modified_file_link_ric(self):
1368
        self._check_kind_change(self.make_file, self.make_link,
1369
            mini_commit=self.mini_commit_record_iter_changes)
3775.2.28 by Robert Collins
Merge .dev.
1370
3831.1.1 by John Arbash Meinel
Before allowing commit to succeed, verify the texts will be 'safe'.
1371
    def test_get_commit_builder_with_invalid_revprops(self):
1372
        branch = self.make_branch('.')
1373
        branch.repository.lock_write()
1374
        self.addCleanup(branch.repository.unlock)
1375
        self.assertRaises(ValueError, branch.repository.get_commit_builder,
6351.3.3 by Jelmer Vernooij
Convert more stuff to use config stacks.
1376
            branch, [], branch.get_config_stack(),
3831.1.1 by John Arbash Meinel
Before allowing commit to succeed, verify the texts will be 'safe'.
1377
            revprops={'invalid': u'property\rwith\r\ninvalid chars'})
1378
1379
    def test_commit_builder_commit_with_invalid_message(self):
1380
        branch = self.make_branch('.')
1381
        branch.repository.lock_write()
1382
        self.addCleanup(branch.repository.unlock)
1383
        builder = branch.repository.get_commit_builder(branch, [],
6351.3.3 by Jelmer Vernooij
Convert more stuff to use config stacks.
1384
            branch.get_config_stack())
3831.1.1 by John Arbash Meinel
Before allowing commit to succeed, verify the texts will be 'safe'.
1385
        self.addCleanup(branch.repository.abort_write_group)
1386
        self.assertRaises(ValueError, builder.commit,
1387
            u'Invalid\r\ncommit message\r\n')
4595.4.2 by Robert Collins
Disable commit builders on stacked repositories.
1388
5485.4.2 by Martin
Move guard to CommitBuilder.__init__ and test to bt.per_repository
1389
    def test_non_ascii_str_committer_rejected(self):
1390
        """Ensure an error is raised on a non-ascii byte string committer"""
1391
        branch = self.make_branch('.')
1392
        branch.repository.lock_write()
1393
        self.addCleanup(branch.repository.unlock)
1394
        self.assertRaises(UnicodeDecodeError,
1395
            branch.repository.get_commit_builder,
6351.3.3 by Jelmer Vernooij
Convert more stuff to use config stacks.
1396
            branch, [], branch.get_config_stack(),
5485.4.2 by Martin
Move guard to CommitBuilder.__init__ and test to bt.per_repository
1397
            committer="Erik B\xe5gfors <erik@example.com>")
1398
4595.4.2 by Robert Collins
Disable commit builders on stacked repositories.
1399
    def test_stacked_repositories_reject_commit_builder(self):
1400
        # As per bug 375013, committing to stacked repositories is currently
5557.1.17 by John Arbash Meinel
Fix the test case that was checking we refused to create a commit_builder
1401
        # broken if we aren't in a chk repository. So old repositories with
1402
        # fallbacks refuse to hand out a commit builder.
4595.4.2 by Robert Collins
Disable commit builders on stacked repositories.
1403
        repo_basis = self.make_repository('basis')
1404
        branch = self.make_branch('local')
1405
        repo_local = branch.repository
1406
        try:
1407
            repo_local.add_fallback_repository(repo_basis)
1408
        except errors.UnstackableRepositoryFormat:
1409
            raise tests.TestNotApplicable("not a stackable format.")
5557.1.17 by John Arbash Meinel
Fix the test case that was checking we refused to create a commit_builder
1410
        self.addCleanup(repo_local.lock_write().unlock)
1411
        if not repo_local._format.supports_chks:
1412
            self.assertRaises(errors.BzrError, repo_local.get_commit_builder,
6351.3.3 by Jelmer Vernooij
Convert more stuff to use config stacks.
1413
                branch, [], branch.get_config_stack())
5557.1.17 by John Arbash Meinel
Fix the test case that was checking we refused to create a commit_builder
1414
        else:
1415
            builder = repo_local.get_commit_builder(branch, [],
6351.3.3 by Jelmer Vernooij
Convert more stuff to use config stacks.
1416
                                                    branch.get_config_stack())
5557.1.17 by John Arbash Meinel
Fix the test case that was checking we refused to create a commit_builder
1417
            builder.abort()
5050.18.1 by Aaron Bentley
CommitBuilder user committer, not username in revision-id.
1418
1419
    def test_committer_no_username(self):
1420
        # Ensure that when no username is available but a committer is
1421
        # supplied, commit works.
5570.3.9 by Vincent Ladeuil
More use cases for overrideEnv, _cleanEnvironment *may* contain too much variables now.
1422
        self.overrideEnv('EMAIL', None)
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
1423
        self.overrideEnv('BRZ_EMAIL', None)
5609.31.2 by mbp at sourcefrog
Also turn off whoami inference in per_repository tests
1424
        # Also, make sure that it's not inferred from mailname.
1425
        self.overrideAttr(config, '_auto_user_id',
1426
            lambda: (None, None))
5050.18.1 by Aaron Bentley
CommitBuilder user committer, not username in revision-id.
1427
        tree = self.make_branch_and_tree(".")
1428
        tree.lock_write()
1429
        try:
1430
            # Make sure no username is available.
1431
            self.assertRaises(errors.NoWhoami, tree.branch.get_commit_builder,
1432
                              [])
1433
            builder = tree.branch.get_commit_builder(
1434
                [], committer='me@example.com')
1435
            try:
1436
                list(builder.record_iter_changes(tree, tree.last_revision(),
1437
                    tree.iter_changes(tree.basis_tree())))
1438
                builder.finish_inventory()
1439
            except:
1440
                builder.abort()
1441
                raise
1442
            repo = tree.branch.repository
1443
            repo.commit_write_group()
1444
        finally:
1445
            tree.unlock()