/brz/remove-bazaar

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

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_transform.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-02-15 18:14:16 UTC
  • mfrom: (2290.1.1 jam-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20070215181416-864dbe690a0f3da8
(John Arbash Meinel) make 'bzr remove-tree' a non-hidden command.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2006 Canonical Ltd
2
 
 
 
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
 
 
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
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
18
20
 
 
21
from bzrlib import (
 
22
    errors,
 
23
    generate_ids,
 
24
    tests,
 
25
    urlutils,
 
26
    )
19
27
from bzrlib.bzrdir import BzrDir
20
28
from bzrlib.conflicts import (DuplicateEntry, DuplicateID, MissingParent,
21
 
                              UnversionedParent, ParentLoop)
 
29
                              UnversionedParent, ParentLoop, DeletingParent,)
22
30
from bzrlib.errors import (DuplicateKey, MalformedTransform, NoSuchFile,
23
 
                           ReusingTransform, CantMoveRoot, NotVersionedError,
24
 
                           ExistingLimbo, ImmortalLimbo, LockError)
 
31
                           ReusingTransform, CantMoveRoot, 
 
32
                           PathsNotVersionedError, ExistingLimbo,
 
33
                           ImmortalLimbo, LockError)
25
34
from bzrlib.osutils import file_kind, has_symlinks, pathjoin
26
35
from bzrlib.merge import Merge3Merger
27
36
from bzrlib.tests import TestCaseInTempDir, TestSkipped, TestCase
29
38
                              resolve_conflicts, cook_conflicts, 
30
39
                              find_interesting, build_tree, get_backup_name)
31
40
 
 
41
 
32
42
class TestTreeTransform(TestCaseInTempDir):
 
43
 
33
44
    def setUp(self):
34
45
        super(TestTreeTransform, self).setUp()
35
46
        self.wt = BzrDir.create_standalone_workingtree('.')
38
49
    def get_transform(self):
39
50
        transform = TreeTransform(self.wt)
40
51
        #self.addCleanup(transform.finalize)
41
 
        return transform, transform.trans_id_tree_file_id(self.wt.get_root_id())
 
52
        return transform, transform.root
42
53
 
43
54
    def test_existing_limbo(self):
44
 
        limbo_name = self.wt._control_files.controlfilename('limbo')
 
55
        limbo_name = urlutils.local_path_from_url(
 
56
            self.wt._control_files.controlfilename('limbo'))
45
57
        transform, root = self.get_transform()
46
58
        os.mkdir(pathjoin(limbo_name, 'hehe'))
47
59
        self.assertRaises(ImmortalLimbo, transform.apply)
57
69
        transform, root = self.get_transform() 
58
70
        self.assertIs(transform.get_tree_parent(root), ROOT_PARENT)
59
71
        imaginary_id = transform.trans_id_tree_path('imaginary')
 
72
        imaginary_id2 = transform.trans_id_tree_path('imaginary/')
 
73
        self.assertEqual(imaginary_id, imaginary_id2)
60
74
        self.assertEqual(transform.get_tree_parent(imaginary_id), root)
61
75
        self.assertEqual(transform.final_kind(root), 'directory')
62
76
        self.assertEqual(transform.final_file_id(root), self.wt.get_root_id())
185
199
        transform3.delete_contents(oz_id)
186
200
        self.assertEqual(transform3.find_conflicts(), 
187
201
                         [('missing parent', oz_id)])
188
 
        root_id = transform3.trans_id_tree_file_id('TREE_ROOT')
 
202
        root_id = transform3.root
189
203
        tip_id = transform3.trans_id_tree_file_id('tip-id')
190
204
        transform3.adjust_path('tip', root_id, tip_id)
191
205
        transform3.apply()
217
231
    def test_name_invariants(self):
218
232
        create_tree, root = self.get_transform()
219
233
        # prepare tree
220
 
        root = create_tree.trans_id_tree_file_id('TREE_ROOT')
 
234
        root = create_tree.root
221
235
        create_tree.new_file('name1', root, 'hello1', 'name1')
222
236
        create_tree.new_file('name2', root, 'hello2', 'name2')
223
237
        ddir = create_tree.new_directory('dying_directory', root, 'ddir')
227
241
        create_tree.apply()
228
242
 
229
243
        mangle_tree,root = self.get_transform()
230
 
        root = mangle_tree.trans_id_tree_file_id('TREE_ROOT')
 
244
        root = mangle_tree.root
231
245
        #swap names
232
246
        name1 = mangle_tree.trans_id_tree_file_id('name1')
233
247
        name2 = mangle_tree.trans_id_tree_file_id('name2')
312
326
    def test_move_dangling_ie(self):
313
327
        create_tree, root = self.get_transform()
314
328
        # prepare tree
315
 
        root = create_tree.trans_id_tree_file_id('TREE_ROOT')
 
329
        root = create_tree.root
316
330
        create_tree.new_file('name1', root, 'hello1', 'name1')
317
331
        create_tree.apply()
318
332
        delete_contents, root = self.get_transform()
328
342
    def test_replace_dangling_ie(self):
329
343
        create_tree, root = self.get_transform()
330
344
        # prepare tree
331
 
        root = create_tree.trans_id_tree_file_id('TREE_ROOT')
 
345
        root = create_tree.root
332
346
        create_tree.new_file('name1', root, 'hello1', 'name1')
333
347
        create_tree.apply()
334
348
        delete_contents = TreeTransform(self.wt)
381
395
                                         'dorothy-id')
382
396
        old_dorothy = conflicts.trans_id_tree_file_id('dorothy-id')
383
397
        oz = conflicts.trans_id_tree_file_id('oz-id')
384
 
        # set up missing, unversioned parent
 
398
        # set up DeletedParent parent conflict
385
399
        conflicts.delete_versioned(oz)
386
400
        emerald = conflicts.trans_id_tree_file_id('emerald-id')
 
401
        # set up MissingParent conflict
 
402
        munchkincity = conflicts.trans_id_file_id('munchkincity-id')
 
403
        conflicts.adjust_path('munchkincity', root, munchkincity)
 
404
        conflicts.new_directory('auntem', munchkincity, 'auntem-id')
387
405
        # set up parent loop
388
406
        conflicts.adjust_path('emeraldcity', emerald, emerald)
389
407
        return conflicts, emerald, oz, old_dorothy, new_dorothy
410
428
                                   'dorothy.moved', 'dorothy', None,
411
429
                                   'dorothy-id')
412
430
        self.assertEqual(cooked_conflicts[1], duplicate_id)
413
 
        missing_parent = MissingParent('Not deleting', 'oz', 'oz-id')
 
431
        missing_parent = MissingParent('Created directory', 'munchkincity',
 
432
                                       'munchkincity-id')
 
433
        deleted_parent = DeletingParent('Not deleting', 'oz', 'oz-id')
414
434
        self.assertEqual(cooked_conflicts[2], missing_parent)
415
 
        unversioned_parent = UnversionedParent('Versioned directory', 'oz',
 
435
        unversioned_parent = UnversionedParent('Versioned directory',
 
436
                                               'munchkincity',
 
437
                                               'munchkincity-id')
 
438
        unversioned_parent2 = UnversionedParent('Versioned directory', 'oz',
416
439
                                               'oz-id')
417
440
        self.assertEqual(cooked_conflicts[3], unversioned_parent)
418
441
        parent_loop = ParentLoop('Cancelled move', 'oz/emeraldcity', 
419
442
                                 'oz/emeraldcity', 'emerald-id', 'emerald-id')
420
 
        self.assertEqual(cooked_conflicts[4], parent_loop)
421
 
        self.assertEqual(len(cooked_conflicts), 5)
 
443
        self.assertEqual(cooked_conflicts[4], deleted_parent)
 
444
        self.assertEqual(cooked_conflicts[5], unversioned_parent2)
 
445
        self.assertEqual(cooked_conflicts[6], parent_loop)
 
446
        self.assertEqual(len(cooked_conflicts), 7)
422
447
        tt.finalize()
423
448
 
424
449
    def test_string_conflicts(self):
434
459
        self.assertEqual(conflicts_s[1], 'Conflict adding id to dorothy.  '
435
460
                                         'Unversioned existing file '
436
461
                                         'dorothy.moved.')
437
 
        self.assertEqual(conflicts_s[2], 'Conflict adding files to oz.  '
438
 
                                         'Not deleting.')
439
 
        self.assertEqual(conflicts_s[3], 'Conflict adding versioned files to '
440
 
                                         'oz.  Versioned directory.')
441
 
        self.assertEqual(conflicts_s[4], 'Conflict moving oz/emeraldcity into'
 
462
        self.assertEqual(conflicts_s[2], 'Conflict adding files to'
 
463
                                         ' munchkincity.  Created directory.')
 
464
        self.assertEqual(conflicts_s[3], 'Conflict because munchkincity is not'
 
465
                                         ' versioned, but has versioned'
 
466
                                         ' children.  Versioned directory.')
 
467
        self.assertEqualDiff(conflicts_s[4], "Conflict: can't delete oz because it"
 
468
                                         " is not empty.  Not deleting.")
 
469
        self.assertEqual(conflicts_s[5], 'Conflict because oz is not'
 
470
                                         ' versioned, but has versioned'
 
471
                                         ' children.  Versioned directory.')
 
472
        self.assertEqual(conflicts_s[6], 'Conflict moving oz/emeraldcity into'
442
473
                                         ' oz/emeraldcity.  Cancelled move.')
443
474
 
444
475
    def test_moving_versioned_directories(self):
487
518
        create.apply()
488
519
        self.assertEqual(find_interesting(wt, wt, ['vfile']),
489
520
                         set(['myfile-id']))
490
 
        self.assertRaises(NotVersionedError, find_interesting, wt, wt,
 
521
        self.assertRaises(PathsNotVersionedError, find_interesting, wt, wt,
491
522
                          ['uvfile'])
492
523
 
 
524
    def test_set_executability_order(self):
 
525
        """Ensure that executability behaves the same, no matter what order.
 
526
        
 
527
        - create file and set executability simultaneously
 
528
        - create file and set executability afterward
 
529
        - unsetting the executability of a file whose executability has not been
 
530
        declared should throw an exception (this may happen when a
 
531
        merge attempts to create a file with a duplicate ID)
 
532
        """
 
533
        transform, root = self.get_transform()
 
534
        wt = transform._tree
 
535
        transform.new_file('set_on_creation', root, 'Set on creation', 'soc',
 
536
                           True)
 
537
        sac = transform.new_file('set_after_creation', root, 'Set after creation', 'sac')
 
538
        transform.set_executability(True, sac)
 
539
        uws = transform.new_file('unset_without_set', root, 'Unset badly', 'uws')
 
540
        self.assertRaises(KeyError, transform.set_executability, None, uws)
 
541
        transform.apply()
 
542
        self.assertTrue(wt.is_executable('soc'))
 
543
        self.assertTrue(wt.is_executable('sac'))
 
544
 
 
545
    def test_preserve_mode(self):
 
546
        """File mode is preserved when replacing content"""
 
547
        if sys.platform == 'win32':
 
548
            raise TestSkipped('chmod has no effect on win32')
 
549
        transform, root = self.get_transform()
 
550
        transform.new_file('file1', root, 'contents', 'file1-id', True)
 
551
        transform.apply()
 
552
        self.assertTrue(self.wt.is_executable('file1-id'))
 
553
        transform, root = self.get_transform()
 
554
        file1_id = transform.trans_id_tree_file_id('file1-id')
 
555
        transform.delete_contents(file1_id)
 
556
        transform.create_file('contents2', file1_id)
 
557
        transform.apply()
 
558
        self.assertTrue(self.wt.is_executable('file1-id'))
 
559
 
 
560
    def test__set_mode_stats_correctly(self):
 
561
        """_set_mode stats to determine file mode."""
 
562
        if sys.platform == 'win32':
 
563
            raise TestSkipped('chmod has no effect on win32')
 
564
 
 
565
        stat_paths = []
 
566
        real_stat = os.stat
 
567
        def instrumented_stat(path):
 
568
            stat_paths.append(path)
 
569
            return real_stat(path)
 
570
 
 
571
        transform, root = self.get_transform()
 
572
 
 
573
        bar1_id = transform.new_file('bar', root, 'bar contents 1\n',
 
574
                                     file_id='bar-id-1', executable=False)
 
575
        transform.apply()
 
576
 
 
577
        transform, root = self.get_transform()
 
578
        bar1_id = transform.trans_id_tree_path('bar')
 
579
        bar2_id = transform.trans_id_tree_path('bar2')
 
580
        try:
 
581
            os.stat = instrumented_stat
 
582
            transform.create_file('bar2 contents\n', bar2_id, mode_id=bar1_id)
 
583
        finally:
 
584
            os.stat = real_stat
 
585
            transform.finalize()
 
586
 
 
587
        bar1_abspath = self.wt.abspath('bar')
 
588
        self.assertEqual([bar1_abspath], stat_paths)
 
589
 
 
590
    def test_iter_changes(self):
 
591
        transform, root = self.get_transform()
 
592
        transform.new_file('old', root, 'blah', 'id-1', True)
 
593
        transform.apply()
 
594
        transform, root = self.get_transform()
 
595
        try:
 
596
            self.assertEqual([], list(transform._iter_changes()))
 
597
            old = transform.trans_id_tree_file_id('id-1')
 
598
            transform.unversion_file(old)
 
599
            self.assertEqual([('id-1', 'old', False, (True, False),
 
600
                ('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', 'file'),
 
601
                (True, True))], list(transform._iter_changes()))
 
602
            transform.new_directory('new', root, 'id-1')
 
603
            self.assertEqual([('id-1', 'new', True, (True, True),
 
604
                ('TREE_ROOT', 'TREE_ROOT'), ('old', 'new'),
 
605
                ('file', 'directory'),
 
606
                (True, False))], list(transform._iter_changes()))
 
607
        finally:
 
608
            transform.finalize()
 
609
 
 
610
    def test_iter_changes_new(self):
 
611
        transform, root = self.get_transform()
 
612
        transform.new_file('old', root, 'blah')
 
613
        transform.apply()
 
614
        transform, root = self.get_transform()
 
615
        try:
 
616
            old = transform.trans_id_tree_path('old')
 
617
            transform.version_file('id-1', old)
 
618
            self.assertEqual([('id-1', 'old', False, (False, True),
 
619
                ('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', 'file'),
 
620
                (False, False))], list(transform._iter_changes()))
 
621
        finally:
 
622
            transform.finalize()
 
623
 
 
624
    def test_iter_changes_modifications(self):
 
625
        transform, root = self.get_transform()
 
626
        transform.new_file('old', root, 'blah', 'id-1')
 
627
        transform.new_file('new', root, 'blah')
 
628
        transform.new_directory('subdir', root, 'subdir-id')
 
629
        transform.apply()
 
630
        transform, root = self.get_transform()
 
631
        try:
 
632
            old = transform.trans_id_tree_path('old')
 
633
            subdir = transform.trans_id_tree_file_id('subdir-id')
 
634
            new = transform.trans_id_tree_path('new')
 
635
            self.assertEqual([], list(transform._iter_changes()))
 
636
 
 
637
            #content deletion
 
638
            transform.delete_contents(old)
 
639
            self.assertEqual([('id-1', 'old', True, (True, True),
 
640
                ('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', None),
 
641
                (False, False))], list(transform._iter_changes()))
 
642
 
 
643
            #content change
 
644
            transform.create_file('blah', old)
 
645
            self.assertEqual([('id-1', 'old', True, (True, True),
 
646
                ('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', 'file'),
 
647
                (False, False))], list(transform._iter_changes()))
 
648
            transform.cancel_deletion(old)
 
649
            self.assertEqual([('id-1', 'old', True, (True, True),
 
650
                ('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', 'file'),
 
651
                (False, False))], list(transform._iter_changes()))
 
652
            transform.cancel_creation(old)
 
653
 
 
654
            # move file_id to a different file
 
655
            self.assertEqual([], list(transform._iter_changes()))
 
656
            transform.unversion_file(old)
 
657
            transform.version_file('id-1', new)
 
658
            transform.adjust_path('old', root, new)
 
659
            self.assertEqual([('id-1', 'old', True, (True, True),
 
660
                ('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', 'file'),
 
661
                (False, False))], list(transform._iter_changes()))
 
662
            transform.cancel_versioning(new)
 
663
            transform._removed_id = set()
 
664
 
 
665
            #execute bit
 
666
            self.assertEqual([], list(transform._iter_changes()))
 
667
            transform.set_executability(True, old)
 
668
            self.assertEqual([('id-1', 'old', False, (True, True),
 
669
                ('TREE_ROOT', 'TREE_ROOT'), ('old', 'old'), ('file', 'file'),
 
670
                (False, True))], list(transform._iter_changes()))
 
671
            transform.set_executability(None, old)
 
672
 
 
673
            # filename
 
674
            self.assertEqual([], list(transform._iter_changes()))
 
675
            transform.adjust_path('new', root, old)
 
676
            transform._new_parent = {}
 
677
            self.assertEqual([('id-1', 'new', False, (True, True),
 
678
                ('TREE_ROOT', 'TREE_ROOT'), ('old', 'new'), ('file', 'file'),
 
679
                (False, False))], list(transform._iter_changes()))
 
680
            transform._new_name = {}
 
681
 
 
682
            # parent directory
 
683
            self.assertEqual([], list(transform._iter_changes()))
 
684
            transform.adjust_path('new', subdir, old)
 
685
            transform._new_name = {}
 
686
            self.assertEqual([('id-1', 'subdir/old', False, (True, True),
 
687
                ('TREE_ROOT', 'subdir-id'), ('old', 'old'), ('file', 'file'),
 
688
                (False, False))], list(transform._iter_changes()))
 
689
            transform._new_path = {}
 
690
 
 
691
        finally:
 
692
            transform.finalize()
 
693
 
 
694
    def test_iter_changes_modified_bleed(self):
 
695
        """Modified flag should not bleed from one change to another"""
 
696
        # unfortunately, we have no guarantee that file1 (which is modified)
 
697
        # will be applied before file2.  And if it's applied after file2, it
 
698
        # obviously can't bleed into file2's change output.  But for now, it
 
699
        # works.
 
700
        transform, root = self.get_transform()
 
701
        transform.new_file('file1', root, 'blah', 'id-1')
 
702
        transform.new_file('file2', root, 'blah', 'id-2')
 
703
        transform.apply()
 
704
        transform, root = self.get_transform()
 
705
        try:
 
706
            transform.delete_contents(transform.trans_id_file_id('id-1'))
 
707
            transform.set_executability(True,
 
708
            transform.trans_id_file_id('id-2'))
 
709
            self.assertEqual([('id-1', u'file1', True, (True, True),
 
710
                ('TREE_ROOT', 'TREE_ROOT'), ('file1', u'file1'),
 
711
                ('file', None), (False, False)),
 
712
                ('id-2', u'file2', False, (True, True),
 
713
                ('TREE_ROOT', 'TREE_ROOT'), ('file2', u'file2'),
 
714
                ('file', 'file'), (False, True))],
 
715
                list(transform._iter_changes()))
 
716
        finally:
 
717
            transform.finalize()
 
718
 
 
719
    def test_iter_changes_pointless(self):
 
720
        """Ensure that no-ops are not treated as modifications"""
 
721
        transform, root = self.get_transform()
 
722
        transform.new_file('old', root, 'blah', 'id-1')
 
723
        transform.new_directory('subdir', root, 'subdir-id')
 
724
        transform.apply()
 
725
        transform, root = self.get_transform()
 
726
        try:
 
727
            old = transform.trans_id_tree_path('old')
 
728
            subdir = transform.trans_id_tree_file_id('subdir-id')
 
729
            self.assertEqual([], list(transform._iter_changes()))
 
730
            transform.delete_contents(subdir)
 
731
            transform.create_directory(subdir)
 
732
            transform.set_executability(False, old)
 
733
            transform.unversion_file(old)
 
734
            transform.version_file('id-1', old)
 
735
            transform.adjust_path('old', root, old)
 
736
            self.assertEqual([], list(transform._iter_changes()))
 
737
        finally:
 
738
            transform.finalize()
493
739
 
494
740
class TransformGroup(object):
495
 
    def __init__(self, dirname):
 
741
    def __init__(self, dirname, root_id):
496
742
        self.name = dirname
497
743
        os.mkdir(dirname)
498
744
        self.wt = BzrDir.create_standalone_workingtree(dirname)
 
745
        self.wt.set_root_id(root_id)
499
746
        self.b = self.wt.branch
500
747
        self.tt = TreeTransform(self.wt)
501
748
        self.root = self.tt.trans_id_tree_file_id(self.wt.get_root_id())
502
749
 
 
750
 
503
751
def conflict_text(tree, merge):
504
752
    template = '%s TREE\n%s%s\n%s%s MERGE-SOURCE\n'
505
753
    return template % ('<' * 7, tree, '=' * 7, merge, '>' * 7)
507
755
 
508
756
class TestTransformMerge(TestCaseInTempDir):
509
757
    def test_text_merge(self):
510
 
        base = TransformGroup("base")
 
758
        root_id = generate_ids.gen_root_id()
 
759
        base = TransformGroup("base", root_id)
511
760
        base.tt.new_file('a', base.root, 'a\nb\nc\nd\be\n', 'a')
512
761
        base.tt.new_file('b', base.root, 'b1', 'b')
513
762
        base.tt.new_file('c', base.root, 'c', 'c')
517
766
        base.tt.new_directory('g', base.root, 'g')
518
767
        base.tt.new_directory('h', base.root, 'h')
519
768
        base.tt.apply()
520
 
        other = TransformGroup("other")
 
769
        other = TransformGroup("other", root_id)
521
770
        other.tt.new_file('a', other.root, 'y\nb\nc\nd\be\n', 'a')
522
771
        other.tt.new_file('b', other.root, 'b2', 'b')
523
772
        other.tt.new_file('c', other.root, 'c2', 'c')
528
777
        other.tt.new_file('h', other.root, 'h\ni\nj\nk\n', 'h')
529
778
        other.tt.new_file('i', other.root, 'h\ni\nj\nk\n', 'i')
530
779
        other.tt.apply()
531
 
        this = TransformGroup("this")
 
780
        this = TransformGroup("this", root_id)
532
781
        this.tt.new_file('a', this.root, 'a\nb\nc\nd\bz\n', 'a')
533
782
        this.tt.new_file('b', this.root, 'b', 'b')
534
783
        this.tt.new_file('c', this.root, 'c', 'c')
585
834
    def test_file_merge(self):
586
835
        if not has_symlinks():
587
836
            raise TestSkipped('Symlinks are not supported on this platform')
588
 
        base = TransformGroup("BASE")
589
 
        this = TransformGroup("THIS")
590
 
        other = TransformGroup("OTHER")
 
837
        root_id = generate_ids.gen_root_id()
 
838
        base = TransformGroup("BASE", root_id)
 
839
        this = TransformGroup("THIS", root_id)
 
840
        other = TransformGroup("OTHER", root_id)
591
841
        for tg in this, base, other:
592
842
            tg.tt.new_directory('a', tg.root, 'a')
593
843
            tg.tt.new_symlink('b', tg.root, 'b', 'b')
625
875
        self.assertIs(os.path.lexists(this.wt.abspath('h.OTHER')), True)
626
876
 
627
877
    def test_filename_merge(self):
628
 
        base = TransformGroup("BASE")
629
 
        this = TransformGroup("THIS")
630
 
        other = TransformGroup("OTHER")
 
878
        root_id = generate_ids.gen_root_id()
 
879
        base = TransformGroup("BASE", root_id)
 
880
        this = TransformGroup("THIS", root_id)
 
881
        other = TransformGroup("OTHER", root_id)
631
882
        base_a, this_a, other_a = [t.tt.new_directory('a', t.root, 'a') 
632
883
                                   for t in [base, this, other]]
633
884
        base_b, this_b, other_b = [t.tt.new_directory('b', t.root, 'b') 
657
908
        self.assertEqual(this.wt.id2path('f'), pathjoin('b/f1'))
658
909
 
659
910
    def test_filename_merge_conflicts(self):
660
 
        base = TransformGroup("BASE")
661
 
        this = TransformGroup("THIS")
662
 
        other = TransformGroup("OTHER")
 
911
        root_id = generate_ids.gen_root_id()
 
912
        base = TransformGroup("BASE", root_id)
 
913
        this = TransformGroup("THIS", root_id)
 
914
        other = TransformGroup("OTHER", root_id)
663
915
        base_a, this_a, other_a = [t.tt.new_directory('a', t.root, 'a') 
664
916
                                   for t in [base, this, other]]
665
917
        base_b, this_b, other_b = [t.tt.new_directory('b', t.root, 'b') 
686
938
        self.assertIs(os.path.lexists(this.wt.abspath('b/h1.OTHER')), False)
687
939
        self.assertEqual(this.wt.id2path('i'), pathjoin('b/i1.OTHER'))
688
940
 
689
 
class TestBuildTree(TestCaseInTempDir):
 
941
 
 
942
class TestBuildTree(tests.TestCaseWithTransport):
 
943
 
690
944
    def test_build_tree(self):
691
945
        if not has_symlinks():
692
946
            raise TestSkipped('Test requires symlink support')
702
956
        self.assertIs(os.path.isdir('b/foo'), True)
703
957
        self.assertEqual(file('b/foo/bar', 'rb').read(), "contents")
704
958
        self.assertEqual(os.readlink('b/foo/baz'), 'a/foo/bar')
 
959
 
 
960
    def test_file_conflict_handling(self):
 
961
        """Ensure that when building trees, conflict handling is done"""
 
962
        source = self.make_branch_and_tree('source')
 
963
        target = self.make_branch_and_tree('target')
 
964
        self.build_tree(['source/file', 'target/file'])
 
965
        source.add('file', 'new-file')
 
966
        source.commit('added file')
 
967
        build_tree(source.basis_tree(), target)
 
968
        self.assertEqual([DuplicateEntry('Moved existing file to',
 
969
                          'file.moved', 'file', None, 'new-file')],
 
970
                         target.conflicts())
 
971
        target2 = self.make_branch_and_tree('target2')
 
972
        target_file = file('target2/file', 'wb')
 
973
        try:
 
974
            source_file = file('source/file', 'rb')
 
975
            try:
 
976
                target_file.write(source_file.read())
 
977
            finally:
 
978
                source_file.close()
 
979
        finally:
 
980
            target_file.close()
 
981
        build_tree(source.basis_tree(), target2)
 
982
        self.assertEqual([], target2.conflicts())
 
983
 
 
984
    def test_symlink_conflict_handling(self):
 
985
        """Ensure that when building trees, conflict handling is done"""
 
986
        if not has_symlinks():
 
987
            raise TestSkipped('Test requires symlink support')
 
988
        source = self.make_branch_and_tree('source')
 
989
        os.symlink('foo', 'source/symlink')
 
990
        source.add('symlink', 'new-symlink')
 
991
        source.commit('added file')
 
992
        target = self.make_branch_and_tree('target')
 
993
        os.symlink('bar', 'target/symlink')
 
994
        build_tree(source.basis_tree(), target)
 
995
        self.assertEqual([DuplicateEntry('Moved existing file to',
 
996
            'symlink.moved', 'symlink', None, 'new-symlink')],
 
997
            target.conflicts())
 
998
        target = self.make_branch_and_tree('target2')
 
999
        os.symlink('foo', 'target2/symlink')
 
1000
        build_tree(source.basis_tree(), target)
 
1001
        self.assertEqual([], target.conflicts())
705
1002
        
 
1003
    def test_directory_conflict_handling(self):
 
1004
        """Ensure that when building trees, conflict handling is done"""
 
1005
        source = self.make_branch_and_tree('source')
 
1006
        target = self.make_branch_and_tree('target')
 
1007
        self.build_tree(['source/dir1/', 'source/dir1/file', 'target/dir1/'])
 
1008
        source.add(['dir1', 'dir1/file'], ['new-dir1', 'new-file'])
 
1009
        source.commit('added file')
 
1010
        build_tree(source.basis_tree(), target)
 
1011
        self.assertEqual([], target.conflicts())
 
1012
        self.failUnlessExists('target/dir1/file')
 
1013
 
 
1014
        # Ensure contents are merged
 
1015
        target = self.make_branch_and_tree('target2')
 
1016
        self.build_tree(['target2/dir1/', 'target2/dir1/file2'])
 
1017
        build_tree(source.basis_tree(), target)
 
1018
        self.assertEqual([], target.conflicts())
 
1019
        self.failUnlessExists('target2/dir1/file2')
 
1020
        self.failUnlessExists('target2/dir1/file')
 
1021
 
 
1022
        # Ensure new contents are suppressed for existing branches
 
1023
        target = self.make_branch_and_tree('target3')
 
1024
        self.make_branch('target3/dir1')
 
1025
        self.build_tree(['target3/dir1/file2'])
 
1026
        build_tree(source.basis_tree(), target)
 
1027
        self.failIfExists('target3/dir1/file')
 
1028
        self.failUnlessExists('target3/dir1/file2')
 
1029
        self.failUnlessExists('target3/dir1.diverted/file')
 
1030
        self.assertEqual([DuplicateEntry('Diverted to',
 
1031
            'dir1.diverted', 'dir1', 'new-dir1', None)],
 
1032
            target.conflicts())
 
1033
 
 
1034
        target = self.make_branch_and_tree('target4')
 
1035
        self.build_tree(['target4/dir1/'])
 
1036
        self.make_branch('target4/dir1/file')
 
1037
        build_tree(source.basis_tree(), target)
 
1038
        self.failUnlessExists('target4/dir1/file')
 
1039
        self.assertEqual('directory', file_kind('target4/dir1/file'))
 
1040
        self.failUnlessExists('target4/dir1/file.diverted')
 
1041
        self.assertEqual([DuplicateEntry('Diverted to',
 
1042
            'dir1/file.diverted', 'dir1/file', 'new-file', None)],
 
1043
            target.conflicts())
 
1044
 
 
1045
    def test_mixed_conflict_handling(self):
 
1046
        """Ensure that when building trees, conflict handling is done"""
 
1047
        source = self.make_branch_and_tree('source')
 
1048
        target = self.make_branch_and_tree('target')
 
1049
        self.build_tree(['source/name', 'target/name/'])
 
1050
        source.add('name', 'new-name')
 
1051
        source.commit('added file')
 
1052
        build_tree(source.basis_tree(), target)
 
1053
        self.assertEqual([DuplicateEntry('Moved existing file to',
 
1054
            'name.moved', 'name', None, 'new-name')], target.conflicts())
 
1055
 
 
1056
    def test_raises_in_populated(self):
 
1057
        source = self.make_branch_and_tree('source')
 
1058
        self.build_tree(['source/name'])
 
1059
        source.add('name')
 
1060
        source.commit('added name')
 
1061
        target = self.make_branch_and_tree('target')
 
1062
        self.build_tree(['target/name'])
 
1063
        target.add('name')
 
1064
        self.assertRaises(errors.WorkingTreeAlreadyPopulated, 
 
1065
            build_tree, source.basis_tree(), target)
 
1066
 
 
1067
 
706
1068
class MockTransform(object):
707
1069
 
708
1070
    def has_named_child(self, by_parent, parent_id, name):