/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2006 Canonical Ltd
1908.5.2 by Robert Collins
Create and test set_parent_trees.
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
1908.5.2 by Robert Collins
Create and test set_parent_trees.
16
1908.5.3 by Robert Collins
Rename the tree.set_parents tests to tree.parents - preparing to add related function tests. Also remove duplication within the tests by factoring out a helper assert.
17
"""Tests of the parent related functions of WorkingTrees."""
18
5809.4.1 by Jelmer Vernooij
Avoid .texts.add_lines, rather use Repository.get_commit_builder.
19
from cStringIO import StringIO
1908.5.2 by Robert Collins
Create and test set_parent_trees.
20
import os
21
2598.5.2 by Aaron Bentley
Got all tests passing with Branch returning 'null:' for null revision
22
from bzrlib import (
23
    errors,
24
    revision as _mod_revision,
25
    )
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
26
from bzrlib.inventory import (
27
    Inventory,
28
    InventoryFile,
29
    InventoryDirectory,
30
    InventoryLink,
31
    )
5809.4.1 by Jelmer Vernooij
Avoid .texts.add_lines, rather use Repository.get_commit_builder.
32
from bzrlib.revisiontree import InventoryRevisionTree
4523.1.4 by Martin Pool
Rename remaining *_implementations tests
33
from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
34
from bzrlib.tests import (
35
    features,
36
    )
1908.5.2 by Robert Collins
Create and test set_parent_trees.
37
from bzrlib.uncommit import uncommit
38
39
1908.5.3 by Robert Collins
Rename the tree.set_parents tests to tree.parents - preparing to add related function tests. Also remove duplication within the tests by factoring out a helper assert.
40
class TestParents(TestCaseWithWorkingTree):
41
42
    def assertConsistentParents(self, expected, tree):
1908.7.6 by Robert Collins
Deprecate WorkingTree.last_revision.
43
        """Check that the parents found are as expected.
44
45
        This test helper also checks that they are consistent with
46
        the pre-get_parent_ids() api - which is now deprecated.
47
        """
1908.5.3 by Robert Collins
Rename the tree.set_parents tests to tree.parents - preparing to add related function tests. Also remove duplication within the tests by factoring out a helper assert.
48
        self.assertEqual(expected, tree.get_parent_ids())
49
        if expected == []:
2598.5.7 by Aaron Bentley
Updates from review
50
            self.assertEqual(_mod_revision.NULL_REVISION,
51
                             _mod_revision.ensure_null(tree.last_revision()))
1908.5.3 by Robert Collins
Rename the tree.set_parents tests to tree.parents - preparing to add related function tests. Also remove duplication within the tests by factoring out a helper assert.
52
        else:
1908.7.11 by Robert Collins
Merge bzr.dev and undeprecated WorkingTree.last_revision as per review feedback.
53
            self.assertEqual(expected[0], tree.last_revision())
1908.5.3 by Robert Collins
Rename the tree.set_parents tests to tree.parents - preparing to add related function tests. Also remove duplication within the tests by factoring out a helper assert.
54
55
2598.5.2 by Aaron Bentley
Got all tests passing with Branch returning 'null:' for null revision
56
class TestGetParents(TestParents):
57
58
    def test_get_parents(self):
59
        t = self.make_branch_and_tree('.')
60
        self.assertEqual([], t.get_parent_ids())
61
62
1908.5.3 by Robert Collins
Rename the tree.set_parents tests to tree.parents - preparing to add related function tests. Also remove duplication within the tests by factoring out a helper assert.
63
class TestSetParents(TestParents):
1908.5.2 by Robert Collins
Create and test set_parent_trees.
64
65
    def test_set_no_parents(self):
66
        t = self.make_branch_and_tree('.')
67
        t.set_parent_trees([])
68
        self.assertEqual([], t.get_parent_ids())
69
        # now give it a real parent, and then set it to no parents again.
70
        t.commit('first post')
71
        t.set_parent_trees([])
1908.5.3 by Robert Collins
Rename the tree.set_parents tests to tree.parents - preparing to add related function tests. Also remove duplication within the tests by factoring out a helper assert.
72
        self.assertConsistentParents([], t)
1908.5.2 by Robert Collins
Create and test set_parent_trees.
73
2598.5.2 by Aaron Bentley
Got all tests passing with Branch returning 'null:' for null revision
74
    def test_set_null_parent(self):
75
        t = self.make_branch_and_tree('.')
76
        self.assertRaises(errors.ReservedId, t.set_parent_ids, ['null:'],
77
                          allow_leftmost_as_ghost=True)
78
        self.assertRaises(errors.ReservedId, t.set_parent_trees,
79
                          [('null:', None)], allow_leftmost_as_ghost=True)
80
1908.5.9 by Robert Collins
Add a guard against setting the tree last-revision value to a ghost in the new tree parent management api.
81
    def test_set_one_ghost_parent_rejects(self):
82
        t = self.make_branch_and_tree('.')
1908.5.12 by Robert Collins
Apply review feedback - paired with Martin.
83
        self.assertRaises(errors.GhostRevisionUnusableHere,
1908.5.9 by Robert Collins
Add a guard against setting the tree last-revision value to a ghost in the new tree parent management api.
84
            t.set_parent_trees, [('missing-revision-id', None)])
85
86
    def test_set_one_ghost_parent_force(self):
87
        t = self.make_branch_and_tree('.')
88
        t.set_parent_trees([('missing-revision-id', None)],
89
            allow_leftmost_as_ghost=True)
1908.5.3 by Robert Collins
Rename the tree.set_parents tests to tree.parents - preparing to add related function tests. Also remove duplication within the tests by factoring out a helper assert.
90
        self.assertConsistentParents(['missing-revision-id'], t)
1908.5.2 by Robert Collins
Create and test set_parent_trees.
91
92
    def test_set_two_parents_one_ghost(self):
93
        t = self.make_branch_and_tree('.')
94
        revision_in_repo = t.commit('first post')
95
        # remove the tree's history
96
        uncommit(t.branch, tree=t)
97
        rev_tree = t.branch.repository.revision_tree(revision_in_repo)
98
        t.set_parent_trees([(revision_in_repo, rev_tree),
99
            ('another-missing', None)])
1908.5.3 by Robert Collins
Rename the tree.set_parents tests to tree.parents - preparing to add related function tests. Also remove duplication within the tests by factoring out a helper assert.
100
        self.assertConsistentParents([revision_in_repo, 'another-missing'], t)
1908.5.2 by Robert Collins
Create and test set_parent_trees.
101
102
    def test_set_three_parents(self):
103
        t = self.make_branch_and_tree('.')
104
        first_revision = t.commit('first post')
105
        uncommit(t.branch, tree=t)
106
        second_revision = t.commit('second post')
107
        uncommit(t.branch, tree=t)
108
        third_revision = t.commit('third post')
109
        uncommit(t.branch, tree=t)
110
        rev_tree1 = t.branch.repository.revision_tree(first_revision)
111
        rev_tree2 = t.branch.repository.revision_tree(second_revision)
112
        rev_tree3 = t.branch.repository.revision_tree(third_revision)
113
        t.set_parent_trees([(first_revision, rev_tree1),
114
            (second_revision, rev_tree2),
115
            (third_revision, rev_tree3)])
1908.5.3 by Robert Collins
Rename the tree.set_parents tests to tree.parents - preparing to add related function tests. Also remove duplication within the tests by factoring out a helper assert.
116
        self.assertConsistentParents(
117
            [first_revision, second_revision, third_revision], t)
1908.5.4 by Robert Collins
Add add_parent_tree_id WorkingTree helper api.
118
1908.5.5 by Robert Collins
Add WorkingTree.set_parent_ids.
119
    def test_set_no_parents_ids(self):
120
        t = self.make_branch_and_tree('.')
121
        t.set_parent_ids([])
122
        self.assertEqual([], t.get_parent_ids())
123
        # now give it a real parent, and then set it to no parents again.
124
        t.commit('first post')
125
        t.set_parent_ids([])
126
        self.assertConsistentParents([], t)
127
1908.5.9 by Robert Collins
Add a guard against setting the tree last-revision value to a ghost in the new tree parent management api.
128
    def test_set_one_ghost_parent_ids_rejects(self):
129
        t = self.make_branch_and_tree('.')
1908.5.12 by Robert Collins
Apply review feedback - paired with Martin.
130
        self.assertRaises(errors.GhostRevisionUnusableHere,
1908.5.9 by Robert Collins
Add a guard against setting the tree last-revision value to a ghost in the new tree parent management api.
131
            t.set_parent_ids, ['missing-revision-id'])
132
133
    def test_set_one_ghost_parent_ids_force(self):
134
        t = self.make_branch_and_tree('.')
135
        t.set_parent_ids(['missing-revision-id'],
136
            allow_leftmost_as_ghost=True)
1908.5.5 by Robert Collins
Add WorkingTree.set_parent_ids.
137
        self.assertConsistentParents(['missing-revision-id'], t)
138
139
    def test_set_two_parents_one_ghost_ids(self):
140
        t = self.make_branch_and_tree('.')
141
        revision_in_repo = t.commit('first post')
142
        # remove the tree's history
143
        uncommit(t.branch, tree=t)
144
        rev_tree = t.branch.repository.revision_tree(revision_in_repo)
145
        t.set_parent_ids([revision_in_repo, 'another-missing'])
146
        self.assertConsistentParents([revision_in_repo, 'another-missing'], t)
147
148
    def test_set_three_parents_ids(self):
149
        t = self.make_branch_and_tree('.')
150
        first_revision = t.commit('first post')
151
        uncommit(t.branch, tree=t)
152
        second_revision = t.commit('second post')
153
        uncommit(t.branch, tree=t)
154
        third_revision = t.commit('third post')
155
        uncommit(t.branch, tree=t)
156
        rev_tree1 = t.branch.repository.revision_tree(first_revision)
157
        rev_tree2 = t.branch.repository.revision_tree(second_revision)
158
        rev_tree3 = t.branch.repository.revision_tree(third_revision)
159
        t.set_parent_ids([first_revision, second_revision, third_revision])
160
        self.assertConsistentParents(
161
            [first_revision, second_revision, third_revision], t)
162
3462.1.2 by John Arbash Meinel
Change WT.set_parent_(ids/trees) to filter out ancestors.
163
    def test_set_duplicate_parent_ids(self):
164
        t = self.make_branch_and_tree('.')
165
        rev1 = t.commit('first post')
166
        uncommit(t.branch, tree=t)
167
        rev2 = t.commit('second post')
168
        uncommit(t.branch, tree=t)
169
        rev3 = t.commit('third post')
170
        uncommit(t.branch, tree=t)
171
        t.set_parent_ids([rev1, rev2, rev2, rev3])
172
        # We strip the duplicate, but preserve the ordering
173
        self.assertConsistentParents([rev1, rev2, rev3], t)
174
175
    def test_set_duplicate_parent_trees(self):
176
        t = self.make_branch_and_tree('.')
177
        rev1 = t.commit('first post')
178
        uncommit(t.branch, tree=t)
179
        rev2 = t.commit('second post')
180
        uncommit(t.branch, tree=t)
181
        rev3 = t.commit('third post')
182
        uncommit(t.branch, tree=t)
183
        rev_tree1 = t.branch.repository.revision_tree(rev1)
184
        rev_tree2 = t.branch.repository.revision_tree(rev2)
185
        rev_tree3 = t.branch.repository.revision_tree(rev3)
186
        t.set_parent_trees([(rev1, rev_tree1), (rev2, rev_tree2),
187
                            (rev2, rev_tree2), (rev3, rev_tree3)])
188
        # We strip the duplicate, but preserve the ordering
189
        self.assertConsistentParents([rev1, rev2, rev3], t)
190
191
    def test_set_parent_ids_in_ancestry(self):
192
        t = self.make_branch_and_tree('.')
193
        rev1 = t.commit('first post')
194
        rev2 = t.commit('second post')
195
        rev3 = t.commit('third post')
196
        # Reset the tree, back to rev1
197
        t.set_parent_ids([rev1])
198
        t.branch.set_last_revision_info(1, rev1)
199
        self.assertConsistentParents([rev1], t)
200
        t.set_parent_ids([rev1, rev2, rev3])
201
        # rev2 is in the ancestry of rev3, so it will be filtered out
202
        self.assertConsistentParents([rev1, rev3], t)
203
        # Order should be preserved, and the first revision should always be
204
        # kept
205
        t.set_parent_ids([rev2, rev3, rev1])
206
        self.assertConsistentParents([rev2, rev3], t)
207
208
    def test_set_parent_trees_in_ancestry(self):
209
        t = self.make_branch_and_tree('.')
210
        rev1 = t.commit('first post')
211
        rev2 = t.commit('second post')
212
        rev3 = t.commit('third post')
213
        # Reset the tree, back to rev1
214
        t.set_parent_ids([rev1])
215
        t.branch.set_last_revision_info(1, rev1)
216
        self.assertConsistentParents([rev1], t)
217
        rev_tree1 = t.branch.repository.revision_tree(rev1)
218
        rev_tree2 = t.branch.repository.revision_tree(rev2)
219
        rev_tree3 = t.branch.repository.revision_tree(rev3)
220
        t.set_parent_trees([(rev1, rev_tree1), (rev2, rev_tree2),
221
                            (rev3, rev_tree3)])
222
        # rev2 is in the ancestry of rev3, so it will be filtered out
223
        self.assertConsistentParents([rev1, rev3], t)
224
        # Order should be preserved, and the first revision should always be
225
        # kept
226
        t.set_parent_trees([(rev2, rev_tree2), (rev1, rev_tree1),
227
                            (rev3, rev_tree3)])
228
        self.assertConsistentParents([rev2, rev3], t)
229
3763.9.7 by Daniel Clemente
Tested Unicode target rather than always trying to create it in UTF-8. Test renamed
230
    def test_unicode_symlink(self):
3763.9.1 by Daniel Clemente
New testcase for bug 272444 (support symlinks to non-ASCII files)
231
        # this tests bug #272444
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
232
        self.requireFeature(features.SymlinkFeature)
233
        self.requireFeature(features.UnicodeFilenameFeature)
3763.9.1 by Daniel Clemente
New testcase for bug 272444 (support symlinks to non-ASCII files)
234
3763.9.3 by Daniel Clemente
Clearer test with better names and just one parent
235
        tree = self.make_branch_and_tree('tree1')
3763.9.2 by Daniel Clemente
Adapted test to use set_parent_ids and raise KnownFailure
236
3763.9.9 by Daniel Clemente
Used a greek omega instead of an accented 'o' to avoid combining characters
237
        # The link points to a file whose name is an omega
238
        # U+03A9 GREEK CAPITAL LETTER OMEGA
239
        # UTF-8: ce a9  UTF-16BE: 03a9  Decimal: Ω
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
240
        target = u'\u03a9'
241
        link_name = u'\N{Euro Sign}link'
242
        os.symlink(target, 'tree1/' + link_name)
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
243
        tree.add([link_name], ['link-id'])
3763.9.2 by Daniel Clemente
Adapted test to use set_parent_ids and raise KnownFailure
244
4095.3.1 by Vincent Ladeuil
Fix #339055 and #277444 by handling non ascii symlink targets.
245
        revision1 = tree.commit('added a link to a Unicode target')
246
        revision2 = tree.commit('this revision will be discarded')
247
        tree.set_parent_ids([revision1])
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
248
        tree.lock_read()
249
        self.addCleanup(tree.unlock)
250
        # Check that the symlink target is safely round-tripped in the trees.
251
        self.assertEqual(target, tree.get_symlink_target('link-id'))
252
        basis = tree.basis_tree()
253
        self.assertEqual(target, basis.get_symlink_target('link-id'))
3763.9.1 by Daniel Clemente
New testcase for bug 272444 (support symlinks to non-ASCII files)
254
1908.5.4 by Robert Collins
Add add_parent_tree_id WorkingTree helper api.
255
1908.5.6 by Robert Collins
Add add_parent_tree to WorkingTree.
256
class TestAddParent(TestParents):
1908.5.4 by Robert Collins
Add add_parent_tree_id WorkingTree helper api.
257
258
    def test_add_first_parent_id(self):
259
        """Test adding the first parent id"""
260
        tree = self.make_branch_and_tree('.')
261
        first_revision = tree.commit('first post')
262
        uncommit(tree.branch, tree=tree)
263
        tree.add_parent_tree_id(first_revision)
264
        self.assertConsistentParents([first_revision], tree)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
265
1908.5.9 by Robert Collins
Add a guard against setting the tree last-revision value to a ghost in the new tree parent management api.
266
    def test_add_first_parent_id_ghost_rejects(self):
267
        """Test adding the first parent id - as a ghost"""
268
        tree = self.make_branch_and_tree('.')
1908.5.12 by Robert Collins
Apply review feedback - paired with Martin.
269
        self.assertRaises(errors.GhostRevisionUnusableHere,
1908.5.9 by Robert Collins
Add a guard against setting the tree last-revision value to a ghost in the new tree parent management api.
270
            tree.add_parent_tree_id, 'first-revision')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
271
1908.5.9 by Robert Collins
Add a guard against setting the tree last-revision value to a ghost in the new tree parent management api.
272
    def test_add_first_parent_id_ghost_force(self):
273
        """Test adding the first parent id - as a ghost"""
274
        tree = self.make_branch_and_tree('.')
275
        tree.add_parent_tree_id('first-revision', allow_leftmost_as_ghost=True)
1908.5.4 by Robert Collins
Add add_parent_tree_id WorkingTree helper api.
276
        self.assertConsistentParents(['first-revision'], tree)
1908.5.13 by Robert Collins
Adding a parent when the first is a ghost already should not require forcing it.
277
278
    def test_add_second_parent_id_with_ghost_first(self):
279
        """Test adding the second parent when the first is a ghost."""
280
        tree = self.make_branch_and_tree('.')
281
        tree.add_parent_tree_id('first-revision', allow_leftmost_as_ghost=True)
282
        tree.add_parent_tree_id('second')
283
        self.assertConsistentParents(['first-revision', 'second'], tree)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
284
1908.5.4 by Robert Collins
Add add_parent_tree_id WorkingTree helper api.
285
    def test_add_second_parent_id(self):
286
        """Test adding the second parent id"""
287
        tree = self.make_branch_and_tree('.')
288
        first_revision = tree.commit('first post')
289
        uncommit(tree.branch, tree=tree)
290
        second_revision = tree.commit('second post')
291
        tree.add_parent_tree_id(first_revision)
292
        self.assertConsistentParents([second_revision, first_revision], tree)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
293
1908.5.4 by Robert Collins
Add add_parent_tree_id WorkingTree helper api.
294
    def test_add_second_parent_id_ghost(self):
295
        """Test adding the second parent id - as a ghost"""
296
        tree = self.make_branch_and_tree('.')
297
        first_revision = tree.commit('first post')
298
        tree.add_parent_tree_id('second')
299
        self.assertConsistentParents([first_revision, 'second'], tree)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
300
1908.5.6 by Robert Collins
Add add_parent_tree to WorkingTree.
301
    def test_add_first_parent_tree(self):
302
        """Test adding the first parent id"""
303
        tree = self.make_branch_and_tree('.')
304
        first_revision = tree.commit('first post')
305
        uncommit(tree.branch, tree=tree)
306
        tree.add_parent_tree((first_revision,
307
            tree.branch.repository.revision_tree(first_revision)))
308
        self.assertConsistentParents([first_revision], tree)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
309
1908.5.9 by Robert Collins
Add a guard against setting the tree last-revision value to a ghost in the new tree parent management api.
310
    def test_add_first_parent_tree_ghost_rejects(self):
311
        """Test adding the first parent id - as a ghost"""
312
        tree = self.make_branch_and_tree('.')
1908.5.12 by Robert Collins
Apply review feedback - paired with Martin.
313
        self.assertRaises(errors.GhostRevisionUnusableHere,
1908.5.9 by Robert Collins
Add a guard against setting the tree last-revision value to a ghost in the new tree parent management api.
314
            tree.add_parent_tree, ('first-revision', None))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
315
1908.5.9 by Robert Collins
Add a guard against setting the tree last-revision value to a ghost in the new tree parent management api.
316
    def test_add_first_parent_tree_ghost_force(self):
317
        """Test adding the first parent id - as a ghost"""
318
        tree = self.make_branch_and_tree('.')
319
        tree.add_parent_tree(('first-revision', None),
320
            allow_leftmost_as_ghost=True)
1908.5.6 by Robert Collins
Add add_parent_tree to WorkingTree.
321
        self.assertConsistentParents(['first-revision'], tree)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
322
1908.5.6 by Robert Collins
Add add_parent_tree to WorkingTree.
323
    def test_add_second_parent_tree(self):
324
        """Test adding the second parent id"""
325
        tree = self.make_branch_and_tree('.')
326
        first_revision = tree.commit('first post')
327
        uncommit(tree.branch, tree=tree)
328
        second_revision = tree.commit('second post')
329
        tree.add_parent_tree((first_revision,
330
            tree.branch.repository.revision_tree(first_revision)))
331
        self.assertConsistentParents([second_revision, first_revision], tree)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
332
1908.5.6 by Robert Collins
Add add_parent_tree to WorkingTree.
333
    def test_add_second_parent_tree_ghost(self):
334
        """Test adding the second parent id - as a ghost"""
335
        tree = self.make_branch_and_tree('.')
336
        first_revision = tree.commit('first post')
337
        tree.add_parent_tree(('second', None))
338
        self.assertConsistentParents([first_revision, 'second'], tree)
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
339
340
3253.2.1 by John Arbash Meinel
Fix moving directories to root nodes.
341
class UpdateToOneParentViaDeltaTests(TestCaseWithWorkingTree):
2903.2.7 by Martin Pool
Rename update_to_one_parent_via_delta to more wieldy update_basis_by_delta
342
    """Tests for the update_basis_by_delta call.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
343
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
344
    This is intuitively defined as 'apply an inventory delta to the basis and
345
    discard other parents', but for trees that have an inventory that is not
346
    managed as a tree-by-id, the implementation requires roughly duplicated
347
    tests with those for apply_inventory_delta on the main tree.
348
    """
349
350
    def assertDeltaApplicationResultsInExpectedBasis(self, tree, revid, delta,
351
        expected_inventory):
2929.2.1 by Robert Collins
* Commit updates the state of the working tree via a delta rather than
352
        tree.lock_write()
353
        try:
354
            tree.update_basis_by_delta(revid, delta)
355
        finally:
356
            tree.unlock()
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
357
        # check the last revision was adjusted to rev_id
358
        self.assertEqual(revid, tree.last_revision())
359
        # check the parents are what we expect
360
        self.assertEqual([revid], tree.get_parent_ids())
361
        # check that the basis tree has the inventory we expect from applying
362
        # the delta.
363
        result_basis = tree.basis_tree()
364
        result_basis.lock_read()
3619.6.6 by Mark Hammond
eagerly unlock the result_basis to prevent handles staying open.
365
        try:
6405.2.9 by Jelmer Vernooij
More test fixes.
366
            self.assertEqual(expected_inventory, result_basis.root_inventory)
3619.6.6 by Mark Hammond
eagerly unlock the result_basis to prevent handles staying open.
367
        finally:
368
            result_basis.unlock()
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
369
370
    def make_inv_delta(self, old, new):
371
        """Make an inventory delta from two inventories."""
372
        old_ids = set(old._byid.iterkeys())
373
        new_ids = set(new._byid.iterkeys())
374
        adds = new_ids - old_ids
375
        deletes = old_ids - new_ids
376
        common = old_ids.intersection(new_ids)
377
        delta = []
378
        for file_id in deletes:
379
            delta.append((old.id2path(file_id), None, file_id, None))
380
        for file_id in adds:
381
            delta.append((None, new.id2path(file_id), file_id, new[file_id]))
382
        for file_id in common:
383
            if old[file_id] != new[file_id]:
384
                delta.append((old.id2path(file_id), new.id2path(file_id),
385
                    file_id, new[file_id]))
386
        return delta
387
388
    def fake_up_revision(self, tree, revid, shape):
5809.4.1 by Jelmer Vernooij
Avoid .texts.add_lines, rather use Repository.get_commit_builder.
389
390
        class ShapeTree(InventoryRevisionTree):
391
392
            def __init__(self, shape):
393
                self._repository = tree.branch.repository
394
                self._inventory = shape
395
396
            def get_file_text(self, file_id, path=None):
6405.2.10 by Jelmer Vernooij
Fix more tests.
397
                ie = self.root_inventory[file_id]
5809.4.1 by Jelmer Vernooij
Avoid .texts.add_lines, rather use Repository.get_commit_builder.
398
                if ie.kind != "file":
399
                    return ""
400
                return 'a' * ie.text_size
401
402
            def get_file(self, file_id, path=None):
403
                return StringIO(self.get_file_text(file_id))
404
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
405
        tree.lock_write()
406
        try:
5809.4.1 by Jelmer Vernooij
Avoid .texts.add_lines, rather use Repository.get_commit_builder.
407
            if shape.root.revision is None:
408
                shape.root.revision = revid
409
            builder = tree.branch.get_commit_builder(
410
                    parents=[],
411
                    timestamp=0,
412
                    timezone=None,
413
                    committer="Foo Bar <foo@example.com>",
414
                    revision_id=revid)
415
            shape_tree = ShapeTree(shape)
5809.4.3 by Jelmer Vernooij
Fix base revid.
416
            base_tree = tree.branch.repository.revision_tree(
417
                    _mod_revision.NULL_REVISION)
5809.4.1 by Jelmer Vernooij
Avoid .texts.add_lines, rather use Repository.get_commit_builder.
418
            changes = shape_tree.iter_changes(
5809.4.3 by Jelmer Vernooij
Fix base revid.
419
                base_tree)
5809.4.1 by Jelmer Vernooij
Avoid .texts.add_lines, rather use Repository.get_commit_builder.
420
            list(builder.record_iter_changes(shape_tree,
5809.4.3 by Jelmer Vernooij
Fix base revid.
421
                base_tree.get_revision_id(), changes))
5809.4.1 by Jelmer Vernooij
Avoid .texts.add_lines, rather use Repository.get_commit_builder.
422
            builder.finish_inventory()
423
            builder.commit("Message")
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
424
        finally:
425
            tree.unlock()
426
427
    def add_entry(self, inv, rev_id, entry):
428
        entry.revision = rev_id
429
        inv.add(entry)
430
431
    def add_dir(self, inv, rev_id, file_id, parent_id, name):
432
        new_dir = InventoryDirectory(file_id, name, parent_id)
433
        self.add_entry(inv, rev_id, new_dir)
434
435
    def add_file(self, inv, rev_id, file_id, parent_id, name, sha, size):
436
        new_file = InventoryFile(file_id, name, parent_id)
437
        new_file.text_sha1 = sha
438
        new_file.text_size = size
439
        self.add_entry(inv, rev_id, new_file)
440
441
    def add_link(self, inv, rev_id, file_id, parent_id, name, target):
442
        new_link = InventoryLink(file_id, name, parent_id)
443
        new_link.symlink_target = target
444
        self.add_entry(inv, rev_id, new_link)
445
446
    def add_new_root(self, new_shape, old_revid, new_revid):
447
        if self.bzrdir_format.repository_format.rich_root_data:
448
            self.add_dir(new_shape, old_revid, 'root-id', None, '')
449
        else:
450
            self.add_dir(new_shape, new_revid, 'root-id', None, '')
451
452
    def assertTransitionFromBasisToShape(self, basis_shape, basis_revid,
6015.45.2 by Brian de Alwis, John Arbash Meinel
Backport the fix for bug #855155 to bzr-2.4
453
        new_shape, new_revid, extra_parent=None, set_current_inventory=True):
2889.1.1 by Robert Collins
* The class ``bzrlib.repofmt.knitrepo.KnitRepository3`` has been folded into
454
        # set the inventory revision ids.
455
        basis_shape.revision_id = basis_revid
456
        new_shape.revision_id = new_revid
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
457
        delta = self.make_inv_delta(basis_shape, new_shape)
458
        tree = self.make_branch_and_tree('tree')
459
        # the shapes need to be in the tree's repository to be able to set them
460
        # as a parent, but the file content is not needed.
461
        if basis_revid is not None:
462
            self.fake_up_revision(tree, basis_revid, basis_shape)
463
            parents = [basis_revid]
464
            if extra_parent is not None:
465
                parents.append(extra_parent)
466
            tree.set_parent_ids(parents)
467
        self.fake_up_revision(tree, new_revid, new_shape)
6015.45.2 by Brian de Alwis, John Arbash Meinel
Backport the fix for bug #855155 to bzr-2.4
468
        if set_current_inventory:
469
            # give tree an inventory of new_shape
470
            tree._write_inventory(new_shape)
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
471
        self.assertDeltaApplicationResultsInExpectedBasis(tree, new_revid,
472
            delta, new_shape)
2929.2.2 by Robert Collins
Review feedback on dirstate update_basis_via_delta logic.
473
        # The tree should be internally consistent; while this is a moderately
474
        # large hammer, this is a particularly sensitive area of code, so the
475
        # extra assurance is well worth it.
476
        tree._validate()
6437.70.4 by John Arbash Meinel
Now that we have 2 possible locations where things exist, we must cleanup both.
477
        # If tree.branch is remote
6437.70.5 by John Arbash Meinel
user_url seems a cleaner way to do the same thing.
478
        if tree.user_url != tree.branch.user_url:
6437.70.4 by John Arbash Meinel
Now that we have 2 possible locations where things exist, we must cleanup both.
479
            # We have a lightweight checkout, delete both locations
480
            tree.branch.bzrdir.root_transport.delete_tree('.')
481
        tree.bzrdir.root_transport.delete_tree('.')
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
482
483
    def test_no_parents_just_root(self):
484
        """Test doing an empty commit - no parent, set a root only."""
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
485
        basis_shape = Inventory(root_id=None)  # empty tree
486
        new_shape = Inventory()  # tree with a root
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
487
        self.assertTransitionFromBasisToShape(basis_shape, None, new_shape,
488
            'new_parent')
489
490
    def test_no_parents_full_tree(self):
491
        """Test doing a regular initial commit with files and dirs."""
492
        basis_shape = Inventory(root_id=None) # empty tree
493
        revid = 'new-parent'
494
        new_shape = Inventory(root_id=None)
495
        self.add_dir(new_shape, revid, 'root-id', None, '')
496
        self.add_link(new_shape, revid, 'link-id', 'root-id', 'link', 'target')
497
        self.add_file(new_shape, revid, 'file-id', 'root-id', 'file', '1' * 32,
498
            12)
499
        self.add_dir(new_shape, revid, 'dir-id', 'root-id', 'dir')
500
        self.add_file(new_shape, revid, 'subfile-id', 'dir-id', 'subfile',
501
            '2' * 32, 24)
502
        self.assertTransitionFromBasisToShape(basis_shape, None, new_shape,
503
            revid)
504
505
    def test_file_content_change(self):
506
        old_revid = 'old-parent'
507
        basis_shape = Inventory(root_id=None)
508
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
509
        self.add_file(basis_shape, old_revid, 'file-id', 'root-id', 'file',
510
            '1' * 32, 12)
511
        new_revid = 'new-parent'
512
        new_shape = Inventory(root_id=None)
513
        self.add_new_root(new_shape, old_revid, new_revid)
514
        self.add_file(new_shape, new_revid, 'file-id', 'root-id', 'file',
515
            '2' * 32, 24)
516
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
517
            new_shape, new_revid)
518
519
    def test_link_content_change(self):
520
        old_revid = 'old-parent'
521
        basis_shape = Inventory(root_id=None)
522
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
523
        self.add_link(basis_shape, old_revid, 'link-id', 'root-id', 'link',
524
            'old-target')
525
        new_revid = 'new-parent'
526
        new_shape = Inventory(root_id=None)
527
        self.add_new_root(new_shape, old_revid, new_revid)
528
        self.add_link(new_shape, new_revid, 'link-id', 'root-id', 'link',
529
            'new-target')
530
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
531
            new_shape, new_revid)
532
533
    def test_kind_changes(self):
534
        def do_file(inv, revid):
535
            self.add_file(inv, revid, 'path-id', 'root-id', 'path', '1' * 32,
536
                12)
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
537
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
538
        def do_link(inv, revid):
539
            self.add_link(inv, revid, 'path-id', 'root-id', 'path', 'target')
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
540
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
541
        def do_dir(inv, revid):
542
            self.add_dir(inv, revid, 'path-id', 'root-id', 'path')
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
543
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
544
        for old_factory in (do_file, do_link, do_dir):
545
            for new_factory in (do_file, do_link, do_dir):
546
                if old_factory == new_factory:
547
                    continue
548
                old_revid = 'old-parent'
549
                basis_shape = Inventory(root_id=None)
550
                self.add_dir(basis_shape, old_revid, 'root-id', None, '')
551
                old_factory(basis_shape, old_revid)
552
                new_revid = 'new-parent'
553
                new_shape = Inventory(root_id=None)
554
                self.add_new_root(new_shape, old_revid, new_revid)
555
                new_factory(new_shape, new_revid)
556
                self.assertTransitionFromBasisToShape(basis_shape, old_revid,
557
                    new_shape, new_revid)
558
559
    def test_content_from_second_parent_is_dropped(self):
560
        left_revid = 'left-parent'
561
        basis_shape = Inventory(root_id=None)
562
        self.add_dir(basis_shape, left_revid, 'root-id', None, '')
563
        self.add_link(basis_shape, left_revid, 'link-id', 'root-id', 'link',
564
            'left-target')
565
        # the right shape has content - file, link, subdir with a child,
566
        # that should all be discarded by the call.
567
        right_revid = 'right-parent'
568
        right_shape = Inventory(root_id=None)
569
        self.add_dir(right_shape, left_revid, 'root-id', None, '')
570
        self.add_link(right_shape, right_revid, 'link-id', 'root-id', 'link',
2865.1.3 by Robert Collins
Review feedback.
571
            'some-target')
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
572
        self.add_dir(right_shape, right_revid, 'subdir-id', 'root-id', 'dir')
573
        self.add_file(right_shape, right_revid, 'file-id', 'subdir-id', 'file',
574
            '2' * 32, 24)
575
        new_revid = 'new-parent'
576
        new_shape = Inventory(root_id=None)
577
        self.add_new_root(new_shape, left_revid, new_revid)
578
        self.add_link(new_shape, new_revid, 'link-id', 'root-id', 'link',
579
            'new-target')
580
        self.assertTransitionFromBasisToShape(basis_shape, left_revid,
581
            new_shape, new_revid, right_revid)
582
583
    def test_parent_id_changed(self):
2865.1.3 by Robert Collins
Review feedback.
584
        # test that when the only change to an entry is its parent id changing
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
585
        # that it is handled correctly (that is it keeps the same path)
586
        old_revid = 'old-parent'
587
        basis_shape = Inventory(root_id=None)
588
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
589
        self.add_dir(basis_shape, old_revid, 'orig-parent-id', 'root-id', 'dir')
590
        self.add_dir(basis_shape, old_revid, 'dir-id', 'orig-parent-id', 'dir')
591
        new_revid = 'new-parent'
592
        new_shape = Inventory(root_id=None)
593
        self.add_new_root(new_shape, old_revid, new_revid)
594
        self.add_dir(new_shape, new_revid, 'new-parent-id', 'root-id', 'dir')
595
        self.add_dir(new_shape, new_revid, 'dir-id', 'new-parent-id', 'dir')
596
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
597
            new_shape, new_revid)
598
599
    def test_name_changed(self):
2865.1.3 by Robert Collins
Review feedback.
600
        # test that when the only change to an entry is its name changing that
601
        # it is handled correctly (that is it keeps the same parent id)
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
602
        old_revid = 'old-parent'
603
        basis_shape = Inventory(root_id=None)
604
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
605
        self.add_dir(basis_shape, old_revid, 'parent-id', 'root-id', 'origdir')
606
        self.add_dir(basis_shape, old_revid, 'dir-id', 'parent-id', 'olddir')
607
        new_revid = 'new-parent'
608
        new_shape = Inventory(root_id=None)
609
        self.add_new_root(new_shape, old_revid, new_revid)
610
        self.add_dir(new_shape, new_revid, 'parent-id', 'root-id', 'newdir')
611
        self.add_dir(new_shape, new_revid, 'dir-id', 'parent-id', 'newdir')
612
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
613
            new_shape, new_revid)
614
2929.2.2 by Robert Collins
Review feedback on dirstate update_basis_via_delta logic.
615
    def test_parent_child_swap(self):
616
        # test a A->A/B and A/B->A path swap.
617
        old_revid = 'old-parent'
618
        basis_shape = Inventory(root_id=None)
619
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
620
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
621
        self.add_dir(basis_shape, old_revid, 'dir-id-B', 'dir-id-A', 'B')
622
        self.add_link(basis_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'C')
623
        new_revid = 'new-parent'
624
        new_shape = Inventory(root_id=None)
625
        self.add_new_root(new_shape, old_revid, new_revid)
626
        self.add_dir(new_shape, new_revid, 'dir-id-B', 'root-id', 'A')
627
        self.add_dir(new_shape, new_revid, 'dir-id-A', 'dir-id-B', 'B')
628
        self.add_link(new_shape, new_revid, 'link-id-C', 'dir-id-A', 'C', 'C')
629
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
630
            new_shape, new_revid)
631
3253.2.1 by John Arbash Meinel
Fix moving directories to root nodes.
632
    def test_parent_deleted_child_renamed(self):
633
        # test a A->None and A/B->A.
634
        old_revid = 'old-parent'
635
        basis_shape = Inventory(root_id=None)
636
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
637
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
638
        self.add_dir(basis_shape, old_revid, 'dir-id-B', 'dir-id-A', 'B')
639
        self.add_link(basis_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'C')
640
        new_revid = 'new-parent'
641
        new_shape = Inventory(root_id=None)
642
        self.add_new_root(new_shape, old_revid, new_revid)
643
        self.add_dir(new_shape, new_revid, 'dir-id-B', 'root-id', 'A')
644
        self.add_link(new_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'C')
645
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
646
            new_shape, new_revid)
647
648
    def test_dir_to_root(self):
649
        # test a A->''.
650
        old_revid = 'old-parent'
651
        basis_shape = Inventory(root_id=None)
652
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
653
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
654
        self.add_link(basis_shape, old_revid, 'link-id-B', 'dir-id-A', 'B', 'B')
655
        new_revid = 'new-parent'
656
        new_shape = Inventory(root_id=None)
657
        self.add_dir(new_shape, new_revid, 'dir-id-A', None, '')
658
        self.add_link(new_shape, old_revid, 'link-id-B', 'dir-id-A', 'B', 'B')
659
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
660
            new_shape, new_revid)
661
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
662
    def test_path_swap(self):
663
        # test a A->B and B->A path swap.
664
        old_revid = 'old-parent'
665
        basis_shape = Inventory(root_id=None)
666
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
667
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
668
        self.add_dir(basis_shape, old_revid, 'dir-id-B', 'root-id', 'B')
669
        self.add_link(basis_shape, old_revid, 'link-id-C', 'root-id', 'C', 'C')
670
        self.add_link(basis_shape, old_revid, 'link-id-D', 'root-id', 'D', 'D')
671
        self.add_file(basis_shape, old_revid, 'file-id-E', 'root-id', 'E',
672
            '1' * 32, 12)
673
        self.add_file(basis_shape, old_revid, 'file-id-F', 'root-id', 'F',
674
            '2' * 32, 24)
675
        new_revid = 'new-parent'
676
        new_shape = Inventory(root_id=None)
677
        self.add_new_root(new_shape, old_revid, new_revid)
678
        self.add_dir(new_shape, new_revid, 'dir-id-A', 'root-id', 'B')
679
        self.add_dir(new_shape, new_revid, 'dir-id-B', 'root-id', 'A')
680
        self.add_link(new_shape, new_revid, 'link-id-C', 'root-id', 'D', 'C')
681
        self.add_link(new_shape, new_revid, 'link-id-D', 'root-id', 'C', 'D')
682
        self.add_file(new_shape, new_revid, 'file-id-E', 'root-id', 'F',
683
            '1' * 32, 12)
684
        self.add_file(new_shape, new_revid, 'file-id-F', 'root-id', 'E',
685
            '2' * 32, 24)
686
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
687
            new_shape, new_revid)
688
689
    def test_adds(self):
690
        # test adding paths and dirs, including adding to a newly added dir.
691
        old_revid = 'old-parent'
692
        basis_shape = Inventory(root_id=None)
693
        # with a root, so its a commit after the first.
694
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
695
        new_revid = 'new-parent'
696
        new_shape = Inventory(root_id=None)
697
        self.add_new_root(new_shape, old_revid, new_revid)
698
        self.add_dir(new_shape, new_revid, 'dir-id-A', 'root-id', 'A')
699
        self.add_link(new_shape, new_revid, 'link-id-B', 'root-id', 'B', 'C')
700
        self.add_file(new_shape, new_revid, 'file-id-C', 'root-id', 'C',
701
            '1' * 32, 12)
702
        self.add_file(new_shape, new_revid, 'file-id-D', 'dir-id-A', 'D',
703
            '2' * 32, 24)
704
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
705
            new_shape, new_revid)
706
707
    def test_removes(self):
708
        # test removing paths, including paths that are within other also
709
        # removed paths.
710
        old_revid = 'old-parent'
711
        basis_shape = Inventory(root_id=None)
712
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
713
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
714
        self.add_link(basis_shape, old_revid, 'link-id-B', 'root-id', 'B', 'C')
715
        self.add_file(basis_shape, old_revid, 'file-id-C', 'root-id', 'C',
716
            '1' * 32, 12)
717
        self.add_file(basis_shape, old_revid, 'file-id-D', 'dir-id-A', 'D',
718
            '2' * 32, 24)
719
        new_revid = 'new-parent'
720
        new_shape = Inventory(root_id=None)
721
        self.add_new_root(new_shape, old_revid, new_revid)
722
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
723
            new_shape, new_revid)
724
725
    def test_move_to_added_dir(self):
726
        old_revid = 'old-parent'
727
        basis_shape = Inventory(root_id=None)
728
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
729
        self.add_link(basis_shape, old_revid, 'link-id-B', 'root-id', 'B', 'C')
730
        new_revid = 'new-parent'
731
        new_shape = Inventory(root_id=None)
732
        self.add_new_root(new_shape, old_revid, new_revid)
733
        self.add_dir(new_shape, new_revid, 'dir-id-A', 'root-id', 'A')
734
        self.add_link(new_shape, new_revid, 'link-id-B', 'dir-id-A', 'B', 'C')
735
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
736
            new_shape, new_revid)
737
738
    def test_move_from_removed_dir(self):
739
        old_revid = 'old-parent'
740
        basis_shape = Inventory(root_id=None)
741
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
742
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
743
        self.add_link(basis_shape, old_revid, 'link-id-B', 'dir-id-A', 'B', 'C')
744
        new_revid = 'new-parent'
745
        new_shape = Inventory(root_id=None)
746
        self.add_new_root(new_shape, old_revid, new_revid)
747
        self.add_link(new_shape, new_revid, 'link-id-B', 'root-id', 'B', 'C')
748
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
749
            new_shape, new_revid)
2929.2.1 by Robert Collins
* Commit updates the state of the working tree via a delta rather than
750
751
    def test_move_moves_children_recursively(self):
752
        old_revid = 'old-parent'
753
        basis_shape = Inventory(root_id=None)
754
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
755
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
756
        self.add_dir(basis_shape, old_revid, 'dir-id-B', 'dir-id-A', 'B')
757
        self.add_link(basis_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'D')
758
        new_revid = 'new-parent'
759
        new_shape = Inventory(root_id=None)
760
        self.add_new_root(new_shape, old_revid, new_revid)
761
        # the moved path:
762
        self.add_dir(new_shape, new_revid, 'dir-id-A', 'root-id', 'B')
763
        # unmoved children.
764
        self.add_dir(new_shape, old_revid, 'dir-id-B', 'dir-id-A', 'B')
765
        self.add_link(new_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'D')
766
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
767
            new_shape, new_revid)
6015.45.2 by Brian de Alwis, John Arbash Meinel
Backport the fix for bug #855155 to bzr-2.4
768
769
    def test_add_files_to_empty_directory(self):
770
        old_revid = 'old-parent'
771
        basis_shape = Inventory(root_id=None)
772
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
773
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
774
        new_revid = 'new-parent'
775
        new_shape = Inventory(root_id=None)
776
        self.add_new_root(new_shape, old_revid, new_revid)
777
        self.add_dir(new_shape, old_revid, 'dir-id-A', 'root-id', 'A')
778
        self.add_file(new_shape, new_revid, 'file-id-B', 'dir-id-A', 'B',
779
            '1' * 32, 24)
780
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
781
                new_shape, new_revid, set_current_inventory=False)