/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_transform.py

  • Committer: Jelmer Vernooij
  • Date: 2020-07-05 12:50:01 UTC
  • mfrom: (7490.40.46 work)
  • mto: (7490.40.48 work)
  • mto: This revision was merged to the branch mainline in revision 7519.
  • Revision ID: jelmer@jelmer.uk-20200705125001-7s3vo0p55szbbws7
Merge lp:brz/3.1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
60
60
)
61
61
from ..merge import Merge3Merger, Merger
62
62
from ..mutabletree import MutableTree
 
63
from ..sixish import (
 
64
    BytesIO,
 
65
    PY3,
 
66
    text_type,
 
67
    )
63
68
from . import (
64
69
    features,
65
70
    TestCaseInTempDir,
84
89
    ReusingTransform,
85
90
    TransformRenameFailed,
86
91
)
 
92
from ..bzr.transform import (
 
93
    InventoryTreeTransform as TreeTransform,
 
94
    )
87
95
 
88
96
 
89
97
class TransformGroup(object):
966
974
        new_globals.update(globals)
967
975
        new_func = types.FunctionType(func.__code__, new_globals,
968
976
                                      func.__name__, func.__defaults__)
969
 
        setattr(instance, method_name,
970
 
                types.MethodType(new_func, instance))
 
977
        if PY3:
 
978
            setattr(instance, method_name,
 
979
                    types.MethodType(new_func, instance))
 
980
        else:
 
981
            setattr(instance, method_name,
 
982
                    types.MethodType(new_func, instance, instance.__class__))
971
983
        self.addCleanup(delattr, instance, method_name)
972
984
 
973
985
    @staticmethod
1118
1130
                         conflicts.pop())
1119
1131
 
1120
1132
 
 
1133
A_ENTRY = (b'a-id', ('a', 'a'), True, (True, True),
 
1134
           (b'TREE_ROOT', b'TREE_ROOT'), ('a', 'a'), ('file', 'file'),
 
1135
           (False, False), False)
 
1136
ROOT_ENTRY = (b'TREE_ROOT', ('', ''), False, (True, True), (None, None),
 
1137
              ('', ''), ('directory', 'directory'), (False, False), False)
 
1138
 
 
1139
 
 
1140
class TestTransformPreview(tests.TestCaseWithTransport):
 
1141
 
 
1142
    def create_tree(self):
 
1143
        tree = self.make_branch_and_tree('.')
 
1144
        self.build_tree_contents([('a', b'content 1')])
 
1145
        tree.set_root_id(b'TREE_ROOT')
 
1146
        tree.add('a', b'a-id')
 
1147
        tree.commit('rev1', rev_id=b'rev1')
 
1148
        return tree.branch.repository.revision_tree(b'rev1')
 
1149
 
 
1150
    def get_empty_preview(self):
 
1151
        repository = self.make_repository('repo')
 
1152
        tree = repository.revision_tree(_mod_revision.NULL_REVISION)
 
1153
        preview = tree.preview_transform()
 
1154
        self.addCleanup(preview.finalize)
 
1155
        return preview
 
1156
 
 
1157
    def test_transform_preview(self):
 
1158
        revision_tree = self.create_tree()
 
1159
        preview = revision_tree.preview_transform()
 
1160
        self.addCleanup(preview.finalize)
 
1161
 
 
1162
    def test_transform_preview_tree(self):
 
1163
        revision_tree = self.create_tree()
 
1164
        preview = revision_tree.preview_transform()
 
1165
        self.addCleanup(preview.finalize)
 
1166
        preview.get_preview_tree()
 
1167
 
 
1168
    def test_transform_new_file(self):
 
1169
        revision_tree = self.create_tree()
 
1170
        preview = revision_tree.preview_transform()
 
1171
        self.addCleanup(preview.finalize)
 
1172
        preview.new_file('file2', preview.root, [b'content B\n'], b'file2-id')
 
1173
        preview_tree = preview.get_preview_tree()
 
1174
        self.assertEqual(preview_tree.kind('file2'), 'file')
 
1175
        with preview_tree.get_file('file2') as f:
 
1176
            self.assertEqual(f.read(), b'content B\n')
 
1177
 
 
1178
    def test_diff_preview_tree(self):
 
1179
        revision_tree = self.create_tree()
 
1180
        preview = revision_tree.preview_transform()
 
1181
        self.addCleanup(preview.finalize)
 
1182
        preview.new_file('file2', preview.root, [b'content B\n'], b'file2-id')
 
1183
        preview_tree = preview.get_preview_tree()
 
1184
        out = BytesIO()
 
1185
        show_diff_trees(revision_tree, preview_tree, out)
 
1186
        lines = out.getvalue().splitlines()
 
1187
        self.assertEqual(lines[0], b"=== added file 'file2'")
 
1188
        # 3 lines of diff administrivia
 
1189
        self.assertEqual(lines[4], b"+content B")
 
1190
 
 
1191
    def test_unsupported_symlink_diff(self):
 
1192
        self.requireFeature(SymlinkFeature)
 
1193
        tree = self.make_branch_and_tree('.')
 
1194
        self.build_tree_contents([('a', 'content 1')])
 
1195
        tree.set_root_id(b'TREE_ROOT')
 
1196
        tree.add('a', b'a-id')
 
1197
        os.symlink('a', 'foo')
 
1198
        tree.add('foo', b'foo-id')
 
1199
        tree.commit('rev1', rev_id=b'rev1')
 
1200
        revision_tree = tree.branch.repository.revision_tree(b'rev1')
 
1201
        preview = revision_tree.preview_transform()
 
1202
        self.addCleanup(preview.finalize)
 
1203
        preview.delete_versioned(preview.trans_id_tree_path('foo'))
 
1204
        preview_tree = preview.get_preview_tree()
 
1205
        out = BytesIO()
 
1206
        log = BytesIO()
 
1207
        trace.push_log_file(log)
 
1208
        os_symlink = getattr(os, 'symlink', None)
 
1209
        os.symlink = None
 
1210
        try:
 
1211
            show_diff_trees(revision_tree, preview_tree, out)
 
1212
            lines = out.getvalue().splitlines()
 
1213
        finally:
 
1214
            os.symlink = os_symlink
 
1215
        self.assertContainsRe(
 
1216
            log.getvalue(),
 
1217
            b'Ignoring "foo" as symlinks are not supported on this filesystem')
 
1218
 
 
1219
    def test_transform_conflicts(self):
 
1220
        revision_tree = self.create_tree()
 
1221
        preview = revision_tree.preview_transform()
 
1222
        self.addCleanup(preview.finalize)
 
1223
        preview.new_file('a', preview.root, [b'content 2'])
 
1224
        resolve_conflicts(preview)
 
1225
        trans_id = preview.trans_id_file_id(b'a-id')
 
1226
        self.assertEqual('a.moved', preview.final_name(trans_id))
 
1227
 
 
1228
    def get_tree_and_preview_tree(self):
 
1229
        revision_tree = self.create_tree()
 
1230
        preview = revision_tree.preview_transform()
 
1231
        self.addCleanup(preview.finalize)
 
1232
        a_trans_id = preview.trans_id_file_id(b'a-id')
 
1233
        preview.delete_contents(a_trans_id)
 
1234
        preview.create_file([b'b content'], a_trans_id)
 
1235
        preview_tree = preview.get_preview_tree()
 
1236
        return revision_tree, preview_tree
 
1237
 
 
1238
    def test_iter_changes(self):
 
1239
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
 
1240
        root = revision_tree.path2id('')
 
1241
        self.assertEqual([(b'a-id', ('a', 'a'), True, (True, True),
 
1242
                           (root, root), ('a', 'a'), ('file', 'file'),
 
1243
                           (False, False), False)],
 
1244
                         list(preview_tree.iter_changes(revision_tree)))
 
1245
 
 
1246
    def test_include_unchanged_succeeds(self):
 
1247
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
 
1248
        changes = preview_tree.iter_changes(revision_tree,
 
1249
                                            include_unchanged=True)
 
1250
        self.assertEqual([ROOT_ENTRY, A_ENTRY], list(changes))
 
1251
 
 
1252
    def test_specific_files(self):
 
1253
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
 
1254
        changes = preview_tree.iter_changes(revision_tree,
 
1255
                                            specific_files=[''])
 
1256
        self.assertEqual([A_ENTRY], list(changes))
 
1257
 
 
1258
    def test_want_unversioned(self):
 
1259
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
 
1260
        changes = preview_tree.iter_changes(revision_tree,
 
1261
                                            want_unversioned=True)
 
1262
        self.assertEqual([A_ENTRY], list(changes))
 
1263
 
 
1264
    def test_ignore_extra_trees_no_specific_files(self):
 
1265
        # extra_trees is harmless without specific_files, so we'll silently
 
1266
        # accept it, even though we won't use it.
 
1267
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
 
1268
        preview_tree.iter_changes(revision_tree, extra_trees=[preview_tree])
 
1269
 
 
1270
    def test_ignore_require_versioned_no_specific_files(self):
 
1271
        # require_versioned is meaningless without specific_files.
 
1272
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
 
1273
        preview_tree.iter_changes(revision_tree, require_versioned=False)
 
1274
 
 
1275
    def test_ignore_pb(self):
 
1276
        # pb could be supported, but TT.iter_changes doesn't support it.
 
1277
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
 
1278
        preview_tree.iter_changes(revision_tree)
 
1279
 
 
1280
    def test_kind(self):
 
1281
        revision_tree = self.create_tree()
 
1282
        preview = revision_tree.preview_transform()
 
1283
        self.addCleanup(preview.finalize)
 
1284
        preview.new_file('file', preview.root, [b'contents'], b'file-id')
 
1285
        preview.new_directory('directory', preview.root, b'dir-id')
 
1286
        preview_tree = preview.get_preview_tree()
 
1287
        self.assertEqual('file', preview_tree.kind('file'))
 
1288
        self.assertEqual('directory', preview_tree.kind('directory'))
 
1289
 
 
1290
    def test_get_file_mtime(self):
 
1291
        preview = self.get_empty_preview()
 
1292
        file_trans_id = preview.new_file('file', preview.root, [b'contents'],
 
1293
                                         b'file-id')
 
1294
        limbo_path = preview._limbo_name(file_trans_id)
 
1295
        preview_tree = preview.get_preview_tree()
 
1296
        self.assertEqual(os.stat(limbo_path).st_mtime,
 
1297
                         preview_tree.get_file_mtime('file'))
 
1298
 
 
1299
    def test_get_file_mtime_renamed(self):
 
1300
        work_tree = self.make_branch_and_tree('tree')
 
1301
        self.build_tree(['tree/file'])
 
1302
        work_tree.add('file', b'file-id')
 
1303
        preview = work_tree.preview_transform()
 
1304
        self.addCleanup(preview.finalize)
 
1305
        file_trans_id = preview.trans_id_tree_path('file')
 
1306
        preview.adjust_path('renamed', preview.root, file_trans_id)
 
1307
        preview_tree = preview.get_preview_tree()
 
1308
        preview_mtime = preview_tree.get_file_mtime('renamed')
 
1309
        work_mtime = work_tree.get_file_mtime('file')
 
1310
 
 
1311
    def test_get_file_size(self):
 
1312
        work_tree = self.make_branch_and_tree('tree')
 
1313
        self.build_tree_contents([('tree/old', b'old')])
 
1314
        work_tree.add('old', b'old-id')
 
1315
        preview = work_tree.preview_transform()
 
1316
        self.addCleanup(preview.finalize)
 
1317
        preview.new_file('name', preview.root, [b'contents'], b'new-id',
 
1318
                         'executable')
 
1319
        tree = preview.get_preview_tree()
 
1320
        self.assertEqual(len('old'), tree.get_file_size('old'))
 
1321
        self.assertEqual(len('contents'), tree.get_file_size('name'))
 
1322
 
 
1323
    def test_get_file(self):
 
1324
        preview = self.get_empty_preview()
 
1325
        preview.new_file('file', preview.root, [b'contents'], b'file-id')
 
1326
        preview_tree = preview.get_preview_tree()
 
1327
        with preview_tree.get_file('file') as tree_file:
 
1328
            self.assertEqual(b'contents', tree_file.read())
 
1329
 
 
1330
    def test_get_symlink_target(self):
 
1331
        self.requireFeature(SymlinkFeature)
 
1332
        preview = self.get_empty_preview()
 
1333
        preview.new_symlink('symlink', preview.root, 'target', b'symlink-id')
 
1334
        preview_tree = preview.get_preview_tree()
 
1335
        self.assertEqual('target',
 
1336
                         preview_tree.get_symlink_target('symlink'))
 
1337
 
 
1338
    def test_all_file_ids(self):
 
1339
        tree = self.make_branch_and_tree('tree')
 
1340
        self.build_tree(['tree/a', 'tree/b', 'tree/c'])
 
1341
        tree.add(['a', 'b', 'c'], [b'a-id', b'b-id', b'c-id'])
 
1342
        preview = tree.preview_transform()
 
1343
        self.addCleanup(preview.finalize)
 
1344
        preview.unversion_file(preview.trans_id_file_id(b'b-id'))
 
1345
        c_trans_id = preview.trans_id_file_id(b'c-id')
 
1346
        preview.unversion_file(c_trans_id)
 
1347
        preview.version_file(c_trans_id, file_id=b'c-id')
 
1348
        preview_tree = preview.get_preview_tree()
 
1349
        self.assertEqual({b'a-id', b'c-id', tree.path2id('')},
 
1350
                         preview_tree.all_file_ids())
 
1351
 
 
1352
    def test_path2id_deleted_unchanged(self):
 
1353
        tree = self.make_branch_and_tree('tree')
 
1354
        self.build_tree(['tree/unchanged', 'tree/deleted'])
 
1355
        tree.add(['unchanged', 'deleted'], [b'unchanged-id', b'deleted-id'])
 
1356
        preview = tree.preview_transform()
 
1357
        self.addCleanup(preview.finalize)
 
1358
        preview.unversion_file(preview.trans_id_file_id(b'deleted-id'))
 
1359
        preview_tree = preview.get_preview_tree()
 
1360
        self.assertEqual(b'unchanged-id', preview_tree.path2id('unchanged'))
 
1361
        self.assertFalse(preview_tree.is_versioned('deleted'))
 
1362
 
 
1363
    def test_path2id_created(self):
 
1364
        tree = self.make_branch_and_tree('tree')
 
1365
        self.build_tree(['tree/unchanged'])
 
1366
        tree.add(['unchanged'], [b'unchanged-id'])
 
1367
        preview = tree.preview_transform()
 
1368
        self.addCleanup(preview.finalize)
 
1369
        preview.new_file('new', preview.trans_id_file_id(b'unchanged-id'),
 
1370
                         [b'contents'], b'new-id')
 
1371
        preview_tree = preview.get_preview_tree()
 
1372
        self.assertEqual(b'new-id', preview_tree.path2id('unchanged/new'))
 
1373
 
 
1374
    def test_path2id_moved(self):
 
1375
        tree = self.make_branch_and_tree('tree')
 
1376
        self.build_tree(['tree/old_parent/', 'tree/old_parent/child'])
 
1377
        tree.add(['old_parent', 'old_parent/child'],
 
1378
                 [b'old_parent-id', b'child-id'])
 
1379
        preview = tree.preview_transform()
 
1380
        self.addCleanup(preview.finalize)
 
1381
        new_parent = preview.new_directory('new_parent', preview.root,
 
1382
                                           b'new_parent-id')
 
1383
        preview.adjust_path('child', new_parent,
 
1384
                            preview.trans_id_file_id(b'child-id'))
 
1385
        preview_tree = preview.get_preview_tree()
 
1386
        self.assertFalse(preview_tree.is_versioned('old_parent/child'))
 
1387
        self.assertEqual(b'child-id', preview_tree.path2id('new_parent/child'))
 
1388
 
 
1389
    def test_path2id_renamed_parent(self):
 
1390
        tree = self.make_branch_and_tree('tree')
 
1391
        self.build_tree(['tree/old_name/', 'tree/old_name/child'])
 
1392
        tree.add(['old_name', 'old_name/child'],
 
1393
                 [b'parent-id', b'child-id'])
 
1394
        preview = tree.preview_transform()
 
1395
        self.addCleanup(preview.finalize)
 
1396
        preview.adjust_path('new_name', preview.root,
 
1397
                            preview.trans_id_file_id(b'parent-id'))
 
1398
        preview_tree = preview.get_preview_tree()
 
1399
        self.assertFalse(preview_tree.is_versioned('old_name/child'))
 
1400
        self.assertEqual(b'child-id', preview_tree.path2id('new_name/child'))
 
1401
 
 
1402
    def assertMatchingIterEntries(self, tt, specific_files=None):
 
1403
        preview_tree = tt.get_preview_tree()
 
1404
        preview_result = list(preview_tree.iter_entries_by_dir(
 
1405
                              specific_files=specific_files))
 
1406
        tree = tt._tree
 
1407
        tt.apply()
 
1408
        actual_result = list(tree.iter_entries_by_dir(
 
1409
            specific_files=specific_files))
 
1410
        self.assertEqual(actual_result, preview_result)
 
1411
 
 
1412
    def test_iter_entries_by_dir_new(self):
 
1413
        tree = self.make_branch_and_tree('tree')
 
1414
        tt = tree.transform()
 
1415
        tt.new_file('new', tt.root, [b'contents'], b'new-id')
 
1416
        self.assertMatchingIterEntries(tt)
 
1417
 
 
1418
    def test_iter_entries_by_dir_deleted(self):
 
1419
        tree = self.make_branch_and_tree('tree')
 
1420
        self.build_tree(['tree/deleted'])
 
1421
        tree.add('deleted', b'deleted-id')
 
1422
        tt = tree.transform()
 
1423
        tt.delete_contents(tt.trans_id_file_id(b'deleted-id'))
 
1424
        self.assertMatchingIterEntries(tt)
 
1425
 
 
1426
    def test_iter_entries_by_dir_unversioned(self):
 
1427
        tree = self.make_branch_and_tree('tree')
 
1428
        self.build_tree(['tree/removed'])
 
1429
        tree.add('removed', b'removed-id')
 
1430
        tt = tree.transform()
 
1431
        tt.unversion_file(tt.trans_id_file_id(b'removed-id'))
 
1432
        self.assertMatchingIterEntries(tt)
 
1433
 
 
1434
    def test_iter_entries_by_dir_moved(self):
 
1435
        tree = self.make_branch_and_tree('tree')
 
1436
        self.build_tree(['tree/moved', 'tree/new_parent/'])
 
1437
        tree.add(['moved', 'new_parent'], [b'moved-id', b'new_parent-id'])
 
1438
        tt = tree.transform()
 
1439
        tt.adjust_path('moved', tt.trans_id_file_id(b'new_parent-id'),
 
1440
                       tt.trans_id_file_id(b'moved-id'))
 
1441
        self.assertMatchingIterEntries(tt)
 
1442
 
 
1443
    def test_iter_entries_by_dir_specific_files(self):
 
1444
        tree = self.make_branch_and_tree('tree')
 
1445
        tree.set_root_id(b'tree-root-id')
 
1446
        self.build_tree(['tree/parent/', 'tree/parent/child'])
 
1447
        tree.add(['parent', 'parent/child'], [b'parent-id', b'child-id'])
 
1448
        tt = tree.transform()
 
1449
        self.assertMatchingIterEntries(tt, ['', 'parent/child'])
 
1450
 
 
1451
    def test_symlink_content_summary(self):
 
1452
        self.requireFeature(SymlinkFeature)
 
1453
        preview = self.get_empty_preview()
 
1454
        preview.new_symlink('path', preview.root, 'target', b'path-id')
 
1455
        summary = preview.get_preview_tree().path_content_summary('path')
 
1456
        self.assertEqual(('symlink', None, None, 'target'), summary)
 
1457
 
 
1458
    def test_missing_content_summary(self):
 
1459
        preview = self.get_empty_preview()
 
1460
        summary = preview.get_preview_tree().path_content_summary('path')
 
1461
        self.assertEqual(('missing', None, None, None), summary)
 
1462
 
 
1463
    def test_deleted_content_summary(self):
 
1464
        tree = self.make_branch_and_tree('tree')
 
1465
        self.build_tree(['tree/path/'])
 
1466
        tree.add('path')
 
1467
        preview = tree.preview_transform()
 
1468
        self.addCleanup(preview.finalize)
 
1469
        preview.delete_contents(preview.trans_id_tree_path('path'))
 
1470
        summary = preview.get_preview_tree().path_content_summary('path')
 
1471
        self.assertEqual(('missing', None, None, None), summary)
 
1472
 
 
1473
    def test_file_content_summary_executable(self):
 
1474
        preview = self.get_empty_preview()
 
1475
        path_id = preview.new_file('path', preview.root, [
 
1476
                                   b'contents'], b'path-id')
 
1477
        preview.set_executability(True, path_id)
 
1478
        summary = preview.get_preview_tree().path_content_summary('path')
 
1479
        self.assertEqual(4, len(summary))
 
1480
        self.assertEqual('file', summary[0])
 
1481
        # size must be known
 
1482
        self.assertEqual(len('contents'), summary[1])
 
1483
        # executable
 
1484
        self.assertEqual(True, summary[2])
 
1485
        # will not have hash (not cheap to determine)
 
1486
        self.assertIs(None, summary[3])
 
1487
 
 
1488
    def test_change_executability(self):
 
1489
        tree = self.make_branch_and_tree('tree')
 
1490
        self.build_tree(['tree/path'])
 
1491
        tree.add('path')
 
1492
        preview = tree.preview_transform()
 
1493
        self.addCleanup(preview.finalize)
 
1494
        path_id = preview.trans_id_tree_path('path')
 
1495
        preview.set_executability(True, path_id)
 
1496
        summary = preview.get_preview_tree().path_content_summary('path')
 
1497
        self.assertEqual(True, summary[2])
 
1498
 
 
1499
    def test_file_content_summary_non_exec(self):
 
1500
        preview = self.get_empty_preview()
 
1501
        preview.new_file('path', preview.root, [b'contents'], b'path-id')
 
1502
        summary = preview.get_preview_tree().path_content_summary('path')
 
1503
        self.assertEqual(4, len(summary))
 
1504
        self.assertEqual('file', summary[0])
 
1505
        # size must be known
 
1506
        self.assertEqual(len('contents'), summary[1])
 
1507
        # not executable
 
1508
        self.assertEqual(False, summary[2])
 
1509
        # will not have hash (not cheap to determine)
 
1510
        self.assertIs(None, summary[3])
 
1511
 
 
1512
    def test_dir_content_summary(self):
 
1513
        preview = self.get_empty_preview()
 
1514
        preview.new_directory('path', preview.root, b'path-id')
 
1515
        summary = preview.get_preview_tree().path_content_summary('path')
 
1516
        self.assertEqual(('directory', None, None, None), summary)
 
1517
 
 
1518
    def test_tree_content_summary(self):
 
1519
        preview = self.get_empty_preview()
 
1520
        path = preview.new_directory('path', preview.root, b'path-id')
 
1521
        preview.set_tree_reference(b'rev-1', path)
 
1522
        summary = preview.get_preview_tree().path_content_summary('path')
 
1523
        self.assertEqual(4, len(summary))
 
1524
        self.assertEqual('tree-reference', summary[0])
 
1525
 
 
1526
    def test_annotate(self):
 
1527
        tree = self.make_branch_and_tree('tree')
 
1528
        self.build_tree_contents([('tree/file', b'a\n')])
 
1529
        tree.add('file', b'file-id')
 
1530
        tree.commit('a', rev_id=b'one')
 
1531
        self.build_tree_contents([('tree/file', b'a\nb\n')])
 
1532
        preview = tree.preview_transform()
 
1533
        self.addCleanup(preview.finalize)
 
1534
        file_trans_id = preview.trans_id_file_id(b'file-id')
 
1535
        preview.delete_contents(file_trans_id)
 
1536
        preview.create_file([b'a\nb\nc\n'], file_trans_id)
 
1537
        preview_tree = preview.get_preview_tree()
 
1538
        expected = [
 
1539
            (b'one', b'a\n'),
 
1540
            (b'me:', b'b\n'),
 
1541
            (b'me:', b'c\n'),
 
1542
        ]
 
1543
        annotation = preview_tree.annotate_iter(
 
1544
            'file', default_revision=b'me:')
 
1545
        self.assertEqual(expected, annotation)
 
1546
 
 
1547
    def test_annotate_missing(self):
 
1548
        preview = self.get_empty_preview()
 
1549
        preview.new_file('file', preview.root, [b'a\nb\nc\n'], b'file-id')
 
1550
        preview_tree = preview.get_preview_tree()
 
1551
        expected = [
 
1552
            (b'me:', b'a\n'),
 
1553
            (b'me:', b'b\n'),
 
1554
            (b'me:', b'c\n'),
 
1555
            ]
 
1556
        annotation = preview_tree.annotate_iter(
 
1557
            'file', default_revision=b'me:')
 
1558
        self.assertEqual(expected, annotation)
 
1559
 
 
1560
    def test_annotate_rename(self):
 
1561
        tree = self.make_branch_and_tree('tree')
 
1562
        self.build_tree_contents([('tree/file', b'a\n')])
 
1563
        tree.add('file', b'file-id')
 
1564
        tree.commit('a', rev_id=b'one')
 
1565
        preview = tree.preview_transform()
 
1566
        self.addCleanup(preview.finalize)
 
1567
        file_trans_id = preview.trans_id_file_id(b'file-id')
 
1568
        preview.adjust_path('newname', preview.root, file_trans_id)
 
1569
        preview_tree = preview.get_preview_tree()
 
1570
        expected = [
 
1571
            (b'one', b'a\n'),
 
1572
        ]
 
1573
        annotation = preview_tree.annotate_iter(
 
1574
            'file', default_revision=b'me:')
 
1575
        self.assertEqual(expected, annotation)
 
1576
 
 
1577
    def test_annotate_deleted(self):
 
1578
        tree = self.make_branch_and_tree('tree')
 
1579
        self.build_tree_contents([('tree/file', b'a\n')])
 
1580
        tree.add('file', b'file-id')
 
1581
        tree.commit('a', rev_id=b'one')
 
1582
        self.build_tree_contents([('tree/file', b'a\nb\n')])
 
1583
        preview = tree.preview_transform()
 
1584
        self.addCleanup(preview.finalize)
 
1585
        file_trans_id = preview.trans_id_file_id(b'file-id')
 
1586
        preview.delete_contents(file_trans_id)
 
1587
        preview_tree = preview.get_preview_tree()
 
1588
        annotation = preview_tree.annotate_iter(
 
1589
            'file', default_revision=b'me:')
 
1590
        self.assertIs(None, annotation)
 
1591
 
 
1592
    def test_stored_kind(self):
 
1593
        preview = self.get_empty_preview()
 
1594
        preview.new_file('file', preview.root, [b'a\nb\nc\n'], b'file-id')
 
1595
        preview_tree = preview.get_preview_tree()
 
1596
        self.assertEqual('file', preview_tree.stored_kind('file'))
 
1597
 
 
1598
    def test_is_executable(self):
 
1599
        preview = self.get_empty_preview()
 
1600
        preview.new_file('file', preview.root, [b'a\nb\nc\n'], b'file-id')
 
1601
        preview.set_executability(True, preview.trans_id_file_id(b'file-id'))
 
1602
        preview_tree = preview.get_preview_tree()
 
1603
        self.assertEqual(True, preview_tree.is_executable('file'))
 
1604
 
 
1605
    def test_get_set_parent_ids(self):
 
1606
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
 
1607
        self.assertEqual([], preview_tree.get_parent_ids())
 
1608
        preview_tree.set_parent_ids([b'rev-1'])
 
1609
        self.assertEqual([b'rev-1'], preview_tree.get_parent_ids())
 
1610
 
 
1611
    def test_plan_file_merge(self):
 
1612
        work_a = self.make_branch_and_tree('wta')
 
1613
        self.build_tree_contents([('wta/file', b'a\nb\nc\nd\n')])
 
1614
        work_a.add('file', b'file-id')
 
1615
        base_id = work_a.commit('base version')
 
1616
        tree_b = work_a.controldir.sprout('wtb').open_workingtree()
 
1617
        preview = work_a.preview_transform()
 
1618
        self.addCleanup(preview.finalize)
 
1619
        trans_id = preview.trans_id_file_id(b'file-id')
 
1620
        preview.delete_contents(trans_id)
 
1621
        preview.create_file([b'b\nc\nd\ne\n'], trans_id)
 
1622
        self.build_tree_contents([('wtb/file', b'a\nc\nd\nf\n')])
 
1623
        tree_a = preview.get_preview_tree()
 
1624
        tree_a.set_parent_ids([base_id])
 
1625
        self.assertEqual([
 
1626
            ('killed-a', b'a\n'),
 
1627
            ('killed-b', b'b\n'),
 
1628
            ('unchanged', b'c\n'),
 
1629
            ('unchanged', b'd\n'),
 
1630
            ('new-a', b'e\n'),
 
1631
            ('new-b', b'f\n'),
 
1632
        ], list(tree_a.plan_file_merge('file', tree_b)))
 
1633
 
 
1634
    def test_plan_file_merge_revision_tree(self):
 
1635
        work_a = self.make_branch_and_tree('wta')
 
1636
        self.build_tree_contents([('wta/file', b'a\nb\nc\nd\n')])
 
1637
        work_a.add('file', b'file-id')
 
1638
        base_id = work_a.commit('base version')
 
1639
        tree_b = work_a.controldir.sprout('wtb').open_workingtree()
 
1640
        preview = work_a.basis_tree().preview_transform()
 
1641
        self.addCleanup(preview.finalize)
 
1642
        trans_id = preview.trans_id_file_id(b'file-id')
 
1643
        preview.delete_contents(trans_id)
 
1644
        preview.create_file([b'b\nc\nd\ne\n'], trans_id)
 
1645
        self.build_tree_contents([('wtb/file', b'a\nc\nd\nf\n')])
 
1646
        tree_a = preview.get_preview_tree()
 
1647
        tree_a.set_parent_ids([base_id])
 
1648
        self.assertEqual([
 
1649
            ('killed-a', b'a\n'),
 
1650
            ('killed-b', b'b\n'),
 
1651
            ('unchanged', b'c\n'),
 
1652
            ('unchanged', b'd\n'),
 
1653
            ('new-a', b'e\n'),
 
1654
            ('new-b', b'f\n'),
 
1655
        ], list(tree_a.plan_file_merge('file', tree_b)))
 
1656
 
 
1657
    def test_walkdirs(self):
 
1658
        preview = self.get_empty_preview()
 
1659
        preview.new_directory('', ROOT_PARENT, b'tree-root')
 
1660
        # FIXME: new_directory should mark root.
 
1661
        preview.fixup_new_roots()
 
1662
        preview_tree = preview.get_preview_tree()
 
1663
        preview.new_file('a', preview.root, [b'contents'], b'a-id')
 
1664
        expected = [(('', b'tree-root'),
 
1665
                     [('a', 'a', 'file', None, b'a-id', 'file')])]
 
1666
        self.assertEqual(expected, list(preview_tree.walkdirs()))
 
1667
 
 
1668
    def test_extras(self):
 
1669
        work_tree = self.make_branch_and_tree('tree')
 
1670
        self.build_tree(['tree/removed-file', 'tree/existing-file',
 
1671
                         'tree/not-removed-file'])
 
1672
        work_tree.add(['removed-file', 'not-removed-file'])
 
1673
        preview = work_tree.preview_transform()
 
1674
        self.addCleanup(preview.finalize)
 
1675
        preview.new_file('new-file', preview.root, [b'contents'])
 
1676
        preview.new_file('new-versioned-file', preview.root, [b'contents'],
 
1677
                         b'new-versioned-id')
 
1678
        tree = preview.get_preview_tree()
 
1679
        preview.unversion_file(preview.trans_id_tree_path('removed-file'))
 
1680
        self.assertEqual({'new-file', 'removed-file', 'existing-file'},
 
1681
                         set(tree.extras()))
 
1682
 
 
1683
    def test_merge_into_preview(self):
 
1684
        work_tree = self.make_branch_and_tree('tree')
 
1685
        self.build_tree_contents([('tree/file', b'b\n')])
 
1686
        work_tree.add('file', b'file-id')
 
1687
        work_tree.commit('first commit')
 
1688
        child_tree = work_tree.controldir.sprout('child').open_workingtree()
 
1689
        self.build_tree_contents([('child/file', b'b\nc\n')])
 
1690
        child_tree.commit('child commit')
 
1691
        child_tree.lock_write()
 
1692
        self.addCleanup(child_tree.unlock)
 
1693
        work_tree.lock_write()
 
1694
        self.addCleanup(work_tree.unlock)
 
1695
        preview = work_tree.preview_transform()
 
1696
        self.addCleanup(preview.finalize)
 
1697
        file_trans_id = preview.trans_id_file_id(b'file-id')
 
1698
        preview.delete_contents(file_trans_id)
 
1699
        preview.create_file([b'a\nb\n'], file_trans_id)
 
1700
        preview_tree = preview.get_preview_tree()
 
1701
        merger = Merger.from_revision_ids(preview_tree,
 
1702
                                          child_tree.branch.last_revision(),
 
1703
                                          other_branch=child_tree.branch,
 
1704
                                          tree_branch=work_tree.branch)
 
1705
        merger.merge_type = Merge3Merger
 
1706
        tt = merger.make_merger().make_preview_transform()
 
1707
        self.addCleanup(tt.finalize)
 
1708
        final_tree = tt.get_preview_tree()
 
1709
        self.assertEqual(
 
1710
            b'a\nb\nc\n',
 
1711
            final_tree.get_file_text(final_tree.id2path(b'file-id')))
 
1712
 
 
1713
    def test_merge_preview_into_workingtree(self):
 
1714
        tree = self.make_branch_and_tree('tree')
 
1715
        tree.set_root_id(b'TREE_ROOT')
 
1716
        tt = tree.preview_transform()
 
1717
        self.addCleanup(tt.finalize)
 
1718
        tt.new_file('name', tt.root, [b'content'], b'file-id')
 
1719
        tree2 = self.make_branch_and_tree('tree2')
 
1720
        tree2.set_root_id(b'TREE_ROOT')
 
1721
        merger = Merger.from_uncommitted(tree2, tt.get_preview_tree(),
 
1722
                                         tree.basis_tree())
 
1723
        merger.merge_type = Merge3Merger
 
1724
        merger.do_merge()
 
1725
 
 
1726
    def test_merge_preview_into_workingtree_handles_conflicts(self):
 
1727
        tree = self.make_branch_and_tree('tree')
 
1728
        self.build_tree_contents([('tree/foo', b'bar')])
 
1729
        tree.add('foo', b'foo-id')
 
1730
        tree.commit('foo')
 
1731
        tt = tree.preview_transform()
 
1732
        self.addCleanup(tt.finalize)
 
1733
        trans_id = tt.trans_id_file_id(b'foo-id')
 
1734
        tt.delete_contents(trans_id)
 
1735
        tt.create_file([b'baz'], trans_id)
 
1736
        tree2 = tree.controldir.sprout('tree2').open_workingtree()
 
1737
        self.build_tree_contents([('tree2/foo', b'qux')])
 
1738
        merger = Merger.from_uncommitted(tree2, tt.get_preview_tree(),
 
1739
                                         tree.basis_tree())
 
1740
        merger.merge_type = Merge3Merger
 
1741
        merger.do_merge()
 
1742
 
 
1743
    def test_has_filename(self):
 
1744
        wt = self.make_branch_and_tree('tree')
 
1745
        self.build_tree(['tree/unmodified', 'tree/removed', 'tree/modified'])
 
1746
        tt = wt.preview_transform()
 
1747
        removed_id = tt.trans_id_tree_path('removed')
 
1748
        tt.delete_contents(removed_id)
 
1749
        tt.new_file('new', tt.root, [b'contents'])
 
1750
        modified_id = tt.trans_id_tree_path('modified')
 
1751
        tt.delete_contents(modified_id)
 
1752
        tt.create_file([b'modified-contents'], modified_id)
 
1753
        self.addCleanup(tt.finalize)
 
1754
        tree = tt.get_preview_tree()
 
1755
        self.assertTrue(tree.has_filename('unmodified'))
 
1756
        self.assertFalse(tree.has_filename('not-present'))
 
1757
        self.assertFalse(tree.has_filename('removed'))
 
1758
        self.assertTrue(tree.has_filename('new'))
 
1759
        self.assertTrue(tree.has_filename('modified'))
 
1760
 
 
1761
    def test_is_executable(self):
 
1762
        tree = self.make_branch_and_tree('tree')
 
1763
        preview = tree.preview_transform()
 
1764
        self.addCleanup(preview.finalize)
 
1765
        preview.new_file('foo', preview.root, [b'bar'], b'baz-id')
 
1766
        preview_tree = preview.get_preview_tree()
 
1767
        self.assertEqual(False, preview_tree.is_executable('tree/foo'))
 
1768
 
 
1769
    def test_commit_preview_tree(self):
 
1770
        tree = self.make_branch_and_tree('tree')
 
1771
        rev_id = tree.commit('rev1')
 
1772
        tree.branch.lock_write()
 
1773
        self.addCleanup(tree.branch.unlock)
 
1774
        tt = tree.preview_transform()
 
1775
        tt.new_file('file', tt.root, [b'contents'], b'file_id')
 
1776
        self.addCleanup(tt.finalize)
 
1777
        preview = tt.get_preview_tree()
 
1778
        preview.set_parent_ids([rev_id])
 
1779
        builder = tree.branch.get_commit_builder([rev_id])
 
1780
        list(builder.record_iter_changes(preview, rev_id, tt.iter_changes()))
 
1781
        builder.finish_inventory()
 
1782
        rev2_id = builder.commit('rev2')
 
1783
        rev2_tree = tree.branch.repository.revision_tree(rev2_id)
 
1784
        self.assertEqual(b'contents', rev2_tree.get_file_text('file'))
 
1785
 
 
1786
    def test_ascii_limbo_paths(self):
 
1787
        self.requireFeature(features.UnicodeFilenameFeature)
 
1788
        branch = self.make_branch('any')
 
1789
        tree = branch.repository.revision_tree(_mod_revision.NULL_REVISION)
 
1790
        tt = tree.preview_transform()
 
1791
        self.addCleanup(tt.finalize)
 
1792
        foo_id = tt.new_directory('', ROOT_PARENT)
 
1793
        bar_id = tt.new_file(u'\u1234bar', foo_id, [b'contents'])
 
1794
        limbo_path = tt._limbo_name(bar_id)
 
1795
        self.assertEqual(limbo_path, limbo_path)
 
1796
 
 
1797
 
1121
1798
class FakeSerializer(object):
1122
1799
    """Serializer implementation that simply returns the input.
1123
1800