/brz/remove-bazaar

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

« back to all changes in this revision

Viewing changes to breezy/tests/test_diff.py

  • Committer: Gustav Hartvigsson
  • Date: 2021-01-09 21:36:27 UTC
  • Revision ID: gustav.hartvigsson@gmail.com-20210109213627-h1xwcutzy9m7a99b
Added 'Case Preserving Working Tree Use Cases' from Canonical Wiki

* Addod a page from the Canonical Bazaar wiki
  with information on the scmeatics of case
  perserving filesystems an a case insensitive
  filesystem works.
  
  * Needs re-work, but this will do as it is the
    same inforamoton as what was on the linked
    page in the currint documentation.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
 
17
import contextlib
 
18
from io import BytesIO
17
19
import os
18
20
import re
19
21
import subprocess
24
26
    diff,
25
27
    errors,
26
28
    osutils,
27
 
    patiencediff,
28
 
    _patiencediff_py,
29
29
    revision as _mod_revision,
30
30
    revisionspec,
31
31
    revisiontree,
32
32
    tests,
33
 
    transform,
34
 
    )
35
 
from ..sixish import (
36
 
    BytesIO,
37
 
    unichr,
38
33
    )
39
34
from ..tests import (
40
35
    features,
564
559
    def test_internal_diff_exec_property(self):
565
560
        tree = self.make_branch_and_tree('tree')
566
561
 
567
 
        tt = transform.TreeTransform(tree)
 
562
        tt = tree.transform()
568
563
        tt.new_file('a', tt.root, [b'contents\n'], b'a-id', True)
569
564
        tt.new_file('b', tt.root, [b'contents\n'], b'b-id', False)
570
565
        tt.new_file('c', tt.root, [b'contents\n'], b'c-id', True)
574
569
        tt.apply()
575
570
        tree.commit('one', rev_id=b'rev-1')
576
571
 
577
 
        tt = transform.TreeTransform(tree)
 
572
        tt = tree.transform()
578
573
        tt.set_executability(False, tt.trans_id_file_id(b'a-id'))
579
574
        tt.set_executability(True, tt.trans_id_file_id(b'b-id'))
580
575
        tt.set_executability(False, tt.trans_id_file_id(b'c-id'))
610
605
            [('tree/' + alpha, b'\0'),
611
606
             ('tree/' + omega,
612
607
              (b'The %s and the %s\n' % (alpha_utf8, omega_utf8)))])
613
 
        tree.add([alpha], [b'file-id'])
614
 
        tree.add([omega], [b'file-id-2'])
 
608
        tree.add([alpha])
 
609
        tree.add([omega])
615
610
        diff_content = StubO()
616
611
        diff.show_diff_trees(tree.basis_tree(), tree, diff_content)
617
612
        diff_content.check_types(self, bytes)
699
694
 
700
695
class DiffWasIs(diff.DiffPath):
701
696
 
702
 
    def diff(self, file_id, old_path, new_path, old_kind, new_kind):
 
697
    def diff(self, old_path, new_path, old_kind, new_kind):
703
698
        self.to_file.write(b'was: ')
704
699
        self.to_file.write(self.old_tree.get_file(old_path).read())
705
700
        self.to_file.write(b'is: ')
728
723
        self.new_tree.add('newdir')
729
724
        self.new_tree.add('newdir/newfile', b'file-id')
730
725
        differ = diff.DiffText(self.old_tree, self.new_tree, BytesIO())
731
 
        differ.diff_text('olddir/oldfile', None, 'old label',
732
 
                         'new label', b'file-id', None)
 
726
        differ.diff_text('olddir/oldfile', None, 'old label', 'new label')
733
727
        self.assertEqual(
734
728
            b'--- old label\n+++ new label\n@@ -1,1 +0,0 @@\n-old\n\n',
735
729
            differ.to_file.getvalue())
736
730
        differ.to_file.seek(0)
737
731
        differ.diff_text(None, 'newdir/newfile',
738
 
                         'old label', 'new label', None, b'file-id')
 
732
                         'old label', 'new label')
739
733
        self.assertEqual(
740
734
            b'--- old label\n+++ new label\n@@ -0,0 +1,1 @@\n+new\n\n',
741
735
            differ.to_file.getvalue())
742
736
        differ.to_file.seek(0)
743
737
        differ.diff_text('olddir/oldfile', 'newdir/newfile',
744
 
                         'old label', 'new label', b'file-id', b'file-id')
 
738
                         'old label', 'new label')
745
739
        self.assertEqual(
746
740
            b'--- old label\n+++ new label\n@@ -1,1 +1,1 @@\n-old\n+new\n\n',
747
741
            differ.to_file.getvalue())
789
783
                                  ('new-tree/newdir/newfile', b'new\n')])
790
784
        self.new_tree.add('newdir')
791
785
        self.new_tree.add('newdir/newfile', b'file-id')
792
 
        self.differ.diff(b'file-id', 'olddir/oldfile', 'newdir/newfile')
 
786
        self.differ.diff('olddir/oldfile', 'newdir/newfile')
793
787
        self.assertContainsRe(
794
788
            self.differ.to_file.getvalue(),
795
789
            br'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+1,1'
805
799
        os.symlink('new', 'new-tree/newdir/newfile')
806
800
        self.new_tree.add('newdir')
807
801
        self.new_tree.add('newdir/newfile', b'file-id')
808
 
        self.differ.diff(b'file-id', 'olddir/oldfile', 'newdir/newfile')
 
802
        self.differ.diff('olddir/oldfile', 'newdir/newfile')
809
803
        self.assertContainsRe(
810
804
            self.differ.to_file.getvalue(),
811
 
            br'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+0,0'
812
 
            br' \@\@\n-old\n\n')
 
805
            br'--- olddir/oldfile.*\n'
 
806
            br'\+\+\+ newdir/newfile.*\n'
 
807
            br'\@\@ -1,1 \+0,0 \@\@\n'
 
808
            br'-old\n'
 
809
            br'\n')
813
810
        self.assertContainsRe(self.differ.to_file.getvalue(),
814
811
                              b"=== target is 'new'\n")
815
812
 
816
813
    def test_diff_directory(self):
817
814
        self.build_tree(['new-tree/new-dir/'])
818
815
        self.new_tree.add('new-dir', b'new-dir-id')
819
 
        self.differ.diff(b'new-dir-id', None, 'new-dir')
 
816
        self.differ.diff(None, 'new-dir')
820
817
        self.assertEqual(self.differ.to_file.getvalue(), b'')
821
818
 
822
819
    def create_old_new(self):
838
835
            differ = diff.DiffTree(self.old_tree, self.new_tree, BytesIO())
839
836
        finally:
840
837
            diff.DiffTree.diff_factories = old_diff_factories
841
 
        differ.diff(b'file-id', 'olddir/oldfile', 'newdir/newfile')
 
838
        differ.diff('olddir/oldfile', 'newdir/newfile')
842
839
        self.assertNotContainsRe(
843
840
            differ.to_file.getvalue(),
844
841
            br'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+1,1'
850
847
        self.create_old_new()
851
848
        differ = diff.DiffTree(self.old_tree, self.new_tree, BytesIO(),
852
849
                               extra_factories=[DiffWasIs.from_diff_tree])
853
 
        differ.diff(b'file-id', 'olddir/oldfile', 'newdir/newfile')
 
850
        differ.diff('olddir/oldfile', 'newdir/newfile')
854
851
        self.assertNotContainsRe(
855
852
            differ.to_file.getvalue(),
856
853
            br'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+1,1'
868
865
                              b'.*a-file(.|\n)*b-file')
869
866
 
870
867
 
871
 
class TestPatienceDiffLib(tests.TestCase):
872
 
 
873
 
    def setUp(self):
874
 
        super(TestPatienceDiffLib, self).setUp()
875
 
        self._unique_lcs = _patiencediff_py.unique_lcs_py
876
 
        self._recurse_matches = _patiencediff_py.recurse_matches_py
877
 
        self._PatienceSequenceMatcher = \
878
 
            _patiencediff_py.PatienceSequenceMatcher_py
879
 
 
880
 
    def test_diff_unicode_string(self):
881
 
        a = ''.join([unichr(i) for i in range(4000, 4500, 3)])
882
 
        b = ''.join([unichr(i) for i in range(4300, 4800, 2)])
883
 
        sm = self._PatienceSequenceMatcher(None, a, b)
884
 
        mb = sm.get_matching_blocks()
885
 
        self.assertEqual(35, len(mb))
886
 
 
887
 
    def test_unique_lcs(self):
888
 
        unique_lcs = self._unique_lcs
889
 
        self.assertEqual(unique_lcs('', ''), [])
890
 
        self.assertEqual(unique_lcs('', 'a'), [])
891
 
        self.assertEqual(unique_lcs('a', ''), [])
892
 
        self.assertEqual(unique_lcs('a', 'a'), [(0, 0)])
893
 
        self.assertEqual(unique_lcs('a', 'b'), [])
894
 
        self.assertEqual(unique_lcs('ab', 'ab'), [(0, 0), (1, 1)])
895
 
        self.assertEqual(unique_lcs('abcde', 'cdeab'),
896
 
                         [(2, 0), (3, 1), (4, 2)])
897
 
        self.assertEqual(unique_lcs('cdeab', 'abcde'),
898
 
                         [(0, 2), (1, 3), (2, 4)])
899
 
        self.assertEqual(unique_lcs('abXde', 'abYde'), [(0, 0), (1, 1),
900
 
                                                        (3, 3), (4, 4)])
901
 
        self.assertEqual(unique_lcs('acbac', 'abc'), [(2, 1)])
902
 
 
903
 
    def test_recurse_matches(self):
904
 
        def test_one(a, b, matches):
905
 
            test_matches = []
906
 
            self._recurse_matches(
907
 
                a, b, 0, 0, len(a), len(b), test_matches, 10)
908
 
            self.assertEqual(test_matches, matches)
909
 
 
910
 
        test_one(['a', '', 'b', '', 'c'], ['a', 'a', 'b', 'c', 'c'],
911
 
                 [(0, 0), (2, 2), (4, 4)])
912
 
        test_one(['a', 'c', 'b', 'a', 'c'], ['a', 'b', 'c'],
913
 
                 [(0, 0), (2, 1), (4, 2)])
914
 
        # Even though 'bc' is not unique globally, and is surrounded by
915
 
        # non-matching lines, we should still match, because they are locally
916
 
        # unique
917
 
        test_one('abcdbce', 'afbcgdbce', [(0, 0), (1, 2), (2, 3), (3, 5),
918
 
                                          (4, 6), (5, 7), (6, 8)])
919
 
 
920
 
        # recurse_matches doesn't match non-unique
921
 
        # lines surrounded by bogus text.
922
 
        # The update has been done in patiencediff.SequenceMatcher instead
923
 
 
924
 
        # This is what it could be
925
 
        #test_one('aBccDe', 'abccde', [(0,0), (2,2), (3,3), (5,5)])
926
 
 
927
 
        # This is what it currently gives:
928
 
        test_one('aBccDe', 'abccde', [(0, 0), (5, 5)])
929
 
 
930
 
    def assertDiffBlocks(self, a, b, expected_blocks):
931
 
        """Check that the sequence matcher returns the correct blocks.
932
 
 
933
 
        :param a: A sequence to match
934
 
        :param b: Another sequence to match
935
 
        :param expected_blocks: The expected output, not including the final
936
 
            matching block (len(a), len(b), 0)
937
 
        """
938
 
        matcher = self._PatienceSequenceMatcher(None, a, b)
939
 
        blocks = matcher.get_matching_blocks()
940
 
        last = blocks.pop()
941
 
        self.assertEqual((len(a), len(b), 0), last)
942
 
        self.assertEqual(expected_blocks, blocks)
943
 
 
944
 
    def test_matching_blocks(self):
945
 
        # Some basic matching tests
946
 
        self.assertDiffBlocks('', '', [])
947
 
        self.assertDiffBlocks([], [], [])
948
 
        self.assertDiffBlocks('abc', '', [])
949
 
        self.assertDiffBlocks('', 'abc', [])
950
 
        self.assertDiffBlocks('abcd', 'abcd', [(0, 0, 4)])
951
 
        self.assertDiffBlocks('abcd', 'abce', [(0, 0, 3)])
952
 
        self.assertDiffBlocks('eabc', 'abce', [(1, 0, 3)])
953
 
        self.assertDiffBlocks('eabce', 'abce', [(1, 0, 4)])
954
 
        self.assertDiffBlocks('abcde', 'abXde', [(0, 0, 2), (3, 3, 2)])
955
 
        self.assertDiffBlocks('abcde', 'abXYZde', [(0, 0, 2), (3, 5, 2)])
956
 
        self.assertDiffBlocks('abde', 'abXYZde', [(0, 0, 2), (2, 5, 2)])
957
 
        # This may check too much, but it checks to see that
958
 
        # a copied block stays attached to the previous section,
959
 
        # not the later one.
960
 
        # difflib would tend to grab the trailing longest match
961
 
        # which would make the diff not look right
962
 
        self.assertDiffBlocks('abcdefghijklmnop', 'abcdefxydefghijklmnop',
963
 
                              [(0, 0, 6), (6, 11, 10)])
964
 
 
965
 
        # make sure it supports passing in lists
966
 
        self.assertDiffBlocks(
967
 
            ['hello there\n',
968
 
             'world\n',
969
 
             'how are you today?\n'],
970
 
            ['hello there\n',
971
 
             'how are you today?\n'],
972
 
            [(0, 0, 1), (2, 1, 1)])
973
 
 
974
 
        # non unique lines surrounded by non-matching lines
975
 
        # won't be found
976
 
        self.assertDiffBlocks('aBccDe', 'abccde', [(0, 0, 1), (5, 5, 1)])
977
 
 
978
 
        # But they only need to be locally unique
979
 
        self.assertDiffBlocks('aBcDec', 'abcdec', [
980
 
                              (0, 0, 1), (2, 2, 1), (4, 4, 2)])
981
 
 
982
 
        # non unique blocks won't be matched
983
 
        self.assertDiffBlocks('aBcdEcdFg', 'abcdecdfg', [(0, 0, 1), (8, 8, 1)])
984
 
 
985
 
        # but locally unique ones will
986
 
        self.assertDiffBlocks('aBcdEeXcdFg', 'abcdecdfg', [(0, 0, 1), (2, 2, 2),
987
 
                                                           (5, 4, 1), (7, 5, 2), (10, 8, 1)])
988
 
 
989
 
        self.assertDiffBlocks('abbabbXd', 'cabbabxd', [(7, 7, 1)])
990
 
        self.assertDiffBlocks('abbabbbb', 'cabbabbc', [])
991
 
        self.assertDiffBlocks('bbbbbbbb', 'cbbbbbbc', [])
992
 
 
993
 
    def test_matching_blocks_tuples(self):
994
 
        # Some basic matching tests
995
 
        self.assertDiffBlocks([], [], [])
996
 
        self.assertDiffBlocks([('a',), ('b',), ('c,')], [], [])
997
 
        self.assertDiffBlocks([], [('a',), ('b',), ('c,')], [])
998
 
        self.assertDiffBlocks([('a',), ('b',), ('c,')],
999
 
                              [('a',), ('b',), ('c,')],
1000
 
                              [(0, 0, 3)])
1001
 
        self.assertDiffBlocks([('a',), ('b',), ('c,')],
1002
 
                              [('a',), ('b',), ('d,')],
1003
 
                              [(0, 0, 2)])
1004
 
        self.assertDiffBlocks([('d',), ('b',), ('c,')],
1005
 
                              [('a',), ('b',), ('c,')],
1006
 
                              [(1, 1, 2)])
1007
 
        self.assertDiffBlocks([('d',), ('a',), ('b',), ('c,')],
1008
 
                              [('a',), ('b',), ('c,')],
1009
 
                              [(1, 0, 3)])
1010
 
        self.assertDiffBlocks([('a', 'b'), ('c', 'd'), ('e', 'f')],
1011
 
                              [('a', 'b'), ('c', 'X'), ('e', 'f')],
1012
 
                              [(0, 0, 1), (2, 2, 1)])
1013
 
        self.assertDiffBlocks([('a', 'b'), ('c', 'd'), ('e', 'f')],
1014
 
                              [('a', 'b'), ('c', 'dX'), ('e', 'f')],
1015
 
                              [(0, 0, 1), (2, 2, 1)])
1016
 
 
1017
 
    def test_opcodes(self):
1018
 
        def chk_ops(a, b, expected_codes):
1019
 
            s = self._PatienceSequenceMatcher(None, a, b)
1020
 
            self.assertEqual(expected_codes, s.get_opcodes())
1021
 
 
1022
 
        chk_ops('', '', [])
1023
 
        chk_ops([], [], [])
1024
 
        chk_ops('abc', '', [('delete', 0, 3, 0, 0)])
1025
 
        chk_ops('', 'abc', [('insert', 0, 0, 0, 3)])
1026
 
        chk_ops('abcd', 'abcd', [('equal', 0, 4, 0, 4)])
1027
 
        chk_ops('abcd', 'abce', [('equal', 0, 3, 0, 3),
1028
 
                                 ('replace', 3, 4, 3, 4)
1029
 
                                 ])
1030
 
        chk_ops('eabc', 'abce', [('delete', 0, 1, 0, 0),
1031
 
                                 ('equal', 1, 4, 0, 3),
1032
 
                                 ('insert', 4, 4, 3, 4)
1033
 
                                 ])
1034
 
        chk_ops('eabce', 'abce', [('delete', 0, 1, 0, 0),
1035
 
                                  ('equal', 1, 5, 0, 4)
1036
 
                                  ])
1037
 
        chk_ops('abcde', 'abXde', [('equal', 0, 2, 0, 2),
1038
 
                                   ('replace', 2, 3, 2, 3),
1039
 
                                   ('equal', 3, 5, 3, 5)
1040
 
                                   ])
1041
 
        chk_ops('abcde', 'abXYZde', [('equal', 0, 2, 0, 2),
1042
 
                                     ('replace', 2, 3, 2, 5),
1043
 
                                     ('equal', 3, 5, 5, 7)
1044
 
                                     ])
1045
 
        chk_ops('abde', 'abXYZde', [('equal', 0, 2, 0, 2),
1046
 
                                    ('insert', 2, 2, 2, 5),
1047
 
                                    ('equal', 2, 4, 5, 7)
1048
 
                                    ])
1049
 
        chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
1050
 
                [('equal', 0, 6, 0, 6),
1051
 
                 ('insert', 6, 6, 6, 11),
1052
 
                 ('equal', 6, 16, 11, 21)
1053
 
                 ])
1054
 
        chk_ops(
1055
 
            ['hello there\n', 'world\n', 'how are you today?\n'],
1056
 
            ['hello there\n', 'how are you today?\n'],
1057
 
            [('equal', 0, 1, 0, 1),
1058
 
             ('delete', 1, 2, 1, 1),
1059
 
             ('equal', 2, 3, 1, 2),
1060
 
             ])
1061
 
        chk_ops('aBccDe', 'abccde',
1062
 
                [('equal', 0, 1, 0, 1),
1063
 
                 ('replace', 1, 5, 1, 5),
1064
 
                 ('equal', 5, 6, 5, 6),
1065
 
                 ])
1066
 
        chk_ops('aBcDec', 'abcdec',
1067
 
                [('equal', 0, 1, 0, 1),
1068
 
                 ('replace', 1, 2, 1, 2),
1069
 
                 ('equal', 2, 3, 2, 3),
1070
 
                 ('replace', 3, 4, 3, 4),
1071
 
                 ('equal', 4, 6, 4, 6),
1072
 
                 ])
1073
 
        chk_ops('aBcdEcdFg', 'abcdecdfg',
1074
 
                [('equal', 0, 1, 0, 1),
1075
 
                 ('replace', 1, 8, 1, 8),
1076
 
                 ('equal', 8, 9, 8, 9)
1077
 
                 ])
1078
 
        chk_ops('aBcdEeXcdFg', 'abcdecdfg',
1079
 
                [('equal', 0, 1, 0, 1),
1080
 
                 ('replace', 1, 2, 1, 2),
1081
 
                 ('equal', 2, 4, 2, 4),
1082
 
                 ('delete', 4, 5, 4, 4),
1083
 
                 ('equal', 5, 6, 4, 5),
1084
 
                 ('delete', 6, 7, 5, 5),
1085
 
                 ('equal', 7, 9, 5, 7),
1086
 
                 ('replace', 9, 10, 7, 8),
1087
 
                 ('equal', 10, 11, 8, 9)
1088
 
                 ])
1089
 
 
1090
 
    def test_grouped_opcodes(self):
1091
 
        def chk_ops(a, b, expected_codes, n=3):
1092
 
            s = self._PatienceSequenceMatcher(None, a, b)
1093
 
            self.assertEqual(expected_codes, list(s.get_grouped_opcodes(n)))
1094
 
 
1095
 
        chk_ops('', '', [])
1096
 
        chk_ops([], [], [])
1097
 
        chk_ops('abc', '', [[('delete', 0, 3, 0, 0)]])
1098
 
        chk_ops('', 'abc', [[('insert', 0, 0, 0, 3)]])
1099
 
        chk_ops('abcd', 'abcd', [])
1100
 
        chk_ops('abcd', 'abce', [[('equal', 0, 3, 0, 3),
1101
 
                                  ('replace', 3, 4, 3, 4)
1102
 
                                  ]])
1103
 
        chk_ops('eabc', 'abce', [[('delete', 0, 1, 0, 0),
1104
 
                                  ('equal', 1, 4, 0, 3),
1105
 
                                  ('insert', 4, 4, 3, 4)
1106
 
                                  ]])
1107
 
        chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
1108
 
                [[('equal', 3, 6, 3, 6),
1109
 
                  ('insert', 6, 6, 6, 11),
1110
 
                  ('equal', 6, 9, 11, 14)
1111
 
                  ]])
1112
 
        chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
1113
 
                [[('equal', 2, 6, 2, 6),
1114
 
                  ('insert', 6, 6, 6, 11),
1115
 
                  ('equal', 6, 10, 11, 15)
1116
 
                  ]], 4)
1117
 
        chk_ops('Xabcdef', 'abcdef',
1118
 
                [[('delete', 0, 1, 0, 0),
1119
 
                  ('equal', 1, 4, 0, 3)
1120
 
                  ]])
1121
 
        chk_ops('abcdef', 'abcdefX',
1122
 
                [[('equal', 3, 6, 3, 6),
1123
 
                  ('insert', 6, 6, 6, 7)
1124
 
                  ]])
1125
 
 
1126
 
    def test_multiple_ranges(self):
1127
 
        # There was an earlier bug where we used a bad set of ranges,
1128
 
        # this triggers that specific bug, to make sure it doesn't regress
1129
 
        self.assertDiffBlocks('abcdefghijklmnop',
1130
 
                              'abcXghiYZQRSTUVWXYZijklmnop',
1131
 
                              [(0, 0, 3), (6, 4, 3), (9, 20, 7)])
1132
 
 
1133
 
        self.assertDiffBlocks('ABCd efghIjk  L',
1134
 
                              'AxyzBCn mo pqrstuvwI1 2  L',
1135
 
                              [(0, 0, 1), (1, 4, 2), (9, 19, 1), (12, 23, 3)])
1136
 
 
1137
 
        # These are rot13 code snippets.
1138
 
        self.assertDiffBlocks('''\
1139
 
    trg nqqrq jura lbh nqq n svyr va gur qverpgbel.
1140
 
    """
1141
 
    gnxrf_netf = ['svyr*']
1142
 
    gnxrf_bcgvbaf = ['ab-erphefr']
1143
 
 
1144
 
    qrs eha(frys, svyr_yvfg, ab_erphefr=Snyfr):
1145
 
        sebz omeyvo.nqq vzcbeg fzneg_nqq, nqq_ercbegre_cevag, nqq_ercbegre_ahyy
1146
 
        vs vf_dhvrg():
1147
 
            ercbegre = nqq_ercbegre_ahyy
1148
 
        ryfr:
1149
 
            ercbegre = nqq_ercbegre_cevag
1150
 
        fzneg_nqq(svyr_yvfg, abg ab_erphefr, ercbegre)
1151
 
 
1152
 
 
1153
 
pynff pzq_zxqve(Pbzznaq):
1154
 
'''.splitlines(True), '''\
1155
 
    trg nqqrq jura lbh nqq n svyr va gur qverpgbel.
1156
 
 
1157
 
    --qel-eha jvyy fubj juvpu svyrf jbhyq or nqqrq, ohg abg npghnyyl
1158
 
    nqq gurz.
1159
 
    """
1160
 
    gnxrf_netf = ['svyr*']
1161
 
    gnxrf_bcgvbaf = ['ab-erphefr', 'qel-eha']
1162
 
 
1163
 
    qrs eha(frys, svyr_yvfg, ab_erphefr=Snyfr, qel_eha=Snyfr):
1164
 
        vzcbeg omeyvo.nqq
1165
 
 
1166
 
        vs qel_eha:
1167
 
            vs vf_dhvrg():
1168
 
                # Guvf vf cbvagyrff, ohg V'q engure abg envfr na reebe
1169
 
                npgvba = omeyvo.nqq.nqq_npgvba_ahyy
1170
 
            ryfr:
1171
 
  npgvba = omeyvo.nqq.nqq_npgvba_cevag
1172
 
        ryvs vf_dhvrg():
1173
 
            npgvba = omeyvo.nqq.nqq_npgvba_nqq
1174
 
        ryfr:
1175
 
       npgvba = omeyvo.nqq.nqq_npgvba_nqq_naq_cevag
1176
 
 
1177
 
        omeyvo.nqq.fzneg_nqq(svyr_yvfg, abg ab_erphefr, npgvba)
1178
 
 
1179
 
 
1180
 
pynff pzq_zxqve(Pbzznaq):
1181
 
'''.splitlines(True), [(0, 0, 1), (1, 4, 2), (9, 19, 1), (12, 23, 3)])
1182
 
 
1183
 
    def test_patience_unified_diff(self):
1184
 
        txt_a = ['hello there\n',
1185
 
                 'world\n',
1186
 
                 'how are you today?\n']
1187
 
        txt_b = ['hello there\n',
1188
 
                 'how are you today?\n']
1189
 
        unified_diff = patiencediff.unified_diff
1190
 
        psm = self._PatienceSequenceMatcher
1191
 
        self.assertEqual(['--- \n',
1192
 
                          '+++ \n',
1193
 
                          '@@ -1,3 +1,2 @@\n',
1194
 
                          ' hello there\n',
1195
 
                          '-world\n',
1196
 
                          ' how are you today?\n'
1197
 
                          ], list(unified_diff(txt_a, txt_b,
1198
 
                                               sequencematcher=psm)))
1199
 
        txt_a = [x + '\n' for x in 'abcdefghijklmnop']
1200
 
        txt_b = [x + '\n' for x in 'abcdefxydefghijklmnop']
1201
 
        # This is the result with LongestCommonSubstring matching
1202
 
        self.assertEqual(['--- \n',
1203
 
                          '+++ \n',
1204
 
                          '@@ -1,6 +1,11 @@\n',
1205
 
                          ' a\n',
1206
 
                          ' b\n',
1207
 
                          ' c\n',
1208
 
                          '+d\n',
1209
 
                          '+e\n',
1210
 
                          '+f\n',
1211
 
                          '+x\n',
1212
 
                          '+y\n',
1213
 
                          ' d\n',
1214
 
                          ' e\n',
1215
 
                          ' f\n'], list(unified_diff(txt_a, txt_b)))
1216
 
        # And the patience diff
1217
 
        self.assertEqual(['--- \n',
1218
 
                          '+++ \n',
1219
 
                          '@@ -4,6 +4,11 @@\n',
1220
 
                          ' d\n',
1221
 
                          ' e\n',
1222
 
                          ' f\n',
1223
 
                          '+x\n',
1224
 
                          '+y\n',
1225
 
                          '+d\n',
1226
 
                          '+e\n',
1227
 
                          '+f\n',
1228
 
                          ' g\n',
1229
 
                          ' h\n',
1230
 
                          ' i\n',
1231
 
                          ], list(unified_diff(txt_a, txt_b,
1232
 
                                               sequencematcher=psm)))
1233
 
 
1234
 
    def test_patience_unified_diff_with_dates(self):
1235
 
        txt_a = ['hello there\n',
1236
 
                 'world\n',
1237
 
                 'how are you today?\n']
1238
 
        txt_b = ['hello there\n',
1239
 
                 'how are you today?\n']
1240
 
        unified_diff = patiencediff.unified_diff
1241
 
        psm = self._PatienceSequenceMatcher
1242
 
        self.assertEqual(['--- a\t2008-08-08\n',
1243
 
                          '+++ b\t2008-09-09\n',
1244
 
                          '@@ -1,3 +1,2 @@\n',
1245
 
                          ' hello there\n',
1246
 
                          '-world\n',
1247
 
                          ' how are you today?\n'
1248
 
                          ], list(unified_diff(txt_a, txt_b,
1249
 
                                               fromfile='a', tofile='b',
1250
 
                                               fromfiledate='2008-08-08',
1251
 
                                               tofiledate='2008-09-09',
1252
 
                                               sequencematcher=psm)))
1253
 
 
1254
 
 
1255
 
class TestPatienceDiffLib_c(TestPatienceDiffLib):
1256
 
 
1257
 
    _test_needs_features = [features.compiled_patiencediff_feature]
1258
 
 
1259
 
    def setUp(self):
1260
 
        super(TestPatienceDiffLib_c, self).setUp()
1261
 
        from breezy import _patiencediff_c
1262
 
        self._unique_lcs = _patiencediff_c.unique_lcs_c
1263
 
        self._recurse_matches = _patiencediff_c.recurse_matches_c
1264
 
        self._PatienceSequenceMatcher = \
1265
 
            _patiencediff_c.PatienceSequenceMatcher_c
1266
 
 
1267
 
    def test_unhashable(self):
1268
 
        """We should get a proper exception here."""
1269
 
        # We need to be able to hash items in the sequence, lists are
1270
 
        # unhashable, and thus cannot be diffed
1271
 
        e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
1272
 
                              None, [[]], [])
1273
 
        e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
1274
 
                              None, ['valid', []], [])
1275
 
        e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
1276
 
                              None, ['valid'], [[]])
1277
 
        e = self.assertRaises(TypeError, self._PatienceSequenceMatcher,
1278
 
                              None, ['valid'], ['valid', []])
1279
 
 
1280
 
 
1281
 
class TestPatienceDiffLibFiles(tests.TestCaseInTempDir):
1282
 
 
1283
 
    def setUp(self):
1284
 
        super(TestPatienceDiffLibFiles, self).setUp()
1285
 
        self._PatienceSequenceMatcher = \
1286
 
            _patiencediff_py.PatienceSequenceMatcher_py
1287
 
 
1288
 
    def test_patience_unified_diff_files(self):
1289
 
        txt_a = [b'hello there\n',
1290
 
                 b'world\n',
1291
 
                 b'how are you today?\n']
1292
 
        txt_b = [b'hello there\n',
1293
 
                 b'how are you today?\n']
1294
 
        with open('a1', 'wb') as f:
1295
 
            f.writelines(txt_a)
1296
 
        with open('b1', 'wb') as f:
1297
 
            f.writelines(txt_b)
1298
 
 
1299
 
        unified_diff_files = patiencediff.unified_diff_files
1300
 
        psm = self._PatienceSequenceMatcher
1301
 
        self.assertEqual([b'--- a1\n',
1302
 
                          b'+++ b1\n',
1303
 
                          b'@@ -1,3 +1,2 @@\n',
1304
 
                          b' hello there\n',
1305
 
                          b'-world\n',
1306
 
                          b' how are you today?\n',
1307
 
                          ], list(unified_diff_files(b'a1', b'b1',
1308
 
                                                     sequencematcher=psm)))
1309
 
 
1310
 
        txt_a = [x + '\n' for x in 'abcdefghijklmnop']
1311
 
        txt_b = [x + '\n' for x in 'abcdefxydefghijklmnop']
1312
 
        with open('a2', 'wt') as f:
1313
 
            f.writelines(txt_a)
1314
 
        with open('b2', 'wt') as f:
1315
 
            f.writelines(txt_b)
1316
 
 
1317
 
        # This is the result with LongestCommonSubstring matching
1318
 
        self.assertEqual([b'--- a2\n',
1319
 
                          b'+++ b2\n',
1320
 
                          b'@@ -1,6 +1,11 @@\n',
1321
 
                          b' a\n',
1322
 
                          b' b\n',
1323
 
                          b' c\n',
1324
 
                          b'+d\n',
1325
 
                          b'+e\n',
1326
 
                          b'+f\n',
1327
 
                          b'+x\n',
1328
 
                          b'+y\n',
1329
 
                          b' d\n',
1330
 
                          b' e\n',
1331
 
                          b' f\n'], list(unified_diff_files(b'a2', b'b2')))
1332
 
 
1333
 
        # And the patience diff
1334
 
        self.assertEqual([b'--- a2\n',
1335
 
                          b'+++ b2\n',
1336
 
                          b'@@ -4,6 +4,11 @@\n',
1337
 
                          b' d\n',
1338
 
                          b' e\n',
1339
 
                          b' f\n',
1340
 
                          b'+x\n',
1341
 
                          b'+y\n',
1342
 
                          b'+d\n',
1343
 
                          b'+e\n',
1344
 
                          b'+f\n',
1345
 
                          b' g\n',
1346
 
                          b' h\n',
1347
 
                          b' i\n'],
1348
 
                         list(unified_diff_files(b'a2', b'b2',
1349
 
                                                 sequencematcher=psm)))
1350
 
 
1351
 
 
1352
 
class TestPatienceDiffLibFiles_c(TestPatienceDiffLibFiles):
1353
 
 
1354
 
    _test_needs_features = [features.compiled_patiencediff_feature]
1355
 
 
1356
 
    def setUp(self):
1357
 
        super(TestPatienceDiffLibFiles_c, self).setUp()
1358
 
        from breezy import _patiencediff_c
1359
 
        self._PatienceSequenceMatcher = \
1360
 
            _patiencediff_c.PatienceSequenceMatcher_c
1361
 
 
1362
 
 
1363
 
class TestUsingCompiledIfAvailable(tests.TestCase):
1364
 
 
1365
 
    def test_PatienceSequenceMatcher(self):
1366
 
        if features.compiled_patiencediff_feature.available():
1367
 
            from breezy._patiencediff_c import PatienceSequenceMatcher_c
1368
 
            self.assertIs(PatienceSequenceMatcher_c,
1369
 
                          patiencediff.PatienceSequenceMatcher)
1370
 
        else:
1371
 
            from breezy._patiencediff_py import PatienceSequenceMatcher_py
1372
 
            self.assertIs(PatienceSequenceMatcher_py,
1373
 
                          patiencediff.PatienceSequenceMatcher)
1374
 
 
1375
 
    def test_unique_lcs(self):
1376
 
        if features.compiled_patiencediff_feature.available():
1377
 
            from breezy._patiencediff_c import unique_lcs_c
1378
 
            self.assertIs(unique_lcs_c,
1379
 
                          patiencediff.unique_lcs)
1380
 
        else:
1381
 
            from breezy._patiencediff_py import unique_lcs_py
1382
 
            self.assertIs(unique_lcs_py,
1383
 
                          patiencediff.unique_lcs)
1384
 
 
1385
 
    def test_recurse_matches(self):
1386
 
        if features.compiled_patiencediff_feature.available():
1387
 
            from breezy._patiencediff_c import recurse_matches_c
1388
 
            self.assertIs(recurse_matches_c,
1389
 
                          patiencediff.recurse_matches)
1390
 
        else:
1391
 
            from breezy._patiencediff_py import recurse_matches_py
1392
 
            self.assertIs(recurse_matches_py,
1393
 
                          patiencediff.recurse_matches)
1394
 
 
1395
 
 
1396
868
class TestDiffFromTool(tests.TestCaseWithTransport):
1397
869
 
1398
870
    def test_from_string(self):
1399
 
        diff_obj = diff.DiffFromTool.from_string('diff', None, None, None)
1400
 
        self.addCleanup(diff_obj.finish)
1401
 
        self.assertEqual(['diff', '@old_path', '@new_path'],
1402
 
                         diff_obj.command_template)
 
871
        diff_obj = diff.DiffFromTool.from_string(
 
872
            ['diff', '{old_path}', '{new_path}'],
 
873
            None, None, None)
 
874
        self.addCleanup(diff_obj.finish)
 
875
        self.assertEqual(['diff', '{old_path}', '{new_path}'],
 
876
                         diff_obj.command_template)
 
877
 
 
878
    def test_from_string_no_paths(self):
 
879
        diff_obj = diff.DiffFromTool.from_string(
 
880
            ['diff', "-u5"], None, None, None)
 
881
        self.addCleanup(diff_obj.finish)
 
882
        self.assertEqual(['diff', '-u5'],
 
883
                         diff_obj.command_template)
 
884
        self.assertEqual(['diff', '-u5', 'old-path', 'new-path'],
 
885
                         diff_obj._get_command('old-path', 'new-path'))
1403
886
 
1404
887
    def test_from_string_u5(self):
1405
 
        diff_obj = diff.DiffFromTool.from_string('diff "-u 5"',
1406
 
                                                 None, None, None)
 
888
        diff_obj = diff.DiffFromTool.from_string(
 
889
            ['diff', "-u 5", '{old_path}', '{new_path}'], None, None, None)
1407
890
        self.addCleanup(diff_obj.finish)
1408
 
        self.assertEqual(['diff', '-u 5', '@old_path', '@new_path'],
 
891
        self.assertEqual(['diff', '-u 5', '{old_path}', '{new_path}'],
1409
892
                         diff_obj.command_template)
1410
893
        self.assertEqual(['diff', '-u 5', 'old-path', 'new-path'],
1411
894
                         diff_obj._get_command('old-path', 'new-path'))
1412
895
 
1413
896
    def test_from_string_path_with_backslashes(self):
1414
897
        self.requireFeature(features.backslashdir_feature)
1415
 
        tool = 'C:\\Tools\\Diff.exe'
 
898
        tool = ['C:\\Tools\\Diff.exe', '{old_path}', '{new_path}']
1416
899
        diff_obj = diff.DiffFromTool.from_string(tool, None, None, None)
1417
900
        self.addCleanup(diff_obj.finish)
1418
 
        self.assertEqual(['C:\\Tools\\Diff.exe', '@old_path', '@new_path'],
 
901
        self.assertEqual(['C:\\Tools\\Diff.exe', '{old_path}', '{new_path}'],
1419
902
                         diff_obj.command_template)
1420
903
        self.assertEqual(['C:\\Tools\\Diff.exe', 'old-path', 'new-path'],
1421
904
                         diff_obj._get_command('old-path', 'new-path'))
1423
906
    def test_execute(self):
1424
907
        output = BytesIO()
1425
908
        diff_obj = diff.DiffFromTool([sys.executable, '-c',
1426
 
                                      'print("@old_path @new_path")'],
 
909
                                      'print("{old_path} {new_path}")'],
1427
910
                                     None, None, output)
1428
911
        self.addCleanup(diff_obj.finish)
1429
912
        diff_obj._execute('old', 'new')
1451
934
        basis_tree.lock_read()
1452
935
        self.addCleanup(basis_tree.unlock)
1453
936
        diff_obj = diff.DiffFromTool([sys.executable, '-c',
1454
 
                                      'print "@old_path @new_path"'],
 
937
                                      'print "{old_path} {new_path}"'],
1455
938
                                     basis_tree, tree, output)
1456
939
        diff_obj._prepare_files('file', 'file', file_id=b'file-id')
1457
940
        # The old content should be readonly
1487
970
        tree.lock_read()
1488
971
        self.addCleanup(tree.unlock)
1489
972
        diff_obj = diff.DiffFromTool([sys.executable, '-c',
1490
 
                                      'print "@old_path @new_path"'],
 
973
                                      'print "{old_path} {new_path}"'],
1491
974
                                     old_tree, tree, output)
1492
975
        self.addCleanup(diff_obj.finish)
1493
976
        self.assertContainsRe(diff_obj._root, 'brz-diff-[^/]*')
1494
977
        old_path, new_path = diff_obj._prepare_files(
1495
 
            'oldname', 'newname', file_id=b'file-id')
 
978
            'oldname', 'newname')
1496
979
        self.assertContainsRe(old_path, 'old/oldname$')
1497
980
        self.assertEqual(315532800, os.stat(old_path).st_mtime)
1498
981
        self.assertContainsRe(new_path, 'tree/newname$')
1501
984
        if osutils.host_os_dereferences_symlinks():
1502
985
            self.assertTrue(os.path.samefile('tree/newname', new_path))
1503
986
        # make sure we can create files with the same parent directories
1504
 
        diff_obj._prepare_files('oldname2', 'newname2', file_id=b'file2-id')
 
987
        diff_obj._prepare_files('oldname2', 'newname2')
1505
988
 
1506
989
 
1507
990
class TestDiffFromToolEncodedFilename(tests.TestCaseWithTransport):
1509
992
    def test_encodable_filename(self):
1510
993
        # Just checks file path for external diff tool.
1511
994
        # We cannot change CPython's internal encoding used by os.exec*.
1512
 
        diffobj = diff.DiffFromTool(['dummy', '@old_path', '@new_path'],
 
995
        diffobj = diff.DiffFromTool(['dummy', '{old_path}', '{new_path}'],
1513
996
                                    None, None, None)
1514
997
        for _, scenario in EncodingAdapter.encoding_scenarios:
1515
998
            encoding = scenario['encoding']
1524
1007
            self.assertTrue(fullpath.startswith(diffobj._root + '/safe'))
1525
1008
 
1526
1009
    def test_unencodable_filename(self):
1527
 
        diffobj = diff.DiffFromTool(['dummy', '@old_path', '@new_path'],
 
1010
        diffobj = diff.DiffFromTool(['dummy', '{old_path}', '{new_path}'],
1528
1011
                                    None, None, None)
1529
1012
        for _, scenario in EncodingAdapter.encoding_scenarios:
1530
1013
            encoding = scenario['encoding']
1548
1031
 
1549
1032
    def call_gtabtd(self, path_list, revision_specs, old_url, new_url):
1550
1033
        """Call get_trees_and_branches_to_diff_locked."""
 
1034
        exit_stack = contextlib.ExitStack()
 
1035
        self.addCleanup(exit_stack.close)
1551
1036
        return diff.get_trees_and_branches_to_diff_locked(
1552
 
            path_list, revision_specs, old_url, new_url, self.addCleanup)
 
1037
            path_list, revision_specs, old_url, new_url, exit_stack)
1553
1038
 
1554
1039
    def test_basic(self):
1555
1040
        tree = self.make_branch_and_tree('tree')