/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/workingtree_implementations/test_parents.py

First attempt to merge .dev and resolve the conflicts (but tests are 
failing)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006 by Canonical Ltd
 
1
# Copyright (C) 2006 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
16
16
 
17
17
"""Tests of the parent related functions of WorkingTrees."""
18
18
 
 
19
from errno import EEXIST
19
20
import os
20
21
 
21
 
from bzrlib import errors, symbol_versioning
 
22
from bzrlib import (
 
23
    errors,
 
24
    osutils,
 
25
    revision as _mod_revision,
 
26
    symbol_versioning,
 
27
    )
 
28
from bzrlib.inventory import (
 
29
    Inventory,
 
30
    InventoryFile,
 
31
    InventoryDirectory,
 
32
    InventoryLink,
 
33
    )
 
34
from bzrlib.revision import Revision
 
35
from bzrlib.tests import SymlinkFeature, TestNotApplicable
22
36
from bzrlib.tests.workingtree_implementations import TestCaseWithWorkingTree
23
37
from bzrlib.uncommit import uncommit
24
38
 
33
47
        """
34
48
        self.assertEqual(expected, tree.get_parent_ids())
35
49
        if expected == []:
36
 
            self.assertEqual(None, tree.last_revision())
 
50
            self.assertEqual(_mod_revision.NULL_REVISION,
 
51
                             _mod_revision.ensure_null(tree.last_revision()))
37
52
        else:
38
53
            self.assertEqual(expected[0], tree.last_revision())
39
 
        self.assertEqual(expected[1:],
40
 
            self.applyDeprecated(symbol_versioning.zero_eleven,
41
 
                tree.pending_merges))
 
54
 
 
55
 
 
56
class TestGetParents(TestParents):
 
57
 
 
58
    def test_get_parents(self):
 
59
        t = self.make_branch_and_tree('.')
 
60
        self.assertEqual([], t.get_parent_ids())
42
61
 
43
62
 
44
63
class TestSetParents(TestParents):
52
71
        t.set_parent_trees([])
53
72
        self.assertConsistentParents([], t)
54
73
 
 
74
    def test_set_null_parent(self):
 
75
        t = self.make_branch_and_tree('.')
 
76
        self.assertRaises(errors.ReservedId, t.set_parent_ids, ['null:'],
 
77
                          allow_leftmost_as_ghost=True)
 
78
        self.assertRaises(errors.ReservedId, t.set_parent_trees,
 
79
                          [('null:', None)], allow_leftmost_as_ghost=True)
 
80
 
55
81
    def test_set_one_ghost_parent_rejects(self):
56
82
        t = self.make_branch_and_tree('.')
57
83
        self.assertRaises(errors.GhostRevisionUnusableHere,
134
160
        self.assertConsistentParents(
135
161
            [first_revision, second_revision, third_revision], t)
136
162
 
 
163
    def test_set_duplicate_parent_ids(self):
 
164
        t = self.make_branch_and_tree('.')
 
165
        rev1 = t.commit('first post')
 
166
        uncommit(t.branch, tree=t)
 
167
        rev2 = t.commit('second post')
 
168
        uncommit(t.branch, tree=t)
 
169
        rev3 = t.commit('third post')
 
170
        uncommit(t.branch, tree=t)
 
171
        t.set_parent_ids([rev1, rev2, rev2, rev3])
 
172
        # We strip the duplicate, but preserve the ordering
 
173
        self.assertConsistentParents([rev1, rev2, rev3], t)
 
174
 
 
175
    def test_set_duplicate_parent_trees(self):
 
176
        t = self.make_branch_and_tree('.')
 
177
        rev1 = t.commit('first post')
 
178
        uncommit(t.branch, tree=t)
 
179
        rev2 = t.commit('second post')
 
180
        uncommit(t.branch, tree=t)
 
181
        rev3 = t.commit('third post')
 
182
        uncommit(t.branch, tree=t)
 
183
        rev_tree1 = t.branch.repository.revision_tree(rev1)
 
184
        rev_tree2 = t.branch.repository.revision_tree(rev2)
 
185
        rev_tree3 = t.branch.repository.revision_tree(rev3)
 
186
        t.set_parent_trees([(rev1, rev_tree1), (rev2, rev_tree2),
 
187
                            (rev2, rev_tree2), (rev3, rev_tree3)])
 
188
        # We strip the duplicate, but preserve the ordering
 
189
        self.assertConsistentParents([rev1, rev2, rev3], t)
 
190
 
 
191
    def test_set_parent_ids_in_ancestry(self):
 
192
        t = self.make_branch_and_tree('.')
 
193
        rev1 = t.commit('first post')
 
194
        rev2 = t.commit('second post')
 
195
        rev3 = t.commit('third post')
 
196
        # Reset the tree, back to rev1
 
197
        t.set_parent_ids([rev1])
 
198
        t.branch.set_last_revision_info(1, rev1)
 
199
        self.assertConsistentParents([rev1], t)
 
200
        t.set_parent_ids([rev1, rev2, rev3])
 
201
        # rev2 is in the ancestry of rev3, so it will be filtered out
 
202
        self.assertConsistentParents([rev1, rev3], t)
 
203
        # Order should be preserved, and the first revision should always be
 
204
        # kept
 
205
        t.set_parent_ids([rev2, rev3, rev1])
 
206
        self.assertConsistentParents([rev2, rev3], t)
 
207
 
 
208
    def test_set_parent_trees_in_ancestry(self):
 
209
        t = self.make_branch_and_tree('.')
 
210
        rev1 = t.commit('first post')
 
211
        rev2 = t.commit('second post')
 
212
        rev3 = t.commit('third post')
 
213
        # Reset the tree, back to rev1
 
214
        t.set_parent_ids([rev1])
 
215
        t.branch.set_last_revision_info(1, rev1)
 
216
        self.assertConsistentParents([rev1], t)
 
217
        rev_tree1 = t.branch.repository.revision_tree(rev1)
 
218
        rev_tree2 = t.branch.repository.revision_tree(rev2)
 
219
        rev_tree3 = t.branch.repository.revision_tree(rev3)
 
220
        t.set_parent_trees([(rev1, rev_tree1), (rev2, rev_tree2),
 
221
                            (rev3, rev_tree3)])
 
222
        # rev2 is in the ancestry of rev3, so it will be filtered out
 
223
        self.assertConsistentParents([rev1, rev3], t)
 
224
        # Order should be preserved, and the first revision should always be
 
225
        # kept
 
226
        t.set_parent_trees([(rev2, rev_tree2), (rev1, rev_tree1),
 
227
                            (rev3, rev_tree3)])
 
228
        self.assertConsistentParents([rev2, rev3], t)
 
229
 
137
230
 
138
231
class TestAddParent(TestParents):
139
232
 
218
311
        first_revision = tree.commit('first post')
219
312
        tree.add_parent_tree(('second', None))
220
313
        self.assertConsistentParents([first_revision, 'second'], tree)
 
314
 
 
315
 
 
316
class UpdateToOneParentViaDeltaTests(TestCaseWithWorkingTree):
 
317
    """Tests for the update_basis_by_delta call.
 
318
    
 
319
    This is intuitively defined as 'apply an inventory delta to the basis and
 
320
    discard other parents', but for trees that have an inventory that is not
 
321
    managed as a tree-by-id, the implementation requires roughly duplicated
 
322
    tests with those for apply_inventory_delta on the main tree.
 
323
    """
 
324
 
 
325
    def assertDeltaApplicationResultsInExpectedBasis(self, tree, revid, delta,
 
326
        expected_inventory):
 
327
        tree.lock_write()
 
328
        try:
 
329
            tree.update_basis_by_delta(revid, delta)
 
330
        finally:
 
331
            tree.unlock()
 
332
        # check the last revision was adjusted to rev_id
 
333
        self.assertEqual(revid, tree.last_revision())
 
334
        # check the parents are what we expect
 
335
        self.assertEqual([revid], tree.get_parent_ids())
 
336
        # check that the basis tree has the inventory we expect from applying
 
337
        # the delta.
 
338
        result_basis = tree.basis_tree()
 
339
        result_basis.lock_read()
 
340
        self.addCleanup(result_basis.unlock)
 
341
        self.assertEqual(expected_inventory, result_basis.inventory)
 
342
 
 
343
    def make_inv_delta(self, old, new):
 
344
        """Make an inventory delta from two inventories."""
 
345
        old_ids = set(old._byid.iterkeys())
 
346
        new_ids = set(new._byid.iterkeys())
 
347
        adds = new_ids - old_ids
 
348
        deletes = old_ids - new_ids
 
349
        common = old_ids.intersection(new_ids)
 
350
        delta = []
 
351
        for file_id in deletes:
 
352
            delta.append((old.id2path(file_id), None, file_id, None))
 
353
        for file_id in adds:
 
354
            delta.append((None, new.id2path(file_id), file_id, new[file_id]))
 
355
        for file_id in common:
 
356
            if old[file_id] != new[file_id]:
 
357
                delta.append((old.id2path(file_id), new.id2path(file_id),
 
358
                    file_id, new[file_id]))
 
359
        return delta
 
360
 
 
361
    def fake_up_revision(self, tree, revid, shape):
 
362
        tree.lock_write()
 
363
        try:
 
364
            tree.branch.repository.start_write_group()
 
365
            try:
 
366
                if shape.root.revision is None:
 
367
                    shape.root.revision = revid
 
368
                sha1 = tree.branch.repository.add_inventory(revid, shape, [])
 
369
                rev = Revision(timestamp=0,
 
370
                               timezone=None,
 
371
                               committer="Foo Bar <foo@example.com>",
 
372
                               message="Message",
 
373
                               inventory_sha1=sha1,
 
374
                               revision_id=revid)
 
375
                tree.branch.repository.add_revision(revid, rev)
 
376
            except:
 
377
                tree.branch.repository.abort_write_group()
 
378
                raise
 
379
            else:
 
380
                tree.branch.repository.commit_write_group()
 
381
        finally:
 
382
            tree.unlock()
 
383
 
 
384
    def add_entry(self, inv, rev_id, entry):
 
385
        entry.revision = rev_id
 
386
        inv.add(entry)
 
387
 
 
388
    def add_dir(self, inv, rev_id, file_id, parent_id, name):
 
389
        new_dir = InventoryDirectory(file_id, name, parent_id)
 
390
        self.add_entry(inv, rev_id, new_dir)
 
391
 
 
392
    def add_file(self, inv, rev_id, file_id, parent_id, name, sha, size):
 
393
        new_file = InventoryFile(file_id, name, parent_id)
 
394
        new_file.text_sha1 = sha
 
395
        new_file.text_size = size
 
396
        self.add_entry(inv, rev_id, new_file)
 
397
 
 
398
    def add_link(self, inv, rev_id, file_id, parent_id, name, target):
 
399
        new_link = InventoryLink(file_id, name, parent_id)
 
400
        new_link.symlink_target = target
 
401
        self.add_entry(inv, rev_id, new_link)
 
402
 
 
403
    def add_new_root(self, new_shape, old_revid, new_revid):
 
404
        if self.bzrdir_format.repository_format.rich_root_data:
 
405
            self.add_dir(new_shape, old_revid, 'root-id', None, '')
 
406
        else:
 
407
            self.add_dir(new_shape, new_revid, 'root-id', None, '')
 
408
 
 
409
    def assertTransitionFromBasisToShape(self, basis_shape, basis_revid,
 
410
        new_shape, new_revid, extra_parent=None):
 
411
        # set the inventory revision ids.
 
412
        basis_shape.revision_id = basis_revid
 
413
        new_shape.revision_id = new_revid
 
414
        delta = self.make_inv_delta(basis_shape, new_shape)
 
415
        tree = self.make_branch_and_tree('tree')
 
416
        # the shapes need to be in the tree's repository to be able to set them
 
417
        # as a parent, but the file content is not needed.
 
418
        if basis_revid is not None:
 
419
            self.fake_up_revision(tree, basis_revid, basis_shape)
 
420
            parents = [basis_revid]
 
421
            if extra_parent is not None:
 
422
                parents.append(extra_parent)
 
423
            tree.set_parent_ids(parents)
 
424
        self.fake_up_revision(tree, new_revid, new_shape)
 
425
        # give tree an inventory of new_shape
 
426
        tree._write_inventory(new_shape)
 
427
        self.assertDeltaApplicationResultsInExpectedBasis(tree, new_revid,
 
428
            delta, new_shape)
 
429
        # The tree should be internally consistent; while this is a moderately
 
430
        # large hammer, this is a particularly sensitive area of code, so the
 
431
        # extra assurance is well worth it.
 
432
        tree._validate()
 
433
        osutils.rmtree('tree')
 
434
 
 
435
    def test_no_parents_just_root(self):
 
436
        """Test doing an empty commit - no parent, set a root only."""
 
437
        basis_shape = Inventory(root_id=None) # empty tree
 
438
        new_shape = Inventory() # tree with a root
 
439
        self.assertTransitionFromBasisToShape(basis_shape, None, new_shape,
 
440
            'new_parent')
 
441
 
 
442
    def test_no_parents_full_tree(self):
 
443
        """Test doing a regular initial commit with files and dirs."""
 
444
        basis_shape = Inventory(root_id=None) # empty tree
 
445
        revid = 'new-parent'
 
446
        new_shape = Inventory(root_id=None)
 
447
        self.add_dir(new_shape, revid, 'root-id', None, '')
 
448
        self.add_link(new_shape, revid, 'link-id', 'root-id', 'link', 'target')
 
449
        self.add_file(new_shape, revid, 'file-id', 'root-id', 'file', '1' * 32,
 
450
            12)
 
451
        self.add_dir(new_shape, revid, 'dir-id', 'root-id', 'dir')
 
452
        self.add_file(new_shape, revid, 'subfile-id', 'dir-id', 'subfile',
 
453
            '2' * 32, 24)
 
454
        self.assertTransitionFromBasisToShape(basis_shape, None, new_shape,
 
455
            revid)
 
456
 
 
457
    def test_file_content_change(self):
 
458
        old_revid = 'old-parent'
 
459
        basis_shape = Inventory(root_id=None)
 
460
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
461
        self.add_file(basis_shape, old_revid, 'file-id', 'root-id', 'file',
 
462
            '1' * 32, 12)
 
463
        new_revid = 'new-parent'
 
464
        new_shape = Inventory(root_id=None)
 
465
        self.add_new_root(new_shape, old_revid, new_revid)
 
466
        self.add_file(new_shape, new_revid, 'file-id', 'root-id', 'file',
 
467
            '2' * 32, 24)
 
468
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
469
            new_shape, new_revid)
 
470
 
 
471
    def test_link_content_change(self):
 
472
        old_revid = 'old-parent'
 
473
        basis_shape = Inventory(root_id=None)
 
474
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
475
        self.add_link(basis_shape, old_revid, 'link-id', 'root-id', 'link',
 
476
            'old-target')
 
477
        new_revid = 'new-parent'
 
478
        new_shape = Inventory(root_id=None)
 
479
        self.add_new_root(new_shape, old_revid, new_revid)
 
480
        self.add_link(new_shape, new_revid, 'link-id', 'root-id', 'link',
 
481
            'new-target')
 
482
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
483
            new_shape, new_revid)
 
484
 
 
485
    def test_kind_changes(self):
 
486
        def do_file(inv, revid):
 
487
            self.add_file(inv, revid, 'path-id', 'root-id', 'path', '1' * 32,
 
488
                12)
 
489
        def do_link(inv, revid):
 
490
            self.add_link(inv, revid, 'path-id', 'root-id', 'path', 'target')
 
491
        def do_dir(inv, revid):
 
492
            self.add_dir(inv, revid, 'path-id', 'root-id', 'path')
 
493
        for old_factory in (do_file, do_link, do_dir):
 
494
            for new_factory in (do_file, do_link, do_dir):
 
495
                if old_factory == new_factory:
 
496
                    continue
 
497
                old_revid = 'old-parent'
 
498
                basis_shape = Inventory(root_id=None)
 
499
                self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
500
                old_factory(basis_shape, old_revid)
 
501
                new_revid = 'new-parent'
 
502
                new_shape = Inventory(root_id=None)
 
503
                self.add_new_root(new_shape, old_revid, new_revid)
 
504
                new_factory(new_shape, new_revid)
 
505
                self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
506
                    new_shape, new_revid)
 
507
 
 
508
    def test_content_from_second_parent_is_dropped(self):
 
509
        left_revid = 'left-parent'
 
510
        basis_shape = Inventory(root_id=None)
 
511
        self.add_dir(basis_shape, left_revid, 'root-id', None, '')
 
512
        self.add_link(basis_shape, left_revid, 'link-id', 'root-id', 'link',
 
513
            'left-target')
 
514
        # the right shape has content - file, link, subdir with a child,
 
515
        # that should all be discarded by the call.
 
516
        right_revid = 'right-parent'
 
517
        right_shape = Inventory(root_id=None)
 
518
        self.add_dir(right_shape, left_revid, 'root-id', None, '')
 
519
        self.add_link(right_shape, right_revid, 'link-id', 'root-id', 'link',
 
520
            'some-target')
 
521
        self.add_dir(right_shape, right_revid, 'subdir-id', 'root-id', 'dir')
 
522
        self.add_file(right_shape, right_revid, 'file-id', 'subdir-id', 'file',
 
523
            '2' * 32, 24)
 
524
        new_revid = 'new-parent'
 
525
        new_shape = Inventory(root_id=None)
 
526
        self.add_new_root(new_shape, left_revid, new_revid)
 
527
        self.add_link(new_shape, new_revid, 'link-id', 'root-id', 'link',
 
528
            'new-target')
 
529
        self.assertTransitionFromBasisToShape(basis_shape, left_revid,
 
530
            new_shape, new_revid, right_revid)
 
531
 
 
532
    def test_parent_id_changed(self):
 
533
        # test that when the only change to an entry is its parent id changing
 
534
        # that it is handled correctly (that is it keeps the same path)
 
535
        old_revid = 'old-parent'
 
536
        basis_shape = Inventory(root_id=None)
 
537
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
538
        self.add_dir(basis_shape, old_revid, 'orig-parent-id', 'root-id', 'dir')
 
539
        self.add_dir(basis_shape, old_revid, 'dir-id', 'orig-parent-id', 'dir')
 
540
        new_revid = 'new-parent'
 
541
        new_shape = Inventory(root_id=None)
 
542
        self.add_new_root(new_shape, old_revid, new_revid)
 
543
        self.add_dir(new_shape, new_revid, 'new-parent-id', 'root-id', 'dir')
 
544
        self.add_dir(new_shape, new_revid, 'dir-id', 'new-parent-id', 'dir')
 
545
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
546
            new_shape, new_revid)
 
547
 
 
548
    def test_name_changed(self):
 
549
        # test that when the only change to an entry is its name changing that
 
550
        # it is handled correctly (that is it keeps the same parent id)
 
551
        old_revid = 'old-parent'
 
552
        basis_shape = Inventory(root_id=None)
 
553
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
554
        self.add_dir(basis_shape, old_revid, 'parent-id', 'root-id', 'origdir')
 
555
        self.add_dir(basis_shape, old_revid, 'dir-id', 'parent-id', 'olddir')
 
556
        new_revid = 'new-parent'
 
557
        new_shape = Inventory(root_id=None)
 
558
        self.add_new_root(new_shape, old_revid, new_revid)
 
559
        self.add_dir(new_shape, new_revid, 'parent-id', 'root-id', 'newdir')
 
560
        self.add_dir(new_shape, new_revid, 'dir-id', 'parent-id', 'newdir')
 
561
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
562
            new_shape, new_revid)
 
563
 
 
564
    def test_parent_child_swap(self):
 
565
        # test a A->A/B and A/B->A path swap.
 
566
        old_revid = 'old-parent'
 
567
        basis_shape = Inventory(root_id=None)
 
568
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
569
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
 
570
        self.add_dir(basis_shape, old_revid, 'dir-id-B', 'dir-id-A', 'B')
 
571
        self.add_link(basis_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'C')
 
572
        new_revid = 'new-parent'
 
573
        new_shape = Inventory(root_id=None)
 
574
        self.add_new_root(new_shape, old_revid, new_revid)
 
575
        self.add_dir(new_shape, new_revid, 'dir-id-B', 'root-id', 'A')
 
576
        self.add_dir(new_shape, new_revid, 'dir-id-A', 'dir-id-B', 'B')
 
577
        self.add_link(new_shape, new_revid, 'link-id-C', 'dir-id-A', 'C', 'C')
 
578
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
579
            new_shape, new_revid)
 
580
 
 
581
    def test_parent_deleted_child_renamed(self):
 
582
        # test a A->None and A/B->A.
 
583
        old_revid = 'old-parent'
 
584
        basis_shape = Inventory(root_id=None)
 
585
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
586
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
 
587
        self.add_dir(basis_shape, old_revid, 'dir-id-B', 'dir-id-A', 'B')
 
588
        self.add_link(basis_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'C')
 
589
        new_revid = 'new-parent'
 
590
        new_shape = Inventory(root_id=None)
 
591
        self.add_new_root(new_shape, old_revid, new_revid)
 
592
        self.add_dir(new_shape, new_revid, 'dir-id-B', 'root-id', 'A')
 
593
        self.add_link(new_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'C')
 
594
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
595
            new_shape, new_revid)
 
596
 
 
597
    def test_dir_to_root(self):
 
598
        # test a A->''.
 
599
        old_revid = 'old-parent'
 
600
        basis_shape = Inventory(root_id=None)
 
601
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
602
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
 
603
        self.add_link(basis_shape, old_revid, 'link-id-B', 'dir-id-A', 'B', 'B')
 
604
        new_revid = 'new-parent'
 
605
        new_shape = Inventory(root_id=None)
 
606
        self.add_dir(new_shape, new_revid, 'dir-id-A', None, '')
 
607
        self.add_link(new_shape, old_revid, 'link-id-B', 'dir-id-A', 'B', 'B')
 
608
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
609
            new_shape, new_revid)
 
610
 
 
611
    def test_path_swap(self):
 
612
        # test a A->B and B->A path swap.
 
613
        old_revid = 'old-parent'
 
614
        basis_shape = Inventory(root_id=None)
 
615
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
616
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
 
617
        self.add_dir(basis_shape, old_revid, 'dir-id-B', 'root-id', 'B')
 
618
        self.add_link(basis_shape, old_revid, 'link-id-C', 'root-id', 'C', 'C')
 
619
        self.add_link(basis_shape, old_revid, 'link-id-D', 'root-id', 'D', 'D')
 
620
        self.add_file(basis_shape, old_revid, 'file-id-E', 'root-id', 'E',
 
621
            '1' * 32, 12)
 
622
        self.add_file(basis_shape, old_revid, 'file-id-F', 'root-id', 'F',
 
623
            '2' * 32, 24)
 
624
        new_revid = 'new-parent'
 
625
        new_shape = Inventory(root_id=None)
 
626
        self.add_new_root(new_shape, old_revid, new_revid)
 
627
        self.add_dir(new_shape, new_revid, 'dir-id-A', 'root-id', 'B')
 
628
        self.add_dir(new_shape, new_revid, 'dir-id-B', 'root-id', 'A')
 
629
        self.add_link(new_shape, new_revid, 'link-id-C', 'root-id', 'D', 'C')
 
630
        self.add_link(new_shape, new_revid, 'link-id-D', 'root-id', 'C', 'D')
 
631
        self.add_file(new_shape, new_revid, 'file-id-E', 'root-id', 'F',
 
632
            '1' * 32, 12)
 
633
        self.add_file(new_shape, new_revid, 'file-id-F', 'root-id', 'E',
 
634
            '2' * 32, 24)
 
635
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
636
            new_shape, new_revid)
 
637
 
 
638
    def test_adds(self):
 
639
        # test adding paths and dirs, including adding to a newly added dir.
 
640
        old_revid = 'old-parent'
 
641
        basis_shape = Inventory(root_id=None)
 
642
        # with a root, so its a commit after the first.
 
643
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
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-A', 'root-id', 'A')
 
648
        self.add_link(new_shape, new_revid, 'link-id-B', 'root-id', 'B', 'C')
 
649
        self.add_file(new_shape, new_revid, 'file-id-C', 'root-id', 'C',
 
650
            '1' * 32, 12)
 
651
        self.add_file(new_shape, new_revid, 'file-id-D', 'dir-id-A', 'D',
 
652
            '2' * 32, 24)
 
653
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
654
            new_shape, new_revid)
 
655
 
 
656
    def test_removes(self):
 
657
        # test removing paths, including paths that are within other also
 
658
        # removed paths.
 
659
        old_revid = 'old-parent'
 
660
        basis_shape = Inventory(root_id=None)
 
661
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
662
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
 
663
        self.add_link(basis_shape, old_revid, 'link-id-B', 'root-id', 'B', 'C')
 
664
        self.add_file(basis_shape, old_revid, 'file-id-C', 'root-id', 'C',
 
665
            '1' * 32, 12)
 
666
        self.add_file(basis_shape, old_revid, 'file-id-D', 'dir-id-A', 'D',
 
667
            '2' * 32, 24)
 
668
        new_revid = 'new-parent'
 
669
        new_shape = Inventory(root_id=None)
 
670
        self.add_new_root(new_shape, old_revid, new_revid)
 
671
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
672
            new_shape, new_revid)
 
673
 
 
674
    def test_move_to_added_dir(self):
 
675
        old_revid = 'old-parent'
 
676
        basis_shape = Inventory(root_id=None)
 
677
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
678
        self.add_link(basis_shape, old_revid, 'link-id-B', 'root-id', 'B', 'C')
 
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', 'A')
 
683
        self.add_link(new_shape, new_revid, 'link-id-B', 'dir-id-A', 'B', 'C')
 
684
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
685
            new_shape, new_revid)
 
686
 
 
687
    def test_move_from_removed_dir(self):
 
688
        old_revid = 'old-parent'
 
689
        basis_shape = Inventory(root_id=None)
 
690
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
691
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
 
692
        self.add_link(basis_shape, old_revid, 'link-id-B', 'dir-id-A', 'B', 'C')
 
693
        new_revid = 'new-parent'
 
694
        new_shape = Inventory(root_id=None)
 
695
        self.add_new_root(new_shape, old_revid, new_revid)
 
696
        self.add_link(new_shape, new_revid, 'link-id-B', 'root-id', 'B', 'C')
 
697
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
698
            new_shape, new_revid)
 
699
 
 
700
    def test_move_moves_children_recursively(self):
 
701
        old_revid = 'old-parent'
 
702
        basis_shape = Inventory(root_id=None)
 
703
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
704
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
 
705
        self.add_dir(basis_shape, old_revid, 'dir-id-B', 'dir-id-A', 'B')
 
706
        self.add_link(basis_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'D')
 
707
        new_revid = 'new-parent'
 
708
        new_shape = Inventory(root_id=None)
 
709
        self.add_new_root(new_shape, old_revid, new_revid)
 
710
        # the moved path:
 
711
        self.add_dir(new_shape, new_revid, 'dir-id-A', 'root-id', 'B')
 
712
        # unmoved children.
 
713
        self.add_dir(new_shape, old_revid, 'dir-id-B', 'dir-id-A', 'B')
 
714
        self.add_link(new_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'D')
 
715
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
716
            new_shape, new_revid)