~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_transform.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-09-01 08:02:42 UTC
  • mfrom: (5390.3.3 faster-revert-593560)
  • Revision ID: pqm@pqm.ubuntu.com-20100901080242-esg62ody4frwmy66
(spiv) Avoid repeatedly calling self.target.all_file_ids() in
 InterTree.iter_changes. (Andrew Bennetts)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2007, 2008 Canonical Ltd
 
1
# Copyright (C) 2006-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
import os
18
 
import stat
19
18
from StringIO import StringIO
20
19
import sys
 
20
import time
21
21
 
22
22
from bzrlib import (
23
23
    bencode,
24
24
    errors,
 
25
    filters,
25
26
    generate_ids,
26
27
    osutils,
27
 
    progress,
28
28
    revision as _mod_revision,
29
 
    symbol_versioning,
 
29
    rules,
30
30
    tests,
31
31
    urlutils,
32
32
    )
33
33
from bzrlib.bzrdir import BzrDir
34
 
from bzrlib.conflicts import (DuplicateEntry, DuplicateID, MissingParent,
35
 
                              UnversionedParent, ParentLoop, DeletingParent,
36
 
                              NonDirectoryParent)
 
34
from bzrlib.conflicts import (
 
35
    DeletingParent,
 
36
    DuplicateEntry,
 
37
    DuplicateID,
 
38
    MissingParent,
 
39
    NonDirectoryParent,
 
40
    ParentLoop,
 
41
    UnversionedParent,
 
42
)
37
43
from bzrlib.diff import show_diff_trees
38
 
from bzrlib.errors import (DuplicateKey, MalformedTransform, NoSuchFile,
39
 
                           ReusingTransform, CantMoveRoot,
40
 
                           PathsNotVersionedError, ExistingLimbo,
41
 
                           ExistingPendingDeletion, ImmortalLimbo,
42
 
                           ImmortalPendingDeletion, LockError)
43
 
from bzrlib.osutils import file_kind, pathjoin
 
44
from bzrlib.errors import (
 
45
    DuplicateKey,
 
46
    ExistingLimbo,
 
47
    ExistingPendingDeletion,
 
48
    ImmortalLimbo,
 
49
    ImmortalPendingDeletion,
 
50
    LockError,
 
51
    MalformedTransform,
 
52
    NoSuchFile,
 
53
    ReusingTransform,
 
54
)
 
55
from bzrlib.osutils import (
 
56
    file_kind,
 
57
    pathjoin,
 
58
)
44
59
from bzrlib.merge import Merge3Merger, Merger
45
60
from bzrlib.tests import (
46
61
    HardlinkFeature,
48
63
    TestCase,
49
64
    TestCaseInTempDir,
50
65
    TestSkipped,
51
 
    )
52
 
from bzrlib.transform import (TreeTransform, ROOT_PARENT, FinalPaths,
53
 
                              resolve_conflicts, cook_conflicts,
54
 
                              build_tree, get_backup_name,
55
 
                              _FileMover, resolve_checkout,
56
 
                              TransformPreview, create_from_tree)
 
66
)
 
67
from bzrlib.transform import (
 
68
    build_tree,
 
69
    create_from_tree,
 
70
    cook_conflicts,
 
71
    _FileMover,
 
72
    FinalPaths,
 
73
    get_backup_name,
 
74
    resolve_conflicts,
 
75
    resolve_checkout,
 
76
    ROOT_PARENT,
 
77
    TransformPreview,
 
78
    TreeTransform,
 
79
)
57
80
 
58
81
 
59
82
class TestTreeTransform(tests.TestCaseWithTransport):
136
159
        transform.finalize()
137
160
        transform.finalize()
138
161
 
 
162
    def test_create_files_same_timestamp(self):
 
163
        transform, root = self.get_transform()
 
164
        self.wt.lock_tree_write()
 
165
        self.addCleanup(self.wt.unlock)
 
166
        # Roll back the clock, so that we know everything is being set to the
 
167
        # exact time
 
168
        transform._creation_mtime = creation_mtime = time.time() - 20.0
 
169
        transform.create_file('content-one',
 
170
                              transform.create_path('one', root))
 
171
        time.sleep(1) # *ugly*
 
172
        transform.create_file('content-two',
 
173
                              transform.create_path('two', root))
 
174
        transform.apply()
 
175
        fo, st1 = self.wt.get_file_with_stat(None, path='one', filtered=False)
 
176
        fo.close()
 
177
        fo, st2 = self.wt.get_file_with_stat(None, path='two', filtered=False)
 
178
        fo.close()
 
179
        # We only guarantee 2s resolution
 
180
        self.assertTrue(abs(creation_mtime - st1.st_mtime) < 2.0,
 
181
            "%s != %s within 2 seconds" % (creation_mtime, st1.st_mtime))
 
182
        # But if we have more than that, all files should get the same result
 
183
        self.assertEqual(st1.st_mtime, st2.st_mtime)
 
184
 
 
185
    def test_change_root_id(self):
 
186
        transform, root = self.get_transform()
 
187
        self.assertNotEqual('new-root-id', self.wt.get_root_id())
 
188
        transform.new_directory('', ROOT_PARENT, 'new-root-id')
 
189
        transform.delete_contents(root)
 
190
        transform.unversion_file(root)
 
191
        transform.fixup_new_roots()
 
192
        transform.apply()
 
193
        self.assertEqual('new-root-id', self.wt.get_root_id())
 
194
 
 
195
    def test_change_root_id_add_files(self):
 
196
        transform, root = self.get_transform()
 
197
        self.assertNotEqual('new-root-id', self.wt.get_root_id())
 
198
        new_trans_id = transform.new_directory('', ROOT_PARENT, 'new-root-id')
 
199
        transform.new_file('file', new_trans_id, ['new-contents\n'],
 
200
                           'new-file-id')
 
201
        transform.delete_contents(root)
 
202
        transform.unversion_file(root)
 
203
        transform.fixup_new_roots()
 
204
        transform.apply()
 
205
        self.assertEqual('new-root-id', self.wt.get_root_id())
 
206
        self.assertEqual('new-file-id', self.wt.path2id('file'))
 
207
        self.assertFileEqual('new-contents\n', self.wt.abspath('file'))
 
208
 
 
209
    def test_add_two_roots(self):
 
210
        transform, root = self.get_transform()
 
211
        new_trans_id = transform.new_directory('', ROOT_PARENT, 'new-root-id')
 
212
        new_trans_id = transform.new_directory('', ROOT_PARENT, 'alt-root-id')
 
213
        self.assertRaises(ValueError, transform.fixup_new_roots)
 
214
 
139
215
    def test_hardlink(self):
140
216
        self.requireFeature(HardlinkFeature)
141
217
        transform, root = self.get_transform()
369
445
        self.assertContainsRe(transform._limbo_name(first), 'new-1/file')
370
446
        self.assertNotContainsRe(transform._limbo_name(second), 'new-1/FiLe')
371
447
 
 
448
    def test_adjust_path_updates_child_limbo_names(self):
 
449
        tree = self.make_branch_and_tree('tree')
 
450
        transform = TreeTransform(tree)
 
451
        self.addCleanup(transform.finalize)
 
452
        foo_id = transform.new_directory('foo', transform.root)
 
453
        bar_id = transform.new_directory('bar', foo_id)
 
454
        baz_id = transform.new_directory('baz', bar_id)
 
455
        qux_id = transform.new_directory('qux', baz_id)
 
456
        transform.adjust_path('quxx', foo_id, bar_id)
 
457
        self.assertStartsWith(transform._limbo_name(qux_id),
 
458
                              transform._limbo_name(bar_id))
 
459
 
372
460
    def test_add_del(self):
373
461
        start, root = self.get_transform()
374
462
        start.new_directory('a', root, 'a')
669
757
                                         ' versioned, but has versioned'
670
758
                                         ' children.  Versioned directory.')
671
759
        self.assertEqual(conflicts_s[6], 'Conflict moving oz/emeraldcity into'
672
 
                                         ' oz/emeraldcity.  Cancelled move.')
 
760
                                         ' oz/emeraldcity. Cancelled move.')
673
761
 
674
762
    def prepare_wrong_parent_kind(self):
675
763
        tt, root = self.get_transform()
746
834
        create.apply()
747
835
        transform, root = self.get_transform()
748
836
        transform.adjust_root_path('oldroot', fun)
749
 
        new_root=transform.trans_id_tree_path('')
 
837
        new_root = transform.trans_id_tree_path('')
750
838
        transform.version_file('new-root', new_root)
751
839
        transform.apply()
752
840
 
764
852
        rename.set_executability(True, myfile)
765
853
        rename.apply()
766
854
 
 
855
    def test_rename_fails(self):
 
856
        # see https://bugs.launchpad.net/bzr/+bug/491763
 
857
        create, root_id = self.get_transform()
 
858
        first_dir = create.new_directory('first-dir', root_id, 'first-id')
 
859
        myfile = create.new_file('myfile', root_id, 'myfile-text',
 
860
                                 'myfile-id')
 
861
        create.apply()
 
862
        if os.name == "posix" and sys.platform != "cygwin":
 
863
            # posix filesystems fail on renaming if the readonly bit is set
 
864
            osutils.make_readonly(self.wt.abspath('first-dir'))
 
865
        elif os.name == "nt":
 
866
            # windows filesystems fail on renaming open files
 
867
            self.addCleanup(file(self.wt.abspath('myfile')).close)
 
868
        else:
 
869
            self.skip("Don't know how to force a permissions error on rename")
 
870
        # now transform to rename
 
871
        rename_transform, root_id = self.get_transform()
 
872
        file_trans_id = rename_transform.trans_id_file_id('myfile-id')
 
873
        dir_id = rename_transform.trans_id_file_id('first-id')
 
874
        rename_transform.adjust_path('newname', dir_id, file_trans_id)
 
875
        e = self.assertRaises(errors.TransformRenameFailed,
 
876
            rename_transform.apply)
 
877
        # On nix looks like: 
 
878
        # "Failed to rename .../work/.bzr/checkout/limbo/new-1
 
879
        # to .../first-dir/newname: [Errno 13] Permission denied"
 
880
        # On windows looks like:
 
881
        # "Failed to rename .../work/myfile to 
 
882
        # .../work/.bzr/checkout/limbo/new-1: [Errno 13] Permission denied"
 
883
        # The strerror will vary per OS and language so it's not checked here
 
884
        self.assertContainsRe(str(e),
 
885
            "Failed to rename .*(first-dir.newname:|myfile)")
 
886
 
767
887
    def test_set_executability_order(self):
768
888
        """Ensure that executability behaves the same, no matter what order.
769
889
 
1856
1976
        self.assertEqual([], list(target.iter_changes(revision_tree)))
1857
1977
        self.assertTrue(source.is_executable('file1-id'))
1858
1978
 
 
1979
    def install_rot13_content_filter(self, pattern):
 
1980
        # We could use
 
1981
        # self.addCleanup(filters._reset_registry, filters._reset_registry())
 
1982
        # below, but that looks a bit... hard to read even if it's exactly
 
1983
        # the same thing.
 
1984
        original_registry = filters._reset_registry()
 
1985
        def restore_registry():
 
1986
            filters._reset_registry(original_registry)
 
1987
        self.addCleanup(restore_registry)
 
1988
        def rot13(chunks, context=None):
 
1989
            return [''.join(chunks).encode('rot13')]
 
1990
        rot13filter = filters.ContentFilter(rot13, rot13)
 
1991
        filters.register_filter_stack_map('rot13', {'yes': [rot13filter]}.get)
 
1992
        os.mkdir(self.test_home_dir + '/.bazaar')
 
1993
        rules_filename = self.test_home_dir + '/.bazaar/rules'
 
1994
        f = open(rules_filename, 'wb')
 
1995
        f.write('[name %s]\nrot13=yes\n' % (pattern,))
 
1996
        f.close()
 
1997
        def uninstall_rules():
 
1998
            os.remove(rules_filename)
 
1999
            rules.reset_rules()
 
2000
        self.addCleanup(uninstall_rules)
 
2001
        rules.reset_rules()
 
2002
 
 
2003
    def test_build_tree_content_filtered_files_are_not_hardlinked(self):
 
2004
        """build_tree will not hardlink files that have content filtering rules
 
2005
        applied to them (but will still hardlink other files from the same tree
 
2006
        if it can).
 
2007
        """
 
2008
        self.requireFeature(HardlinkFeature)
 
2009
        self.install_rot13_content_filter('file1')
 
2010
        source = self.create_ab_tree()
 
2011
        target = self.make_branch_and_tree('target')
 
2012
        revision_tree = source.basis_tree()
 
2013
        revision_tree.lock_read()
 
2014
        self.addCleanup(revision_tree.unlock)
 
2015
        build_tree(revision_tree, target, source, hardlink=True)
 
2016
        target.lock_read()
 
2017
        self.addCleanup(target.unlock)
 
2018
        self.assertEqual([], list(target.iter_changes(revision_tree)))
 
2019
        source_stat = os.stat('source/file1')
 
2020
        target_stat = os.stat('target/file1')
 
2021
        self.assertNotEqual(source_stat, target_stat)
 
2022
        source_stat = os.stat('source/file2')
 
2023
        target_stat = os.stat('target/file2')
 
2024
        self.assertEqualStat(source_stat, target_stat)
 
2025
 
1859
2026
    def test_case_insensitive_build_tree_inventory(self):
1860
2027
        if (tests.CaseInsensitiveFilesystemFeature.available()
1861
2028
            or tests.CaseInsCasePresFilenameFeature.available()):
1916
2083
        branch.lock_write()
1917
2084
        self.addCleanup(branch.unlock)
1918
2085
        tt = TransformPreview(branch.basis_tree())
 
2086
        self.addCleanup(tt.finalize)
1919
2087
        tt.new_directory('', ROOT_PARENT, 'TREE_ROOT')
1920
2088
        rev = tt.commit(branch, 'my message')
1921
2089
        self.assertEqual([], branch.basis_tree().get_parent_ids())
1927
2095
        branch.lock_write()
1928
2096
        self.addCleanup(branch.unlock)
1929
2097
        tt = TransformPreview(branch.basis_tree())
 
2098
        self.addCleanup(tt.finalize)
1930
2099
        e = self.assertRaises(ValueError, tt.commit, branch,
1931
2100
                          'my message', ['rev1b-id'])
1932
2101
        self.assertEqual('Cannot supply merge parents for first commit.',
1937
2106
        branch, tt = self.get_branch_and_transform()
1938
2107
        tt.new_file('file', tt.root, 'contents', 'file-id')
1939
2108
        trans_id = tt.new_directory('dir', tt.root, 'dir-id')
1940
 
        tt.new_symlink('symlink', trans_id, 'target', 'symlink-id')
 
2109
        if SymlinkFeature.available():
 
2110
            tt.new_symlink('symlink', trans_id, 'target', 'symlink-id')
1941
2111
        rev = tt.commit(branch, 'message')
1942
2112
        tree = branch.basis_tree()
1943
2113
        self.assertEqual('file', tree.id2path('file-id'))
1944
2114
        self.assertEqual('contents', tree.get_file_text('file-id'))
1945
2115
        self.assertEqual('dir', tree.id2path('dir-id'))
1946
 
        self.assertEqual('dir/symlink', tree.id2path('symlink-id'))
1947
 
        self.assertEqual('target', tree.get_symlink_target('symlink-id'))
 
2116
        if SymlinkFeature.available():
 
2117
            self.assertEqual('dir/symlink', tree.id2path('symlink-id'))
 
2118
            self.assertEqual('target', tree.get_symlink_target('symlink-id'))
1948
2119
 
1949
2120
    def test_add_unversioned(self):
1950
2121
        branch, tt = self.get_branch_and_transform()
1957
2128
        tt.new_file('file', tt.root, 'contents', 'file-id')
1958
2129
        tt.commit(branch, 'message', strict=True)
1959
2130
        tt = TransformPreview(branch.basis_tree())
 
2131
        self.addCleanup(tt.finalize)
1960
2132
        trans_id = tt.trans_id_file_id('file-id')
1961
2133
        tt.delete_contents(trans_id)
1962
2134
        tt.create_file('contents', trans_id)
1973
2145
        self.assertRaises(errors.MalformedTransform, tt.commit, branch,
1974
2146
                          'message')
1975
2147
 
 
2148
    def test_commit_rich_revision_data(self):
 
2149
        branch, tt = self.get_branch_and_transform()
 
2150
        rev_id = tt.commit(branch, 'message', timestamp=1, timezone=43201,
 
2151
                           committer='me <me@example.com>',
 
2152
                           revprops={'foo': 'bar'}, revision_id='revid-1',
 
2153
                           authors=['Author1 <author1@example.com>',
 
2154
                              'Author2 <author2@example.com>',
 
2155
                               ])
 
2156
        self.assertEqual('revid-1', rev_id)
 
2157
        revision = branch.repository.get_revision(rev_id)
 
2158
        self.assertEqual(1, revision.timestamp)
 
2159
        self.assertEqual(43201, revision.timezone)
 
2160
        self.assertEqual('me <me@example.com>', revision.committer)
 
2161
        self.assertEqual(['Author1 <author1@example.com>',
 
2162
                          'Author2 <author2@example.com>'],
 
2163
                         revision.get_apparent_authors())
 
2164
        del revision.properties['authors']
 
2165
        self.assertEqual({'foo': 'bar',
 
2166
                          'branch-nick': 'tree'},
 
2167
                         revision.properties)
 
2168
 
 
2169
    def test_no_explicit_revprops(self):
 
2170
        branch, tt = self.get_branch_and_transform()
 
2171
        rev_id = tt.commit(branch, 'message', authors=[
 
2172
            'Author1 <author1@example.com>',
 
2173
            'Author2 <author2@example.com>', ])
 
2174
        revision = branch.repository.get_revision(rev_id)
 
2175
        self.assertEqual(['Author1 <author1@example.com>',
 
2176
                          'Author2 <author2@example.com>'],
 
2177
                         revision.get_apparent_authors())
 
2178
        self.assertEqual('tree', revision.properties['branch-nick'])
 
2179
 
1976
2180
 
1977
2181
class MockTransform(object):
1978
2182
 
2146
2350
    def create_tree(self):
2147
2351
        tree = self.make_branch_and_tree('.')
2148
2352
        self.build_tree_contents([('a', 'content 1')])
 
2353
        tree.set_root_id('TREE_ROOT')
2149
2354
        tree.add('a', 'a-id')
2150
2355
        tree.commit('rev1', rev_id='rev1')
2151
2356
        return tree.branch.repository.revision_tree('rev1')
2252
2457
    def test_ignore_pb(self):
2253
2458
        # pb could be supported, but TT.iter_changes doesn't support it.
2254
2459
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
2255
 
        preview_tree.iter_changes(revision_tree, pb=progress.DummyProgress())
 
2460
        preview_tree.iter_changes(revision_tree)
2256
2461
 
2257
2462
    def test_kind(self):
2258
2463
        revision_tree = self.create_tree()
2273
2478
        self.assertEqual(os.stat(limbo_path).st_mtime,
2274
2479
                         preview_tree.get_file_mtime('file-id'))
2275
2480
 
 
2481
    def test_get_file_mtime_renamed(self):
 
2482
        work_tree = self.make_branch_and_tree('tree')
 
2483
        self.build_tree(['tree/file'])
 
2484
        work_tree.add('file', 'file-id')
 
2485
        preview = TransformPreview(work_tree)
 
2486
        self.addCleanup(preview.finalize)
 
2487
        file_trans_id = preview.trans_id_tree_file_id('file-id')
 
2488
        preview.adjust_path('renamed', preview.root, file_trans_id)
 
2489
        preview_tree = preview.get_preview_tree()
 
2490
        preview_mtime = preview_tree.get_file_mtime('file-id', 'renamed')
 
2491
        work_mtime = work_tree.get_file_mtime('file-id', 'file')
 
2492
 
2276
2493
    def test_get_file(self):
2277
2494
        preview = self.get_empty_preview()
2278
2495
        preview.new_file('file', preview.root, 'contents', 'file-id')
2426
2643
        self.assertEqual(('missing', None, None, None), summary)
2427
2644
 
2428
2645
    def test_file_content_summary_executable(self):
2429
 
        if not osutils.supports_executable():
2430
 
            raise TestNotApplicable()
2431
2646
        preview = self.get_empty_preview()
2432
2647
        path_id = preview.new_file('path', preview.root, 'contents', 'path-id')
2433
2648
        preview.set_executability(True, path_id)
2442
2657
        self.assertIs(None, summary[3])
2443
2658
 
2444
2659
    def test_change_executability(self):
2445
 
        if not osutils.supports_executable():
2446
 
            raise TestNotApplicable()
2447
2660
        tree = self.make_branch_and_tree('tree')
2448
2661
        self.build_tree(['tree/path'])
2449
2662
        tree.add('path')
2463
2676
        # size must be known
2464
2677
        self.assertEqual(len('contents'), summary[1])
2465
2678
        # not executable
2466
 
        if osutils.supports_executable():
2467
 
            self.assertEqual(False, summary[2])
2468
 
        else:
2469
 
            self.assertEqual(None, summary[2])
 
2679
        self.assertEqual(False, summary[2])
2470
2680
        # will not have hash (not cheap to determine)
2471
2681
        self.assertIs(None, summary[3])
2472
2682
 
2613
2823
 
2614
2824
    def test_walkdirs(self):
2615
2825
        preview = self.get_empty_preview()
2616
 
        preview.version_file('tree-root', preview.root)
 
2826
        root = preview.new_directory('', ROOT_PARENT, 'tree-root')
 
2827
        # FIXME: new_directory should mark root.
 
2828
        preview.fixup_new_roots()
2617
2829
        preview_tree = preview.get_preview_tree()
2618
2830
        file_trans_id = preview.new_file('a', preview.root, 'contents',
2619
2831
                                         'a-id')
2650
2862
        self.addCleanup(work_tree.unlock)
2651
2863
        preview = TransformPreview(work_tree)
2652
2864
        self.addCleanup(preview.finalize)
2653
 
        preview_tree = preview.get_preview_tree()
2654
2865
        file_trans_id = preview.trans_id_file_id('file-id')
2655
2866
        preview.delete_contents(file_trans_id)
2656
2867
        preview.create_file('a\nb\n', file_trans_id)
2657
 
        pb = progress.DummyProgress()
2658
 
        merger = Merger.from_revision_ids(pb, preview_tree,
 
2868
        preview_tree = preview.get_preview_tree()
 
2869
        merger = Merger.from_revision_ids(None, preview_tree,
2659
2870
                                          child_tree.branch.last_revision(),
2660
2871
                                          other_branch=child_tree.branch,
2661
2872
                                          tree_branch=work_tree.branch)
2667
2878
 
2668
2879
    def test_merge_preview_into_workingtree(self):
2669
2880
        tree = self.make_branch_and_tree('tree')
 
2881
        tree.set_root_id('TREE_ROOT')
2670
2882
        tt = TransformPreview(tree)
2671
2883
        self.addCleanup(tt.finalize)
2672
2884
        tt.new_file('name', tt.root, 'content', 'file-id')
2673
2885
        tree2 = self.make_branch_and_tree('tree2')
2674
 
        pb = progress.DummyProgress()
 
2886
        tree2.set_root_id('TREE_ROOT')
2675
2887
        merger = Merger.from_uncommitted(tree2, tt.get_preview_tree(),
2676
 
                                         pb, tree.basis_tree())
 
2888
                                         None, tree.basis_tree())
2677
2889
        merger.merge_type = Merge3Merger
2678
2890
        merger.do_merge()
2679
2891
 
2689
2901
        tt.create_file('baz', trans_id)
2690
2902
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
2691
2903
        self.build_tree_contents([('tree2/foo', 'qux')])
2692
 
        pb = progress.DummyProgress()
 
2904
        pb = None
2693
2905
        merger = Merger.from_uncommitted(tree2, tt.get_preview_tree(),
2694
2906
                                         pb, tree.basis_tree())
2695
2907
        merger.merge_type = Merge3Merger
2722
2934
        rev2_tree = tree.branch.repository.revision_tree(rev2_id)
2723
2935
        self.assertEqual('contents', rev2_tree.get_file_text('file_id'))
2724
2936
 
 
2937
    def test_ascii_limbo_paths(self):
 
2938
        self.requireFeature(tests.UnicodeFilenameFeature)
 
2939
        branch = self.make_branch('any')
 
2940
        tree = branch.repository.revision_tree(_mod_revision.NULL_REVISION)
 
2941
        tt = TransformPreview(tree)
 
2942
        self.addCleanup(tt.finalize)
 
2943
        foo_id = tt.new_directory('', ROOT_PARENT)
 
2944
        bar_id = tt.new_file(u'\u1234bar', foo_id, 'contents')
 
2945
        limbo_path = tt._limbo_name(bar_id)
 
2946
        self.assertEqual(limbo_path.encode('ascii', 'replace'), limbo_path)
 
2947
 
2725
2948
 
2726
2949
class FakeSerializer(object):
2727
2950
    """Serializer implementation that simply returns the input.