~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_transform.py

  • Committer: Alexander Belchenko
  • Date: 2007-01-04 23:36:44 UTC
  • mfrom: (2224 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2225.
  • Revision ID: bialix@ukr.net-20070104233644-7znkxoj9b0y7ev28
merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
from bzrlib import (
22
22
    errors,
23
23
    generate_ids,
24
 
    symbol_versioning,
25
24
    tests,
26
25
    urlutils,
27
26
    )
37
36
from bzrlib.tests import TestCaseInTempDir, TestSkipped, TestCase
38
37
from bzrlib.transform import (TreeTransform, ROOT_PARENT, FinalPaths, 
39
38
                              resolve_conflicts, cook_conflicts, 
40
 
                              find_interesting, build_tree, get_backup_name,
41
 
                              change_entry)
42
 
 
43
 
 
44
 
class TestTreeTransform(tests.TestCaseWithTransport):
 
39
                              find_interesting, build_tree, get_backup_name)
 
40
 
 
41
 
 
42
class TestTreeTransform(TestCaseInTempDir):
45
43
 
46
44
    def setUp(self):
47
45
        super(TestTreeTransform, self).setUp()
48
 
        self.wt = self.make_branch_and_tree('.', format='dirstate-with-subtree')
 
46
        self.wt = BzrDir.create_standalone_workingtree('.')
49
47
        os.chdir('..')
50
48
 
51
49
    def get_transform(self):
128
126
        self.assertEqual(self.wt.path2id('oz/dorothy'), 'dorothy-id')
129
127
        self.assertEqual(self.wt.path2id('oz/dorothy/toto'), 'toto-id')
130
128
 
131
 
        self.assertEqual('toto-contents',
 
129
        self.assertEqual('toto-contents', 
132
130
                         self.wt.get_file_byname('oz/dorothy/toto').read())
133
131
        self.assertIs(self.wt.is_executable('toto-id'), False)
134
132
 
135
 
    def test_tree_reference(self):
136
 
        transform, root = self.get_transform()
137
 
        tree = transform._tree
138
 
        trans_id = transform.new_directory('reference', root, 'subtree-id')
139
 
        transform.set_tree_reference('subtree-revision', trans_id)
140
 
        transform.apply()
141
 
        tree.lock_read()
142
 
        self.addCleanup(tree.unlock)
143
 
        self.assertEqual('subtree-revision',
144
 
                         tree.inventory['subtree-id'].reference_revision)
145
 
 
146
133
    def test_conflicts(self):
147
134
        transform, root = self.get_transform()
148
135
        trans_id = transform.new_file('name', root, 'contents', 
395
382
        self.assertEqual(os.readlink(self.wt.abspath('oz/wizard')),
396
383
                         'wizard-target')
397
384
 
 
385
 
398
386
    def get_conflicted(self):
399
387
        create,root = self.get_transform()
400
388
        create.new_file('dorothy', root, 'dorothy', 'dorothy-id')
528
516
        create.new_file('vfile', root, 'myfile-text', 'myfile-id')
529
517
        create.new_file('uvfile', root, 'othertext')
530
518
        create.apply()
531
 
        result = self.applyDeprecated(symbol_versioning.zero_fifteen,
532
 
            find_interesting, wt, wt, ['vfile'])
533
 
        self.assertEqual(result, set(['myfile-id']))
 
519
        self.assertEqual(find_interesting(wt, wt, ['vfile']),
 
520
                         set(['myfile-id']))
 
521
        self.assertRaises(PathsNotVersionedError, find_interesting, wt, wt,
 
522
                          ['uvfile'])
534
523
 
535
524
    def test_set_executability_order(self):
536
525
        """Ensure that executability behaves the same, no matter what order.
545
534
        wt = transform._tree
546
535
        transform.new_file('set_on_creation', root, 'Set on creation', 'soc',
547
536
                           True)
548
 
        sac = transform.new_file('set_after_creation', root,
549
 
                                 'Set after creation', 'sac')
 
537
        sac = transform.new_file('set_after_creation', root, 'Set after creation', 'sac')
550
538
        transform.set_executability(True, sac)
551
 
        uws = transform.new_file('unset_without_set', root, 'Unset badly',
552
 
                                 'uws')
 
539
        uws = transform.new_file('unset_without_set', root, 'Unset badly', 'uws')
553
540
        self.assertRaises(KeyError, transform.set_executability, None, uws)
554
541
        transform.apply()
555
542
        self.assertTrue(wt.is_executable('soc'))
600
587
        bar1_abspath = self.wt.abspath('bar')
601
588
        self.assertEqual([bar1_abspath], stat_paths)
602
589
 
603
 
    def test_iter_changes(self):
604
 
        self.wt.set_root_id('eert_toor')
605
 
        transform, root = self.get_transform()
606
 
        transform.new_file('old', root, 'blah', 'id-1', True)
607
 
        transform.apply()
608
 
        transform, root = self.get_transform()
609
 
        try:
610
 
            self.assertEqual([], list(transform._iter_changes()))
611
 
            old = transform.trans_id_tree_file_id('id-1')
612
 
            transform.unversion_file(old)
613
 
            self.assertEqual([('id-1', ('old', None), False, (True, False),
614
 
                ('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
615
 
                (True, True))], list(transform._iter_changes()))
616
 
            transform.new_directory('new', root, 'id-1')
617
 
            self.assertEqual([('id-1', ('old', 'new'), True, (True, True),
618
 
                ('eert_toor', 'eert_toor'), ('old', 'new'),
619
 
                ('file', 'directory'),
620
 
                (True, False))], list(transform._iter_changes()))
621
 
        finally:
622
 
            transform.finalize()
623
 
 
624
 
    def test_iter_changes_new(self):
625
 
        self.wt.set_root_id('eert_toor')
626
 
        transform, root = self.get_transform()
627
 
        transform.new_file('old', root, 'blah')
628
 
        transform.apply()
629
 
        transform, root = self.get_transform()
630
 
        try:
631
 
            old = transform.trans_id_tree_path('old')
632
 
            transform.version_file('id-1', old)
633
 
            self.assertEqual([('id-1', (None, 'old'), False, (False, True),
634
 
                ('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
635
 
                (False, False))], list(transform._iter_changes()))
636
 
        finally:
637
 
            transform.finalize()
638
 
 
639
 
    def test_iter_changes_modifications(self):
640
 
        self.wt.set_root_id('eert_toor')
641
 
        transform, root = self.get_transform()
642
 
        transform.new_file('old', root, 'blah', 'id-1')
643
 
        transform.new_file('new', root, 'blah')
644
 
        transform.new_directory('subdir', root, 'subdir-id')
645
 
        transform.apply()
646
 
        transform, root = self.get_transform()
647
 
        try:
648
 
            old = transform.trans_id_tree_path('old')
649
 
            subdir = transform.trans_id_tree_file_id('subdir-id')
650
 
            new = transform.trans_id_tree_path('new')
651
 
            self.assertEqual([], list(transform._iter_changes()))
652
 
 
653
 
            #content deletion
654
 
            transform.delete_contents(old)
655
 
            self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
656
 
                ('eert_toor', 'eert_toor'), ('old', 'old'), ('file', None),
657
 
                (False, False))], list(transform._iter_changes()))
658
 
 
659
 
            #content change
660
 
            transform.create_file('blah', old)
661
 
            self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
662
 
                ('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
663
 
                (False, False))], list(transform._iter_changes()))
664
 
            transform.cancel_deletion(old)
665
 
            self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
666
 
                ('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
667
 
                (False, False))], list(transform._iter_changes()))
668
 
            transform.cancel_creation(old)
669
 
 
670
 
            # move file_id to a different file
671
 
            self.assertEqual([], list(transform._iter_changes()))
672
 
            transform.unversion_file(old)
673
 
            transform.version_file('id-1', new)
674
 
            transform.adjust_path('old', root, new)
675
 
            self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
676
 
                ('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
677
 
                (False, False))], list(transform._iter_changes()))
678
 
            transform.cancel_versioning(new)
679
 
            transform._removed_id = set()
680
 
 
681
 
            #execute bit
682
 
            self.assertEqual([], list(transform._iter_changes()))
683
 
            transform.set_executability(True, old)
684
 
            self.assertEqual([('id-1', ('old', 'old'), False, (True, True),
685
 
                ('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
686
 
                (False, True))], list(transform._iter_changes()))
687
 
            transform.set_executability(None, old)
688
 
 
689
 
            # filename
690
 
            self.assertEqual([], list(transform._iter_changes()))
691
 
            transform.adjust_path('new', root, old)
692
 
            transform._new_parent = {}
693
 
            self.assertEqual([('id-1', ('old', 'new'), False, (True, True),
694
 
                ('eert_toor', 'eert_toor'), ('old', 'new'), ('file', 'file'),
695
 
                (False, False))], list(transform._iter_changes()))
696
 
            transform._new_name = {}
697
 
 
698
 
            # parent directory
699
 
            self.assertEqual([], list(transform._iter_changes()))
700
 
            transform.adjust_path('new', subdir, old)
701
 
            transform._new_name = {}
702
 
            self.assertEqual([('id-1', ('old', 'subdir/old'), False,
703
 
                (True, True), ('eert_toor', 'subdir-id'), ('old', 'old'),
704
 
                ('file', 'file'), (False, False))],
705
 
                list(transform._iter_changes()))
706
 
            transform._new_path = {}
707
 
 
708
 
        finally:
709
 
            transform.finalize()
710
 
 
711
 
    def test_iter_changes_modified_bleed(self):
712
 
        self.wt.set_root_id('eert_toor')
713
 
        """Modified flag should not bleed from one change to another"""
714
 
        # unfortunately, we have no guarantee that file1 (which is modified)
715
 
        # will be applied before file2.  And if it's applied after file2, it
716
 
        # obviously can't bleed into file2's change output.  But for now, it
717
 
        # works.
718
 
        transform, root = self.get_transform()
719
 
        transform.new_file('file1', root, 'blah', 'id-1')
720
 
        transform.new_file('file2', root, 'blah', 'id-2')
721
 
        transform.apply()
722
 
        transform, root = self.get_transform()
723
 
        try:
724
 
            transform.delete_contents(transform.trans_id_file_id('id-1'))
725
 
            transform.set_executability(True,
726
 
            transform.trans_id_file_id('id-2'))
727
 
            self.assertEqual([('id-1', (u'file1', u'file1'), True, (True, True),
728
 
                ('eert_toor', 'eert_toor'), ('file1', u'file1'),
729
 
                ('file', None), (False, False)),
730
 
                ('id-2', (u'file2', u'file2'), False, (True, True),
731
 
                ('eert_toor', 'eert_toor'), ('file2', u'file2'),
732
 
                ('file', 'file'), (False, True))],
733
 
                list(transform._iter_changes()))
734
 
        finally:
735
 
            transform.finalize()
736
 
 
737
 
    def test_iter_changes_move_missing(self):
738
 
        """Test moving ids with no files around"""
739
 
        self.wt.set_root_id('toor_eert')
740
 
        # Need two steps because versioning a non-existant file is a conflict.
741
 
        transform, root = self.get_transform()
742
 
        transform.new_directory('floater', root, 'floater-id')
743
 
        transform.apply()
744
 
        transform, root = self.get_transform()
745
 
        transform.delete_contents(transform.trans_id_tree_path('floater'))
746
 
        transform.apply()
747
 
        transform, root = self.get_transform()
748
 
        floater = transform.trans_id_tree_path('floater')
749
 
        try:
750
 
            transform.adjust_path('flitter', root, floater)
751
 
            self.assertEqual([('floater-id', ('floater', 'flitter'), False,
752
 
            (True, True), ('toor_eert', 'toor_eert'), ('floater', 'flitter'),
753
 
            (None, None), (False, False))], list(transform._iter_changes()))
754
 
        finally:
755
 
            transform.finalize()
756
 
 
757
 
    def test_iter_changes_pointless(self):
758
 
        """Ensure that no-ops are not treated as modifications"""
759
 
        self.wt.set_root_id('eert_toor')
760
 
        transform, root = self.get_transform()
761
 
        transform.new_file('old', root, 'blah', 'id-1')
762
 
        transform.new_directory('subdir', root, 'subdir-id')
763
 
        transform.apply()
764
 
        transform, root = self.get_transform()
765
 
        try:
766
 
            old = transform.trans_id_tree_path('old')
767
 
            subdir = transform.trans_id_tree_file_id('subdir-id')
768
 
            self.assertEqual([], list(transform._iter_changes()))
769
 
            transform.delete_contents(subdir)
770
 
            transform.create_directory(subdir)
771
 
            transform.set_executability(False, old)
772
 
            transform.unversion_file(old)
773
 
            transform.version_file('id-1', old)
774
 
            transform.adjust_path('old', root, old)
775
 
            self.assertEqual([], list(transform._iter_changes()))
776
 
        finally:
777
 
            transform.finalize()
778
 
 
779
 
    def test_rename_count(self):
780
 
        transform, root = self.get_transform()
781
 
        transform.new_file('name1', root, 'contents')
782
 
        self.assertEqual(transform.rename_count, 0)
783
 
        transform.apply()
784
 
        self.assertEqual(transform.rename_count, 1)
785
 
        transform2, root = self.get_transform()
786
 
        transform2.adjust_path('name2', root,
787
 
                               transform2.trans_id_tree_path('name1'))
788
 
        self.assertEqual(transform2.rename_count, 0)
789
 
        transform2.apply()
790
 
        self.assertEqual(transform2.rename_count, 2)
791
 
 
792
 
    def test_change_parent(self):
793
 
        """Ensure that after we change a parent, the results are still right.
794
 
 
795
 
        Renames and parent changes on pending transforms can happen as part
796
 
        of conflict resolution, and are explicitly permitted by the
797
 
        TreeTransform API.
798
 
 
799
 
        This test ensures they work correctly with the rename-avoidance
800
 
        optimization.
801
 
        """
802
 
        transform, root = self.get_transform()
803
 
        parent1 = transform.new_directory('parent1', root)
804
 
        child1 = transform.new_file('child1', parent1, 'contents')
805
 
        parent2 = transform.new_directory('parent2', root)
806
 
        transform.adjust_path('child1', parent2, child1)
807
 
        transform.apply()
808
 
        self.failIfExists(self.wt.abspath('parent1/child1'))
809
 
        self.failUnlessExists(self.wt.abspath('parent2/child1'))
810
 
        # rename limbo/new-1 => parent1, rename limbo/new-3 => parent2
811
 
        # no rename for child1 (counting only renames during apply)
812
 
        self.failUnlessEqual(2, transform.rename_count)
813
 
 
814
 
    def test_cancel_parent(self):
815
 
        """Cancelling a parent doesn't cause deletion of a non-empty directory
816
 
 
817
 
        This is like the test_change_parent, except that we cancel the parent
818
 
        before adjusting the path.  The transform must detect that the
819
 
        directory is non-empty, and move children to safe locations.
820
 
        """
821
 
        transform, root = self.get_transform()
822
 
        parent1 = transform.new_directory('parent1', root)
823
 
        child1 = transform.new_file('child1', parent1, 'contents')
824
 
        child2 = transform.new_file('child2', parent1, 'contents')
825
 
        try:
826
 
            transform.cancel_creation(parent1)
827
 
        except OSError:
828
 
            self.fail('Failed to move child1 before deleting parent1')
829
 
        transform.cancel_creation(child2)
830
 
        transform.create_directory(parent1)
831
 
        try:
832
 
            transform.cancel_creation(parent1)
833
 
        # If the transform incorrectly believes that child2 is still in
834
 
        # parent1's limbo directory, it will try to rename it and fail
835
 
        # because was already moved by the first cancel_creation.
836
 
        except OSError:
837
 
            self.fail('Transform still thinks child2 is a child of parent1')
838
 
        parent2 = transform.new_directory('parent2', root)
839
 
        transform.adjust_path('child1', parent2, child1)
840
 
        transform.apply()
841
 
        self.failIfExists(self.wt.abspath('parent1'))
842
 
        self.failUnlessExists(self.wt.abspath('parent2/child1'))
843
 
        # rename limbo/new-3 => parent2, rename limbo/new-2 => child1
844
 
        self.failUnlessEqual(2, transform.rename_count)
845
 
 
846
 
    def test_adjust_and_cancel(self):
847
 
        """Make sure adjust_path keeps track of limbo children properly"""
848
 
        transform, root = self.get_transform()
849
 
        parent1 = transform.new_directory('parent1', root)
850
 
        child1 = transform.new_file('child1', parent1, 'contents')
851
 
        parent2 = transform.new_directory('parent2', root)
852
 
        transform.adjust_path('child1', parent2, child1)
853
 
        transform.cancel_creation(child1)
854
 
        try:
855
 
            transform.cancel_creation(parent1)
856
 
        # if the transform thinks child1 is still in parent1's limbo
857
 
        # directory, it will attempt to move it and fail.
858
 
        except OSError:
859
 
            self.fail('Transform still thinks child1 is a child of parent1')
860
 
        transform.finalize()
861
 
 
862
 
    def test_noname_contents(self):
863
 
        """TreeTransform should permit deferring naming files."""
864
 
        transform, root = self.get_transform()
865
 
        parent = transform.trans_id_file_id('parent-id')
866
 
        try:
867
 
            transform.create_directory(parent)
868
 
        except KeyError:
869
 
            self.fail("Can't handle contents with no name")
870
 
        transform.finalize()
871
 
 
872
 
    def test_noname_contents_nested(self):
873
 
        """TreeTransform should permit deferring naming files."""
874
 
        transform, root = self.get_transform()
875
 
        parent = transform.trans_id_file_id('parent-id')
876
 
        try:
877
 
            transform.create_directory(parent)
878
 
        except KeyError:
879
 
            self.fail("Can't handle contents with no name")
880
 
        child = transform.new_directory('child', parent)
881
 
        transform.adjust_path('parent', root, parent)
882
 
        transform.apply()
883
 
        self.failUnlessExists(self.wt.abspath('parent/child'))
884
 
        self.assertEqual(1, transform.rename_count)
885
 
 
886
 
    def test_reuse_name(self):
887
 
        """Avoid reusing the same limbo name for different files"""
888
 
        transform, root = self.get_transform()
889
 
        parent = transform.new_directory('parent', root)
890
 
        child1 = transform.new_directory('child', parent)
891
 
        try:
892
 
            child2 = transform.new_directory('child', parent)
893
 
        except OSError:
894
 
            self.fail('Tranform tried to use the same limbo name twice')
895
 
        transform.adjust_path('child2', parent, child2)
896
 
        transform.apply()
897
 
        # limbo/new-1 => parent, limbo/new-3 => parent/child2
898
 
        # child2 is put into top-level limbo because child1 has already
899
 
        # claimed the direct limbo path when child2 is created.  There is no
900
 
        # advantage in renaming files once they're in top-level limbo, except
901
 
        # as part of apply.
902
 
        self.assertEqual(2, transform.rename_count)
903
 
 
904
 
    def test_reuse_when_first_moved(self):
905
 
        """Don't avoid direct paths when it is safe to use them"""
906
 
        transform, root = self.get_transform()
907
 
        parent = transform.new_directory('parent', root)
908
 
        child1 = transform.new_directory('child', parent)
909
 
        transform.adjust_path('child1', parent, child1)
910
 
        child2 = transform.new_directory('child', parent)
911
 
        transform.apply()
912
 
        # limbo/new-1 => parent
913
 
        self.assertEqual(1, transform.rename_count)
914
 
 
915
 
    def test_reuse_after_cancel(self):
916
 
        """Don't avoid direct paths when it is safe to use them"""
917
 
        transform, root = self.get_transform()
918
 
        parent2 = transform.new_directory('parent2', root)
919
 
        child1 = transform.new_directory('child1', parent2)
920
 
        transform.cancel_creation(parent2)
921
 
        transform.create_directory(parent2)
922
 
        child2 = transform.new_directory('child1', parent2)
923
 
        transform.adjust_path('child2', parent2, child1)
924
 
        transform.apply()
925
 
        # limbo/new-1 => parent2, limbo/new-2 => parent2/child1
926
 
        self.assertEqual(2, transform.rename_count)
927
 
 
928
 
    def test_finalize_order(self):
929
 
        """Finalize must be done in child-to-parent order"""
930
 
        transform, root = self.get_transform()
931
 
        parent = transform.new_directory('parent', root)
932
 
        child = transform.new_directory('child', parent)
933
 
        try:
934
 
            transform.finalize()
935
 
        except OSError:
936
 
            self.fail('Tried to remove parent before child1')
937
 
 
938
 
    def test_cancel_with_cancelled_child_should_succeed(self):
939
 
        transform, root = self.get_transform()
940
 
        parent = transform.new_directory('parent', root)
941
 
        child = transform.new_directory('child', parent)
942
 
        transform.cancel_creation(child)
943
 
        transform.cancel_creation(parent)
944
 
        transform.finalize()
945
 
 
946
 
    def test_change_entry(self):
947
 
        txt = 'bzrlib.transform.change_entry was deprecated in version 0.19.'
948
 
        self.callDeprecated([txt], change_entry, None, None, None, None, None,
949
 
            None, None, None)
950
 
 
951
590
 
952
591
class TransformGroup(object):
953
592
    def __init__(self, dirname, root_id):
959
598
        self.tt = TreeTransform(self.wt)
960
599
        self.root = self.tt.trans_id_tree_file_id(self.wt.get_root_id())
961
600
 
962
 
 
963
601
def conflict_text(tree, merge):
964
602
    template = '%s TREE\n%s%s\n%s%s MERGE-SOURCE\n'
965
603
    return template % ('<' * 7, tree, '=' * 7, merge, '>' * 7)
1164
802
        a.add(['foo', 'foo/bar', 'foo/baz'])
1165
803
        a.commit('initial commit')
1166
804
        b = BzrDir.create_standalone_workingtree('b')
1167
 
        basis = a.basis_tree()
1168
 
        basis.lock_read()
1169
 
        self.addCleanup(basis.unlock)
1170
 
        build_tree(basis, b)
 
805
        build_tree(a.basis_tree(), b)
1171
806
        self.assertIs(os.path.isdir('b/foo'), True)
1172
807
        self.assertEqual(file('b/foo/bar', 'rb').read(), "contents")
1173
808
        self.assertEqual(os.readlink('b/foo/baz'), 'a/foo/bar')
1174
809
 
1175
 
    def test_build_with_references(self):
1176
 
        tree = self.make_branch_and_tree('source',
1177
 
            format='dirstate-with-subtree')
1178
 
        subtree = self.make_branch_and_tree('source/subtree',
1179
 
            format='dirstate-with-subtree')
1180
 
        tree.add_reference(subtree)
1181
 
        tree.commit('a revision')
1182
 
        tree.branch.create_checkout('target')
1183
 
        self.failUnlessExists('target')
1184
 
        self.failUnlessExists('target/subtree')
1185
 
 
1186
810
    def test_file_conflict_handling(self):
1187
811
        """Ensure that when building trees, conflict handling is done"""
1188
812
        source = self.make_branch_and_tree('source')
1290
914
        self.assertRaises(errors.WorkingTreeAlreadyPopulated, 
1291
915
            build_tree, source.basis_tree(), target)
1292
916
 
1293
 
    def test_build_tree_rename_count(self):
1294
 
        source = self.make_branch_and_tree('source')
1295
 
        self.build_tree(['source/file1', 'source/dir1/'])
1296
 
        source.add(['file1', 'dir1'])
1297
 
        source.commit('add1')
1298
 
        target1 = self.make_branch_and_tree('target1')
1299
 
        transform_result = build_tree(source.basis_tree(), target1)
1300
 
        self.assertEqual(2, transform_result.rename_count)
1301
 
 
1302
 
        self.build_tree(['source/dir1/file2'])
1303
 
        source.add(['dir1/file2'])
1304
 
        source.commit('add3')
1305
 
        target2 = self.make_branch_and_tree('target2')
1306
 
        transform_result = build_tree(source.basis_tree(), target2)
1307
 
        # children of non-root directories should not be renamed
1308
 
        self.assertEqual(2, transform_result.rename_count)
1309
 
 
1310
917
 
1311
918
class MockTransform(object):
1312
919
 
1319
926
                return True
1320
927
        return False
1321
928
 
1322
 
 
1323
929
class MockEntry(object):
1324
930
    def __init__(self):
1325
931
        object.__init__(self)