/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

Add WSGI smart server.

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
    tests,
 
23
    urlutils,
 
24
    )
19
25
from bzrlib.bzrdir import BzrDir
20
26
from bzrlib.conflicts import (DuplicateEntry, DuplicateID, MissingParent,
21
 
                              UnversionedParent, ParentLoop)
 
27
                              UnversionedParent, ParentLoop, DeletingParent,)
22
28
from bzrlib.errors import (DuplicateKey, MalformedTransform, NoSuchFile,
23
 
                           ReusingTransform, CantMoveRoot, NotVersionedError,
24
 
                           ExistingLimbo, ImmortalLimbo, LockError)
 
29
                           ReusingTransform, CantMoveRoot, 
 
30
                           PathsNotVersionedError, ExistingLimbo,
 
31
                           ImmortalLimbo, LockError)
25
32
from bzrlib.osutils import file_kind, has_symlinks, pathjoin
26
33
from bzrlib.merge import Merge3Merger
27
34
from bzrlib.tests import TestCaseInTempDir, TestSkipped, TestCase
29
36
                              resolve_conflicts, cook_conflicts, 
30
37
                              find_interesting, build_tree, get_backup_name)
31
38
 
 
39
 
32
40
class TestTreeTransform(TestCaseInTempDir):
 
41
 
33
42
    def setUp(self):
34
43
        super(TestTreeTransform, self).setUp()
35
44
        self.wt = BzrDir.create_standalone_workingtree('.')
41
50
        return transform, transform.trans_id_tree_file_id(self.wt.get_root_id())
42
51
 
43
52
    def test_existing_limbo(self):
44
 
        limbo_name = self.wt._control_files.controlfilename('limbo')
 
53
        limbo_name = urlutils.local_path_from_url(
 
54
            self.wt._control_files.controlfilename('limbo'))
45
55
        transform, root = self.get_transform()
46
56
        os.mkdir(pathjoin(limbo_name, 'hehe'))
47
57
        self.assertRaises(ImmortalLimbo, transform.apply)
57
67
        transform, root = self.get_transform() 
58
68
        self.assertIs(transform.get_tree_parent(root), ROOT_PARENT)
59
69
        imaginary_id = transform.trans_id_tree_path('imaginary')
 
70
        imaginary_id2 = transform.trans_id_tree_path('imaginary/')
 
71
        self.assertEqual(imaginary_id, imaginary_id2)
60
72
        self.assertEqual(transform.get_tree_parent(imaginary_id), root)
61
73
        self.assertEqual(transform.final_kind(root), 'directory')
62
74
        self.assertEqual(transform.final_file_id(root), self.wt.get_root_id())
381
393
                                         'dorothy-id')
382
394
        old_dorothy = conflicts.trans_id_tree_file_id('dorothy-id')
383
395
        oz = conflicts.trans_id_tree_file_id('oz-id')
384
 
        # set up missing, unversioned parent
 
396
        # set up DeletedParent parent conflict
385
397
        conflicts.delete_versioned(oz)
386
398
        emerald = conflicts.trans_id_tree_file_id('emerald-id')
 
399
        # set up MissingParent conflict
 
400
        munchkincity = conflicts.trans_id_file_id('munchkincity-id')
 
401
        conflicts.adjust_path('munchkincity', root, munchkincity)
 
402
        conflicts.new_directory('auntem', munchkincity, 'auntem-id')
387
403
        # set up parent loop
388
404
        conflicts.adjust_path('emeraldcity', emerald, emerald)
389
405
        return conflicts, emerald, oz, old_dorothy, new_dorothy
410
426
                                   'dorothy.moved', 'dorothy', None,
411
427
                                   'dorothy-id')
412
428
        self.assertEqual(cooked_conflicts[1], duplicate_id)
413
 
        missing_parent = MissingParent('Not deleting', 'oz', 'oz-id')
 
429
        missing_parent = MissingParent('Created directory', 'munchkincity',
 
430
                                       'munchkincity-id')
 
431
        deleted_parent = DeletingParent('Not deleting', 'oz', 'oz-id')
414
432
        self.assertEqual(cooked_conflicts[2], missing_parent)
415
 
        unversioned_parent = UnversionedParent('Versioned directory', 'oz',
 
433
        unversioned_parent = UnversionedParent('Versioned directory',
 
434
                                               'munchkincity',
 
435
                                               'munchkincity-id')
 
436
        unversioned_parent2 = UnversionedParent('Versioned directory', 'oz',
416
437
                                               'oz-id')
417
438
        self.assertEqual(cooked_conflicts[3], unversioned_parent)
418
439
        parent_loop = ParentLoop('Cancelled move', 'oz/emeraldcity', 
419
440
                                 'oz/emeraldcity', 'emerald-id', 'emerald-id')
420
 
        self.assertEqual(cooked_conflicts[4], parent_loop)
421
 
        self.assertEqual(len(cooked_conflicts), 5)
 
441
        self.assertEqual(cooked_conflicts[4], deleted_parent)
 
442
        self.assertEqual(cooked_conflicts[5], unversioned_parent2)
 
443
        self.assertEqual(cooked_conflicts[6], parent_loop)
 
444
        self.assertEqual(len(cooked_conflicts), 7)
422
445
        tt.finalize()
423
446
 
424
447
    def test_string_conflicts(self):
434
457
        self.assertEqual(conflicts_s[1], 'Conflict adding id to dorothy.  '
435
458
                                         'Unversioned existing file '
436
459
                                         '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'
 
460
        self.assertEqual(conflicts_s[2], 'Conflict adding files to'
 
461
                                         ' munchkincity.  Created directory.')
 
462
        self.assertEqual(conflicts_s[3], 'Conflict because munchkincity is not'
 
463
                                         ' versioned, but has versioned'
 
464
                                         ' children.  Versioned directory.')
 
465
        self.assertEqualDiff(conflicts_s[4], "Conflict: can't delete oz because it"
 
466
                                         " is not empty.  Not deleting.")
 
467
        self.assertEqual(conflicts_s[5], 'Conflict because oz is not'
 
468
                                         ' versioned, but has versioned'
 
469
                                         ' children.  Versioned directory.')
 
470
        self.assertEqual(conflicts_s[6], 'Conflict moving oz/emeraldcity into'
442
471
                                         ' oz/emeraldcity.  Cancelled move.')
443
472
 
444
473
    def test_moving_versioned_directories(self):
487
516
        create.apply()
488
517
        self.assertEqual(find_interesting(wt, wt, ['vfile']),
489
518
                         set(['myfile-id']))
490
 
        self.assertRaises(NotVersionedError, find_interesting, wt, wt,
 
519
        self.assertRaises(PathsNotVersionedError, find_interesting, wt, wt,
491
520
                          ['uvfile'])
492
521
 
 
522
    def test_set_executability_order(self):
 
523
        """Ensure that executability behaves the same, no matter what order.
 
524
        
 
525
        - create file and set executability simultaneously
 
526
        - create file and set executability afterward
 
527
        - unsetting the executability of a file whose executability has not been
 
528
        declared should throw an exception (this may happen when a
 
529
        merge attempts to create a file with a duplicate ID)
 
530
        """
 
531
        transform, root = self.get_transform()
 
532
        wt = transform._tree
 
533
        transform.new_file('set_on_creation', root, 'Set on creation', 'soc',
 
534
                           True)
 
535
        sac = transform.new_file('set_after_creation', root, 'Set after creation', 'sac')
 
536
        transform.set_executability(True, sac)
 
537
        uws = transform.new_file('unset_without_set', root, 'Unset badly', 'uws')
 
538
        self.assertRaises(KeyError, transform.set_executability, None, uws)
 
539
        transform.apply()
 
540
        self.assertTrue(wt.is_executable('soc'))
 
541
        self.assertTrue(wt.is_executable('sac'))
 
542
 
 
543
    def test_preserve_mode(self):
 
544
        """File mode is preserved when replacing content"""
 
545
        if sys.platform == 'win32':
 
546
            raise TestSkipped('chmod has no effect on win32')
 
547
        transform, root = self.get_transform()
 
548
        transform.new_file('file1', root, 'contents', 'file1-id', True)
 
549
        transform.apply()
 
550
        self.assertTrue(self.wt.is_executable('file1-id'))
 
551
        transform, root = self.get_transform()
 
552
        file1_id = transform.trans_id_tree_file_id('file1-id')
 
553
        transform.delete_contents(file1_id)
 
554
        transform.create_file('contents2', file1_id)
 
555
        transform.apply()
 
556
        self.assertTrue(self.wt.is_executable('file1-id'))
 
557
 
 
558
    def test__set_mode_stats_correctly(self):
 
559
        """_set_mode stats to determine file mode."""
 
560
        if sys.platform == 'win32':
 
561
            raise TestSkipped('chmod has no effect on win32')
 
562
 
 
563
        stat_paths = []
 
564
        real_stat = os.stat
 
565
        def instrumented_stat(path):
 
566
            stat_paths.append(path)
 
567
            return real_stat(path)
 
568
 
 
569
        transform, root = self.get_transform()
 
570
 
 
571
        bar1_id = transform.new_file('bar', root, 'bar contents 1\n',
 
572
                                     file_id='bar-id-1', executable=False)
 
573
        transform.apply()
 
574
 
 
575
        transform, root = self.get_transform()
 
576
        bar1_id = transform.trans_id_tree_path('bar')
 
577
        bar2_id = transform.trans_id_tree_path('bar2')
 
578
        try:
 
579
            os.stat = instrumented_stat
 
580
            transform.create_file('bar2 contents\n', bar2_id, mode_id=bar1_id)
 
581
        finally:
 
582
            os.stat = real_stat
 
583
            transform.finalize()
 
584
 
 
585
        bar1_abspath = self.wt.abspath('bar')
 
586
        self.assertEqual([bar1_abspath], stat_paths)
 
587
 
493
588
 
494
589
class TransformGroup(object):
495
590
    def __init__(self, dirname):
686
781
        self.assertIs(os.path.lexists(this.wt.abspath('b/h1.OTHER')), False)
687
782
        self.assertEqual(this.wt.id2path('i'), pathjoin('b/i1.OTHER'))
688
783
 
689
 
class TestBuildTree(TestCaseInTempDir):
 
784
 
 
785
class TestBuildTree(tests.TestCaseWithTransport):
 
786
 
690
787
    def test_build_tree(self):
691
788
        if not has_symlinks():
692
789
            raise TestSkipped('Test requires symlink support')
702
799
        self.assertIs(os.path.isdir('b/foo'), True)
703
800
        self.assertEqual(file('b/foo/bar', 'rb').read(), "contents")
704
801
        self.assertEqual(os.readlink('b/foo/baz'), 'a/foo/bar')
 
802
 
 
803
    def test_file_conflict_handling(self):
 
804
        """Ensure that when building trees, conflict handling is done"""
 
805
        source = self.make_branch_and_tree('source')
 
806
        target = self.make_branch_and_tree('target')
 
807
        self.build_tree(['source/file', 'target/file'])
 
808
        source.add('file', 'new-file')
 
809
        source.commit('added file')
 
810
        build_tree(source.basis_tree(), target)
 
811
        self.assertEqual([DuplicateEntry('Moved existing file to',
 
812
                          'file.moved', 'file', None, 'new-file')],
 
813
                         target.conflicts())
 
814
        target2 = self.make_branch_and_tree('target2')
 
815
        target_file = file('target2/file', 'wb')
 
816
        try:
 
817
            source_file = file('source/file', 'rb')
 
818
            try:
 
819
                target_file.write(source_file.read())
 
820
            finally:
 
821
                source_file.close()
 
822
        finally:
 
823
            target_file.close()
 
824
        build_tree(source.basis_tree(), target2)
 
825
        self.assertEqual([], target2.conflicts())
 
826
 
 
827
    def test_symlink_conflict_handling(self):
 
828
        """Ensure that when building trees, conflict handling is done"""
 
829
        if not has_symlinks():
 
830
            raise TestSkipped('Test requires symlink support')
 
831
        source = self.make_branch_and_tree('source')
 
832
        os.symlink('foo', 'source/symlink')
 
833
        source.add('symlink', 'new-symlink')
 
834
        source.commit('added file')
 
835
        target = self.make_branch_and_tree('target')
 
836
        os.symlink('bar', 'target/symlink')
 
837
        build_tree(source.basis_tree(), target)
 
838
        self.assertEqual([DuplicateEntry('Moved existing file to',
 
839
            'symlink.moved', 'symlink', None, 'new-symlink')],
 
840
            target.conflicts())
 
841
        target = self.make_branch_and_tree('target2')
 
842
        os.symlink('foo', 'target2/symlink')
 
843
        build_tree(source.basis_tree(), target)
 
844
        self.assertEqual([], target.conflicts())
705
845
        
 
846
    def test_directory_conflict_handling(self):
 
847
        """Ensure that when building trees, conflict handling is done"""
 
848
        source = self.make_branch_and_tree('source')
 
849
        target = self.make_branch_and_tree('target')
 
850
        self.build_tree(['source/dir1/', 'source/dir1/file', 'target/dir1/'])
 
851
        source.add(['dir1', 'dir1/file'], ['new-dir1', 'new-file'])
 
852
        source.commit('added file')
 
853
        build_tree(source.basis_tree(), target)
 
854
        self.assertEqual([], target.conflicts())
 
855
        self.failUnlessExists('target/dir1/file')
 
856
 
 
857
        # Ensure contents are merged
 
858
        target = self.make_branch_and_tree('target2')
 
859
        self.build_tree(['target2/dir1/', 'target2/dir1/file2'])
 
860
        build_tree(source.basis_tree(), target)
 
861
        self.assertEqual([], target.conflicts())
 
862
        self.failUnlessExists('target2/dir1/file2')
 
863
        self.failUnlessExists('target2/dir1/file')
 
864
 
 
865
        # Ensure new contents are suppressed for existing branches
 
866
        target = self.make_branch_and_tree('target3')
 
867
        self.make_branch('target3/dir1')
 
868
        self.build_tree(['target3/dir1/file2'])
 
869
        build_tree(source.basis_tree(), target)
 
870
        self.failIfExists('target3/dir1/file')
 
871
        self.failUnlessExists('target3/dir1/file2')
 
872
        self.failUnlessExists('target3/dir1.diverted/file')
 
873
        self.assertEqual([DuplicateEntry('Diverted to',
 
874
            'dir1.diverted', 'dir1', 'new-dir1', None)],
 
875
            target.conflicts())
 
876
 
 
877
        target = self.make_branch_and_tree('target4')
 
878
        self.build_tree(['target4/dir1/'])
 
879
        self.make_branch('target4/dir1/file')
 
880
        build_tree(source.basis_tree(), target)
 
881
        self.failUnlessExists('target4/dir1/file')
 
882
        self.assertEqual('directory', file_kind('target4/dir1/file'))
 
883
        self.failUnlessExists('target4/dir1/file.diverted')
 
884
        self.assertEqual([DuplicateEntry('Diverted to',
 
885
            'dir1/file.diverted', 'dir1/file', 'new-file', None)],
 
886
            target.conflicts())
 
887
 
 
888
    def test_mixed_conflict_handling(self):
 
889
        """Ensure that when building trees, conflict handling is done"""
 
890
        source = self.make_branch_and_tree('source')
 
891
        target = self.make_branch_and_tree('target')
 
892
        self.build_tree(['source/name', 'target/name/'])
 
893
        source.add('name', 'new-name')
 
894
        source.commit('added file')
 
895
        build_tree(source.basis_tree(), target)
 
896
        self.assertEqual([DuplicateEntry('Moved existing file to',
 
897
            'name.moved', 'name', None, 'new-name')], target.conflicts())
 
898
 
 
899
    def test_raises_in_populated(self):
 
900
        source = self.make_branch_and_tree('source')
 
901
        self.build_tree(['source/name'])
 
902
        source.add('name')
 
903
        source.commit('added name')
 
904
        target = self.make_branch_and_tree('target')
 
905
        self.build_tree(['target/name'])
 
906
        target.add('name')
 
907
        self.assertRaises(AssertionError, build_tree, source.basis_tree(),
 
908
                          target)
 
909
 
 
910
 
706
911
class MockTransform(object):
707
912
 
708
913
    def has_named_child(self, by_parent, parent_id, name):