~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_diff.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-03-11 13:47:06 UTC
  • mfrom: (5051.3.16 use-branch-open)
  • Revision ID: pqm@pqm.ubuntu.com-20100311134706-kaerqhx3lf7xn6rh
(Jelmer) Pass colocated branch names further down the call stack.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005-2010 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
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
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
import os
18
18
import os.path
32
32
    external_diff,
33
33
    internal_diff,
34
34
    show_diff_trees,
 
35
    get_trees_and_branches_to_diff,
35
36
    )
36
37
from bzrlib.errors import BinaryFile, NoDiff, ExecutableMissing
37
38
import bzrlib.osutils as osutils
 
39
import bzrlib.revision as _mod_revision
38
40
import bzrlib.transform as transform
39
41
import bzrlib.patiencediff
40
42
import bzrlib._patiencediff_py
41
43
from bzrlib.tests import (Feature, TestCase, TestCaseWithTransport,
42
44
                          TestCaseInTempDir, TestSkipped)
 
45
from bzrlib.revisiontree import RevisionTree
 
46
from bzrlib.revisionspec import RevisionSpec
 
47
 
 
48
from bzrlib.tests.test_win32utils import BackslashDirSeparatorFeature
43
49
 
44
50
 
45
51
class _AttribFeature(Feature):
59
65
AttribFeature = _AttribFeature()
60
66
 
61
67
 
62
 
class _CompiledPatienceDiffFeature(Feature):
63
 
 
64
 
    def _probe(self):
65
 
        try:
66
 
            import bzrlib._patiencediff_c
67
 
        except ImportError:
68
 
            return False
69
 
        return True
70
 
 
71
 
    def feature_name(self):
72
 
        return 'bzrlib._patiencediff_c'
73
 
 
74
 
CompiledPatienceDiffFeature = _CompiledPatienceDiffFeature()
 
68
compiled_patiencediff_feature = tests.ModuleAvailableFeature(
 
69
                                    'bzrlib._patiencediff_c')
75
70
 
76
71
 
77
72
def udiff_lines(old, new, allow_binary=False):
183
178
                              StringIO(), diff_opts=['-u'])
184
179
        finally:
185
180
            os.environ['PATH'] = orig_path
186
 
        
 
181
 
187
182
    def test_internal_diff_default(self):
188
183
        # Default internal diff encoding is utf8
189
184
        output = StringIO()
354
349
+file2 contents at rev 3
355
350
 
356
351
''')
357
 
        
 
352
 
358
353
    def test_diff_add_files(self):
359
 
        tree1 = self.b.repository.revision_tree(None)
 
354
        tree1 = self.b.repository.revision_tree(_mod_revision.NULL_REVISION)
360
355
        tree2 = self.b.repository.revision_tree('rev-1')
361
356
        output = self.get_diff(tree1, tree2)
362
357
        # the files have the epoch time stamp for the tree in which
396
391
        self.wt.rename_one('file1', 'file1b')
397
392
        old_tree = self.b.repository.revision_tree('rev-1')
398
393
        new_tree = self.b.repository.revision_tree('rev-4')
399
 
        out = self.get_diff(old_tree, new_tree, specific_files=['file1b'], 
 
394
        out = self.get_diff(old_tree, new_tree, specific_files=['file1b'],
400
395
                            working_tree=self.wt)
401
396
        self.assertContainsRe(out, 'file1\t')
402
397
 
408
403
        self.wt.rename_one('file1', 'dir1/file1')
409
404
        old_tree = self.b.repository.revision_tree('rev-1')
410
405
        new_tree = self.b.repository.revision_tree('rev-4')
411
 
        out = self.get_diff(old_tree, new_tree, specific_files=['dir1'], 
 
406
        out = self.get_diff(old_tree, new_tree, specific_files=['dir1'],
412
407
                            working_tree=self.wt)
413
408
        self.assertContainsRe(out, 'file1\t')
414
 
        out = self.get_diff(old_tree, new_tree, specific_files=['dir2'], 
 
409
        out = self.get_diff(old_tree, new_tree, specific_files=['dir2'],
415
410
                            working_tree=self.wt)
416
411
        self.assertNotContainsRe(out, 'file1\t')
417
412
 
703
698
            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+0,0'
704
699
             ' \@\@\n-old\n\n')
705
700
        self.assertContainsRe(self.differ.to_file.getvalue(),
706
 
                              "=== target is 'new'\n")
 
701
                              "=== target is u'new'\n")
707
702
 
708
703
    def test_diff_directory(self):
709
704
        self.build_tree(['new-tree/new-dir/'])
786
781
        self.assertEquals(unique_lcs('ab', 'ab'), [(0,0), (1,1)])
787
782
        self.assertEquals(unique_lcs('abcde', 'cdeab'), [(2,0), (3,1), (4,2)])
788
783
        self.assertEquals(unique_lcs('cdeab', 'abcde'), [(0,2), (1,3), (2,4)])
789
 
        self.assertEquals(unique_lcs('abXde', 'abYde'), [(0,0), (1,1), 
 
784
        self.assertEquals(unique_lcs('abXde', 'abYde'), [(0,0), (1,1),
790
785
                                                         (3,3), (4,4)])
791
786
        self.assertEquals(unique_lcs('acbac', 'abc'), [(2,1)])
792
787
 
807
802
        test_one('abcdbce', 'afbcgdbce', [(0,0), (1, 2), (2, 3), (3, 5),
808
803
                                          (4, 6), (5, 7), (6, 8)])
809
804
 
810
 
        # recurse_matches doesn't match non-unique 
 
805
        # recurse_matches doesn't match non-unique
811
806
        # lines surrounded by bogus text.
812
807
        # The update has been done in patiencediff.SequenceMatcher instead
813
808
 
950
945
                 ('delete', 1,2, 1,1),
951
946
                 ('equal',  2,3, 1,2),
952
947
                ])
953
 
        chk_ops('aBccDe', 'abccde', 
 
948
        chk_ops('aBccDe', 'abccde',
954
949
                [('equal',   0,1, 0,1),
955
950
                 ('replace', 1,5, 1,5),
956
951
                 ('equal',   5,6, 5,6),
957
952
                ])
958
 
        chk_ops('aBcDec', 'abcdec', 
 
953
        chk_ops('aBcDec', 'abcdec',
959
954
                [('equal',   0,1, 0,1),
960
955
                 ('replace', 1,2, 1,2),
961
956
                 ('equal',   2,3, 2,3),
962
957
                 ('replace', 3,4, 3,4),
963
958
                 ('equal',   4,6, 4,6),
964
959
                ])
965
 
        chk_ops('aBcdEcdFg', 'abcdecdfg', 
 
960
        chk_ops('aBcdEcdFg', 'abcdecdfg',
966
961
                [('equal',   0,1, 0,1),
967
962
                 ('replace', 1,8, 1,8),
968
963
                 ('equal',   8,9, 8,9)
969
964
                ])
970
 
        chk_ops('aBcdEeXcdFg', 'abcdecdfg', 
 
965
        chk_ops('aBcdEeXcdFg', 'abcdecdfg',
971
966
                [('equal',   0,1, 0,1),
972
967
                 ('replace', 1,2, 1,2),
973
968
                 ('equal',   2,4, 2,4),
1033
1028
    """
1034
1029
    gnxrf_netf = ['svyr*']
1035
1030
    gnxrf_bcgvbaf = ['ab-erphefr']
1036
 
  
 
1031
 
1037
1032
    qrs eha(frys, svyr_yvfg, ab_erphefr=Snyfr):
1038
1033
        sebz omeyvo.nqq vzcbeg fzneg_nqq, nqq_ercbegre_cevag, nqq_ercbegre_ahyy
1039
1034
        vs vf_dhvrg():
1047
1042
'''.splitlines(True), '''\
1048
1043
    trg nqqrq jura lbh nqq n svyr va gur qverpgbel.
1049
1044
 
1050
 
    --qel-eha jvyy fubj juvpu svyrf jbhyq or nqqrq, ohg abg npghnyyl 
 
1045
    --qel-eha jvyy fubj juvpu svyrf jbhyq or nqqrq, ohg abg npghnyyl
1051
1046
    nqq gurz.
1052
1047
    """
1053
1048
    gnxrf_netf = ['svyr*']
1082
1077
                 'how are you today?\n']
1083
1078
        unified_diff = bzrlib.patiencediff.unified_diff
1084
1079
        psm = self._PatienceSequenceMatcher
1085
 
        self.assertEquals([ '---  \n',
1086
 
                           '+++  \n',
 
1080
        self.assertEquals(['--- \n',
 
1081
                           '+++ \n',
1087
1082
                           '@@ -1,3 +1,2 @@\n',
1088
1083
                           ' hello there\n',
1089
1084
                           '-world\n',
1094
1089
        txt_a = map(lambda x: x+'\n', 'abcdefghijklmnop')
1095
1090
        txt_b = map(lambda x: x+'\n', 'abcdefxydefghijklmnop')
1096
1091
        # This is the result with LongestCommonSubstring matching
1097
 
        self.assertEquals(['---  \n',
1098
 
                           '+++  \n',
 
1092
        self.assertEquals(['--- \n',
 
1093
                           '+++ \n',
1099
1094
                           '@@ -1,6 +1,11 @@\n',
1100
1095
                           ' a\n',
1101
1096
                           ' b\n',
1110
1105
                           ' f\n']
1111
1106
                          , list(unified_diff(txt_a, txt_b)))
1112
1107
        # And the patience diff
1113
 
        self.assertEquals(['---  \n',
1114
 
                           '+++  \n',
 
1108
        self.assertEquals(['--- \n',
 
1109
                           '+++ \n',
1115
1110
                           '@@ -4,6 +4,11 @@\n',
1116
1111
                           ' d\n',
1117
1112
                           ' e\n',
1128
1123
                          , list(unified_diff(txt_a, txt_b,
1129
1124
                                 sequencematcher=psm)))
1130
1125
 
 
1126
    def test_patience_unified_diff_with_dates(self):
 
1127
        txt_a = ['hello there\n',
 
1128
                 'world\n',
 
1129
                 'how are you today?\n']
 
1130
        txt_b = ['hello there\n',
 
1131
                 'how are you today?\n']
 
1132
        unified_diff = bzrlib.patiencediff.unified_diff
 
1133
        psm = self._PatienceSequenceMatcher
 
1134
        self.assertEquals(['--- a\t2008-08-08\n',
 
1135
                           '+++ b\t2008-09-09\n',
 
1136
                           '@@ -1,3 +1,2 @@\n',
 
1137
                           ' hello there\n',
 
1138
                           '-world\n',
 
1139
                           ' how are you today?\n'
 
1140
                          ]
 
1141
                          , list(unified_diff(txt_a, txt_b,
 
1142
                                 fromfile='a', tofile='b',
 
1143
                                 fromfiledate='2008-08-08',
 
1144
                                 tofiledate='2008-09-09',
 
1145
                                 sequencematcher=psm)))
 
1146
 
1131
1147
 
1132
1148
class TestPatienceDiffLib_c(TestPatienceDiffLib):
1133
1149
 
1134
 
    _test_needs_features = [CompiledPatienceDiffFeature]
 
1150
    _test_needs_features = [compiled_patiencediff_feature]
1135
1151
 
1136
1152
    def setUp(self):
1137
1153
        super(TestPatienceDiffLib_c, self).setUp()
1173
1189
 
1174
1190
        unified_diff_files = bzrlib.patiencediff.unified_diff_files
1175
1191
        psm = self._PatienceSequenceMatcher
1176
 
        self.assertEquals(['--- a1 \n',
1177
 
                           '+++ b1 \n',
 
1192
        self.assertEquals(['--- a1\n',
 
1193
                           '+++ b1\n',
1178
1194
                           '@@ -1,3 +1,2 @@\n',
1179
1195
                           ' hello there\n',
1180
1196
                           '-world\n',
1189
1205
        open('b2', 'wb').writelines(txt_b)
1190
1206
 
1191
1207
        # This is the result with LongestCommonSubstring matching
1192
 
        self.assertEquals(['--- a2 \n',
1193
 
                           '+++ b2 \n',
 
1208
        self.assertEquals(['--- a2\n',
 
1209
                           '+++ b2\n',
1194
1210
                           '@@ -1,6 +1,11 @@\n',
1195
1211
                           ' a\n',
1196
1212
                           ' b\n',
1206
1222
                          , list(unified_diff_files('a2', 'b2')))
1207
1223
 
1208
1224
        # And the patience diff
1209
 
        self.assertEquals(['--- a2 \n',
1210
 
                           '+++ b2 \n',
 
1225
        self.assertEquals(['--- a2\n',
 
1226
                           '+++ b2\n',
1211
1227
                           '@@ -4,6 +4,11 @@\n',
1212
1228
                           ' d\n',
1213
1229
                           ' e\n',
1227
1243
 
1228
1244
class TestPatienceDiffLibFiles_c(TestPatienceDiffLibFiles):
1229
1245
 
1230
 
    _test_needs_features = [CompiledPatienceDiffFeature]
 
1246
    _test_needs_features = [compiled_patiencediff_feature]
1231
1247
 
1232
1248
    def setUp(self):
1233
1249
        super(TestPatienceDiffLibFiles_c, self).setUp()
1239
1255
class TestUsingCompiledIfAvailable(TestCase):
1240
1256
 
1241
1257
    def test_PatienceSequenceMatcher(self):
1242
 
        if CompiledPatienceDiffFeature.available():
 
1258
        if compiled_patiencediff_feature.available():
1243
1259
            from bzrlib._patiencediff_c import PatienceSequenceMatcher_c
1244
1260
            self.assertIs(PatienceSequenceMatcher_c,
1245
1261
                          bzrlib.patiencediff.PatienceSequenceMatcher)
1249
1265
                          bzrlib.patiencediff.PatienceSequenceMatcher)
1250
1266
 
1251
1267
    def test_unique_lcs(self):
1252
 
        if CompiledPatienceDiffFeature.available():
 
1268
        if compiled_patiencediff_feature.available():
1253
1269
            from bzrlib._patiencediff_c import unique_lcs_c
1254
1270
            self.assertIs(unique_lcs_c,
1255
1271
                          bzrlib.patiencediff.unique_lcs)
1259
1275
                          bzrlib.patiencediff.unique_lcs)
1260
1276
 
1261
1277
    def test_recurse_matches(self):
1262
 
        if CompiledPatienceDiffFeature.available():
 
1278
        if compiled_patiencediff_feature.available():
1263
1279
            from bzrlib._patiencediff_c import recurse_matches_c
1264
1280
            self.assertIs(recurse_matches_c,
1265
1281
                          bzrlib.patiencediff.recurse_matches)
1274
1290
    def test_from_string(self):
1275
1291
        diff_obj = DiffFromTool.from_string('diff', None, None, None)
1276
1292
        self.addCleanup(diff_obj.finish)
1277
 
        self.assertEqual(['diff', '%(old_path)s', '%(new_path)s'],
 
1293
        self.assertEqual(['diff', '@old_path', '@new_path'],
1278
1294
            diff_obj.command_template)
1279
1295
 
1280
1296
    def test_from_string_u5(self):
1281
 
        diff_obj = DiffFromTool.from_string('diff -u\\ 5', None, None, None)
 
1297
        diff_obj = DiffFromTool.from_string('diff "-u 5"', None, None, None)
1282
1298
        self.addCleanup(diff_obj.finish)
1283
 
        self.assertEqual(['diff', '-u 5', '%(old_path)s', '%(new_path)s'],
 
1299
        self.assertEqual(['diff', '-u 5', '@old_path', '@new_path'],
1284
1300
                         diff_obj.command_template)
1285
1301
        self.assertEqual(['diff', '-u 5', 'old-path', 'new-path'],
1286
1302
                         diff_obj._get_command('old-path', 'new-path'))
 
1303
        
 
1304
    def test_from_string_path_with_backslashes(self):
 
1305
        self.requireFeature(BackslashDirSeparatorFeature)
 
1306
        tool = 'C:\\Tools\\Diff.exe'
 
1307
        diff_obj = DiffFromTool.from_string(tool, None, None, None)
 
1308
        self.addCleanup(diff_obj.finish)
 
1309
        self.assertEqual(['C:\\Tools\\Diff.exe', '@old_path', '@new_path'],
 
1310
                         diff_obj.command_template)
 
1311
        self.assertEqual(['C:\\Tools\\Diff.exe', 'old-path', 'new-path'],
 
1312
                         diff_obj._get_command('old-path', 'new-path'))
1287
1313
 
1288
1314
    def test_execute(self):
1289
1315
        output = StringIO()
1290
1316
        diff_obj = DiffFromTool(['python', '-c',
1291
 
                                 'print "%(old_path)s %(new_path)s"'],
 
1317
                                 'print "@old_path @new_path"'],
1292
1318
                                None, None, output)
1293
1319
        self.addCleanup(diff_obj.finish)
1294
1320
        diff_obj._execute('old', 'new')
1312
1338
        tree.commit('old tree')
1313
1339
        tree.lock_read()
1314
1340
        self.addCleanup(tree.unlock)
 
1341
        basis_tree = tree.basis_tree()
 
1342
        basis_tree.lock_read()
 
1343
        self.addCleanup(basis_tree.unlock)
1315
1344
        diff_obj = DiffFromTool(['python', '-c',
1316
 
                                 'print "%(old_path)s %(new_path)s"'],
1317
 
                                tree, tree, output)
 
1345
                                 'print "@old_path @new_path"'],
 
1346
                                basis_tree, tree, output)
1318
1347
        diff_obj._prepare_files('file-id', 'file', 'file')
1319
 
        self.assertReadableByAttrib(diff_obj._root, 'old\\file', r'old\\file')
1320
 
        self.assertReadableByAttrib(diff_obj._root, 'new\\file', r'new\\file')
 
1348
        # The old content should be readonly
 
1349
        self.assertReadableByAttrib(diff_obj._root, 'old\\file',
 
1350
                                    r'R.*old\\file$')
 
1351
        # The new content should use the tree object, not a 'new' file anymore
 
1352
        self.assertEndsWith(tree.basedir, 'work/tree')
 
1353
        self.assertReadableByAttrib(tree.basedir, 'file', r'work\\tree\\file$')
1321
1354
 
1322
1355
    def assertReadableByAttrib(self, cwd, relpath, regex):
1323
1356
        proc = subprocess.Popen(['attrib', relpath],
1324
1357
                                stdout=subprocess.PIPE,
1325
1358
                                cwd=cwd)
1326
 
        proc.wait()
1327
 
        result = proc.stdout.read()
1328
 
        self.assertContainsRe(result, regex)
 
1359
        (result, err) = proc.communicate()
 
1360
        self.assertContainsRe(result.replace('\r\n', '\n'), regex)
1329
1361
 
1330
1362
    def test_prepare_files(self):
1331
1363
        output = StringIO()
1345
1377
        tree.lock_read()
1346
1378
        self.addCleanup(tree.unlock)
1347
1379
        diff_obj = DiffFromTool(['python', '-c',
1348
 
                                 'print "%(old_path)s %(new_path)s"'],
 
1380
                                 'print "@old_path @new_path"'],
1349
1381
                                old_tree, tree, output)
1350
1382
        self.addCleanup(diff_obj.finish)
1351
1383
        self.assertContainsRe(diff_obj._root, 'bzr-diff-[^/]*')
1353
1385
                                                     'newname')
1354
1386
        self.assertContainsRe(old_path, 'old/oldname$')
1355
1387
        self.assertEqual(0, os.stat(old_path).st_mtime)
1356
 
        self.assertContainsRe(new_path, 'new/newname$')
 
1388
        self.assertContainsRe(new_path, 'tree/newname$')
1357
1389
        self.assertFileEqual('oldcontent', old_path)
1358
1390
        self.assertFileEqual('newcontent', new_path)
1359
1391
        if osutils.host_os_dereferences_symlinks():
1360
1392
            self.assertTrue(os.path.samefile('tree/newname', new_path))
1361
1393
        # make sure we can create files with the same parent directories
1362
1394
        diff_obj._prepare_files('file2-id', 'oldname2', 'newname2')
 
1395
 
 
1396
 
 
1397
class TestGetTreesAndBranchesToDiff(TestCaseWithTransport):
 
1398
 
 
1399
    def test_basic(self):
 
1400
        tree = self.make_branch_and_tree('tree')
 
1401
        (old_tree, new_tree,
 
1402
         old_branch, new_branch,
 
1403
         specific_files, extra_trees) = \
 
1404
            get_trees_and_branches_to_diff(['tree'], None, None, None)
 
1405
 
 
1406
        self.assertIsInstance(old_tree, RevisionTree)
 
1407
        #print dir (old_tree)
 
1408
        self.assertEqual(_mod_revision.NULL_REVISION, old_tree.get_revision_id())
 
1409
        self.assertEqual(tree.basedir, new_tree.basedir)
 
1410
        self.assertEqual(tree.branch.base, old_branch.base)
 
1411
        self.assertEqual(tree.branch.base, new_branch.base)
 
1412
        self.assertIs(None, specific_files)
 
1413
        self.assertIs(None, extra_trees)
 
1414
 
 
1415
    def test_with_rev_specs(self):
 
1416
        tree = self.make_branch_and_tree('tree')
 
1417
        self.build_tree_contents([('tree/file', 'oldcontent')])
 
1418
        tree.add('file', 'file-id')
 
1419
        tree.commit('old tree', timestamp=0, rev_id="old-id")
 
1420
        self.build_tree_contents([('tree/file', 'newcontent')])
 
1421
        tree.commit('new tree', timestamp=0, rev_id="new-id")
 
1422
 
 
1423
        revisions = [RevisionSpec.from_string('1'),
 
1424
                     RevisionSpec.from_string('2')]
 
1425
        (old_tree, new_tree,
 
1426
         old_branch, new_branch,
 
1427
         specific_files, extra_trees) = \
 
1428
            get_trees_and_branches_to_diff(['tree'], revisions, None, None)
 
1429
 
 
1430
        self.assertIsInstance(old_tree, RevisionTree)
 
1431
        self.assertEqual("old-id", old_tree.get_revision_id())
 
1432
        self.assertIsInstance(new_tree, RevisionTree)
 
1433
        self.assertEqual("new-id", new_tree.get_revision_id())
 
1434
        self.assertEqual(tree.branch.base, old_branch.base)
 
1435
        self.assertEqual(tree.branch.base, new_branch.base)
 
1436
        self.assertIs(None, specific_files)
 
1437
        self.assertEqual(tree.basedir, extra_trees[0].basedir)