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