~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_transform.py

  • Committer: Alexander Belchenko
  • Date: 2006-07-30 16:43:12 UTC
  • mto: (1711.2.111 jam-integration)
  • mto: This revision was merged to the branch mainline in revision 1906.
  • Revision ID: bialix@ukr.net-20060730164312-b025fd3ff0cee59e
rename  gpl.txt => COPYING.txt

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
import os
18
 
import stat
19
 
import sys
20
18
 
21
 
from bzrlib import (
22
 
    errors,
23
 
    generate_ids,
24
 
    symbol_versioning,
25
 
    tests,
26
 
    urlutils,
27
 
    )
28
19
from bzrlib.bzrdir import BzrDir
29
20
from bzrlib.conflicts import (DuplicateEntry, DuplicateID, MissingParent,
30
 
                              UnversionedParent, ParentLoop, DeletingParent,)
 
21
                              UnversionedParent, ParentLoop)
31
22
from bzrlib.errors import (DuplicateKey, MalformedTransform, NoSuchFile,
32
23
                           ReusingTransform, CantMoveRoot, 
33
24
                           PathsNotVersionedError, ExistingLimbo,
38
29
from bzrlib.transform import (TreeTransform, ROOT_PARENT, FinalPaths, 
39
30
                              resolve_conflicts, cook_conflicts, 
40
31
                              find_interesting, build_tree, get_backup_name)
41
 
 
42
 
 
43
 
class TestTreeTransform(tests.TestCaseWithTransport):
 
32
import bzrlib.urlutils as urlutils
 
33
 
 
34
class TestTreeTransform(TestCaseInTempDir):
44
35
 
45
36
    def setUp(self):
46
37
        super(TestTreeTransform, self).setUp()
47
 
        self.wt = self.make_branch_and_tree('.', format='dirstate-with-subtree')
 
38
        self.wt = BzrDir.create_standalone_workingtree('.')
48
39
        os.chdir('..')
49
40
 
50
41
    def get_transform(self):
51
42
        transform = TreeTransform(self.wt)
52
43
        #self.addCleanup(transform.finalize)
53
 
        return transform, transform.root
 
44
        return transform, transform.trans_id_tree_file_id(self.wt.get_root_id())
54
45
 
55
46
    def test_existing_limbo(self):
56
47
        limbo_name = urlutils.local_path_from_url(
127
118
        self.assertEqual(self.wt.path2id('oz/dorothy'), 'dorothy-id')
128
119
        self.assertEqual(self.wt.path2id('oz/dorothy/toto'), 'toto-id')
129
120
 
130
 
        self.assertEqual('toto-contents',
 
121
        self.assertEqual('toto-contents', 
131
122
                         self.wt.get_file_byname('oz/dorothy/toto').read())
132
123
        self.assertIs(self.wt.is_executable('toto-id'), False)
133
124
 
134
 
    def test_tree_reference(self):
135
 
        transform, root = self.get_transform()
136
 
        tree = transform._tree
137
 
        trans_id = transform.new_directory('reference', root, 'subtree-id')
138
 
        transform.set_tree_reference('subtree-revision', trans_id)
139
 
        transform.apply()
140
 
        tree.lock_read()
141
 
        self.addCleanup(tree.unlock)
142
 
        self.assertEqual('subtree-revision',
143
 
                         tree.inventory['subtree-id'].reference_revision)
144
 
 
145
125
    def test_conflicts(self):
146
126
        transform, root = self.get_transform()
147
127
        trans_id = transform.new_file('name', root, 'contents', 
211
191
        transform3.delete_contents(oz_id)
212
192
        self.assertEqual(transform3.find_conflicts(), 
213
193
                         [('missing parent', oz_id)])
214
 
        root_id = transform3.root
 
194
        root_id = transform3.trans_id_tree_file_id('TREE_ROOT')
215
195
        tip_id = transform3.trans_id_tree_file_id('tip-id')
216
196
        transform3.adjust_path('tip', root_id, tip_id)
217
197
        transform3.apply()
243
223
    def test_name_invariants(self):
244
224
        create_tree, root = self.get_transform()
245
225
        # prepare tree
246
 
        root = create_tree.root
 
226
        root = create_tree.trans_id_tree_file_id('TREE_ROOT')
247
227
        create_tree.new_file('name1', root, 'hello1', 'name1')
248
228
        create_tree.new_file('name2', root, 'hello2', 'name2')
249
229
        ddir = create_tree.new_directory('dying_directory', root, 'ddir')
253
233
        create_tree.apply()
254
234
 
255
235
        mangle_tree,root = self.get_transform()
256
 
        root = mangle_tree.root
 
236
        root = mangle_tree.trans_id_tree_file_id('TREE_ROOT')
257
237
        #swap names
258
238
        name1 = mangle_tree.trans_id_tree_file_id('name1')
259
239
        name2 = mangle_tree.trans_id_tree_file_id('name2')
338
318
    def test_move_dangling_ie(self):
339
319
        create_tree, root = self.get_transform()
340
320
        # prepare tree
341
 
        root = create_tree.root
 
321
        root = create_tree.trans_id_tree_file_id('TREE_ROOT')
342
322
        create_tree.new_file('name1', root, 'hello1', 'name1')
343
323
        create_tree.apply()
344
324
        delete_contents, root = self.get_transform()
354
334
    def test_replace_dangling_ie(self):
355
335
        create_tree, root = self.get_transform()
356
336
        # prepare tree
357
 
        root = create_tree.root
 
337
        root = create_tree.trans_id_tree_file_id('TREE_ROOT')
358
338
        create_tree.new_file('name1', root, 'hello1', 'name1')
359
339
        create_tree.apply()
360
340
        delete_contents = TreeTransform(self.wt)
407
387
                                         'dorothy-id')
408
388
        old_dorothy = conflicts.trans_id_tree_file_id('dorothy-id')
409
389
        oz = conflicts.trans_id_tree_file_id('oz-id')
410
 
        # set up DeletedParent parent conflict
 
390
        # set up missing, unversioned parent
411
391
        conflicts.delete_versioned(oz)
412
392
        emerald = conflicts.trans_id_tree_file_id('emerald-id')
413
 
        # set up MissingParent conflict
414
 
        munchkincity = conflicts.trans_id_file_id('munchkincity-id')
415
 
        conflicts.adjust_path('munchkincity', root, munchkincity)
416
 
        conflicts.new_directory('auntem', munchkincity, 'auntem-id')
417
393
        # set up parent loop
418
394
        conflicts.adjust_path('emeraldcity', emerald, emerald)
419
395
        return conflicts, emerald, oz, old_dorothy, new_dorothy
440
416
                                   'dorothy.moved', 'dorothy', None,
441
417
                                   'dorothy-id')
442
418
        self.assertEqual(cooked_conflicts[1], duplicate_id)
443
 
        missing_parent = MissingParent('Created directory', 'munchkincity',
444
 
                                       'munchkincity-id')
445
 
        deleted_parent = DeletingParent('Not deleting', 'oz', 'oz-id')
 
419
        missing_parent = MissingParent('Not deleting', 'oz', 'oz-id')
446
420
        self.assertEqual(cooked_conflicts[2], missing_parent)
447
 
        unversioned_parent = UnversionedParent('Versioned directory',
448
 
                                               'munchkincity',
449
 
                                               'munchkincity-id')
450
 
        unversioned_parent2 = UnversionedParent('Versioned directory', 'oz',
 
421
        unversioned_parent = UnversionedParent('Versioned directory', 'oz',
451
422
                                               'oz-id')
452
423
        self.assertEqual(cooked_conflicts[3], unversioned_parent)
453
424
        parent_loop = ParentLoop('Cancelled move', 'oz/emeraldcity', 
454
425
                                 'oz/emeraldcity', 'emerald-id', 'emerald-id')
455
 
        self.assertEqual(cooked_conflicts[4], deleted_parent)
456
 
        self.assertEqual(cooked_conflicts[5], unversioned_parent2)
457
 
        self.assertEqual(cooked_conflicts[6], parent_loop)
458
 
        self.assertEqual(len(cooked_conflicts), 7)
 
426
        self.assertEqual(cooked_conflicts[4], parent_loop)
 
427
        self.assertEqual(len(cooked_conflicts), 5)
459
428
        tt.finalize()
460
429
 
461
430
    def test_string_conflicts(self):
471
440
        self.assertEqual(conflicts_s[1], 'Conflict adding id to dorothy.  '
472
441
                                         'Unversioned existing file '
473
442
                                         'dorothy.moved.')
474
 
        self.assertEqual(conflicts_s[2], 'Conflict adding files to'
475
 
                                         ' munchkincity.  Created directory.')
476
 
        self.assertEqual(conflicts_s[3], 'Conflict because munchkincity is not'
477
 
                                         ' versioned, but has versioned'
478
 
                                         ' children.  Versioned directory.')
479
 
        self.assertEqualDiff(conflicts_s[4], "Conflict: can't delete oz because it"
480
 
                                         " is not empty.  Not deleting.")
481
 
        self.assertEqual(conflicts_s[5], 'Conflict because oz is not'
482
 
                                         ' versioned, but has versioned'
483
 
                                         ' children.  Versioned directory.')
484
 
        self.assertEqual(conflicts_s[6], 'Conflict moving oz/emeraldcity into'
 
443
        self.assertEqual(conflicts_s[2], 'Conflict adding files to oz.  '
 
444
                                         'Not deleting.')
 
445
        self.assertEqual(conflicts_s[3], 'Conflict adding versioned files to '
 
446
                                         'oz.  Versioned directory.')
 
447
        self.assertEqual(conflicts_s[4], 'Conflict moving oz/emeraldcity into'
485
448
                                         ' oz/emeraldcity.  Cancelled move.')
486
449
 
487
450
    def test_moving_versioned_directories(self):
528
491
        create.new_file('vfile', root, 'myfile-text', 'myfile-id')
529
492
        create.new_file('uvfile', root, 'othertext')
530
493
        create.apply()
531
 
        result = self.applyDeprecated(symbol_versioning.zero_fifteen,
532
 
            find_interesting, wt, wt, ['vfile'])
533
 
        self.assertEqual(result, set(['myfile-id']))
 
494
        self.assertEqual(find_interesting(wt, wt, ['vfile']),
 
495
                         set(['myfile-id']))
 
496
        self.assertRaises(PathsNotVersionedError, find_interesting, wt, wt,
 
497
                          ['uvfile'])
534
498
 
535
499
    def test_set_executability_order(self):
536
500
        """Ensure that executability behaves the same, no matter what order.
553
517
        self.assertTrue(wt.is_executable('soc'))
554
518
        self.assertTrue(wt.is_executable('sac'))
555
519
 
556
 
    def test_preserve_mode(self):
557
 
        """File mode is preserved when replacing content"""
558
 
        if sys.platform == 'win32':
559
 
            raise TestSkipped('chmod has no effect on win32')
560
 
        transform, root = self.get_transform()
561
 
        transform.new_file('file1', root, 'contents', 'file1-id', True)
562
 
        transform.apply()
563
 
        self.assertTrue(self.wt.is_executable('file1-id'))
564
 
        transform, root = self.get_transform()
565
 
        file1_id = transform.trans_id_tree_file_id('file1-id')
566
 
        transform.delete_contents(file1_id)
567
 
        transform.create_file('contents2', file1_id)
568
 
        transform.apply()
569
 
        self.assertTrue(self.wt.is_executable('file1-id'))
570
 
 
571
 
    def test__set_mode_stats_correctly(self):
572
 
        """_set_mode stats to determine file mode."""
573
 
        if sys.platform == 'win32':
574
 
            raise TestSkipped('chmod has no effect on win32')
575
 
 
576
 
        stat_paths = []
577
 
        real_stat = os.stat
578
 
        def instrumented_stat(path):
579
 
            stat_paths.append(path)
580
 
            return real_stat(path)
581
 
 
582
 
        transform, root = self.get_transform()
583
 
 
584
 
        bar1_id = transform.new_file('bar', root, 'bar contents 1\n',
585
 
                                     file_id='bar-id-1', executable=False)
586
 
        transform.apply()
587
 
 
588
 
        transform, root = self.get_transform()
589
 
        bar1_id = transform.trans_id_tree_path('bar')
590
 
        bar2_id = transform.trans_id_tree_path('bar2')
591
 
        try:
592
 
            os.stat = instrumented_stat
593
 
            transform.create_file('bar2 contents\n', bar2_id, mode_id=bar1_id)
594
 
        finally:
595
 
            os.stat = real_stat
596
 
            transform.finalize()
597
 
 
598
 
        bar1_abspath = self.wt.abspath('bar')
599
 
        self.assertEqual([bar1_abspath], stat_paths)
600
 
 
601
 
    def test_iter_changes(self):
602
 
        self.wt.set_root_id('eert_toor')
603
 
        transform, root = self.get_transform()
604
 
        transform.new_file('old', root, 'blah', 'id-1', True)
605
 
        transform.apply()
606
 
        transform, root = self.get_transform()
607
 
        try:
608
 
            self.assertEqual([], list(transform._iter_changes()))
609
 
            old = transform.trans_id_tree_file_id('id-1')
610
 
            transform.unversion_file(old)
611
 
            self.assertEqual([('id-1', ('old', None), False, (True, False),
612
 
                ('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
613
 
                (True, True))], list(transform._iter_changes()))
614
 
            transform.new_directory('new', root, 'id-1')
615
 
            self.assertEqual([('id-1', ('old', 'new'), True, (True, True),
616
 
                ('eert_toor', 'eert_toor'), ('old', 'new'),
617
 
                ('file', 'directory'),
618
 
                (True, False))], list(transform._iter_changes()))
619
 
        finally:
620
 
            transform.finalize()
621
 
 
622
 
    def test_iter_changes_new(self):
623
 
        self.wt.set_root_id('eert_toor')
624
 
        transform, root = self.get_transform()
625
 
        transform.new_file('old', root, 'blah')
626
 
        transform.apply()
627
 
        transform, root = self.get_transform()
628
 
        try:
629
 
            old = transform.trans_id_tree_path('old')
630
 
            transform.version_file('id-1', old)
631
 
            self.assertEqual([('id-1', (None, 'old'), False, (False, True),
632
 
                ('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
633
 
                (False, False))], list(transform._iter_changes()))
634
 
        finally:
635
 
            transform.finalize()
636
 
 
637
 
    def test_iter_changes_modifications(self):
638
 
        self.wt.set_root_id('eert_toor')
639
 
        transform, root = self.get_transform()
640
 
        transform.new_file('old', root, 'blah', 'id-1')
641
 
        transform.new_file('new', root, 'blah')
642
 
        transform.new_directory('subdir', root, 'subdir-id')
643
 
        transform.apply()
644
 
        transform, root = self.get_transform()
645
 
        try:
646
 
            old = transform.trans_id_tree_path('old')
647
 
            subdir = transform.trans_id_tree_file_id('subdir-id')
648
 
            new = transform.trans_id_tree_path('new')
649
 
            self.assertEqual([], list(transform._iter_changes()))
650
 
 
651
 
            #content deletion
652
 
            transform.delete_contents(old)
653
 
            self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
654
 
                ('eert_toor', 'eert_toor'), ('old', 'old'), ('file', None),
655
 
                (False, False))], list(transform._iter_changes()))
656
 
 
657
 
            #content change
658
 
            transform.create_file('blah', old)
659
 
            self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
660
 
                ('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
661
 
                (False, False))], list(transform._iter_changes()))
662
 
            transform.cancel_deletion(old)
663
 
            self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
664
 
                ('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
665
 
                (False, False))], list(transform._iter_changes()))
666
 
            transform.cancel_creation(old)
667
 
 
668
 
            # move file_id to a different file
669
 
            self.assertEqual([], list(transform._iter_changes()))
670
 
            transform.unversion_file(old)
671
 
            transform.version_file('id-1', new)
672
 
            transform.adjust_path('old', root, new)
673
 
            self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
674
 
                ('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
675
 
                (False, False))], list(transform._iter_changes()))
676
 
            transform.cancel_versioning(new)
677
 
            transform._removed_id = set()
678
 
 
679
 
            #execute bit
680
 
            self.assertEqual([], list(transform._iter_changes()))
681
 
            transform.set_executability(True, old)
682
 
            self.assertEqual([('id-1', ('old', 'old'), False, (True, True),
683
 
                ('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
684
 
                (False, True))], list(transform._iter_changes()))
685
 
            transform.set_executability(None, old)
686
 
 
687
 
            # filename
688
 
            self.assertEqual([], list(transform._iter_changes()))
689
 
            transform.adjust_path('new', root, old)
690
 
            transform._new_parent = {}
691
 
            self.assertEqual([('id-1', ('old', 'new'), False, (True, True),
692
 
                ('eert_toor', 'eert_toor'), ('old', 'new'), ('file', 'file'),
693
 
                (False, False))], list(transform._iter_changes()))
694
 
            transform._new_name = {}
695
 
 
696
 
            # parent directory
697
 
            self.assertEqual([], list(transform._iter_changes()))
698
 
            transform.adjust_path('new', subdir, old)
699
 
            transform._new_name = {}
700
 
            self.assertEqual([('id-1', ('old', 'subdir/old'), False,
701
 
                (True, True), ('eert_toor', 'subdir-id'), ('old', 'old'),
702
 
                ('file', 'file'), (False, False))],
703
 
                list(transform._iter_changes()))
704
 
            transform._new_path = {}
705
 
 
706
 
        finally:
707
 
            transform.finalize()
708
 
 
709
 
    def test_iter_changes_modified_bleed(self):
710
 
        self.wt.set_root_id('eert_toor')
711
 
        """Modified flag should not bleed from one change to another"""
712
 
        # unfortunately, we have no guarantee that file1 (which is modified)
713
 
        # will be applied before file2.  And if it's applied after file2, it
714
 
        # obviously can't bleed into file2's change output.  But for now, it
715
 
        # works.
716
 
        transform, root = self.get_transform()
717
 
        transform.new_file('file1', root, 'blah', 'id-1')
718
 
        transform.new_file('file2', root, 'blah', 'id-2')
719
 
        transform.apply()
720
 
        transform, root = self.get_transform()
721
 
        try:
722
 
            transform.delete_contents(transform.trans_id_file_id('id-1'))
723
 
            transform.set_executability(True,
724
 
            transform.trans_id_file_id('id-2'))
725
 
            self.assertEqual([('id-1', (u'file1', u'file1'), True, (True, True),
726
 
                ('eert_toor', 'eert_toor'), ('file1', u'file1'),
727
 
                ('file', None), (False, False)),
728
 
                ('id-2', (u'file2', u'file2'), False, (True, True),
729
 
                ('eert_toor', 'eert_toor'), ('file2', u'file2'),
730
 
                ('file', 'file'), (False, True))],
731
 
                list(transform._iter_changes()))
732
 
        finally:
733
 
            transform.finalize()
734
 
 
735
 
    def test_iter_changes_move_missing(self):
736
 
        """Test moving ids with no files around"""
737
 
        self.wt.set_root_id('toor_eert')
738
 
        # Need two steps because versioning a non-existant file is a conflict.
739
 
        transform, root = self.get_transform()
740
 
        transform.new_directory('floater', root, 'floater-id')
741
 
        transform.apply()
742
 
        transform, root = self.get_transform()
743
 
        transform.delete_contents(transform.trans_id_tree_path('floater'))
744
 
        transform.apply()
745
 
        transform, root = self.get_transform()
746
 
        floater = transform.trans_id_tree_path('floater')
747
 
        try:
748
 
            transform.adjust_path('flitter', root, floater)
749
 
            self.assertEqual([('floater-id', ('floater', 'flitter'), False,
750
 
            (True, True), ('toor_eert', 'toor_eert'), ('floater', 'flitter'),
751
 
            (None, None), (False, False))], list(transform._iter_changes()))
752
 
        finally:
753
 
            transform.finalize()
754
 
 
755
 
    def test_iter_changes_pointless(self):
756
 
        """Ensure that no-ops are not treated as modifications"""
757
 
        self.wt.set_root_id('eert_toor')
758
 
        transform, root = self.get_transform()
759
 
        transform.new_file('old', root, 'blah', 'id-1')
760
 
        transform.new_directory('subdir', root, 'subdir-id')
761
 
        transform.apply()
762
 
        transform, root = self.get_transform()
763
 
        try:
764
 
            old = transform.trans_id_tree_path('old')
765
 
            subdir = transform.trans_id_tree_file_id('subdir-id')
766
 
            self.assertEqual([], list(transform._iter_changes()))
767
 
            transform.delete_contents(subdir)
768
 
            transform.create_directory(subdir)
769
 
            transform.set_executability(False, old)
770
 
            transform.unversion_file(old)
771
 
            transform.version_file('id-1', old)
772
 
            transform.adjust_path('old', root, old)
773
 
            self.assertEqual([], list(transform._iter_changes()))
774
 
        finally:
775
 
            transform.finalize()
776
520
 
777
521
class TransformGroup(object):
778
 
    def __init__(self, dirname, root_id):
 
522
    def __init__(self, dirname):
779
523
        self.name = dirname
780
524
        os.mkdir(dirname)
781
525
        self.wt = BzrDir.create_standalone_workingtree(dirname)
782
 
        self.wt.set_root_id(root_id)
783
526
        self.b = self.wt.branch
784
527
        self.tt = TreeTransform(self.wt)
785
528
        self.root = self.tt.trans_id_tree_file_id(self.wt.get_root_id())
786
529
 
787
 
 
788
530
def conflict_text(tree, merge):
789
531
    template = '%s TREE\n%s%s\n%s%s MERGE-SOURCE\n'
790
532
    return template % ('<' * 7, tree, '=' * 7, merge, '>' * 7)
792
534
 
793
535
class TestTransformMerge(TestCaseInTempDir):
794
536
    def test_text_merge(self):
795
 
        root_id = generate_ids.gen_root_id()
796
 
        base = TransformGroup("base", root_id)
 
537
        base = TransformGroup("base")
797
538
        base.tt.new_file('a', base.root, 'a\nb\nc\nd\be\n', 'a')
798
539
        base.tt.new_file('b', base.root, 'b1', 'b')
799
540
        base.tt.new_file('c', base.root, 'c', 'c')
803
544
        base.tt.new_directory('g', base.root, 'g')
804
545
        base.tt.new_directory('h', base.root, 'h')
805
546
        base.tt.apply()
806
 
        other = TransformGroup("other", root_id)
 
547
        other = TransformGroup("other")
807
548
        other.tt.new_file('a', other.root, 'y\nb\nc\nd\be\n', 'a')
808
549
        other.tt.new_file('b', other.root, 'b2', 'b')
809
550
        other.tt.new_file('c', other.root, 'c2', 'c')
814
555
        other.tt.new_file('h', other.root, 'h\ni\nj\nk\n', 'h')
815
556
        other.tt.new_file('i', other.root, 'h\ni\nj\nk\n', 'i')
816
557
        other.tt.apply()
817
 
        this = TransformGroup("this", root_id)
 
558
        this = TransformGroup("this")
818
559
        this.tt.new_file('a', this.root, 'a\nb\nc\nd\bz\n', 'a')
819
560
        this.tt.new_file('b', this.root, 'b', 'b')
820
561
        this.tt.new_file('c', this.root, 'c', 'c')
871
612
    def test_file_merge(self):
872
613
        if not has_symlinks():
873
614
            raise TestSkipped('Symlinks are not supported on this platform')
874
 
        root_id = generate_ids.gen_root_id()
875
 
        base = TransformGroup("BASE", root_id)
876
 
        this = TransformGroup("THIS", root_id)
877
 
        other = TransformGroup("OTHER", root_id)
 
615
        base = TransformGroup("BASE")
 
616
        this = TransformGroup("THIS")
 
617
        other = TransformGroup("OTHER")
878
618
        for tg in this, base, other:
879
619
            tg.tt.new_directory('a', tg.root, 'a')
880
620
            tg.tt.new_symlink('b', tg.root, 'b', 'b')
912
652
        self.assertIs(os.path.lexists(this.wt.abspath('h.OTHER')), True)
913
653
 
914
654
    def test_filename_merge(self):
915
 
        root_id = generate_ids.gen_root_id()
916
 
        base = TransformGroup("BASE", root_id)
917
 
        this = TransformGroup("THIS", root_id)
918
 
        other = TransformGroup("OTHER", root_id)
 
655
        base = TransformGroup("BASE")
 
656
        this = TransformGroup("THIS")
 
657
        other = TransformGroup("OTHER")
919
658
        base_a, this_a, other_a = [t.tt.new_directory('a', t.root, 'a') 
920
659
                                   for t in [base, this, other]]
921
660
        base_b, this_b, other_b = [t.tt.new_directory('b', t.root, 'b') 
945
684
        self.assertEqual(this.wt.id2path('f'), pathjoin('b/f1'))
946
685
 
947
686
    def test_filename_merge_conflicts(self):
948
 
        root_id = generate_ids.gen_root_id()
949
 
        base = TransformGroup("BASE", root_id)
950
 
        this = TransformGroup("THIS", root_id)
951
 
        other = TransformGroup("OTHER", root_id)
 
687
        base = TransformGroup("BASE")
 
688
        this = TransformGroup("THIS")
 
689
        other = TransformGroup("OTHER")
952
690
        base_a, this_a, other_a = [t.tt.new_directory('a', t.root, 'a') 
953
691
                                   for t in [base, this, other]]
954
692
        base_b, this_b, other_b = [t.tt.new_directory('b', t.root, 'b') 
975
713
        self.assertIs(os.path.lexists(this.wt.abspath('b/h1.OTHER')), False)
976
714
        self.assertEqual(this.wt.id2path('i'), pathjoin('b/i1.OTHER'))
977
715
 
978
 
 
979
 
class TestBuildTree(tests.TestCaseWithTransport):
980
 
 
 
716
class TestBuildTree(TestCaseInTempDir):
981
717
    def test_build_tree(self):
982
718
        if not has_symlinks():
983
719
            raise TestSkipped('Test requires symlink support')
989
725
        a.add(['foo', 'foo/bar', 'foo/baz'])
990
726
        a.commit('initial commit')
991
727
        b = BzrDir.create_standalone_workingtree('b')
992
 
        basis = a.basis_tree()
993
 
        basis.lock_read()
994
 
        self.addCleanup(basis.unlock)
995
 
        build_tree(basis, b)
 
728
        build_tree(a.basis_tree(), b)
996
729
        self.assertIs(os.path.isdir('b/foo'), True)
997
730
        self.assertEqual(file('b/foo/bar', 'rb').read(), "contents")
998
731
        self.assertEqual(os.readlink('b/foo/baz'), 'a/foo/bar')
999
 
 
1000
 
    def test_build_with_references(self):
1001
 
        tree = self.make_branch_and_tree('source',
1002
 
            format='dirstate-with-subtree')
1003
 
        subtree = self.make_branch_and_tree('source/subtree',
1004
 
            format='dirstate-with-subtree')
1005
 
        tree.add_reference(subtree)
1006
 
        tree.commit('a revision')
1007
 
        tree.branch.create_checkout('target')
1008
 
        self.failUnlessExists('target')
1009
 
        self.failUnlessExists('target/subtree')
1010
 
 
1011
 
    def test_file_conflict_handling(self):
1012
 
        """Ensure that when building trees, conflict handling is done"""
1013
 
        source = self.make_branch_and_tree('source')
1014
 
        target = self.make_branch_and_tree('target')
1015
 
        self.build_tree(['source/file', 'target/file'])
1016
 
        source.add('file', 'new-file')
1017
 
        source.commit('added file')
1018
 
        build_tree(source.basis_tree(), target)
1019
 
        self.assertEqual([DuplicateEntry('Moved existing file to',
1020
 
                          'file.moved', 'file', None, 'new-file')],
1021
 
                         target.conflicts())
1022
 
        target2 = self.make_branch_and_tree('target2')
1023
 
        target_file = file('target2/file', 'wb')
1024
 
        try:
1025
 
            source_file = file('source/file', 'rb')
1026
 
            try:
1027
 
                target_file.write(source_file.read())
1028
 
            finally:
1029
 
                source_file.close()
1030
 
        finally:
1031
 
            target_file.close()
1032
 
        build_tree(source.basis_tree(), target2)
1033
 
        self.assertEqual([], target2.conflicts())
1034
 
 
1035
 
    def test_symlink_conflict_handling(self):
1036
 
        """Ensure that when building trees, conflict handling is done"""
1037
 
        if not has_symlinks():
1038
 
            raise TestSkipped('Test requires symlink support')
1039
 
        source = self.make_branch_and_tree('source')
1040
 
        os.symlink('foo', 'source/symlink')
1041
 
        source.add('symlink', 'new-symlink')
1042
 
        source.commit('added file')
1043
 
        target = self.make_branch_and_tree('target')
1044
 
        os.symlink('bar', 'target/symlink')
1045
 
        build_tree(source.basis_tree(), target)
1046
 
        self.assertEqual([DuplicateEntry('Moved existing file to',
1047
 
            'symlink.moved', 'symlink', None, 'new-symlink')],
1048
 
            target.conflicts())
1049
 
        target = self.make_branch_and_tree('target2')
1050
 
        os.symlink('foo', 'target2/symlink')
1051
 
        build_tree(source.basis_tree(), target)
1052
 
        self.assertEqual([], target.conflicts())
1053
732
        
1054
 
    def test_directory_conflict_handling(self):
1055
 
        """Ensure that when building trees, conflict handling is done"""
1056
 
        source = self.make_branch_and_tree('source')
1057
 
        target = self.make_branch_and_tree('target')
1058
 
        self.build_tree(['source/dir1/', 'source/dir1/file', 'target/dir1/'])
1059
 
        source.add(['dir1', 'dir1/file'], ['new-dir1', 'new-file'])
1060
 
        source.commit('added file')
1061
 
        build_tree(source.basis_tree(), target)
1062
 
        self.assertEqual([], target.conflicts())
1063
 
        self.failUnlessExists('target/dir1/file')
1064
 
 
1065
 
        # Ensure contents are merged
1066
 
        target = self.make_branch_and_tree('target2')
1067
 
        self.build_tree(['target2/dir1/', 'target2/dir1/file2'])
1068
 
        build_tree(source.basis_tree(), target)
1069
 
        self.assertEqual([], target.conflicts())
1070
 
        self.failUnlessExists('target2/dir1/file2')
1071
 
        self.failUnlessExists('target2/dir1/file')
1072
 
 
1073
 
        # Ensure new contents are suppressed for existing branches
1074
 
        target = self.make_branch_and_tree('target3')
1075
 
        self.make_branch('target3/dir1')
1076
 
        self.build_tree(['target3/dir1/file2'])
1077
 
        build_tree(source.basis_tree(), target)
1078
 
        self.failIfExists('target3/dir1/file')
1079
 
        self.failUnlessExists('target3/dir1/file2')
1080
 
        self.failUnlessExists('target3/dir1.diverted/file')
1081
 
        self.assertEqual([DuplicateEntry('Diverted to',
1082
 
            'dir1.diverted', 'dir1', 'new-dir1', None)],
1083
 
            target.conflicts())
1084
 
 
1085
 
        target = self.make_branch_and_tree('target4')
1086
 
        self.build_tree(['target4/dir1/'])
1087
 
        self.make_branch('target4/dir1/file')
1088
 
        build_tree(source.basis_tree(), target)
1089
 
        self.failUnlessExists('target4/dir1/file')
1090
 
        self.assertEqual('directory', file_kind('target4/dir1/file'))
1091
 
        self.failUnlessExists('target4/dir1/file.diverted')
1092
 
        self.assertEqual([DuplicateEntry('Diverted to',
1093
 
            'dir1/file.diverted', 'dir1/file', 'new-file', None)],
1094
 
            target.conflicts())
1095
 
 
1096
 
    def test_mixed_conflict_handling(self):
1097
 
        """Ensure that when building trees, conflict handling is done"""
1098
 
        source = self.make_branch_and_tree('source')
1099
 
        target = self.make_branch_and_tree('target')
1100
 
        self.build_tree(['source/name', 'target/name/'])
1101
 
        source.add('name', 'new-name')
1102
 
        source.commit('added file')
1103
 
        build_tree(source.basis_tree(), target)
1104
 
        self.assertEqual([DuplicateEntry('Moved existing file to',
1105
 
            'name.moved', 'name', None, 'new-name')], target.conflicts())
1106
 
 
1107
 
    def test_raises_in_populated(self):
1108
 
        source = self.make_branch_and_tree('source')
1109
 
        self.build_tree(['source/name'])
1110
 
        source.add('name')
1111
 
        source.commit('added name')
1112
 
        target = self.make_branch_and_tree('target')
1113
 
        self.build_tree(['target/name'])
1114
 
        target.add('name')
1115
 
        self.assertRaises(errors.WorkingTreeAlreadyPopulated, 
1116
 
            build_tree, source.basis_tree(), target)
1117
 
 
1118
 
 
1119
733
class MockTransform(object):
1120
734
 
1121
735
    def has_named_child(self, by_parent, parent_id, name):