/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 bzrlib/tests/test_transform.py

  • Committer: Robert Collins
  • Date: 2008-02-13 03:30:01 UTC
  • mfrom: (3221 +trunk)
  • mto: This revision was merged to the branch mainline in revision 3224.
  • Revision ID: robertc@robertcollins.net-20080213033001-rw70ul0zb02ph856
Merge to fix conflicts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
import os
18
18
import stat
 
19
from StringIO import StringIO
19
20
import sys
20
21
 
21
22
from bzrlib import (
22
23
    errors,
23
24
    generate_ids,
 
25
    osutils,
 
26
    progress,
 
27
    revision as _mod_revision,
24
28
    symbol_versioning,
25
29
    tests,
26
30
    urlutils,
27
31
    )
28
32
from bzrlib.bzrdir import BzrDir
29
33
from bzrlib.conflicts import (DuplicateEntry, DuplicateID, MissingParent,
30
 
                              UnversionedParent, ParentLoop, DeletingParent,)
 
34
                              UnversionedParent, ParentLoop, DeletingParent,
 
35
                              NonDirectoryParent)
 
36
from bzrlib.diff import show_diff_trees
31
37
from bzrlib.errors import (DuplicateKey, MalformedTransform, NoSuchFile,
32
38
                           ReusingTransform, CantMoveRoot, 
33
39
                           PathsNotVersionedError, ExistingLimbo,
36
42
from bzrlib.osutils import file_kind, pathjoin
37
43
from bzrlib.merge import Merge3Merger
38
44
from bzrlib.tests import (
 
45
    CaseInsensitiveFilesystemFeature,
39
46
    SymlinkFeature,
40
47
    TestCase,
41
48
    TestCaseInTempDir,
44
51
from bzrlib.transform import (TreeTransform, ROOT_PARENT, FinalPaths, 
45
52
                              resolve_conflicts, cook_conflicts, 
46
53
                              find_interesting, build_tree, get_backup_name,
47
 
                              change_entry, _FileMover)
48
 
 
 
54
                              change_entry, _FileMover, resolve_checkout,
 
55
                              TransformPreview)
49
56
 
50
57
class TestTreeTransform(tests.TestCaseWithTransport):
51
58
 
84
91
        self.assertRaises(ExistingPendingDeletion, self.get_transform)
85
92
 
86
93
    def test_build(self):
87
 
        transform, root = self.get_transform() 
 
94
        transform, root = self.get_transform()
 
95
        self.wt.lock_tree_write()
 
96
        self.addCleanup(self.wt.unlock)
88
97
        self.assertIs(transform.get_tree_parent(root), ROOT_PARENT)
89
98
        imaginary_id = transform.trans_id_tree_path('imaginary')
90
99
        imaginary_id2 = transform.trans_id_tree_path('imaginary/')
127
136
 
128
137
    def test_convenience(self):
129
138
        transform, root = self.get_transform()
 
139
        self.wt.lock_tree_write()
 
140
        self.addCleanup(self.wt.unlock)
130
141
        trans_id = transform.new_file('name', root, 'contents', 
131
142
                                      'my_pretties', True)
132
143
        oz = transform.new_directory('oz', root, 'oz-id')
233
244
        transform3.adjust_path('tip', root_id, tip_id)
234
245
        transform3.apply()
235
246
 
 
247
    def test_conflict_on_case_insensitive(self):
 
248
        tree = self.make_branch_and_tree('tree')
 
249
        # Don't try this at home, kids!
 
250
        # Force the tree to report that it is case sensitive, for conflict
 
251
        # resolution tests
 
252
        tree.case_sensitive = True
 
253
        transform = TreeTransform(tree)
 
254
        self.addCleanup(transform.finalize)
 
255
        transform.new_file('file', transform.root, 'content')
 
256
        transform.new_file('FiLe', transform.root, 'content')
 
257
        result = transform.find_conflicts()
 
258
        self.assertEqual([], result)
 
259
        transform.finalize()
 
260
        # Force the tree to report that it is case insensitive, for conflict
 
261
        # generation tests
 
262
        tree.case_sensitive = False
 
263
        transform = TreeTransform(tree)
 
264
        self.addCleanup(transform.finalize)
 
265
        transform.new_file('file', transform.root, 'content')
 
266
        transform.new_file('FiLe', transform.root, 'content')
 
267
        result = transform.find_conflicts()
 
268
        self.assertEqual([('duplicate', 'new-1', 'new-2', 'file')], result)
 
269
 
 
270
    def test_conflict_on_case_insensitive_existing(self):
 
271
        tree = self.make_branch_and_tree('tree')
 
272
        self.build_tree(['tree/FiLe'])
 
273
        # Don't try this at home, kids!
 
274
        # Force the tree to report that it is case sensitive, for conflict
 
275
        # resolution tests
 
276
        tree.case_sensitive = True
 
277
        transform = TreeTransform(tree)
 
278
        self.addCleanup(transform.finalize)
 
279
        transform.new_file('file', transform.root, 'content')
 
280
        result = transform.find_conflicts()
 
281
        self.assertEqual([], result)
 
282
        transform.finalize()
 
283
        # Force the tree to report that it is case insensitive, for conflict
 
284
        # generation tests
 
285
        tree.case_sensitive = False
 
286
        transform = TreeTransform(tree)
 
287
        self.addCleanup(transform.finalize)
 
288
        transform.new_file('file', transform.root, 'content')
 
289
        result = transform.find_conflicts()
 
290
        self.assertEqual([('duplicate', 'new-1', 'new-2', 'file')], result)
 
291
 
 
292
    def test_resolve_case_insensitive_conflict(self):
 
293
        tree = self.make_branch_and_tree('tree')
 
294
        # Don't try this at home, kids!
 
295
        # Force the tree to report that it is case insensitive, for conflict
 
296
        # resolution tests
 
297
        tree.case_sensitive = False
 
298
        transform = TreeTransform(tree)
 
299
        self.addCleanup(transform.finalize)
 
300
        transform.new_file('file', transform.root, 'content')
 
301
        transform.new_file('FiLe', transform.root, 'content')
 
302
        resolve_conflicts(transform)
 
303
        transform.apply()
 
304
        self.failUnlessExists('tree/file')
 
305
        self.failUnlessExists('tree/FiLe.moved')
 
306
 
 
307
    def test_resolve_checkout_case_conflict(self):
 
308
        tree = self.make_branch_and_tree('tree')
 
309
        # Don't try this at home, kids!
 
310
        # Force the tree to report that it is case insensitive, for conflict
 
311
        # resolution tests
 
312
        tree.case_sensitive = False
 
313
        transform = TreeTransform(tree)
 
314
        self.addCleanup(transform.finalize)
 
315
        transform.new_file('file', transform.root, 'content')
 
316
        transform.new_file('FiLe', transform.root, 'content')
 
317
        resolve_conflicts(transform,
 
318
                          pass_func=lambda t, c: resolve_checkout(t, c, []))
 
319
        transform.apply()
 
320
        self.failUnlessExists('tree/file')
 
321
        self.failUnlessExists('tree/FiLe.moved')
 
322
 
 
323
    def test_apply_case_conflict(self):
 
324
        """Ensure that a transform with case conflicts can always be applied"""
 
325
        tree = self.make_branch_and_tree('tree')
 
326
        transform = TreeTransform(tree)
 
327
        self.addCleanup(transform.finalize)
 
328
        transform.new_file('file', transform.root, 'content')
 
329
        transform.new_file('FiLe', transform.root, 'content')
 
330
        dir = transform.new_directory('dir', transform.root)
 
331
        transform.new_file('dirfile', dir, 'content')
 
332
        transform.new_file('dirFiLe', dir, 'content')
 
333
        resolve_conflicts(transform)
 
334
        transform.apply()
 
335
        self.failUnlessExists('tree/file')
 
336
        if not os.path.exists('tree/FiLe.moved'):
 
337
            self.failUnlessExists('tree/FiLe')
 
338
        self.failUnlessExists('tree/dir/dirfile')
 
339
        if not os.path.exists('tree/dir/dirFiLe.moved'):
 
340
            self.failUnlessExists('tree/dir/dirFiLe')
 
341
 
 
342
    def test_case_insensitive_limbo(self):
 
343
        tree = self.make_branch_and_tree('tree')
 
344
        # Don't try this at home, kids!
 
345
        # Force the tree to report that it is case insensitive
 
346
        tree.case_sensitive = False
 
347
        transform = TreeTransform(tree)
 
348
        self.addCleanup(transform.finalize)
 
349
        dir = transform.new_directory('dir', transform.root)
 
350
        first = transform.new_file('file', dir, 'content')
 
351
        second = transform.new_file('FiLe', dir, 'content')
 
352
        self.assertContainsRe(transform._limbo_name(first), 'new-1/file')
 
353
        self.assertNotContainsRe(transform._limbo_name(second), 'new-1/FiLe')
 
354
 
236
355
    def test_add_del(self):
237
356
        start, root = self.get_transform()
238
357
        start.new_directory('a', root, 'a')
410
529
        self.assertEqual(os.readlink(self.wt.abspath('oz/wizard')),
411
530
                         'wizard-target')
412
531
 
 
532
    def test_unable_create_symlink(self):
 
533
        def tt_helper():
 
534
            wt = self.make_branch_and_tree('.')
 
535
            tt = TreeTransform(wt)  # TreeTransform obtains write lock
 
536
            try:
 
537
                tt.new_symlink('foo', tt.root, 'bar')
 
538
                tt.apply()
 
539
            finally:
 
540
                wt.unlock()
 
541
        os_symlink = getattr(os, 'symlink', None)
 
542
        os.symlink = None
 
543
        try:
 
544
            err = self.assertRaises(errors.UnableCreateSymlink, tt_helper)
 
545
            self.assertEquals(
 
546
                "Unable to create symlink 'foo' on this platform",
 
547
                str(err))
 
548
        finally:
 
549
            if os_symlink:
 
550
                os.symlink = os_symlink
 
551
 
413
552
    def get_conflicted(self):
414
553
        create,root = self.get_transform()
415
554
        create.new_file('dorothy', root, 'dorothy', 'dorothy-id')
499
638
        self.assertEqual(conflicts_s[6], 'Conflict moving oz/emeraldcity into'
500
639
                                         ' oz/emeraldcity.  Cancelled move.')
501
640
 
 
641
    def prepare_wrong_parent_kind(self):
 
642
        tt, root = self.get_transform()
 
643
        tt.new_file('parent', root, 'contents', 'parent-id')
 
644
        tt.apply()
 
645
        tt, root = self.get_transform()
 
646
        parent_id = tt.trans_id_file_id('parent-id')
 
647
        tt.new_file('child,', parent_id, 'contents2', 'file-id')
 
648
        return tt
 
649
 
 
650
    def test_find_conflicts_wrong_parent_kind(self):
 
651
        tt = self.prepare_wrong_parent_kind()
 
652
        tt.find_conflicts()
 
653
 
 
654
    def test_resolve_conflicts_wrong_existing_parent_kind(self):
 
655
        tt = self.prepare_wrong_parent_kind()
 
656
        raw_conflicts = resolve_conflicts(tt)
 
657
        self.assertEqual(set([('non-directory parent', 'Created directory',
 
658
                         'new-3')]), raw_conflicts)
 
659
        cooked_conflicts = cook_conflicts(raw_conflicts, tt)
 
660
        self.assertEqual([NonDirectoryParent('Created directory', 'parent.new',
 
661
        'parent-id')], cooked_conflicts)
 
662
        tt.apply()
 
663
        self.assertEqual(None, self.wt.path2id('parent'))
 
664
        self.assertEqual('parent-id', self.wt.path2id('parent.new'))
 
665
 
 
666
    def test_resolve_conflicts_wrong_new_parent_kind(self):
 
667
        tt, root = self.get_transform()
 
668
        parent_id = tt.new_directory('parent', root, 'parent-id')
 
669
        tt.new_file('child,', parent_id, 'contents2', 'file-id')
 
670
        tt.apply()
 
671
        tt, root = self.get_transform()
 
672
        parent_id = tt.trans_id_file_id('parent-id')
 
673
        tt.delete_contents(parent_id)
 
674
        tt.create_file('contents', parent_id)
 
675
        raw_conflicts = resolve_conflicts(tt)
 
676
        self.assertEqual(set([('non-directory parent', 'Created directory',
 
677
                         'new-3')]), raw_conflicts)
 
678
        tt.apply()
 
679
        self.assertEqual(None, self.wt.path2id('parent'))
 
680
        self.assertEqual('parent-id', self.wt.path2id('parent.new'))
 
681
 
 
682
    def test_resolve_conflicts_wrong_parent_kind_unversioned(self):
 
683
        tt, root = self.get_transform()
 
684
        parent_id = tt.new_directory('parent', root)
 
685
        tt.new_file('child,', parent_id, 'contents2')
 
686
        tt.apply()
 
687
        tt, root = self.get_transform()
 
688
        parent_id = tt.trans_id_tree_path('parent')
 
689
        tt.delete_contents(parent_id)
 
690
        tt.create_file('contents', parent_id)
 
691
        resolve_conflicts(tt)
 
692
        tt.apply()
 
693
        self.assertIs(None, self.wt.path2id('parent'))
 
694
        self.assertIs(None, self.wt.path2id('parent.new'))
 
695
 
502
696
    def test_moving_versioned_directories(self):
503
697
        create, root = self.get_transform()
504
698
        kansas = create.new_directory('kansas', root, 'kansas-id')
558
752
        """
559
753
        transform, root = self.get_transform()
560
754
        wt = transform._tree
 
755
        wt.lock_read()
 
756
        self.addCleanup(wt.unlock)
561
757
        transform.new_file('set_on_creation', root, 'Set on creation', 'soc',
562
758
                           True)
563
759
        sac = transform.new_file('set_after_creation', root,
577
773
        transform, root = self.get_transform()
578
774
        transform.new_file('file1', root, 'contents', 'file1-id', True)
579
775
        transform.apply()
 
776
        self.wt.lock_write()
 
777
        self.addCleanup(self.wt.unlock)
580
778
        self.assertTrue(self.wt.is_executable('file1-id'))
581
779
        transform, root = self.get_transform()
582
780
        file1_id = transform.trans_id_tree_file_id('file1-id')
963
1161
        self.callDeprecated([txt], change_entry, None, None, None, None, None,
964
1162
            None, None, None)
965
1163
 
 
1164
    def test_case_insensitive_clash(self):
 
1165
        self.requireFeature(CaseInsensitiveFilesystemFeature)
 
1166
        def tt_helper():
 
1167
            wt = self.make_branch_and_tree('.')
 
1168
            tt = TreeTransform(wt)  # TreeTransform obtains write lock
 
1169
            try:
 
1170
                tt.new_file('foo', tt.root, 'bar')
 
1171
                tt.new_file('Foo', tt.root, 'spam')
 
1172
                # Lie to tt that we've already resolved all conflicts.
 
1173
                tt.apply(no_conflicts=True)
 
1174
            except:
 
1175
                wt.unlock()
 
1176
                raise
 
1177
        err = self.assertRaises(errors.FileExists, tt_helper)
 
1178
        self.assertContainsRe(str(err),
 
1179
            "^File exists: .+/foo")
 
1180
 
 
1181
    def test_two_directories_clash(self):
 
1182
        def tt_helper():
 
1183
            wt = self.make_branch_and_tree('.')
 
1184
            tt = TreeTransform(wt)  # TreeTransform obtains write lock
 
1185
            try:
 
1186
                foo_1 = tt.new_directory('foo', tt.root)
 
1187
                tt.new_directory('bar', foo_1)
 
1188
                foo_2 = tt.new_directory('foo', tt.root)
 
1189
                tt.new_directory('baz', foo_2)
 
1190
                # Lie to tt that we've already resolved all conflicts.
 
1191
                tt.apply(no_conflicts=True)
 
1192
            except:
 
1193
                wt.unlock()
 
1194
                raise
 
1195
        err = self.assertRaises(errors.FileExists, tt_helper)
 
1196
        self.assertContainsRe(str(err),
 
1197
            "^File exists: .+/foo")
 
1198
 
 
1199
    def test_two_directories_clash_finalize(self):
 
1200
        def tt_helper():
 
1201
            wt = self.make_branch_and_tree('.')
 
1202
            tt = TreeTransform(wt)  # TreeTransform obtains write lock
 
1203
            try:
 
1204
                foo_1 = tt.new_directory('foo', tt.root)
 
1205
                tt.new_directory('bar', foo_1)
 
1206
                foo_2 = tt.new_directory('foo', tt.root)
 
1207
                tt.new_directory('baz', foo_2)
 
1208
                # Lie to tt that we've already resolved all conflicts.
 
1209
                tt.apply(no_conflicts=True)
 
1210
            except:
 
1211
                tt.finalize()
 
1212
                raise
 
1213
        err = self.assertRaises(errors.FileExists, tt_helper)
 
1214
        self.assertContainsRe(str(err),
 
1215
            "^File exists: .+/foo")
 
1216
 
966
1217
 
967
1218
class TransformGroup(object):
 
1219
 
968
1220
    def __init__(self, dirname, root_id):
969
1221
        self.name = dirname
970
1222
        os.mkdir(dirname)
981
1233
 
982
1234
 
983
1235
class TestTransformMerge(TestCaseInTempDir):
 
1236
 
984
1237
    def test_text_merge(self):
985
1238
        root_id = generate_ids.gen_root_id()
986
1239
        base = TransformGroup("base", root_id)
1016
1269
        this.tt.new_file('i', this.root, '1\n2\n3\n4\n', 'i')
1017
1270
        this.tt.apply()
1018
1271
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
 
1272
 
1019
1273
        # textual merge
1020
1274
        self.assertEqual(this.wt.get_file('a').read(), 'y\nb\nc\nd\bz\n')
1021
1275
        # three-way text conflict
1167
1421
 
1168
1422
class TestBuildTree(tests.TestCaseWithTransport):
1169
1423
 
1170
 
    def test_build_tree(self):
 
1424
    def test_build_tree_with_symlinks(self):
1171
1425
        self.requireFeature(SymlinkFeature)
1172
1426
        os.mkdir('a')
1173
1427
        a = BzrDir.create_standalone_workingtree('a')
1319
1573
        # children of non-root directories should not be renamed
1320
1574
        self.assertEqual(2, transform_result.rename_count)
1321
1575
 
 
1576
    def test_build_tree_accelerator_tree(self):
 
1577
        source = self.make_branch_and_tree('source')
 
1578
        self.build_tree_contents([('source/file1', 'A')])
 
1579
        self.build_tree_contents([('source/file2', 'B')])
 
1580
        source.add(['file1', 'file2'], ['file1-id', 'file2-id'])
 
1581
        source.commit('commit files')
 
1582
        self.build_tree_contents([('source/file2', 'C')])
 
1583
        calls = []
 
1584
        real_source_get_file = source.get_file
 
1585
        def get_file(file_id, path=None):
 
1586
            calls.append(file_id)
 
1587
            return real_source_get_file(file_id, path)
 
1588
        source.get_file = get_file
 
1589
        source.lock_read()
 
1590
        self.addCleanup(source.unlock)
 
1591
        target = self.make_branch_and_tree('target')
 
1592
        revision_tree = source.basis_tree()
 
1593
        revision_tree.lock_read()
 
1594
        self.addCleanup(revision_tree.unlock)
 
1595
        build_tree(revision_tree, target, source)
 
1596
        self.assertEqual(['file1-id'], calls)
 
1597
        target.lock_read()
 
1598
        self.addCleanup(target.unlock)
 
1599
        self.assertEqual([], list(target._iter_changes(revision_tree)))
 
1600
 
 
1601
    def test_build_tree_accelerator_tree_missing_file(self):
 
1602
        source = self.make_branch_and_tree('source')
 
1603
        self.build_tree_contents([('source/file1', 'A')])
 
1604
        self.build_tree_contents([('source/file2', 'B')])
 
1605
        source.add(['file1', 'file2'])
 
1606
        source.commit('commit files')
 
1607
        os.unlink('source/file1')
 
1608
        source.remove(['file2'])
 
1609
        target = self.make_branch_and_tree('target')
 
1610
        revision_tree = source.basis_tree()
 
1611
        revision_tree.lock_read()
 
1612
        self.addCleanup(revision_tree.unlock)
 
1613
        build_tree(revision_tree, target, source)
 
1614
        target.lock_read()
 
1615
        self.addCleanup(target.unlock)
 
1616
        self.assertEqual([], list(target._iter_changes(revision_tree)))
 
1617
 
 
1618
    def test_build_tree_accelerator_wrong_kind(self):
 
1619
        self.requireFeature(SymlinkFeature)
 
1620
        source = self.make_branch_and_tree('source')
 
1621
        self.build_tree_contents([('source/file1', '')])
 
1622
        self.build_tree_contents([('source/file2', '')])
 
1623
        source.add(['file1', 'file2'], ['file1-id', 'file2-id'])
 
1624
        source.commit('commit files')
 
1625
        os.unlink('source/file2')
 
1626
        self.build_tree_contents([('source/file2/', 'C')])
 
1627
        os.unlink('source/file1')
 
1628
        os.symlink('file2', 'source/file1')
 
1629
        calls = []
 
1630
        real_source_get_file = source.get_file
 
1631
        def get_file(file_id, path=None):
 
1632
            calls.append(file_id)
 
1633
            return real_source_get_file(file_id, path)
 
1634
        source.get_file = get_file
 
1635
        source.lock_read()
 
1636
        self.addCleanup(source.unlock)
 
1637
        target = self.make_branch_and_tree('target')
 
1638
        revision_tree = source.basis_tree()
 
1639
        revision_tree.lock_read()
 
1640
        self.addCleanup(revision_tree.unlock)
 
1641
        build_tree(revision_tree, target, source)
 
1642
        self.assertEqual([], calls)
 
1643
        target.lock_read()
 
1644
        self.addCleanup(target.unlock)
 
1645
        self.assertEqual([], list(target._iter_changes(revision_tree)))
 
1646
 
 
1647
    def test_build_tree_accelerator_tree_moved(self):
 
1648
        source = self.make_branch_and_tree('source')
 
1649
        self.build_tree_contents([('source/file1', 'A')])
 
1650
        source.add(['file1'], ['file1-id'])
 
1651
        source.commit('commit files')
 
1652
        source.rename_one('file1', 'file2')
 
1653
        source.lock_read()
 
1654
        self.addCleanup(source.unlock)
 
1655
        target = self.make_branch_and_tree('target')
 
1656
        revision_tree = source.basis_tree()
 
1657
        revision_tree.lock_read()
 
1658
        self.addCleanup(revision_tree.unlock)
 
1659
        build_tree(revision_tree, target, source)
 
1660
        target.lock_read()
 
1661
        self.addCleanup(target.unlock)
 
1662
        self.assertEqual([], list(target._iter_changes(revision_tree)))
 
1663
 
1322
1664
 
1323
1665
class MockTransform(object):
1324
1666
 
1337
1679
        object.__init__(self)
1338
1680
        self.name = "name"
1339
1681
 
 
1682
 
1340
1683
class TestGetBackupName(TestCase):
1341
1684
    def test_get_backup_name(self):
1342
1685
        tt = MockTransform()
1396
1739
        mover.rename('c/e', 'c/d')
1397
1740
        try:
1398
1741
            mover.rename('a', 'c')
1399
 
        except OSError, e:
 
1742
        except errors.FileExists, e:
1400
1743
            mover.rollback()
1401
1744
        self.failUnlessExists('a')
1402
1745
        self.failUnlessExists('c/d')
1469
1812
                          _mover=self.ExceptionFileMover(bad_target='d'))
1470
1813
        self.failUnlessExists('a')
1471
1814
        self.failUnlessExists('a/b')
 
1815
 
 
1816
    def test_resolve_no_parent(self):
 
1817
        wt = self.make_branch_and_tree('.')
 
1818
        tt = TreeTransform(wt)
 
1819
        self.addCleanup(tt.finalize)
 
1820
        parent = tt.trans_id_file_id('parent-id')
 
1821
        tt.new_file('file', parent, 'Contents')
 
1822
        resolve_conflicts(tt)
 
1823
 
 
1824
 
 
1825
class TestTransformPreview(tests.TestCaseWithTransport):
 
1826
 
 
1827
    def create_tree(self):
 
1828
        tree = self.make_branch_and_tree('.')
 
1829
        self.build_tree_contents([('a', 'content 1')])
 
1830
        tree.add('a', 'a-id')
 
1831
        tree.commit('rev1', rev_id='rev1')
 
1832
        return tree.branch.repository.revision_tree('rev1')
 
1833
 
 
1834
    def get_empty_preview(self):
 
1835
        repository = self.make_repository('repo')
 
1836
        tree = repository.revision_tree(_mod_revision.NULL_REVISION)
 
1837
        preview = TransformPreview(tree)
 
1838
        self.addCleanup(preview.finalize)
 
1839
        return preview
 
1840
 
 
1841
    def test_transform_preview(self):
 
1842
        revision_tree = self.create_tree()
 
1843
        preview = TransformPreview(revision_tree)
 
1844
        self.addCleanup(preview.finalize)
 
1845
 
 
1846
    def test_transform_preview_tree(self):
 
1847
        revision_tree = self.create_tree()
 
1848
        preview = TransformPreview(revision_tree)
 
1849
        self.addCleanup(preview.finalize)
 
1850
        preview.get_preview_tree()
 
1851
 
 
1852
    def test_transform_new_file(self):
 
1853
        revision_tree = self.create_tree()
 
1854
        preview = TransformPreview(revision_tree)
 
1855
        self.addCleanup(preview.finalize)
 
1856
        preview.new_file('file2', preview.root, 'content B\n', 'file2-id')
 
1857
        preview_tree = preview.get_preview_tree()
 
1858
        self.assertEqual(preview_tree.kind('file2-id'), 'file')
 
1859
        self.assertEqual(
 
1860
            preview_tree.get_file('file2-id').read(), 'content B\n')
 
1861
 
 
1862
    def test_diff_preview_tree(self):
 
1863
        revision_tree = self.create_tree()
 
1864
        preview = TransformPreview(revision_tree)
 
1865
        self.addCleanup(preview.finalize)
 
1866
        preview.new_file('file2', preview.root, 'content B\n', 'file2-id')
 
1867
        preview_tree = preview.get_preview_tree()
 
1868
        out = StringIO()
 
1869
        show_diff_trees(revision_tree, preview_tree, out)
 
1870
        lines = out.getvalue().splitlines()
 
1871
        self.assertEqual(lines[0], "=== added file 'file2'")
 
1872
        # 3 lines of diff administrivia
 
1873
        self.assertEqual(lines[4], "+content B")
 
1874
 
 
1875
    def test_transform_conflicts(self):
 
1876
        revision_tree = self.create_tree()
 
1877
        preview = TransformPreview(revision_tree)
 
1878
        self.addCleanup(preview.finalize)
 
1879
        preview.new_file('a', preview.root, 'content 2')
 
1880
        resolve_conflicts(preview)
 
1881
        trans_id = preview.trans_id_file_id('a-id')
 
1882
        self.assertEqual('a.moved', preview.final_name(trans_id))
 
1883
 
 
1884
    def get_tree_and_preview_tree(self):
 
1885
        revision_tree = self.create_tree()
 
1886
        preview = TransformPreview(revision_tree)
 
1887
        self.addCleanup(preview.finalize)
 
1888
        a_trans_id = preview.trans_id_file_id('a-id')
 
1889
        preview.delete_contents(a_trans_id)
 
1890
        preview.create_file('b content', a_trans_id)
 
1891
        preview_tree = preview.get_preview_tree()
 
1892
        return revision_tree, preview_tree
 
1893
 
 
1894
    def test_iter_changes(self):
 
1895
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
 
1896
        root = revision_tree.inventory.root.file_id
 
1897
        self.assertEqual([('a-id', ('a', 'a'), True, (True, True),
 
1898
                          (root, root), ('a', 'a'), ('file', 'file'),
 
1899
                          (False, False))],
 
1900
                          list(preview_tree._iter_changes(revision_tree)))
 
1901
 
 
1902
    def test_wrong_tree_value_error(self):
 
1903
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
 
1904
        e = self.assertRaises(ValueError, preview_tree._iter_changes,
 
1905
                              preview_tree)
 
1906
        self.assertEqual('from_tree must be transform source tree.', str(e))
 
1907
 
 
1908
    def test_include_unchanged_value_error(self):
 
1909
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
 
1910
        e = self.assertRaises(ValueError, preview_tree._iter_changes,
 
1911
                              revision_tree, include_unchanged=True)
 
1912
        self.assertEqual('include_unchanged is not supported', str(e))
 
1913
 
 
1914
    def test_specific_files(self):
 
1915
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
 
1916
        e = self.assertRaises(ValueError, preview_tree._iter_changes,
 
1917
                              revision_tree, specific_files=['pete'])
 
1918
        self.assertEqual('specific_files is not supported', str(e))
 
1919
 
 
1920
    def test_want_unversioned_value_error(self):
 
1921
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
 
1922
        e = self.assertRaises(ValueError, preview_tree._iter_changes,
 
1923
                              revision_tree, want_unversioned=True)
 
1924
        self.assertEqual('want_unversioned is not supported', str(e))
 
1925
 
 
1926
    def test_ignore_extra_trees_no_specific_files(self):
 
1927
        # extra_trees is harmless without specific_files, so we'll silently
 
1928
        # accept it, even though we won't use it.
 
1929
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
 
1930
        preview_tree._iter_changes(revision_tree, extra_trees=[preview_tree])
 
1931
 
 
1932
    def test_ignore_require_versioned_no_specific_files(self):
 
1933
        # require_versioned is meaningless without specific_files.
 
1934
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
 
1935
        preview_tree._iter_changes(revision_tree, require_versioned=False)
 
1936
 
 
1937
    def test_ignore_pb(self):
 
1938
        # pb could be supported, but TT.iter_changes doesn't support it.
 
1939
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
 
1940
        preview_tree._iter_changes(revision_tree, pb=progress.DummyProgress())
 
1941
 
 
1942
    def test_kind(self):
 
1943
        revision_tree = self.create_tree()
 
1944
        preview = TransformPreview(revision_tree)
 
1945
        self.addCleanup(preview.finalize)
 
1946
        preview.new_file('file', preview.root, 'contents', 'file-id')
 
1947
        preview.new_directory('directory', preview.root, 'dir-id')
 
1948
        preview_tree = preview.get_preview_tree()
 
1949
        self.assertEqual('file', preview_tree.kind('file-id'))
 
1950
        self.assertEqual('directory', preview_tree.kind('dir-id'))
 
1951
 
 
1952
    def test_get_file_mtime(self):
 
1953
        preview = self.get_empty_preview()
 
1954
        file_trans_id = preview.new_file('file', preview.root, 'contents',
 
1955
                                         'file-id')
 
1956
        limbo_path = preview._limbo_name(file_trans_id)
 
1957
        preview_tree = preview.get_preview_tree()
 
1958
        self.assertEqual(os.stat(limbo_path).st_mtime,
 
1959
                         preview_tree.get_file_mtime('file-id'))
 
1960
 
 
1961
    def test_get_file(self):
 
1962
        preview = self.get_empty_preview()
 
1963
        preview.new_file('file', preview.root, 'contents', 'file-id')
 
1964
        preview_tree = preview.get_preview_tree()
 
1965
        tree_file = preview_tree.get_file('file-id')
 
1966
        try:
 
1967
            self.assertEqual('contents', tree_file.read())
 
1968
        finally:
 
1969
            tree_file.close()