~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/intertree_implementations/test_compare.py

  • Committer: Robert Collins
  • Date: 2007-04-23 02:29:35 UTC
  • mfrom: (2441 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2442.
  • Revision ID: robertc@robertcollins.net-20070423022935-9hhongamvk6bfdso
Resolve conflicts with bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
import shutil
21
21
 
22
22
from bzrlib import errors, tests, workingtree_4
23
 
from bzrlib.osutils import file_kind
 
23
from bzrlib.osutils import file_kind, has_symlinks
24
24
from bzrlib.tests.intertree_implementations import TestCaseWithTwoTrees
25
25
 
26
26
# TODO: test the include_root option.
321
321
        tree2 = self.make_to_branch_and_tree('tree2')
322
322
        tree2.set_root_id(tree1.get_root_id())
323
323
        self.build_tree(['tree2/file', 'tree2/dir/'])
324
 
        # try:
325
 
        os.symlink('target', 'tree2/link')
326
 
        links_supported = True
327
 
        # except ???:
328
 
        #   links_supported = False
 
324
        if has_symlinks():
 
325
            os.symlink('target', 'tree2/link')
 
326
            links_supported = True
 
327
        else:
 
328
            links_supported = False
329
329
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
330
330
        d = self.intertree_class(tree1, tree2).compare(want_unversioned=True)
331
331
        self.assertEqual([], d.added)
333
333
        self.assertEqual([], d.removed)
334
334
        self.assertEqual([], d.renamed)
335
335
        self.assertEqual([], d.unchanged)
336
 
        self.assertEqual([(u'dir', None, 'directory'), (u'file', None, 'file'),
337
 
            (u'link', None, 'symlink')], d.unversioned)
 
336
        expected_unversioned = [(u'dir', None, 'directory'),
 
337
                                (u'file', None, 'file')]
 
338
        if links_supported:
 
339
            expected_unversioned.append((u'link', None, 'symlink'))
 
340
        self.assertEqual(expected_unversioned, d.unversioned)
338
341
 
339
342
 
340
343
class TestIterChanges(TestCaseWithTwoTrees):
358
361
            tree1.unlock()
359
362
            tree2.unlock()
360
363
 
 
364
    def mutable_trees_to_locked_test_trees(self, tree1, tree2):
 
365
        """Convert the working trees into test trees.
 
366
 
 
367
        Read lock them, and add the unlock to the cleanup.
 
368
        """
 
369
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
 
370
        tree1.lock_read()
 
371
        self.addCleanup(tree1.unlock)
 
372
        tree2.lock_read()
 
373
        self.addCleanup(tree2.unlock)
 
374
        return tree1, tree2
 
375
 
361
376
    def make_tree_with_special_names(self):
362
377
        """Create a tree with filenames chosen to exercise the walk order."""
363
378
        tree1 = self.make_branch_and_tree('tree1')
365
380
        tree2.set_root_id(tree1.get_root_id())
366
381
        paths, path_ids = self._create_special_names(tree2, 'tree2')
367
382
        tree2.commit('initial', rev_id='rev-1')
368
 
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
 
383
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
369
384
        return (tree1, tree2, paths, path_ids)
370
385
 
371
386
    def make_trees_with_special_names(self):
378
393
        tree2.set_root_id(tree1.get_root_id())
379
394
        paths, path_ids = self._create_special_names(tree1, 'tree1')
380
395
        paths, path_ids = self._create_special_names(tree2, 'tree2')
381
 
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
 
396
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
382
397
        return (tree1, tree2, paths, path_ids)
383
398
 
384
399
    def _create_special_names(self, tree, base_path):
489
504
        tree2 = self.make_to_branch_and_tree('2')
490
505
        tree1 = self.get_tree_no_parents_no_content(tree1)
491
506
        tree2 = self.get_tree_no_parents_abc_content(tree2)
492
 
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
493
 
        tree1.lock_read()
494
 
        tree2.lock_read()
 
507
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
495
508
        expected_results = sorted([
496
509
            self.added(tree2, 'root-id'),
497
510
            self.added(tree2, 'a-id'),
498
511
            self.added(tree2, 'b-id'),
499
512
            self.added(tree2, 'c-id'),
500
513
            self.deleted(tree1, 'empty-root-id')])
501
 
        tree1.unlock()
502
 
        tree2.unlock()
503
514
        self.assertEqual(expected_results, self.do_iter_changes(tree1, tree2))
504
515
 
505
516
    def test_empty_to_abc_content_a_only(self):
507
518
        tree2 = self.make_to_branch_and_tree('2')
508
519
        tree1 = self.get_tree_no_parents_no_content(tree1)
509
520
        tree2 = self.get_tree_no_parents_abc_content(tree2)
510
 
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
511
 
        tree1.lock_read()
512
 
        tree2.lock_read()
 
521
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
513
522
        self.assertEqual(
514
523
            [self.added(tree2, 'a-id')],
515
524
            self.do_iter_changes(tree1, tree2, specific_files=['a']))
516
 
        tree1.unlock()
517
 
        tree2.unlock()
518
525
 
519
526
    def test_abc_content_to_empty_to_abc_content_a_only(self):
520
527
        tree1 = self.make_branch_and_tree('1')
521
528
        tree2 = self.make_to_branch_and_tree('2')
522
529
        tree1 = self.get_tree_no_parents_abc_content(tree1)
523
530
        tree2 = self.get_tree_no_parents_no_content(tree2)
524
 
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
525
 
        tree1.lock_read()
526
 
        tree2.lock_read()
 
531
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
527
532
        self.assertEqual(
528
533
            [self.deleted(tree1, 'a-id')],
529
534
            self.do_iter_changes(tree1, tree2, specific_files=['a']))
530
 
        tree1.unlock()
531
 
        tree2.unlock()
532
535
 
533
536
    def test_empty_to_abc_content_a_and_c_only(self):
534
537
        tree1 = self.make_branch_and_tree('1')
535
538
        tree2 = self.make_to_branch_and_tree('2')
536
539
        tree1 = self.get_tree_no_parents_no_content(tree1)
537
540
        tree2 = self.get_tree_no_parents_abc_content(tree2)
538
 
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
539
 
        tree1.lock_read()
540
 
        tree2.lock_read()
 
541
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
541
542
        expected_result = [self.added(tree2, 'a-id'), self.added(tree2, 'c-id')]
542
 
        tree1.unlock()
543
 
        tree2.unlock()
544
543
        self.assertEqual(expected_result,
545
544
            self.do_iter_changes(tree1, tree2, specific_files=['a', 'b/c']))
546
545
 
549
548
        tree2 = self.make_to_branch_and_tree('2')
550
549
        tree1 = self.get_tree_no_parents_abc_content(tree1)
551
550
        tree2 = self.get_tree_no_parents_no_content(tree2)
552
 
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
553
 
        tree1.lock_read()
554
 
        tree2.lock_read()
 
551
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
555
552
        def deleted(file_id):
556
553
            entry = tree1.inventory[file_id]
557
554
            path = tree1.id2path(file_id)
563
560
            self.added(tree2, 'empty-root-id'),
564
561
            deleted('root-id'), deleted('a-id'),
565
562
            deleted('b-id'), deleted('c-id')])
566
 
        tree1.unlock()
567
 
        tree2.unlock()
568
563
        self.assertEqual(
569
564
            expected_results,
570
565
            self.do_iter_changes(tree1, tree2))
669
664
        self.build_tree(['tree2/directory/'])
670
665
        tree2.add(['directory'], ['file-id'])
671
666
        os.rmdir('tree2/directory')
672
 
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
673
 
        tree1.lock_read()
674
 
        self.addCleanup(tree1.unlock)
675
 
        tree2.lock_read()
676
 
        self.addCleanup(tree2.unlock)
 
667
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
 
668
 
677
669
        root_id = tree1.path2id('')
678
670
        expected = sorted([
679
671
            self.missing('file-id', 'file', 'directory', root_id, 'file'),
686
678
        tree2 = self.make_to_branch_and_tree('2')
687
679
        tree1 = self.get_tree_no_parents_abc_content(tree1)
688
680
        tree2 = self.get_tree_no_parents_abc_content_5(tree2)
689
 
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
 
681
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
690
682
        root_id = tree1.path2id('')
691
 
        tree1.lock_read()
692
 
        self.addCleanup(tree1.unlock)
693
 
        tree2.lock_read()
694
 
        self.addCleanup(tree2.unlock)
 
683
 
695
684
        self.assertEqual(sorted([self.unchanged(tree1, root_id),
696
685
            self.unchanged(tree1, 'b-id'),
697
686
            ('a-id', ('a', 'd'), True, (True, True),
700
689
            self.do_iter_changes(tree1, tree2, include_unchanged=True))
701
690
 
702
691
    def test_compare_subtrees(self):
703
 
        """want_unchanged should generate a list of unchanged entries."""
704
692
        tree1 = self.make_branch_and_tree('1')
705
693
        if not tree1.supports_tree_reference():
706
 
            raise tests.TestSkipped('Tree %s does not support references'
707
 
                % (tree1,))
 
694
            return
708
695
        tree1.set_root_id('root-id')
709
696
        subtree1 = self.make_branch_and_tree('1/sub')
710
697
        subtree1.set_root_id('subtree-id')
712
699
 
713
700
        tree2 = self.make_to_branch_and_tree('2')
714
701
        if not tree2.supports_tree_reference():
715
 
            raise tests.TestSkipped('Tree %s does not support references'
716
 
                % (tree2,))
 
702
            return
717
703
        tree2.set_root_id('root-id')
718
704
        subtree2 = self.make_to_branch_and_tree('2/sub')
719
705
        subtree2.set_root_id('subtree-id')
720
706
        tree2.add_reference(subtree2)
721
 
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
722
 
        tree1.lock_read()
723
 
        self.addCleanup(tree1.unlock)
724
 
        tree2.lock_read()
725
 
        self.addCleanup(tree2.unlock)
 
707
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
 
708
 
726
709
        self.assertEqual([], list(tree2._iter_changes(tree1)))
727
710
        subtree1.commit('commit', rev_id='commit-a')
728
711
        self.assertEqual([
745
728
                         list(tree2._iter_changes(tree1,
746
729
                             include_unchanged=True)))
747
730
 
 
731
    def test_disk_in_subtrees_skipped(self):
 
732
        """subtrees are considered not-in-the-current-tree.
 
733
        
 
734
        This test tests the trivial case, where the basis has no paths in the
 
735
        current trees subtree.
 
736
        """
 
737
        tree1 = self.make_branch_and_tree('1')
 
738
        tree1.set_root_id('root-id')
 
739
        tree2 = self.make_to_branch_and_tree('2')
 
740
        if not tree2.supports_tree_reference():
 
741
            return
 
742
        tree2.set_root_id('root-id')
 
743
        subtree2 = self.make_to_branch_and_tree('2/sub')
 
744
        subtree2.set_root_id('subtree-id')
 
745
        tree2.add(['sub'], ['subtree-id'])
 
746
        self.build_tree(['2/sub/file'])
 
747
        subtree2.add(['file'])
 
748
 
 
749
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
 
750
        # this should filter correctly from above
 
751
        self.assertEqual([self.added(tree2, 'subtree-id')],
 
752
            self.do_iter_changes(tree1, tree2, want_unversioned=True))
 
753
        # and when the path is named
 
754
        self.assertEqual([self.added(tree2, 'subtree-id')],
 
755
            self.do_iter_changes(tree1, tree2, specific_files=['sub'],
 
756
                want_unversioned=True))
 
757
 
748
758
    def test_default_ignores_unversioned_files(self):
749
759
        tree1 = self.make_branch_and_tree('tree1')
750
760
        tree2 = self.make_to_branch_and_tree('tree2')
754
764
        tree1.add(['a', 'c'], ['a-id', 'c-id'])
755
765
        tree2.add(['a', 'c'], ['a-id', 'c-id'])
756
766
 
757
 
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
758
 
        tree1.lock_read()
759
 
        self.addCleanup(tree1.unlock)
760
 
        tree2.lock_read()
761
 
        self.addCleanup(tree2.unlock)
 
767
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
762
768
 
763
769
        # We should ignore the fact that 'b' exists in tree-2
764
770
        # because the want_unversioned parameter was not given.
773
779
        tree2 = self.make_to_branch_and_tree('tree2')
774
780
        tree2.set_root_id(tree1.get_root_id())
775
781
        self.build_tree(['tree2/file', 'tree2/dir/'])
776
 
        # try:
777
 
        os.symlink('target', 'tree2/link')
778
 
        links_supported = True
779
 
        # except ???:
780
 
        #   links_supported = False
781
 
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
782
 
        tree1.lock_read()
783
 
        self.addCleanup(tree1.unlock)
784
 
        tree2.lock_read()
785
 
        self.addCleanup(tree2.unlock)
 
782
        if has_symlinks():
 
783
            os.symlink('target', 'tree2/link')
 
784
            links_supported = True
 
785
        else:
 
786
            links_supported = False
 
787
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
786
788
        expected = [
787
789
            self.unversioned(tree2, 'file'),
788
790
            self.unversioned(tree2, 'dir'),
797
799
        tree1 = self.make_branch_and_tree('tree1')
798
800
        tree2 = self.make_to_branch_and_tree('tree2')
799
801
        self.build_tree(['tree2/file', 'tree2/dir/'])
800
 
        # try:
801
 
        os.symlink('target', 'tree2/link')
802
 
        links_supported = True
803
 
        # except ???:
804
 
        #   links_supported = False
805
 
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
806
 
        tree1.lock_read()
807
 
        self.addCleanup(tree1.unlock)
808
 
        tree2.lock_read()
809
 
        self.addCleanup(tree2.unlock)
 
802
        if has_symlinks():
 
803
            os.symlink('target', 'tree2/link')
 
804
            links_supported = True
 
805
        else:
 
806
            links_supported = False
 
807
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
810
808
        expected = [
811
809
            self.unversioned(tree2, 'file'),
812
810
            self.unversioned(tree2, 'dir'),
834
832
        self.build_tree(['tree2/file', 'tree2/dir/',
835
833
            'tree1/file', 'tree2/movedfile',
836
834
            'tree1/dir/', 'tree2/moveddir/'])
837
 
        # try:
838
 
        os.symlink('target', 'tree1/link')
839
 
        os.symlink('target', 'tree2/link')
840
 
        os.symlink('target', 'tree2/movedlink')
841
 
        links_supported = True
842
 
        # except ???:
843
 
        #   links_supported = False
844
 
        tree1.add(['file', 'dir', 'link'], ['file-id', 'dir-id', 'link-id'])
845
 
        tree2.add(['movedfile', 'moveddir', 'movedlink'],
846
 
            ['file-id', 'dir-id', 'link-id'])
847
 
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
 
835
        if has_symlinks():
 
836
            os.symlink('target', 'tree1/link')
 
837
            os.symlink('target', 'tree2/link')
 
838
            os.symlink('target', 'tree2/movedlink')
 
839
            links_supported = True
 
840
        else:
 
841
            links_supported = False
 
842
        tree1.add(['file', 'dir'], ['file-id', 'dir-id'])
 
843
        tree2.add(['movedfile', 'moveddir'], ['file-id', 'dir-id'])
 
844
        if links_supported:
 
845
            tree1.add(['link'], ['link-id'])
 
846
            tree2.add(['movedlink'], ['link-id'])
 
847
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
848
848
        root_id = tree1.path2id('')
849
 
        tree1.lock_read()
850
 
        self.addCleanup(tree1.unlock)
851
 
        tree2.lock_read()
852
 
        self.addCleanup(tree2.unlock)
853
849
        expected = [
854
850
            self.renamed(tree1, tree2, 'dir-id', False),
855
851
            self.renamed(tree1, tree2, 'file-id', True),
925
921
        # except ???:
926
922
        #   raise TestSkipped('OS does not support symlinks')
927
923
        #   links_supported = False
928
 
        return self.mutable_trees_to_test_trees(tree1, tree2)
 
924
        return self.mutable_trees_to_locked_test_trees(tree1, tree2)
929
925
 
930
926
    def test_versioned_symlinks(self):
 
927
        if not has_symlinks():
 
928
            raise tests.TestSkipped("No symlink support")
931
929
        tree1, tree2 = self.make_trees_with_symlinks()
932
930
        root_id = tree1.path2id('')
933
 
        tree1.lock_read()
934
 
        self.addCleanup(tree1.unlock)
935
 
        tree2.lock_read()
936
 
        self.addCleanup(tree2.unlock)
937
931
        expected = [
938
932
            self.unchanged(tree1, tree1.path2id('')),
939
933
            self.added(tree2, 'added'),
952
946
                want_unversioned=True))
953
947
 
954
948
    def test_versioned_symlinks_specific_files(self):
 
949
        if not has_symlinks():
 
950
            raise tests.TestSkipped("No symlink support")
955
951
        tree1, tree2 = self.make_trees_with_symlinks()
956
952
        root_id = tree1.path2id('')
957
 
        tree1.lock_read()
958
 
        self.addCleanup(tree1.unlock)
959
 
        tree2.lock_read()
960
 
        self.addCleanup(tree2.unlock)
961
953
        expected = [
962
954
            self.added(tree2, 'added'),
963
955
            self.content_changed(tree2, 'changed'),
977
969
 
978
970
    def test_tree_with_special_names(self):
979
971
        tree1, tree2, paths, path_ids = self.make_tree_with_special_names()
980
 
        tree1.lock_read()
981
 
        self.addCleanup(tree1.unlock)
982
 
        tree2.lock_read()
983
 
        self.addCleanup(tree2.unlock)
984
972
        expected = sorted(self.added(tree2, f_id) for f_id in path_ids)
985
973
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
986
974
 
987
975
    def test_trees_with_special_names(self):
988
976
        tree1, tree2, paths, path_ids = self.make_trees_with_special_names()
989
 
        tree1.lock_read()
990
 
        self.addCleanup(tree1.unlock)
991
 
        tree2.lock_read()
992
 
        self.addCleanup(tree2.unlock)
993
977
        expected = sorted(self.content_changed(tree2, f_id) for f_id in path_ids
994
978
                          if f_id.endswith('_f-id'))
995
979
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
1005
989
                  ['a-id', 'b-id', 'c-id', 'd-id', 'e-id', 'f-id', 'g-id'])
1006
990
        tree2.add(['a', 'f', 'f/g'], ['a-id', 'f-id', 'g-id'])
1007
991
 
1008
 
        tree1, tree2 = self.mutable_trees_to_test_trees(tree1, tree2)
1009
 
        tree1.lock_read()
1010
 
        self.addCleanup(tree1.unlock)
1011
 
        tree2.lock_read()
1012
 
        self.addCleanup(tree2.unlock)
 
992
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
1013
993
        # We should notice that 'b' and all its children are deleted
1014
994
        expected = sorted([
1015
995
            self.content_changed(tree2, 'a-id'),
1020
1000
            self.deleted(tree1, 'e-id'),
1021
1001
            ])
1022
1002
        self.assertEqual(expected, self.do_iter_changes(tree1, tree2))
 
1003
 
 
1004
    def test_added_unicode(self):
 
1005
        tree1 = self.make_branch_and_tree('tree1')
 
1006
        tree2 = self.make_to_branch_and_tree('tree2')
 
1007
        root_id = tree1.get_root_id()
 
1008
        tree2.set_root_id(root_id)
 
1009
 
 
1010
        # u'\u03b1' == GREEK SMALL LETTER ALPHA
 
1011
        # u'\u03c9' == GREEK SMALL LETTER OMEGA
 
1012
        a_id = u'\u03b1-id'.encode('utf8')
 
1013
        added_id = u'\u03c9_added_id'.encode('utf8')
 
1014
        try:
 
1015
            self.build_tree([u'tree1/\u03b1/',
 
1016
                             u'tree2/\u03b1/',
 
1017
                             u'tree2/\u03b1/\u03c9-added',
 
1018
                            ])
 
1019
        except UnicodeError:
 
1020
            raise tests.TestSkipped("Could not create Unicode files.")
 
1021
        tree1.add([u'\u03b1'], [a_id])
 
1022
        tree2.add([u'\u03b1', u'\u03b1/\u03c9-added'], [a_id, added_id])
 
1023
 
 
1024
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
 
1025
 
 
1026
        self.assertEqual([self.added(tree2, added_id)],
 
1027
                         self.do_iter_changes(tree1, tree2))
 
1028
        self.assertEqual([self.added(tree2, added_id)],
 
1029
                         self.do_iter_changes(tree1, tree2,
 
1030
                                              specific_files=[u'\u03b1']))
 
1031
 
 
1032
    def test_deleted_unicode(self):
 
1033
        tree1 = self.make_branch_and_tree('tree1')
 
1034
        tree2 = self.make_to_branch_and_tree('tree2')
 
1035
        root_id = tree1.get_root_id()
 
1036
        tree2.set_root_id(root_id)
 
1037
 
 
1038
        # u'\u03b1' == GREEK SMALL LETTER ALPHA
 
1039
        # u'\u03c9' == GREEK SMALL LETTER OMEGA
 
1040
        a_id = u'\u03b1-id'.encode('utf8')
 
1041
        deleted_id = u'\u03c9_deleted_id'.encode('utf8')
 
1042
        try:
 
1043
            self.build_tree([u'tree1/\u03b1/',
 
1044
                             u'tree1/\u03b1/\u03c9-deleted',
 
1045
                             u'tree2/\u03b1/',
 
1046
                            ])
 
1047
        except UnicodeError:
 
1048
            raise tests.TestSkipped("Could not create Unicode files.")
 
1049
        tree1.add([u'\u03b1', u'\u03b1/\u03c9-deleted'], [a_id, deleted_id])
 
1050
        tree2.add([u'\u03b1'], [a_id])
 
1051
 
 
1052
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
 
1053
 
 
1054
        self.assertEqual([self.deleted(tree1, deleted_id)],
 
1055
                         self.do_iter_changes(tree1, tree2))
 
1056
        self.assertEqual([self.deleted(tree1, deleted_id)],
 
1057
                         self.do_iter_changes(tree1, tree2,
 
1058
                                              specific_files=[u'\u03b1']))
 
1059
 
 
1060
    def test_modified_unicode(self):
 
1061
        tree1 = self.make_branch_and_tree('tree1')
 
1062
        tree2 = self.make_to_branch_and_tree('tree2')
 
1063
        root_id = tree1.get_root_id()
 
1064
        tree2.set_root_id(root_id)
 
1065
 
 
1066
        # u'\u03b1' == GREEK SMALL LETTER ALPHA
 
1067
        # u'\u03c9' == GREEK SMALL LETTER OMEGA
 
1068
        a_id = u'\u03b1-id'.encode('utf8')
 
1069
        mod_id = u'\u03c9_mod_id'.encode('utf8')
 
1070
        try:
 
1071
            self.build_tree([u'tree1/\u03b1/',
 
1072
                             u'tree1/\u03b1/\u03c9-modified',
 
1073
                             u'tree2/\u03b1/',
 
1074
                             u'tree2/\u03b1/\u03c9-modified',
 
1075
                            ])
 
1076
        except UnicodeError:
 
1077
            raise tests.TestSkipped("Could not create Unicode files.")
 
1078
        tree1.add([u'\u03b1', u'\u03b1/\u03c9-modified'], [a_id, mod_id])
 
1079
        tree2.add([u'\u03b1', u'\u03b1/\u03c9-modified'], [a_id, mod_id])
 
1080
 
 
1081
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
 
1082
 
 
1083
        self.assertEqual([self.content_changed(tree1, mod_id)],
 
1084
                         self.do_iter_changes(tree1, tree2))
 
1085
        self.assertEqual([self.content_changed(tree1, mod_id)],
 
1086
                         self.do_iter_changes(tree1, tree2,
 
1087
                                              specific_files=[u'\u03b1']))
 
1088
 
 
1089
    def test_renamed_unicode(self):
 
1090
        tree1 = self.make_branch_and_tree('tree1')
 
1091
        tree2 = self.make_to_branch_and_tree('tree2')
 
1092
        root_id = tree1.get_root_id()
 
1093
        tree2.set_root_id(root_id)
 
1094
 
 
1095
        # u'\u03b1' == GREEK SMALL LETTER ALPHA
 
1096
        # u'\u03c9' == GREEK SMALL LETTER OMEGA
 
1097
        a_id = u'\u03b1-id'.encode('utf8')
 
1098
        rename_id = u'\u03c9_rename_id'.encode('utf8')
 
1099
        try:
 
1100
            self.build_tree([u'tree1/\u03b1/',
 
1101
                             u'tree2/\u03b1/',
 
1102
                            ])
 
1103
        except UnicodeError:
 
1104
            raise tests.TestSkipped("Could not create Unicode files.")
 
1105
        self.build_tree_contents([(u'tree1/\u03c9-source', 'contents\n'),
 
1106
                                  (u'tree2/\u03b1/\u03c9-target', 'contents\n'),
 
1107
                                 ])
 
1108
        tree1.add([u'\u03b1', u'\u03c9-source'], [a_id, rename_id])
 
1109
        tree2.add([u'\u03b1', u'\u03b1/\u03c9-target'], [a_id, rename_id])
 
1110
 
 
1111
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
 
1112
 
 
1113
        self.assertEqual([self.renamed(tree1, tree2, rename_id, False)],
 
1114
                         self.do_iter_changes(tree1, tree2))
 
1115
        self.assertEqual([self.renamed(tree1, tree2, rename_id, False)],
 
1116
                         self.do_iter_changes(tree1, tree2,
 
1117
                                              specific_files=[u'\u03b1']))
 
1118
 
 
1119
    def test_unchanged_unicode(self):
 
1120
        tree1 = self.make_branch_and_tree('tree1')
 
1121
        tree2 = self.make_to_branch_and_tree('tree2')
 
1122
        root_id = tree1.get_root_id()
 
1123
        tree2.set_root_id(root_id)
 
1124
        # u'\u03b1' == GREEK SMALL LETTER ALPHA
 
1125
        # u'\u03c9' == GREEK SMALL LETTER OMEGA
 
1126
        a_id = u'\u03b1-id'.encode('utf8')
 
1127
        subfile_id = u'\u03c9-subfile-id'.encode('utf8')
 
1128
        rootfile_id = u'\u03c9-root-id'.encode('utf8')
 
1129
        try:
 
1130
            self.build_tree([u'tree1/\u03b1/',
 
1131
                             u'tree2/\u03b1/',
 
1132
                            ])
 
1133
        except UnicodeError:
 
1134
            raise tests.TestSkipped("Could not create Unicode files.")
 
1135
        self.build_tree_contents([
 
1136
            (u'tree1/\u03b1/\u03c9-subfile', 'sub contents\n'),
 
1137
            (u'tree2/\u03b1/\u03c9-subfile', 'sub contents\n'),
 
1138
            (u'tree1/\u03c9-rootfile', 'root contents\n'),
 
1139
            (u'tree2/\u03c9-rootfile', 'root contents\n'),
 
1140
            ])
 
1141
        tree1.add([u'\u03b1', u'\u03b1/\u03c9-subfile', u'\u03c9-rootfile'],
 
1142
                  [a_id, subfile_id, rootfile_id])
 
1143
        tree2.add([u'\u03b1', u'\u03b1/\u03c9-subfile', u'\u03c9-rootfile'],
 
1144
                  [a_id, subfile_id, rootfile_id])
 
1145
 
 
1146
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
 
1147
 
 
1148
        expected = sorted([
 
1149
            self.unchanged(tree1, root_id),
 
1150
            self.unchanged(tree1, a_id),
 
1151
            self.unchanged(tree1, subfile_id),
 
1152
            self.unchanged(tree1, rootfile_id),
 
1153
            ])
 
1154
        self.assertEqual(expected,
 
1155
                         self.do_iter_changes(tree1, tree2,
 
1156
                                              include_unchanged=True))
 
1157
 
 
1158
        # We should also be able to select just a subset
 
1159
        expected = sorted([
 
1160
            self.unchanged(tree1, a_id),
 
1161
            self.unchanged(tree1, subfile_id),
 
1162
            ])
 
1163
        self.assertEqual(expected,
 
1164
                         self.do_iter_changes(tree1, tree2,
 
1165
                                              specific_files=[u'\u03b1'],
 
1166
                                              include_unchanged=True))
 
1167
 
 
1168
    def test_unknown_unicode(self):
 
1169
        tree1 = self.make_branch_and_tree('tree1')
 
1170
        tree2 = self.make_to_branch_and_tree('tree2')
 
1171
        root_id = tree1.get_root_id()
 
1172
        tree2.set_root_id(root_id)
 
1173
        # u'\u03b1' == GREEK SMALL LETTER ALPHA
 
1174
        # u'\u03c9' == GREEK SMALL LETTER OMEGA
 
1175
        a_id = u'\u03b1-id'.encode('utf8')
 
1176
        try:
 
1177
            self.build_tree([u'tree1/\u03b1/',
 
1178
                             u'tree2/\u03b1/',
 
1179
                             u'tree2/\u03b1/unknown_dir/',
 
1180
                             u'tree2/\u03b1/unknown_file',
 
1181
                             u'tree2/\u03b1/unknown_dir/file',
 
1182
                             u'tree2/\u03c9-unknown_root_file',
 
1183
                            ])
 
1184
        except UnicodeError:
 
1185
            raise tests.TestSkipped("Could not create Unicode files.")
 
1186
        tree1.add([u'\u03b1'], [a_id])
 
1187
        tree2.add([u'\u03b1'], [a_id])
 
1188
 
 
1189
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
 
1190
 
 
1191
        expected = sorted([
 
1192
            self.unversioned(tree2, u'\u03b1/unknown_dir'),
 
1193
            self.unversioned(tree2, u'\u03b1/unknown_file'),
 
1194
            self.unversioned(tree2, u'\u03c9-unknown_root_file'),
 
1195
            # a/unknown_dir/file should not be included because we should not
 
1196
            # recurse into unknown_dir
 
1197
            # self.unversioned(tree2, 'a/unknown_dir/file'),
 
1198
            ])
 
1199
        self.assertEqual(expected,
 
1200
                         self.do_iter_changes(tree1, tree2,
 
1201
                                              require_versioned=False,
 
1202
                                              want_unversioned=True))
 
1203
        self.assertEqual([], # Without want_unversioned we should get nothing
 
1204
                         self.do_iter_changes(tree1, tree2))
 
1205
 
 
1206
        # We should also be able to select just a subset
 
1207
        expected = sorted([
 
1208
            self.unversioned(tree2, u'\u03b1/unknown_dir'),
 
1209
            self.unversioned(tree2, u'\u03b1/unknown_file'),
 
1210
            ])
 
1211
        self.assertEqual(expected,
 
1212
                         self.do_iter_changes(tree1, tree2,
 
1213
                                              specific_files=[u'\u03b1'],
 
1214
                                              require_versioned=False,
 
1215
                                              want_unversioned=True))
 
1216
        self.assertEqual([], # Without want_unversioned we should get nothing
 
1217
                         self.do_iter_changes(tree1, tree2,
 
1218
                                              specific_files=[u'\u03b1']))
 
1219
 
 
1220
    def test_unknown_empty_dir(self):
 
1221
        tree1 = self.make_branch_and_tree('tree1')
 
1222
        tree2 = self.make_to_branch_and_tree('tree2')
 
1223
        root_id = tree1.get_root_id()
 
1224
        tree2.set_root_id(root_id)
 
1225
 
 
1226
        # Start with 2 identical trees
 
1227
        self.build_tree(['tree1/a/', 'tree1/b/',
 
1228
                         'tree2/a/', 'tree2/b/'])
 
1229
        self.build_tree_contents([('tree1/b/file', 'contents\n'),
 
1230
                                  ('tree2/b/file', 'contents\n')])
 
1231
        tree1.add(['a', 'b', 'b/file'], ['a-id', 'b-id', 'b-file-id'])
 
1232
        tree2.add(['a', 'b', 'b/file'], ['a-id', 'b-id', 'b-file-id'])
 
1233
 
 
1234
        # Now create some unknowns in tree2
 
1235
        # We should find both a/file and a/dir as unknown, but we shouldn't
 
1236
        # recurse into a/dir to find that a/dir/subfile is also unknown.
 
1237
        self.build_tree(['tree2/a/file', 'tree2/a/dir/', 'tree2/a/dir/subfile'])
 
1238
 
 
1239
        tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
 
1240
 
 
1241
        expected = sorted([
 
1242
            self.unversioned(tree2, u'a/file'),
 
1243
            self.unversioned(tree2, u'a/dir'),
 
1244
            ])
 
1245
        self.assertEqual(expected,
 
1246
                         self.do_iter_changes(tree1, tree2,
 
1247
                                              require_versioned=False,
 
1248
                                              want_unversioned=True))