/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 breezy/tests/per_workingtree/test_transform.py

  • Committer: Jelmer Vernooij
  • Date: 2020-08-22 22:46:24 UTC
  • mfrom: (7490.40.105 work)
  • mto: This revision was merged to the branch mainline in revision 7521.
  • Revision ID: jelmer@jelmer.uk-20200822224624-om4a4idsr7cn8jew
merge lp:brz/3.1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
    transform,
29
29
    urlutils,
30
30
    )
 
31
from ...tree import TreeChange
31
32
from ...bzr.conflicts import (
32
33
    DeletingParent,
33
34
    DuplicateEntry,
69
70
    TransformRenameFailed,
70
71
)
71
72
 
 
73
from breezy.bzr.inventorytree import InventoryTreeChange
 
74
 
72
75
from breezy.tests.per_workingtree import TestCaseWithWorkingTree
73
76
 
74
77
 
77
80
 
78
81
    def setUp(self):
79
82
        super(TestTreeTransform, self).setUp()
80
 
        if not self.workingtree_format.supports_setting_file_ids:
81
 
            self.skipTest('test not compatible with non-file-id trees yet')
82
83
        self.wt = self.make_branch_and_tree('wt')
83
84
 
84
85
    def transform(self):
88
89
 
89
90
    def transform_for_sha1_test(self):
90
91
        trans, root = self.transform()
 
92
        if getattr(self.wt, '_observed_sha1', None) is None:
 
93
            raise tests.TestNotApplicable(
 
94
                'wt format does not use _observed_sha1')
91
95
        self.wt.lock_tree_write()
92
96
        self.addCleanup(self.wt.unlock)
93
97
        contents = [b'just some content\n']
130
134
        self.assertEqual(imaginary_id, imaginary_id2)
131
135
        self.assertEqual(root, transform.get_tree_parent(imaginary_id))
132
136
        self.assertEqual('directory', transform.final_kind(root))
133
 
        self.assertEqual(self.wt.path2id(''), transform.final_file_id(root))
 
137
        if self.wt.supports_setting_file_ids():
 
138
            self.assertEqual(self.wt.path2id(''), transform.final_file_id(root))
134
139
        trans_id = transform.create_path('name', root)
135
 
        self.assertIs(transform.final_file_id(trans_id), None)
 
140
        if self.wt.supports_setting_file_ids():
 
141
            self.assertIs(transform.final_file_id(trans_id), None)
 
142
        self.assertFalse(transform.final_is_versioned(trans_id))
136
143
        self.assertIs(None, transform.final_kind(trans_id))
137
144
        transform.create_file([b'contents'], trans_id)
138
145
        transform.set_executability(True, trans_id)
139
146
        transform.version_file(trans_id, file_id=b'my_pretties')
140
147
        self.assertRaises(DuplicateKey, transform.version_file,
141
148
                          trans_id, file_id=b'my_pretties')
142
 
        self.assertEqual(transform.final_file_id(trans_id), b'my_pretties')
 
149
        if self.wt.supports_setting_file_ids():
 
150
            self.assertEqual(transform.final_file_id(trans_id), b'my_pretties')
 
151
        self.assertTrue(transform.final_is_versioned(trans_id))
143
152
        self.assertEqual(transform.final_parent(trans_id), root)
144
153
        self.assertIs(transform.final_parent(root), ROOT_PARENT)
145
154
        self.assertIs(transform.get_tree_parent(root), ROOT_PARENT)
153
162
        modified_paths = transform.apply().modified_paths
154
163
        with self.wt.get_file('name') as f:
155
164
            self.assertEqual(b'contents', f.read())
156
 
        self.assertEqual(self.wt.path2id('name'), b'my_pretties')
 
165
        if self.wt.supports_setting_file_ids():
 
166
            self.assertEqual(self.wt.path2id('name'), b'my_pretties')
157
167
        self.assertIs(self.wt.is_executable('name'), True)
158
168
        self.assertIs(self.wt.is_executable('name2'), False)
159
169
        self.assertEqual('directory', file_kind(self.wt.abspath('oz')))
160
170
        self.assertEqual(len(modified_paths), 3)
161
 
        tree_mod_paths = [self.wt.abspath(self.wt.id2path(f)) for f in
162
 
                          (b'ozzie', b'my_pretties', b'my_pretties2')]
163
 
        self.assertSubset(tree_mod_paths, modified_paths)
 
171
        if self.wt.supports_setting_file_ids():
 
172
            tree_mod_paths = [self.wt.abspath(self.wt.id2path(f)) for f in
 
173
                              (b'ozzie', b'my_pretties', b'my_pretties2')]
 
174
            self.assertSubset(tree_mod_paths, modified_paths)
164
175
        # is it safe to finalize repeatedly?
165
176
        transform.finalize()
166
177
        transform.finalize()
167
178
 
168
179
    def test_apply_informs_tree_of_observed_sha1(self):
169
180
        trans, root, contents, sha1 = self.transform_for_sha1_test()
 
181
        from ...bzr.workingtree import InventoryWorkingTree
 
182
        if not isinstance(self.wt, InventoryWorkingTree):
 
183
            self.skipTest('not a bzr working tree')
170
184
        trans_id = trans.new_file('file1', root, contents, file_id=b'file1-id',
171
185
                                  sha1=sha1)
172
186
        calls = []
300
314
        with tt:
301
315
            tt.new_directory('', ROOT_PARENT, b'new-root-id')
302
316
            tt.fixup_new_roots()
303
 
            self.assertNotEqual(b'new-root-id', tt.final_file_id(tt.root))
 
317
            if self.wt.has_versioned_directories():
 
318
                self.assertTrue(tt.final_is_versioned(tt.root))
 
319
            if self.wt.supports_setting_file_ids():
 
320
                self.assertNotEqual(b'new-root-id', tt.final_file_id(tt.root))
304
321
 
305
322
    def test_retain_existing_root_added_file(self):
306
323
        tt, root = self.transform()
314
331
        transform.new_directory('', ROOT_PARENT, None)
315
332
        transform.delete_contents(transform.root)
316
333
        transform.fixup_new_roots()
317
 
        self.assertNotIn(transform.root, transform._new_id)
 
334
        self.assertNotIn(transform.root, getattr(transform, '_new_id', []))
318
335
 
319
336
    def test_remove_root_fixup(self):
320
337
        transform, root = self.transform()
337
354
        transform.unversion_file(root)
338
355
        transform.fixup_new_roots()
339
356
        self.assertIs(None, transform.final_kind(root))
340
 
        self.assertIs(None, transform.final_file_id(root))
 
357
        if self.wt.supports_setting_file_ids():
 
358
            self.assertIs(None, transform.final_file_id(root))
341
359
 
342
360
    def test_apply_retains_root_directory(self):
343
361
        # Do not attempt to delete the physical root directory, because that
352
370
 
353
371
    def test_apply_retains_file_id(self):
354
372
        transform, root = self.transform()
 
373
        if not self.wt.supports_setting_file_ids():
 
374
            self.skipTest('format does not support file ids')
355
375
        old_root_id = transform.tree_file_id(root)
356
376
        transform.unversion_file(root)
357
377
        transform.apply()
387
407
        self.assertRaises(ReusingTransform, transform.find_raw_conflicts)
388
408
        with open(self.wt.abspath('name'), 'r') as f:
389
409
            self.assertEqual('contents', f.read())
390
 
        self.assertEqual(self.wt.path2id('name'), b'my_pretties')
391
410
        self.assertIs(self.wt.is_executable('name'), True)
392
 
        self.assertEqual(self.wt.path2id('oz'), b'oz-id')
393
 
        self.assertEqual(self.wt.path2id('oz/dorothy'), b'dorothy-id')
394
 
        self.assertEqual(self.wt.path2id('oz/dorothy/toto'), b'toto-id')
 
411
        self.assertTrue(self.wt.is_versioned('name'))
 
412
        self.assertTrue(self.wt.is_versioned('oz'))
 
413
        self.assertTrue(self.wt.is_versioned('oz/dorothy'))
 
414
        self.assertTrue(self.wt.is_versioned('oz/dorothy/toto'))
 
415
        if self.wt.supports_setting_file_ids():
 
416
            self.assertEqual(self.wt.path2id('name'), b'my_pretties')
 
417
            self.assertEqual(self.wt.path2id('oz'), b'oz-id')
 
418
            self.assertEqual(self.wt.path2id('oz/dorothy'), b'dorothy-id')
 
419
            self.assertEqual(self.wt.path2id('oz/dorothy/toto'), b'toto-id')
395
420
 
396
 
        self.assertEqual(b'toto-contents',
397
 
                         self.wt.get_file('oz/dorothy/toto').read())
 
421
        with self.wt.get_file('oz/dorothy/toto') as f:
 
422
            self.assertEqual(b'toto-contents', f.read())
398
423
        self.assertIs(self.wt.is_executable('oz/dorothy/toto'), False)
399
424
 
400
425
    def test_tree_reference(self):
403
428
        if not tree.supports_tree_reference():
404
429
            raise tests.TestNotApplicable(
405
430
                'Tree format does not support references')
 
431
        nested_tree = self.make_branch_and_tree('nested')
 
432
        nested_revid = nested_tree.commit('commit')
406
433
 
407
434
        trans_id = transform.new_directory('reference', root, b'subtree-id')
408
 
        transform.set_tree_reference(b'subtree-revision', trans_id)
 
435
        transform.set_tree_reference(nested_revid, trans_id)
409
436
        transform.apply()
410
437
        tree.lock_read()
411
438
        self.addCleanup(tree.unlock)
412
439
        self.assertEqual(
413
 
            b'subtree-revision',
414
 
            tree.root_inventory.get_entry(b'subtree-id').reference_revision)
 
440
            nested_revid,
 
441
            tree.get_reference_revision('reference'))
415
442
 
416
443
    def test_conflicts(self):
417
444
        transform, root = self.transform()
427
454
                         [('non-directory parent', trans_id)])
428
455
        tinman_id = transform.trans_id_tree_path('tinman')
429
456
        transform.adjust_path('name', tinman_id, trans_id2)
430
 
        self.assertEqual(transform.find_raw_conflicts(),
431
 
                         [('unversioned parent', tinman_id),
432
 
                          ('missing parent', tinman_id)])
 
457
        if self.wt.has_versioned_directories():
 
458
            self.assertEqual(transform.find_raw_conflicts(),
 
459
                             [('unversioned parent', tinman_id),
 
460
                              ('missing parent', tinman_id)])
 
461
        else:
 
462
            self.assertEqual(transform.find_raw_conflicts(),
 
463
                             [('missing parent', tinman_id)])
433
464
        lion_id = transform.create_path('lion', root)
434
 
        self.assertEqual(transform.find_raw_conflicts(),
435
 
                         [('unversioned parent', tinman_id),
436
 
                          ('missing parent', tinman_id)])
 
465
        if self.wt.has_versioned_directories():
 
466
            self.assertEqual(transform.find_raw_conflicts(),
 
467
                             [('unversioned parent', tinman_id),
 
468
                              ('missing parent', tinman_id)])
 
469
        else:
 
470
            self.assertEqual(transform.find_raw_conflicts(),
 
471
                             [('missing parent', tinman_id)])
437
472
        transform.adjust_path('name', lion_id, trans_id2)
438
 
        self.assertEqual(transform.find_raw_conflicts(),
439
 
                         [('unversioned parent', lion_id),
440
 
                          ('missing parent', lion_id)])
 
473
        if self.wt.has_versioned_directories():
 
474
            self.assertEqual(transform.find_raw_conflicts(),
 
475
                             [('unversioned parent', lion_id),
 
476
                              ('missing parent', lion_id)])
 
477
        else:
 
478
            self.assertEqual(transform.find_raw_conflicts(),
 
479
                             [('missing parent', lion_id)])
441
480
        transform.version_file(lion_id, file_id=b"Courage")
442
481
        self.assertEqual(transform.find_raw_conflicts(),
443
482
                         [('missing parent', lion_id),
461
500
        transform.set_executability(None, oz_id)
462
501
        tip_id = transform.new_file('tip', oz_id, [b'ozma'], b'tip-id')
463
502
        transform.apply()
464
 
        self.assertEqual(self.wt.path2id('name'), b'my_pretties')
 
503
        if self.wt.supports_setting_file_ids():
 
504
            self.assertEqual(self.wt.path2id('name'), b'my_pretties')
465
505
        with open(self.wt.abspath('name'), 'rb') as f:
466
506
            self.assertEqual(b'contents', f.read())
467
507
        transform2, root = self.transform()
471
511
        fp = FinalPaths(transform2)
472
512
        self.assertTrue('oz/tip' in transform2._tree_path_ids)
473
513
        self.assertEqual(fp.get_path(newtip), pathjoin('oz', 'tip'))
474
 
        self.assertEqual(len(result), 2)
 
514
        if self.wt.supports_setting_file_ids():
 
515
            self.assertEqual(len(result), 2)
 
516
            self.assertEqual((result[1][0], result[1][2]),
 
517
                             ('duplicate id', newtip))
 
518
        else:
 
519
            self.assertEqual(len(result), 1)
475
520
        self.assertEqual((result[0][0], result[0][1]),
476
521
                         ('duplicate', newtip))
477
 
        self.assertEqual((result[1][0], result[1][2]),
478
 
                         ('duplicate id', newtip))
479
522
        transform2.finalize()
480
523
        transform3 = self.wt.transform()
481
524
        self.addCleanup(transform3.finalize)
626
669
        self.addCleanup(unversion.finalize)
627
670
        parent = unversion.trans_id_tree_path('parent')
628
671
        unversion.unversion_file(parent)
629
 
        self.assertEqual(unversion.find_raw_conflicts(),
630
 
                         [('unversioned parent', parent_id)])
 
672
        if self.wt.has_versioned_directories():
 
673
            self.assertEqual(unversion.find_raw_conflicts(),
 
674
                             [('unversioned parent', parent_id)])
 
675
        else:
 
676
            self.assertEqual(unversion.find_raw_conflicts(), [])
631
677
        file_id = unversion.trans_id_tree_path('parent/child')
632
678
        unversion.unversion_file(file_id)
633
679
        unversion.apply()
666
712
        mfile2 = mangle_tree.trans_id_tree_path('moving_file2')
667
713
        mangle_tree.adjust_path('mfile2', newdir, mfile2)
668
714
        mangle_tree.new_file('newfile', newdir, [b'hello3'], b'dfile')
669
 
        self.assertEqual(mangle_tree.final_file_id(mfile2), b'mfile2')
 
715
        if self.wt.supports_setting_file_ids():
 
716
            self.assertEqual(mangle_tree.final_file_id(mfile2), b'mfile2')
670
717
        self.assertEqual(mangle_tree.final_parent(mfile2), newdir)
671
 
        self.assertEqual(mangle_tree.final_file_id(mfile2), b'mfile2')
672
718
        mangle_tree.apply()
673
719
        with open(self.wt.abspath('name1'), 'r') as f:
674
720
            self.assertEqual(f.read(), 'hello2')
678
724
        self.assertEqual(mangle_tree.final_parent(mfile2), newdir)
679
725
        with open(mfile2_path, 'r') as f:
680
726
            self.assertEqual(f.read(), 'later2')
681
 
        self.assertEqual(self.wt.id2path(b'mfile2'), 'new_directory/mfile2')
682
 
        self.assertEqual(self.wt.path2id('new_directory/mfile2'), b'mfile2')
 
727
        if self.wt.supports_setting_file_ids():
 
728
            self.assertEqual(self.wt.id2path(b'mfile2'), 'new_directory/mfile2')
 
729
            self.assertEqual(self.wt.path2id('new_directory/mfile2'), b'mfile2')
683
730
        newfile_path = self.wt.abspath(pathjoin('new_directory', 'newfile'))
684
731
        with open(newfile_path, 'r') as f:
685
732
            self.assertEqual(f.read(), 'hello3')
686
 
        self.assertEqual(self.wt.path2id('dying_directory'), b'ddir')
687
 
        self.assertIs(self.wt.path2id('dying_directory/dying_file'), None)
 
733
        if self.wt.supports_setting_file_ids():
 
734
            self.assertEqual(self.wt.path2id('dying_directory'), b'ddir')
 
735
            self.assertIs(self.wt.path2id('dying_directory/dying_file'), None)
688
736
        mfile2_path = self.wt.abspath(pathjoin('new_directory', 'mfile2'))
689
737
 
690
738
    def test_both_rename(self):
767
815
        name2 = replace.new_file('name2', root, [b'hello2'], b'name1')
768
816
        conflicts = replace.find_raw_conflicts()
769
817
        name1 = replace.trans_id_tree_path('name1')
770
 
        self.assertEqual(conflicts, [('duplicate id', name1, name2)])
 
818
        if self.wt.supports_setting_file_ids():
 
819
            self.assertEqual(conflicts, [('duplicate id', name1, name2)])
 
820
        else:
 
821
            self.assertEqual(conflicts, [])
771
822
        resolve_conflicts(replace)
772
823
        replace.apply()
773
824
 
789
840
                         [('non-file executability', wiz_id)])
790
841
        transform.set_executability(None, wiz_id)
791
842
        transform.apply()
792
 
        self.assertEqual(self.wt.path2id(ozpath(link_name1)), b'wizard-id')
 
843
        if self.wt.supports_setting_file_ids():
 
844
            self.assertEqual(self.wt.path2id(ozpath(link_name1)), b'wizard-id')
793
845
        self.assertEqual('symlink',
794
846
                         file_kind(self.wt.abspath(ozpath(link_name1))))
795
847
        self.assertEqual(link_target2,
840
892
        conflicts.delete_versioned(oz)
841
893
        emerald = conflicts.trans_id_tree_path('oz/emeraldcity')
842
894
        # set up MissingParent conflict
843
 
        munchkincity = conflicts.trans_id_file_id(b'munchkincity-id')
 
895
        if conflicts._tree.supports_setting_file_ids():
 
896
            munchkincity = conflicts.trans_id_file_id(b'munchkincity-id')
 
897
        else:
 
898
            munchkincity = conflicts.assign_id()
844
899
        conflicts.adjust_path('munchkincity', root, munchkincity)
845
900
        conflicts.new_directory('auntem', munchkincity, b'auntem-id')
846
901
        # set up parent loop
847
902
        conflicts.adjust_path('emeraldcity', emerald, emerald)
848
 
        return conflicts, emerald, oz, old_dorothy, new_dorothy
 
903
        return conflicts, emerald, oz, old_dorothy, new_dorothy, munchkincity
849
904
 
850
905
    def test_conflict_resolution(self):
851
 
        conflicts, emerald, oz, old_dorothy, new_dorothy =\
 
906
        conflicts, emerald, oz, old_dorothy, new_dorothy, munchkincity =\
852
907
            self.get_conflicted()
853
908
        resolve_conflicts(conflicts)
854
909
        self.assertEqual(conflicts.final_name(old_dorothy), 'dorothy.moved')
855
 
        self.assertIs(conflicts.final_file_id(old_dorothy), None)
 
910
        if self.wt.supports_setting_file_ids():
 
911
            self.assertIs(conflicts.final_file_id(old_dorothy), None)
 
912
            self.assertEqual(conflicts.final_file_id(new_dorothy), b'dorothy-id')
856
913
        self.assertEqual(conflicts.final_name(new_dorothy), 'dorothy')
857
 
        self.assertEqual(conflicts.final_file_id(new_dorothy), b'dorothy-id')
858
914
        self.assertEqual(conflicts.final_parent(emerald), oz)
859
915
        conflicts.apply()
860
916
 
861
917
    def test_cook_conflicts(self):
862
 
        tt, emerald, oz, old_dorothy, new_dorothy = self.get_conflicted()
 
918
        tt, emerald, oz, old_dorothy, new_dorothy, munchkincity = self.get_conflicted()
863
919
        raw_conflicts = resolve_conflicts(tt)
864
 
        cooked_conflicts = tt.cook_conflicts(raw_conflicts)
865
 
        duplicate = DuplicateEntry('Moved existing file to', 'dorothy.moved',
866
 
                                   'dorothy', None, b'dorothy-id')
867
 
        self.assertEqual(cooked_conflicts[0], duplicate)
868
 
        duplicate_id = DuplicateID('Unversioned existing file',
869
 
                                   'dorothy.moved', 'dorothy', None,
870
 
                                   b'dorothy-id')
871
 
        self.assertEqual(cooked_conflicts[1], duplicate_id)
872
 
        missing_parent = MissingParent('Created directory', 'munchkincity',
873
 
                                       b'munchkincity-id')
874
 
        deleted_parent = DeletingParent('Not deleting', 'oz', b'oz-id')
875
 
        self.assertEqual(cooked_conflicts[2], missing_parent)
876
 
        unversioned_parent = UnversionedParent('Versioned directory',
877
 
                                               'munchkincity',
878
 
                                               b'munchkincity-id')
879
 
        unversioned_parent2 = UnversionedParent('Versioned directory', 'oz',
880
 
                                                b'oz-id')
881
 
        self.assertEqual(cooked_conflicts[3], unversioned_parent)
882
 
        parent_loop = ParentLoop(
883
 
            'Cancelled move', 'oz/emeraldcity',
884
 
            'oz/emeraldcity', b'emerald-id', b'emerald-id')
885
 
        self.assertEqual(cooked_conflicts[4], deleted_parent)
886
 
        self.assertEqual(cooked_conflicts[5], unversioned_parent2)
887
 
        self.assertEqual(cooked_conflicts[6], parent_loop)
888
 
        self.assertEqual(len(cooked_conflicts), 7)
 
920
        cooked_conflicts = list(tt.cook_conflicts(raw_conflicts))
 
921
        if self.wt.supports_setting_file_ids():
 
922
            duplicate = DuplicateEntry('Moved existing file to', 'dorothy.moved',
 
923
                                       'dorothy', None, b'dorothy-id')
 
924
            self.assertEqual(cooked_conflicts[0], duplicate)
 
925
            duplicate_id = DuplicateID('Unversioned existing file',
 
926
                                       'dorothy.moved', 'dorothy', None,
 
927
                                       b'dorothy-id')
 
928
            self.assertEqual(cooked_conflicts[1], duplicate_id)
 
929
            missing_parent = MissingParent('Created directory', 'munchkincity',
 
930
                                           b'munchkincity-id')
 
931
            deleted_parent = DeletingParent('Not deleting', 'oz', b'oz-id')
 
932
            self.assertEqual(cooked_conflicts[2], missing_parent)
 
933
            unversioned_parent = UnversionedParent('Versioned directory',
 
934
                                                   'munchkincity',
 
935
                                                   b'munchkincity-id')
 
936
            unversioned_parent2 = UnversionedParent('Versioned directory', 'oz',
 
937
                                                    b'oz-id')
 
938
            self.assertEqual(cooked_conflicts[3], unversioned_parent)
 
939
            parent_loop = ParentLoop(
 
940
                'Cancelled move', 'oz/emeraldcity',
 
941
                'oz/emeraldcity', b'emerald-id', b'emerald-id')
 
942
            self.assertEqual(cooked_conflicts[4], deleted_parent)
 
943
            self.assertEqual(cooked_conflicts[5], unversioned_parent2)
 
944
            self.assertEqual(cooked_conflicts[6], parent_loop)
 
945
            self.assertEqual(len(cooked_conflicts), 7)
 
946
        else:
 
947
            self.assertEqual(
 
948
                set([c.path for c in cooked_conflicts]),
 
949
                set(['oz/emeraldcity', 'oz', 'munchkincity', 'dorothy.moved']))
889
950
        tt.finalize()
890
951
 
891
952
    def test_string_conflicts(self):
892
 
        tt, emerald, oz, old_dorothy, new_dorothy = self.get_conflicted()
 
953
        tt, emerald, oz, old_dorothy, new_dorothy, munchkincity = self.get_conflicted()
893
954
        raw_conflicts = resolve_conflicts(tt)
894
 
        cooked_conflicts = tt.cook_conflicts(raw_conflicts)
 
955
        cooked_conflicts = list(tt.cook_conflicts(raw_conflicts))
895
956
        tt.finalize()
896
957
        conflicts_s = [str(c) for c in cooked_conflicts]
897
958
        self.assertEqual(len(cooked_conflicts), len(conflicts_s))
898
 
        self.assertEqual(conflicts_s[0], 'Conflict adding file dorothy.  '
899
 
                                         'Moved existing file to '
900
 
                                         'dorothy.moved.')
901
 
        self.assertEqual(conflicts_s[1], 'Conflict adding id to dorothy.  '
902
 
                                         'Unversioned existing file '
903
 
                                         'dorothy.moved.')
904
 
        self.assertEqual(conflicts_s[2], 'Conflict adding files to'
905
 
                                         ' munchkincity.  Created directory.')
906
 
        self.assertEqual(conflicts_s[3], 'Conflict because munchkincity is not'
907
 
                                         ' versioned, but has versioned'
908
 
                                         ' children.  Versioned directory.')
909
 
        self.assertEqualDiff(
910
 
            conflicts_s[4], "Conflict: can't delete oz because it"
911
 
                            " is not empty.  Not deleting.")
912
 
        self.assertEqual(conflicts_s[5], 'Conflict because oz is not'
913
 
                                         ' versioned, but has versioned'
914
 
                                         ' children.  Versioned directory.')
915
 
        self.assertEqual(conflicts_s[6], 'Conflict moving oz/emeraldcity into'
916
 
                                         ' oz/emeraldcity. Cancelled move.')
 
959
        if self.wt.supports_setting_file_ids():
 
960
            self.assertEqual(conflicts_s[0], 'Conflict adding file dorothy.  '
 
961
                                             'Moved existing file to '
 
962
                                             'dorothy.moved.')
 
963
            self.assertEqual(conflicts_s[1], 'Conflict adding id to dorothy.  '
 
964
                                             'Unversioned existing file '
 
965
                                             'dorothy.moved.')
 
966
            self.assertEqual(conflicts_s[2], 'Conflict adding files to'
 
967
                                             ' munchkincity.  Created directory.')
 
968
            self.assertEqual(conflicts_s[3], 'Conflict because munchkincity is not'
 
969
                                             ' versioned, but has versioned'
 
970
                                             ' children.  Versioned directory.')
 
971
            self.assertEqualDiff(
 
972
                conflicts_s[4], "Conflict: can't delete oz because it"
 
973
                                " is not empty.  Not deleting.")
 
974
            self.assertEqual(conflicts_s[5], 'Conflict because oz is not'
 
975
                                             ' versioned, but has versioned'
 
976
                                             ' children.  Versioned directory.')
 
977
            self.assertEqual(conflicts_s[6], 'Conflict moving oz/emeraldcity into'
 
978
                                             ' oz/emeraldcity. Cancelled move.')
 
979
        else:
 
980
            self.assertEqual(
 
981
                {'Text conflict in dorothy.moved',
 
982
                 'Text conflict in munchkincity',
 
983
                 'Text conflict in oz',
 
984
                 'Text conflict in oz/emeraldcity'},
 
985
                set([c for c in conflicts_s]))
917
986
 
918
987
    def prepare_wrong_parent_kind(self):
919
988
        tt, root = self.transform()
920
989
        tt.new_file('parent', root, [b'contents'], b'parent-id')
921
990
        tt.apply()
922
991
        tt, root = self.transform()
923
 
        parent_id = tt.trans_id_file_id(b'parent-id')
 
992
        parent_id = tt.trans_id_tree_path('parent')
924
993
        tt.new_file('child,', parent_id, [b'contents2'], b'file-id')
925
994
        return tt
926
995
 
933
1002
        raw_conflicts = resolve_conflicts(tt)
934
1003
        self.assertEqual({('non-directory parent', 'Created directory',
935
1004
                           'new-3')}, raw_conflicts)
936
 
        cooked_conflicts = tt.cook_conflicts(raw_conflicts)
937
 
        self.assertEqual([NonDirectoryParent('Created directory', 'parent.new',
938
 
                                             b'parent-id')], cooked_conflicts)
 
1005
        cooked_conflicts = list(tt.cook_conflicts(raw_conflicts))
 
1006
        from ...bzr.workingtree import InventoryWorkingTree
 
1007
        if isinstance(tt._tree, InventoryWorkingTree):
 
1008
            self.assertEqual([NonDirectoryParent('Created directory', 'parent.new',
 
1009
                                                 b'parent-id')], cooked_conflicts)
 
1010
        else:
 
1011
            self.assertEqual(1, len(cooked_conflicts))
 
1012
            self.assertEqual('parent.new', cooked_conflicts[0].path)
939
1013
        tt.apply()
940
 
        self.assertFalse(self.wt.is_versioned('parent'))
941
 
        self.assertEqual(b'parent-id', self.wt.path2id('parent.new'))
 
1014
        if self.wt.has_versioned_directories():
 
1015
            self.assertFalse(self.wt.is_versioned('parent'))
 
1016
        if self.wt.supports_setting_file_ids():
 
1017
            self.assertEqual(b'parent-id', self.wt.path2id('parent.new'))
942
1018
 
943
1019
    def test_resolve_conflicts_wrong_new_parent_kind(self):
944
1020
        tt, root = self.transform()
946
1022
        tt.new_file('child,', parent_id, [b'contents2'], b'file-id')
947
1023
        tt.apply()
948
1024
        tt, root = self.transform()
949
 
        parent_id = tt.trans_id_file_id(b'parent-id')
 
1025
        parent_id = tt.trans_id_tree_path('parent')
950
1026
        tt.delete_contents(parent_id)
951
1027
        tt.create_file([b'contents'], parent_id)
952
1028
        raw_conflicts = resolve_conflicts(tt)
953
1029
        self.assertEqual({('non-directory parent', 'Created directory',
954
1030
                           'new-3')}, raw_conflicts)
955
1031
        tt.apply()
956
 
        self.assertFalse(self.wt.is_versioned('parent'))
957
 
        self.assertEqual(b'parent-id', self.wt.path2id('parent.new'))
 
1032
        if self.wt.has_versioned_directories():
 
1033
            self.assertFalse(self.wt.is_versioned('parent'))
 
1034
            self.assertTrue(self.wt.is_versioned('parent.new'))
 
1035
        if self.wt.supports_setting_file_ids():
 
1036
            self.assertEqual(b'parent-id', self.wt.path2id('parent.new'))
958
1037
 
959
1038
    def test_resolve_conflicts_wrong_parent_kind_unversioned(self):
960
1039
        tt, root = self.transform()
967
1046
        tt.create_file([b'contents'], parent_id)
968
1047
        resolve_conflicts(tt)
969
1048
        tt.apply()
970
 
        self.assertFalse(self.wt.is_versioned('parent'))
971
 
        self.assertFalse(self.wt.is_versioned('parent.new'))
 
1049
        if self.wt.has_versioned_directories():
 
1050
            self.assertFalse(self.wt.is_versioned('parent'))
 
1051
            self.assertFalse(self.wt.is_versioned('parent.new'))
972
1052
 
973
1053
    def test_resolve_conflicts_missing_parent(self):
974
1054
        wt = self.make_branch_and_tree('.')
975
1055
        tt = wt.transform()
976
1056
        self.addCleanup(tt.finalize)
977
 
        parent = tt.trans_id_file_id(b'parent-id')
 
1057
        parent = tt.assign_id()
978
1058
        tt.new_file('file', parent, [b'Contents'])
979
1059
        raw_conflicts = resolve_conflicts(tt)
980
1060
        # Since the directory doesn't exist it's seen as 'missing'.  So
1017
1097
                                 b'myfile-id')
1018
1098
        create.apply()
1019
1099
        rename, root = self.transform()
1020
 
        old = rename.trans_id_file_id(b'old-id')
 
1100
        old = rename.trans_id_tree_path('old-parent')
1021
1101
        rename.adjust_path('new', root, old)
1022
 
        myfile = rename.trans_id_file_id(b'myfile-id')
 
1102
        myfile = rename.trans_id_tree_path('old-parent/intermediate/myfile')
1023
1103
        rename.set_executability(True, myfile)
1024
1104
        rename.apply()
1025
1105
 
1040
1120
            self.skipTest("Can't force a permissions error on rename")
1041
1121
        # now transform to rename
1042
1122
        rename_transform, root_id = self.transform()
1043
 
        file_trans_id = rename_transform.trans_id_file_id(b'myfile-id')
1044
 
        dir_id = rename_transform.trans_id_file_id(b'first-id')
 
1123
        file_trans_id = rename_transform.trans_id_tree_path('myfile')
 
1124
        dir_id = rename_transform.trans_id_tree_path('first-dir')
1045
1125
        rename_transform.adjust_path('newname', dir_id, file_trans_id)
1046
1126
        e = self.assertRaises(TransformRenameFailed,
1047
1127
                              rename_transform.apply)
1142
1222
        transform.apply()
1143
1223
        transform, root = self.transform()
1144
1224
        try:
1145
 
            self.assertEqual([], list(transform.iter_changes()))
 
1225
            self.assertTreeChanges(transform, [])
1146
1226
            old = transform.trans_id_tree_path('old')
1147
1227
            transform.unversion_file(old)
1148
 
            self.assertEqual([(b'id-1', ('old', None), False, (True, False),
1149
 
                               (root_id, root_id),
1150
 
                               ('old', 'old'), ('file', 'file'),
1151
 
                               (True, True), False)],
1152
 
                             list(transform.iter_changes()))
 
1228
            self.assertTreeChanges(
 
1229
                transform, [
 
1230
                    InventoryTreeChange(
 
1231
                        b'id-1', ('old', None), False, (True, False),
 
1232
                        (root_id, root_id), ('old', 'old'), ('file', 'file'),
 
1233
                        (True, True), False)])
1153
1234
            transform.new_directory('new', root, b'id-1')
1154
 
            self.assertEqual([(b'id-1', ('old', 'new'), True, (True, True),
1155
 
                               (root_id, root_id), ('old', 'new'),
1156
 
                               ('file', 'directory'),
1157
 
                               (True, False), False)],
1158
 
                             list(transform.iter_changes()))
 
1235
            if transform._tree.supports_setting_file_ids():
 
1236
                self.assertTreeChanges(
 
1237
                    transform,
 
1238
                    [InventoryTreeChange(
 
1239
                        b'id-1', ('old', 'new'), True, (True, True),
 
1240
                        (root_id, root_id), ('old', 'new'),
 
1241
                        ('file', 'directory'),
 
1242
                        (True, False), False)])
 
1243
            else:
 
1244
                self.assertTreeChanges(
 
1245
                    transform,
 
1246
                    [TreeChange(
 
1247
                        (None, 'new'), False, (False, True),
 
1248
                        (None, 'new'), (None, 'directory'),
 
1249
                        (False, False), False),
 
1250
                     TreeChange(
 
1251
                        ('old', None), False, (True, False),
 
1252
                        ('old', 'old'), ('file', 'file'),
 
1253
                        (True, True), False)])
1159
1254
        finally:
1160
1255
            transform.finalize()
1161
1256
 
1168
1263
        try:
1169
1264
            old = transform.trans_id_tree_path('old')
1170
1265
            transform.version_file(old, file_id=b'id-1')
1171
 
            self.assertEqual([(b'id-1', (None, 'old'), False, (False, True),
1172
 
                               (root_id, root_id),
1173
 
                               ('old', 'old'), ('file', 'file'),
1174
 
                               (False, False), False)],
1175
 
                             list(transform.iter_changes()))
 
1266
            changes = list(transform.iter_changes())
 
1267
            self.assertEqual(1, len(changes))
 
1268
            self.assertEqual((None, 'old'), changes[0].path)
 
1269
            self.assertEqual(False, changes[0].changed_content)
 
1270
            self.assertEqual((False, True), changes[0].versioned)
 
1271
            self.assertEqual((False, False), changes[0].executable)
 
1272
            if self.wt.supports_setting_file_ids():
 
1273
                self.assertEqual((root_id, root_id), changes[0].parent_id)
 
1274
                self.assertEqual(b'id-1', changes[0].file_id)
1176
1275
        finally:
1177
1276
            transform.finalize()
1178
1277
 
1188
1287
            old = transform.trans_id_tree_path('old')
1189
1288
            subdir = transform.trans_id_tree_path('subdir')
1190
1289
            new = transform.trans_id_tree_path('new')
1191
 
            self.assertEqual([], list(transform.iter_changes()))
 
1290
            self.assertTreeChanges(transform, [])
1192
1291
 
1193
1292
            # content deletion
1194
1293
            transform.delete_contents(old)
1195
 
            self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
1196
 
                               (root_id, root_id),
1197
 
                               ('old', 'old'), ('file', None),
1198
 
                               (False, False), False)],
1199
 
                             list(transform.iter_changes()))
 
1294
            self.assertTreeChanges(
 
1295
                transform,
 
1296
                [InventoryTreeChange(
 
1297
                    b'id-1', ('old', 'old'), True, (True, True),
 
1298
                    (root_id, root_id),
 
1299
                    ('old', 'old'), ('file', None),
 
1300
                    (False, False), False)])
1200
1301
 
1201
1302
            # content change
1202
1303
            transform.create_file([b'blah'], old)
1203
 
            self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
1204
 
                               (root_id, root_id),
1205
 
                               ('old', 'old'), ('file', 'file'),
1206
 
                               (False, False), False)],
1207
 
                             list(transform.iter_changes()))
 
1304
            self.assertTreeChanges(
 
1305
                transform,
 
1306
                [InventoryTreeChange(
 
1307
                    b'id-1', ('old', 'old'), True, (True, True),
 
1308
                    (root_id, root_id),
 
1309
                    ('old', 'old'), ('file', 'file'),
 
1310
                    (False, False), False)])
1208
1311
            transform.cancel_deletion(old)
1209
 
            self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
1210
 
                               (root_id, root_id),
1211
 
                               ('old', 'old'), ('file', 'file'),
1212
 
                               (False, False), False)],
1213
 
                             list(transform.iter_changes()))
 
1312
            self.assertTreeChanges(
 
1313
                transform,
 
1314
                [InventoryTreeChange(
 
1315
                    b'id-1', ('old', 'old'), True, (True, True),
 
1316
                    (root_id, root_id),
 
1317
                    ('old', 'old'), ('file', 'file'),
 
1318
                    (False, False), False)])
1214
1319
            transform.cancel_creation(old)
1215
1320
 
1216
1321
            # move file_id to a different file
1217
 
            self.assertEqual([], list(transform.iter_changes()))
 
1322
            self.assertTreeChanges(transform, [])
1218
1323
            transform.unversion_file(old)
1219
1324
            transform.version_file(new, file_id=b'id-1')
1220
1325
            transform.adjust_path('old', root, new)
1221
 
            self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
1222
 
                               (root_id, root_id),
1223
 
                               ('old', 'old'), ('file', 'file'),
1224
 
                               (False, False), False)],
1225
 
                             list(transform.iter_changes()))
 
1326
            if transform._tree.supports_setting_file_ids():
 
1327
                self.assertTreeChanges(
 
1328
                    transform,
 
1329
                    [InventoryTreeChange(
 
1330
                        b'id-1', ('old', 'old'), True, (True, True),
 
1331
                        (root_id, root_id),
 
1332
                        ('old', 'old'), ('file', 'file'),
 
1333
                        (False, False), False)])
 
1334
            else:
 
1335
                self.assertTreeChanges(
 
1336
                    transform,
 
1337
                    [TreeChange(
 
1338
                        (None, 'old'), False, (False, True),
 
1339
                        (None, 'old'), (None, 'file'), (False, False), False),
 
1340
                     TreeChange(
 
1341
                         ('old', None), False, (True, False), ('old', 'old'),
 
1342
                         ('file', 'file'), (False, False), False)])
 
1343
 
1226
1344
            transform.cancel_versioning(new)
1227
1345
            transform._removed_id = set()
1228
1346
 
1229
1347
            # execute bit
1230
 
            self.assertEqual([], list(transform.iter_changes()))
 
1348
            self.assertTreeChanges(transform, [])
1231
1349
            transform.set_executability(True, old)
1232
 
            self.assertEqual([(b'id-1', ('old', 'old'), False, (True, True),
1233
 
                               (root_id, root_id),
1234
 
                               ('old', 'old'), ('file', 'file'),
1235
 
                               (False, True), False)],
1236
 
                             list(transform.iter_changes()))
 
1350
            self.assertTreeChanges(
 
1351
                transform,
 
1352
                [InventoryTreeChange(
 
1353
                    b'id-1', ('old', 'old'), False, (True, True),
 
1354
                    (root_id, root_id),
 
1355
                    ('old', 'old'), ('file', 'file'),
 
1356
                    (False, True), False)])
1237
1357
            transform.set_executability(None, old)
1238
1358
 
1239
1359
            # filename
1240
 
            self.assertEqual([], list(transform.iter_changes()))
 
1360
            self.assertTreeChanges(transform, [])
1241
1361
            transform.adjust_path('new', root, old)
1242
1362
            transform._new_parent = {}
1243
 
            self.assertEqual([(b'id-1', ('old', 'new'), False, (True, True),
1244
 
                               (root_id, root_id),
1245
 
                               ('old', 'new'), ('file', 'file'),
1246
 
                               (False, False), False)],
1247
 
                             list(transform.iter_changes()))
 
1363
            self.assertTreeChanges(
 
1364
                transform,
 
1365
                [InventoryTreeChange(
 
1366
                    b'id-1', ('old', 'new'), False, (True, True),
 
1367
                    (root_id, root_id),
 
1368
                    ('old', 'new'), ('file', 'file'),
 
1369
                    (False, False), False)])
1248
1370
            transform._new_name = {}
1249
1371
 
1250
1372
            # parent directory
1251
 
            self.assertEqual([], list(transform.iter_changes()))
 
1373
            self.assertTreeChanges(transform, [])
1252
1374
            transform.adjust_path('new', subdir, old)
1253
1375
            transform._new_name = {}
1254
 
            self.assertEqual([(b'id-1', ('old', 'subdir/old'), False,
1255
 
                               (True, True), (root_id, b'subdir-id'), ('old', 'old'),
1256
 
                               ('file', 'file'), (False, False), False)],
1257
 
                             list(transform.iter_changes()))
 
1376
            self.assertTreeChanges(
 
1377
                transform, [
 
1378
                    InventoryTreeChange(
 
1379
                        b'id-1', ('old', 'subdir/old'), False,
 
1380
                        (True, True), (root_id, b'subdir-id'), ('old', 'old'),
 
1381
                        ('file', 'file'), (False, False), False)])
1258
1382
            transform._new_path = {}
1259
 
 
1260
1383
        finally:
1261
1384
            transform.finalize()
1262
1385
 
 
1386
    def assertTreeChanges(self, tt, expected):
 
1387
        # TODO(jelmer): Turn this into a matcher?
 
1388
        actual = list(tt.iter_changes())
 
1389
        if tt._tree.supports_setting_file_ids():
 
1390
            self.assertEqual(expected, actual)
 
1391
        else:
 
1392
            expected = [
 
1393
                TreeChange(path=c.path, changed_content=c.changed_content,
 
1394
                           versioned=c.versioned, name=c.name,
 
1395
                           kind=c.kind, executable=c.executable,
 
1396
                           copied=c.copied) for c in expected]
 
1397
            actual = [
 
1398
                TreeChange(path=c.path, changed_content=c.changed_content,
 
1399
                           versioned=c.versioned, name=c.name,
 
1400
                           kind=c.kind, executable=c.executable,
 
1401
                           copied=c.copied) for c in actual]
 
1402
            self.assertEqual(expected, actual)
 
1403
 
1263
1404
    def test_iter_changes_modified_bleed(self):
1264
1405
        root_id = self.wt.path2id('')
1265
1406
        """Modified flag should not bleed from one change to another"""
1273
1414
        transform.apply()
1274
1415
        transform, root = self.transform()
1275
1416
        try:
1276
 
            transform.delete_contents(transform.trans_id_file_id(b'id-1'))
1277
 
            transform.set_executability(True,
1278
 
                                        transform.trans_id_file_id(b'id-2'))
1279
 
            self.assertEqual(
1280
 
                [(b'id-1', (u'file1', u'file1'), True, (True, True),
1281
 
                 (root_id, root_id), ('file1', u'file1'),
1282
 
                 ('file', None), (False, False), False),
1283
 
                 (b'id-2', (u'file2', u'file2'), False, (True, True),
1284
 
                 (root_id, root_id), ('file2', u'file2'),
1285
 
                 ('file', 'file'), (False, True), False)],
1286
 
                list(transform.iter_changes()))
 
1417
            transform.delete_contents(transform.trans_id_tree_path('file1'))
 
1418
            transform.set_executability(True, transform.trans_id_tree_path('file2'))
 
1419
            self.assertTreeChanges(transform, [
 
1420
                InventoryTreeChange(
 
1421
                b'id-1', (u'file1', u'file1'), True, (True, True),
 
1422
                (root_id, root_id), ('file1', u'file1'),
 
1423
                ('file', None), (False, False), False),
 
1424
                InventoryTreeChange(
 
1425
                b'id-2', (u'file2', u'file2'), False, (True, True),
 
1426
                (root_id, root_id), ('file2', u'file2'),
 
1427
                ('file', 'file'), (False, True), False)])
1287
1428
        finally:
1288
1429
            transform.finalize()
1289
1430
 
1301
1442
        floater = transform.trans_id_tree_path('floater')
1302
1443
        try:
1303
1444
            transform.adjust_path('flitter', root, floater)
1304
 
            self.assertEqual([(b'floater-id', ('floater', 'flitter'), False,
1305
 
                               (True, True),
1306
 
                               (root_id, root_id),
1307
 
                               ('floater', 'flitter'),
1308
 
                               (None, None), (False, False), False)],
1309
 
                             list(transform.iter_changes()))
 
1445
            if self.wt.has_versioned_directories():
 
1446
                self.assertTreeChanges(
 
1447
                    transform,
 
1448
                    [InventoryTreeChange(
 
1449
                        b'floater-id', ('floater', 'flitter'), False,
 
1450
                        (True, True),
 
1451
                        (root_id, root_id),
 
1452
                        ('floater', 'flitter'),
 
1453
                        (None, None), (False, False), False)])
 
1454
            else:
 
1455
                self.assertTreeChanges(transform, [])
1310
1456
        finally:
1311
1457
            transform.finalize()
1312
1458
 
1320
1466
        try:
1321
1467
            old = transform.trans_id_tree_path('old')
1322
1468
            subdir = transform.trans_id_tree_path('subdir')
1323
 
            self.assertEqual([], list(transform.iter_changes()))
 
1469
            self.assertTreeChanges(transform, [])
1324
1470
            transform.delete_contents(subdir)
1325
1471
            transform.create_directory(subdir)
1326
1472
            transform.set_executability(False, old)
1327
1473
            transform.unversion_file(old)
1328
1474
            transform.version_file(old, file_id=b'id-1')
1329
1475
            transform.adjust_path('old', root, old)
1330
 
            self.assertEqual([], list(transform.iter_changes()))
 
1476
            self.assertTreeChanges(transform, [])
1331
1477
        finally:
1332
1478
            transform.finalize()
1333
1479
 
1415
1561
    def test_noname_contents(self):
1416
1562
        """TreeTransform should permit deferring naming files."""
1417
1563
        transform, root = self.transform()
1418
 
        parent = transform.trans_id_file_id(b'parent-id')
 
1564
        parent = transform.trans_id_tree_path('parent')
1419
1565
        try:
1420
1566
            transform.create_directory(parent)
1421
1567
        except KeyError:
1425
1571
    def test_noname_contents_nested(self):
1426
1572
        """TreeTransform should permit deferring naming files."""
1427
1573
        transform, root = self.transform()
1428
 
        parent = transform.trans_id_file_id(b'parent-id')
 
1574
        parent = transform.trans_id_tree_path('parent-early')
1429
1575
        try:
1430
1576
            transform.create_directory(parent)
1431
1577
        except KeyError:
1650
1796
 
1651
1797
    def test_no_final_path(self):
1652
1798
        transform, root = self.transform()
1653
 
        trans_id = transform.trans_id_file_id(b'foo')
 
1799
        trans_id = transform.trans_id_tree_path('foo')
1654
1800
        transform.create_file([b'bar'], trans_id)
1655
1801
        transform.cancel_creation(trans_id)
1656
1802
        transform.apply()