/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-08-10 15:00:17 UTC
  • mfrom: (7490.40.99 work)
  • mto: This revision was merged to the branch mainline in revision 7521.
  • Revision ID: jelmer@jelmer.uk-20200810150017-vs7xnrd1vat4iktg
Merge lp:brz/3.1.

Show diffs side-by-side

added added

removed removed

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