/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.
6809.4.7 by Jelmer Vernooij
Swap arguments for get_symlink_target and kind/stored_kind.
253
        self.assertEqual(target, tree.get_symlink_target(link_name))
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
254
        basis = tree.basis_tree()
6809.4.7 by Jelmer Vernooij
Swap arguments for get_symlink_target and kind/stored_kind.
255
        self.assertEqual(target, basis.get_symlink_target(link_name))
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
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
398
            def get_file_text(self, path, file_id=None):
399
                if file_id is None:
400
                    file_id = self.path2id(path)
6405.2.10 by Jelmer Vernooij
Fix more tests.
401
                ie = self.root_inventory[file_id]
5809.4.1 by Jelmer Vernooij
Avoid .texts.add_lines, rather use Repository.get_commit_builder.
402
                if ie.kind != "file":
403
                    return ""
404
                return 'a' * ie.text_size
405
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
406
            def get_file(self, path, file_id=None):
407
                return BytesIO(self.get_file_text(path, file_id))
5809.4.1 by Jelmer Vernooij
Avoid .texts.add_lines, rather use Repository.get_commit_builder.
408
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
409
        tree.lock_write()
410
        try:
5809.4.1 by Jelmer Vernooij
Avoid .texts.add_lines, rather use Repository.get_commit_builder.
411
            if shape.root.revision is None:
412
                shape.root.revision = revid
413
            builder = tree.branch.get_commit_builder(
414
                    parents=[],
415
                    timestamp=0,
416
                    timezone=None,
417
                    committer="Foo Bar <foo@example.com>",
418
                    revision_id=revid)
419
            shape_tree = ShapeTree(shape)
5809.4.3 by Jelmer Vernooij
Fix base revid.
420
            base_tree = tree.branch.repository.revision_tree(
421
                    _mod_revision.NULL_REVISION)
5809.4.1 by Jelmer Vernooij
Avoid .texts.add_lines, rather use Repository.get_commit_builder.
422
            changes = shape_tree.iter_changes(
5809.4.3 by Jelmer Vernooij
Fix base revid.
423
                base_tree)
5809.4.1 by Jelmer Vernooij
Avoid .texts.add_lines, rather use Repository.get_commit_builder.
424
            list(builder.record_iter_changes(shape_tree,
5809.4.3 by Jelmer Vernooij
Fix base revid.
425
                base_tree.get_revision_id(), changes))
5809.4.1 by Jelmer Vernooij
Avoid .texts.add_lines, rather use Repository.get_commit_builder.
426
            builder.finish_inventory()
427
            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.
428
        finally:
429
            tree.unlock()
430
431
    def add_entry(self, inv, rev_id, entry):
432
        entry.revision = rev_id
433
        inv.add(entry)
434
435
    def add_dir(self, inv, rev_id, file_id, parent_id, name):
436
        new_dir = InventoryDirectory(file_id, name, parent_id)
437
        self.add_entry(inv, rev_id, new_dir)
438
439
    def add_file(self, inv, rev_id, file_id, parent_id, name, sha, size):
440
        new_file = InventoryFile(file_id, name, parent_id)
441
        new_file.text_sha1 = sha
442
        new_file.text_size = size
443
        self.add_entry(inv, rev_id, new_file)
444
445
    def add_link(self, inv, rev_id, file_id, parent_id, name, target):
446
        new_link = InventoryLink(file_id, name, parent_id)
447
        new_link.symlink_target = target
448
        self.add_entry(inv, rev_id, new_link)
449
450
    def add_new_root(self, new_shape, old_revid, new_revid):
451
        if self.bzrdir_format.repository_format.rich_root_data:
452
            self.add_dir(new_shape, old_revid, 'root-id', None, '')
453
        else:
454
            self.add_dir(new_shape, new_revid, 'root-id', None, '')
455
456
    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
457
        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
458
        # set the inventory revision ids.
459
        basis_shape.revision_id = basis_revid
460
        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.
461
        delta = self.make_inv_delta(basis_shape, new_shape)
462
        tree = self.make_branch_and_tree('tree')
463
        # the shapes need to be in the tree's repository to be able to set them
464
        # as a parent, but the file content is not needed.
465
        if basis_revid is not None:
466
            self.fake_up_revision(tree, basis_revid, basis_shape)
467
            parents = [basis_revid]
468
            if extra_parent is not None:
469
                parents.append(extra_parent)
470
            tree.set_parent_ids(parents)
471
        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
472
        if set_current_inventory:
473
            # give tree an inventory of new_shape
474
            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.
475
        self.assertDeltaApplicationResultsInExpectedBasis(tree, new_revid,
476
            delta, new_shape)
2929.2.2 by Robert Collins
Review feedback on dirstate update_basis_via_delta logic.
477
        # The tree should be internally consistent; while this is a moderately
478
        # large hammer, this is a particularly sensitive area of code, so the
479
        # extra assurance is well worth it.
480
        tree._validate()
6437.70.4 by John Arbash Meinel
Now that we have 2 possible locations where things exist, we must cleanup both.
481
        # If tree.branch is remote
6437.70.5 by John Arbash Meinel
user_url seems a cleaner way to do the same thing.
482
        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.
483
            # We have a lightweight checkout, delete both locations
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
484
            tree.branch.controldir.root_transport.delete_tree('.')
485
        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.
486
487
    def test_no_parents_just_root(self):
488
        """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
489
        basis_shape = Inventory(root_id=None)  # empty tree
490
        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.
491
        self.assertTransitionFromBasisToShape(basis_shape, None, new_shape,
492
            'new_parent')
493
494
    def test_no_parents_full_tree(self):
495
        """Test doing a regular initial commit with files and dirs."""
496
        basis_shape = Inventory(root_id=None) # empty tree
497
        revid = 'new-parent'
498
        new_shape = Inventory(root_id=None)
499
        self.add_dir(new_shape, revid, 'root-id', None, '')
500
        self.add_link(new_shape, revid, 'link-id', 'root-id', 'link', 'target')
501
        self.add_file(new_shape, revid, 'file-id', 'root-id', 'file', '1' * 32,
502
            12)
503
        self.add_dir(new_shape, revid, 'dir-id', 'root-id', 'dir')
504
        self.add_file(new_shape, revid, 'subfile-id', 'dir-id', 'subfile',
505
            '2' * 32, 24)
506
        self.assertTransitionFromBasisToShape(basis_shape, None, new_shape,
507
            revid)
508
509
    def test_file_content_change(self):
510
        old_revid = 'old-parent'
511
        basis_shape = Inventory(root_id=None)
512
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
513
        self.add_file(basis_shape, old_revid, 'file-id', 'root-id', 'file',
514
            '1' * 32, 12)
515
        new_revid = 'new-parent'
516
        new_shape = Inventory(root_id=None)
517
        self.add_new_root(new_shape, old_revid, new_revid)
518
        self.add_file(new_shape, new_revid, 'file-id', 'root-id', 'file',
519
            '2' * 32, 24)
520
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
521
            new_shape, new_revid)
522
523
    def test_link_content_change(self):
524
        old_revid = 'old-parent'
525
        basis_shape = Inventory(root_id=None)
526
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
527
        self.add_link(basis_shape, old_revid, 'link-id', 'root-id', 'link',
528
            'old-target')
529
        new_revid = 'new-parent'
530
        new_shape = Inventory(root_id=None)
531
        self.add_new_root(new_shape, old_revid, new_revid)
532
        self.add_link(new_shape, new_revid, 'link-id', 'root-id', 'link',
533
            'new-target')
534
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
535
            new_shape, new_revid)
536
537
    def test_kind_changes(self):
538
        def do_file(inv, revid):
539
            self.add_file(inv, revid, 'path-id', 'root-id', 'path', '1' * 32,
540
                12)
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
541
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
542
        def do_link(inv, revid):
543
            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
544
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
545
        def do_dir(inv, revid):
546
            self.add_dir(inv, revid, 'path-id', 'root-id', 'path')
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
547
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
548
        for old_factory in (do_file, do_link, do_dir):
549
            for new_factory in (do_file, do_link, do_dir):
550
                if old_factory == new_factory:
551
                    continue
552
                old_revid = 'old-parent'
553
                basis_shape = Inventory(root_id=None)
554
                self.add_dir(basis_shape, old_revid, 'root-id', None, '')
555
                old_factory(basis_shape, old_revid)
556
                new_revid = 'new-parent'
557
                new_shape = Inventory(root_id=None)
558
                self.add_new_root(new_shape, old_revid, new_revid)
559
                new_factory(new_shape, new_revid)
560
                self.assertTransitionFromBasisToShape(basis_shape, old_revid,
561
                    new_shape, new_revid)
562
563
    def test_content_from_second_parent_is_dropped(self):
564
        left_revid = 'left-parent'
565
        basis_shape = Inventory(root_id=None)
566
        self.add_dir(basis_shape, left_revid, 'root-id', None, '')
567
        self.add_link(basis_shape, left_revid, 'link-id', 'root-id', 'link',
568
            'left-target')
569
        # the right shape has content - file, link, subdir with a child,
570
        # that should all be discarded by the call.
571
        right_revid = 'right-parent'
572
        right_shape = Inventory(root_id=None)
573
        self.add_dir(right_shape, left_revid, 'root-id', None, '')
574
        self.add_link(right_shape, right_revid, 'link-id', 'root-id', 'link',
2865.1.3 by Robert Collins
Review feedback.
575
            'some-target')
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
576
        self.add_dir(right_shape, right_revid, 'subdir-id', 'root-id', 'dir')
577
        self.add_file(right_shape, right_revid, 'file-id', 'subdir-id', 'file',
578
            '2' * 32, 24)
579
        new_revid = 'new-parent'
580
        new_shape = Inventory(root_id=None)
581
        self.add_new_root(new_shape, left_revid, new_revid)
582
        self.add_link(new_shape, new_revid, 'link-id', 'root-id', 'link',
583
            'new-target')
584
        self.assertTransitionFromBasisToShape(basis_shape, left_revid,
585
            new_shape, new_revid, right_revid)
586
587
    def test_parent_id_changed(self):
2865.1.3 by Robert Collins
Review feedback.
588
        # 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.
589
        # that it is handled correctly (that is it keeps the same path)
590
        old_revid = 'old-parent'
591
        basis_shape = Inventory(root_id=None)
592
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
593
        self.add_dir(basis_shape, old_revid, 'orig-parent-id', 'root-id', 'dir')
594
        self.add_dir(basis_shape, old_revid, 'dir-id', 'orig-parent-id', 'dir')
595
        new_revid = 'new-parent'
596
        new_shape = Inventory(root_id=None)
597
        self.add_new_root(new_shape, old_revid, new_revid)
598
        self.add_dir(new_shape, new_revid, 'new-parent-id', 'root-id', 'dir')
599
        self.add_dir(new_shape, new_revid, 'dir-id', 'new-parent-id', 'dir')
600
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
601
            new_shape, new_revid)
602
603
    def test_name_changed(self):
2865.1.3 by Robert Collins
Review feedback.
604
        # test that when the only change to an entry is its name changing that
605
        # 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.
606
        old_revid = 'old-parent'
607
        basis_shape = Inventory(root_id=None)
608
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
609
        self.add_dir(basis_shape, old_revid, 'parent-id', 'root-id', 'origdir')
610
        self.add_dir(basis_shape, old_revid, 'dir-id', 'parent-id', 'olddir')
611
        new_revid = 'new-parent'
612
        new_shape = Inventory(root_id=None)
613
        self.add_new_root(new_shape, old_revid, new_revid)
614
        self.add_dir(new_shape, new_revid, 'parent-id', 'root-id', 'newdir')
615
        self.add_dir(new_shape, new_revid, 'dir-id', 'parent-id', 'newdir')
616
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
617
            new_shape, new_revid)
618
2929.2.2 by Robert Collins
Review feedback on dirstate update_basis_via_delta logic.
619
    def test_parent_child_swap(self):
620
        # test a A->A/B and A/B->A path swap.
621
        old_revid = 'old-parent'
622
        basis_shape = Inventory(root_id=None)
623
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
624
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
625
        self.add_dir(basis_shape, old_revid, 'dir-id-B', 'dir-id-A', 'B')
626
        self.add_link(basis_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'C')
627
        new_revid = 'new-parent'
628
        new_shape = Inventory(root_id=None)
629
        self.add_new_root(new_shape, old_revid, new_revid)
630
        self.add_dir(new_shape, new_revid, 'dir-id-B', 'root-id', 'A')
631
        self.add_dir(new_shape, new_revid, 'dir-id-A', 'dir-id-B', 'B')
632
        self.add_link(new_shape, new_revid, 'link-id-C', 'dir-id-A', 'C', 'C')
633
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
634
            new_shape, new_revid)
635
3253.2.1 by John Arbash Meinel
Fix moving directories to root nodes.
636
    def test_parent_deleted_child_renamed(self):
637
        # test a A->None and A/B->A.
638
        old_revid = 'old-parent'
639
        basis_shape = Inventory(root_id=None)
640
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
641
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
642
        self.add_dir(basis_shape, old_revid, 'dir-id-B', 'dir-id-A', 'B')
643
        self.add_link(basis_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'C')
644
        new_revid = 'new-parent'
645
        new_shape = Inventory(root_id=None)
646
        self.add_new_root(new_shape, old_revid, new_revid)
647
        self.add_dir(new_shape, new_revid, 'dir-id-B', 'root-id', 'A')
648
        self.add_link(new_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'C')
649
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
650
            new_shape, new_revid)
651
652
    def test_dir_to_root(self):
653
        # test a A->''.
654
        old_revid = 'old-parent'
655
        basis_shape = Inventory(root_id=None)
656
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
657
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
658
        self.add_link(basis_shape, old_revid, 'link-id-B', 'dir-id-A', 'B', 'B')
659
        new_revid = 'new-parent'
660
        new_shape = Inventory(root_id=None)
661
        self.add_dir(new_shape, new_revid, 'dir-id-A', None, '')
662
        self.add_link(new_shape, old_revid, 'link-id-B', 'dir-id-A', 'B', 'B')
663
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
664
            new_shape, new_revid)
665
2865.1.1 by Robert Collins
Create new mutable tree method update_to_one_parent_via_delta for eventual use by commit.
666
    def test_path_swap(self):
667
        # test a A->B and B->A path swap.
668
        old_revid = 'old-parent'
669
        basis_shape = Inventory(root_id=None)
670
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
671
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
672
        self.add_dir(basis_shape, old_revid, 'dir-id-B', 'root-id', 'B')
673
        self.add_link(basis_shape, old_revid, 'link-id-C', 'root-id', 'C', 'C')
674
        self.add_link(basis_shape, old_revid, 'link-id-D', 'root-id', 'D', 'D')
675
        self.add_file(basis_shape, old_revid, 'file-id-E', 'root-id', 'E',
676
            '1' * 32, 12)
677
        self.add_file(basis_shape, old_revid, 'file-id-F', 'root-id', 'F',
678
            '2' * 32, 24)
679
        new_revid = 'new-parent'
680
        new_shape = Inventory(root_id=None)
681
        self.add_new_root(new_shape, old_revid, new_revid)
682
        self.add_dir(new_shape, new_revid, 'dir-id-A', 'root-id', 'B')
683
        self.add_dir(new_shape, new_revid, 'dir-id-B', 'root-id', 'A')
684
        self.add_link(new_shape, new_revid, 'link-id-C', 'root-id', 'D', 'C')
685
        self.add_link(new_shape, new_revid, 'link-id-D', 'root-id', 'C', 'D')
686
        self.add_file(new_shape, new_revid, 'file-id-E', 'root-id', 'F',
687
            '1' * 32, 12)
688
        self.add_file(new_shape, new_revid, 'file-id-F', 'root-id', 'E',
689
            '2' * 32, 24)
690
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
691
            new_shape, new_revid)
692
693
    def test_adds(self):
694
        # test adding paths and dirs, including adding to a newly added dir.
695
        old_revid = 'old-parent'
696
        basis_shape = Inventory(root_id=None)
697
        # with a root, so its a commit after the first.
698
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
699
        new_revid = 'new-parent'
700
        new_shape = Inventory(root_id=None)
701
        self.add_new_root(new_shape, old_revid, new_revid)
702
        self.add_dir(new_shape, new_revid, 'dir-id-A', 'root-id', 'A')
703
        self.add_link(new_shape, new_revid, 'link-id-B', 'root-id', 'B', 'C')
704
        self.add_file(new_shape, new_revid, 'file-id-C', 'root-id', 'C',
705
            '1' * 32, 12)
706
        self.add_file(new_shape, new_revid, 'file-id-D', 'dir-id-A', 'D',
707
            '2' * 32, 24)
708
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
709
            new_shape, new_revid)
710
711
    def test_removes(self):
712
        # test removing paths, including paths that are within other also
713
        # removed paths.
714
        old_revid = 'old-parent'
715
        basis_shape = Inventory(root_id=None)
716
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
717
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
718
        self.add_link(basis_shape, old_revid, 'link-id-B', 'root-id', 'B', 'C')
719
        self.add_file(basis_shape, old_revid, 'file-id-C', 'root-id', 'C',
720
            '1' * 32, 12)
721
        self.add_file(basis_shape, old_revid, 'file-id-D', 'dir-id-A', 'D',
722
            '2' * 32, 24)
723
        new_revid = 'new-parent'
724
        new_shape = Inventory(root_id=None)
725
        self.add_new_root(new_shape, old_revid, new_revid)
726
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
727
            new_shape, new_revid)
728
729
    def test_move_to_added_dir(self):
730
        old_revid = 'old-parent'
731
        basis_shape = Inventory(root_id=None)
732
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
733
        self.add_link(basis_shape, old_revid, 'link-id-B', 'root-id', 'B', 'C')
734
        new_revid = 'new-parent'
735
        new_shape = Inventory(root_id=None)
736
        self.add_new_root(new_shape, old_revid, new_revid)
737
        self.add_dir(new_shape, new_revid, 'dir-id-A', 'root-id', 'A')
738
        self.add_link(new_shape, new_revid, 'link-id-B', 'dir-id-A', 'B', 'C')
739
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
740
            new_shape, new_revid)
741
742
    def test_move_from_removed_dir(self):
743
        old_revid = 'old-parent'
744
        basis_shape = Inventory(root_id=None)
745
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
746
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
747
        self.add_link(basis_shape, old_revid, 'link-id-B', 'dir-id-A', 'B', 'C')
748
        new_revid = 'new-parent'
749
        new_shape = Inventory(root_id=None)
750
        self.add_new_root(new_shape, old_revid, new_revid)
751
        self.add_link(new_shape, new_revid, 'link-id-B', 'root-id', 'B', 'C')
752
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
753
            new_shape, new_revid)
2929.2.1 by Robert Collins
* Commit updates the state of the working tree via a delta rather than
754
755
    def test_move_moves_children_recursively(self):
756
        old_revid = 'old-parent'
757
        basis_shape = Inventory(root_id=None)
758
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
759
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
760
        self.add_dir(basis_shape, old_revid, 'dir-id-B', 'dir-id-A', 'B')
761
        self.add_link(basis_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'D')
762
        new_revid = 'new-parent'
763
        new_shape = Inventory(root_id=None)
764
        self.add_new_root(new_shape, old_revid, new_revid)
765
        # the moved path:
766
        self.add_dir(new_shape, new_revid, 'dir-id-A', 'root-id', 'B')
767
        # unmoved children.
768
        self.add_dir(new_shape, old_revid, 'dir-id-B', 'dir-id-A', 'B')
769
        self.add_link(new_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'D')
770
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
771
            new_shape, new_revid)
6015.45.2 by Brian de Alwis, John Arbash Meinel
Backport the fix for bug #855155 to bzr-2.4
772
773
    def test_add_files_to_empty_directory(self):
774
        old_revid = 'old-parent'
775
        basis_shape = Inventory(root_id=None)
776
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
777
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
778
        new_revid = 'new-parent'
779
        new_shape = Inventory(root_id=None)
780
        self.add_new_root(new_shape, old_revid, new_revid)
781
        self.add_dir(new_shape, old_revid, 'dir-id-A', 'root-id', 'A')
782
        self.add_file(new_shape, new_revid, 'file-id-B', 'dir-id-A', 'B',
783
            '1' * 32, 24)
784
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
785
                new_shape, new_revid, set_current_inventory=False)