/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: 2009-07-16 01:36:57 UTC
  • mto: This revision was merged to the branch mainline in revision 4543.
  • Revision ID: robertc@robertcollins.net-20090716013657-6f1046zvotn9shm3
Change cmd_mv not to take out branch locks. (Robert Collins, bug 216541)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006, 2007, 2008 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
18
19
from StringIO import StringIO
19
20
import sys
20
 
import time
21
21
 
22
22
from bzrlib import (
23
23
    bencode,
24
24
    errors,
25
 
    filters,
26
25
    generate_ids,
27
26
    osutils,
 
27
    progress,
28
28
    revision as _mod_revision,
29
 
    rules,
 
29
    symbol_versioning,
30
30
    tests,
31
31
    urlutils,
32
32
    )
33
33
from bzrlib.bzrdir import BzrDir
34
 
from bzrlib.conflicts import (
35
 
    DeletingParent,
36
 
    DuplicateEntry,
37
 
    DuplicateID,
38
 
    MissingParent,
39
 
    NonDirectoryParent,
40
 
    ParentLoop,
41
 
    UnversionedParent,
42
 
)
 
34
from bzrlib.conflicts import (DuplicateEntry, DuplicateID, MissingParent,
 
35
                              UnversionedParent, ParentLoop, DeletingParent,
 
36
                              NonDirectoryParent)
43
37
from bzrlib.diff import show_diff_trees
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
 
)
 
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
59
44
from bzrlib.merge import Merge3Merger, Merger
60
45
from bzrlib.tests import (
61
46
    HardlinkFeature,
63
48
    TestCase,
64
49
    TestCaseInTempDir,
65
50
    TestSkipped,
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
 
)
 
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)
80
57
 
81
58
 
82
59
class TestTreeTransform(tests.TestCaseWithTransport):
159
136
        transform.finalize()
160
137
        transform.finalize()
161
138
 
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
 
 
215
139
    def test_hardlink(self):
216
140
        self.requireFeature(HardlinkFeature)
217
141
        transform, root = self.get_transform()
445
369
        self.assertContainsRe(transform._limbo_name(first), 'new-1/file')
446
370
        self.assertNotContainsRe(transform._limbo_name(second), 'new-1/FiLe')
447
371
 
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
 
 
460
372
    def test_add_del(self):
461
373
        start, root = self.get_transform()
462
374
        start.new_directory('a', root, 'a')
757
669
                                         ' versioned, but has versioned'
758
670
                                         ' children.  Versioned directory.')
759
671
        self.assertEqual(conflicts_s[6], 'Conflict moving oz/emeraldcity into'
760
 
                                         ' oz/emeraldcity. Cancelled move.')
 
672
                                         ' oz/emeraldcity.  Cancelled move.')
761
673
 
762
674
    def prepare_wrong_parent_kind(self):
763
675
        tt, root = self.get_transform()
834
746
        create.apply()
835
747
        transform, root = self.get_transform()
836
748
        transform.adjust_root_path('oldroot', fun)
837
 
        new_root = transform.trans_id_tree_path('')
 
749
        new_root=transform.trans_id_tree_path('')
838
750
        transform.version_file('new-root', new_root)
839
751
        transform.apply()
840
752
 
1944
1856
        self.assertEqual([], list(target.iter_changes(revision_tree)))
1945
1857
        self.assertTrue(source.is_executable('file1-id'))
1946
1858
 
1947
 
    def install_rot13_content_filter(self, pattern):
1948
 
        # We could use
1949
 
        # self.addCleanup(filters._reset_registry, filters._reset_registry())
1950
 
        # below, but that looks a bit... hard to read even if it's exactly
1951
 
        # the same thing.
1952
 
        original_registry = filters._reset_registry()
1953
 
        def restore_registry():
1954
 
            filters._reset_registry(original_registry)
1955
 
        self.addCleanup(restore_registry)
1956
 
        def rot13(chunks, context=None):
1957
 
            return [''.join(chunks).encode('rot13')]
1958
 
        rot13filter = filters.ContentFilter(rot13, rot13)
1959
 
        filters.register_filter_stack_map('rot13', {'yes': [rot13filter]}.get)
1960
 
        os.mkdir(self.test_home_dir + '/.bazaar')
1961
 
        rules_filename = self.test_home_dir + '/.bazaar/rules'
1962
 
        f = open(rules_filename, 'wb')
1963
 
        f.write('[name %s]\nrot13=yes\n' % (pattern,))
1964
 
        f.close()
1965
 
        def uninstall_rules():
1966
 
            os.remove(rules_filename)
1967
 
            rules.reset_rules()
1968
 
        self.addCleanup(uninstall_rules)
1969
 
        rules.reset_rules()
1970
 
 
1971
 
    def test_build_tree_content_filtered_files_are_not_hardlinked(self):
1972
 
        """build_tree will not hardlink files that have content filtering rules
1973
 
        applied to them (but will still hardlink other files from the same tree
1974
 
        if it can).
1975
 
        """
1976
 
        self.requireFeature(HardlinkFeature)
1977
 
        self.install_rot13_content_filter('file1')
1978
 
        source = self.create_ab_tree()
1979
 
        target = self.make_branch_and_tree('target')
1980
 
        revision_tree = source.basis_tree()
1981
 
        revision_tree.lock_read()
1982
 
        self.addCleanup(revision_tree.unlock)
1983
 
        build_tree(revision_tree, target, source, hardlink=True)
1984
 
        target.lock_read()
1985
 
        self.addCleanup(target.unlock)
1986
 
        self.assertEqual([], list(target.iter_changes(revision_tree)))
1987
 
        source_stat = os.stat('source/file1')
1988
 
        target_stat = os.stat('target/file1')
1989
 
        self.assertNotEqual(source_stat, target_stat)
1990
 
        source_stat = os.stat('source/file2')
1991
 
        target_stat = os.stat('target/file2')
1992
 
        self.assertEqualStat(source_stat, target_stat)
1993
 
 
1994
1859
    def test_case_insensitive_build_tree_inventory(self):
1995
1860
        if (tests.CaseInsensitiveFilesystemFeature.available()
1996
1861
            or tests.CaseInsCasePresFilenameFeature.available()):
2051
1916
        branch.lock_write()
2052
1917
        self.addCleanup(branch.unlock)
2053
1918
        tt = TransformPreview(branch.basis_tree())
2054
 
        self.addCleanup(tt.finalize)
2055
 
        tt.new_directory('', ROOT_PARENT, 'TREE_ROOT')
2056
1919
        rev = tt.commit(branch, 'my message')
2057
1920
        self.assertEqual([], branch.basis_tree().get_parent_ids())
2058
1921
        self.assertNotEqual(_mod_revision.NULL_REVISION,
2063
1926
        branch.lock_write()
2064
1927
        self.addCleanup(branch.unlock)
2065
1928
        tt = TransformPreview(branch.basis_tree())
2066
 
        self.addCleanup(tt.finalize)
2067
1929
        e = self.assertRaises(ValueError, tt.commit, branch,
2068
1930
                          'my message', ['rev1b-id'])
2069
1931
        self.assertEqual('Cannot supply merge parents for first commit.',
2074
1936
        branch, tt = self.get_branch_and_transform()
2075
1937
        tt.new_file('file', tt.root, 'contents', 'file-id')
2076
1938
        trans_id = tt.new_directory('dir', tt.root, 'dir-id')
2077
 
        if SymlinkFeature.available():
2078
 
            tt.new_symlink('symlink', trans_id, 'target', 'symlink-id')
 
1939
        tt.new_symlink('symlink', trans_id, 'target', 'symlink-id')
2079
1940
        rev = tt.commit(branch, 'message')
2080
1941
        tree = branch.basis_tree()
2081
1942
        self.assertEqual('file', tree.id2path('file-id'))
2082
1943
        self.assertEqual('contents', tree.get_file_text('file-id'))
2083
1944
        self.assertEqual('dir', tree.id2path('dir-id'))
2084
 
        if SymlinkFeature.available():
2085
 
            self.assertEqual('dir/symlink', tree.id2path('symlink-id'))
2086
 
            self.assertEqual('target', tree.get_symlink_target('symlink-id'))
 
1945
        self.assertEqual('dir/symlink', tree.id2path('symlink-id'))
 
1946
        self.assertEqual('target', tree.get_symlink_target('symlink-id'))
2087
1947
 
2088
1948
    def test_add_unversioned(self):
2089
1949
        branch, tt = self.get_branch_and_transform()
2096
1956
        tt.new_file('file', tt.root, 'contents', 'file-id')
2097
1957
        tt.commit(branch, 'message', strict=True)
2098
1958
        tt = TransformPreview(branch.basis_tree())
2099
 
        self.addCleanup(tt.finalize)
2100
1959
        trans_id = tt.trans_id_file_id('file-id')
2101
1960
        tt.delete_contents(trans_id)
2102
1961
        tt.create_file('contents', trans_id)
2113
1972
        self.assertRaises(errors.MalformedTransform, tt.commit, branch,
2114
1973
                          'message')
2115
1974
 
2116
 
    def test_commit_rich_revision_data(self):
2117
 
        branch, tt = self.get_branch_and_transform()
2118
 
        rev_id = tt.commit(branch, 'message', timestamp=1, timezone=43201,
2119
 
                           committer='me <me@example.com>',
2120
 
                           revprops={'foo': 'bar'}, revision_id='revid-1',
2121
 
                           authors=['Author1 <author1@example.com>',
2122
 
                              'Author2 <author2@example.com>',
2123
 
                               ])
2124
 
        self.assertEqual('revid-1', rev_id)
2125
 
        revision = branch.repository.get_revision(rev_id)
2126
 
        self.assertEqual(1, revision.timestamp)
2127
 
        self.assertEqual(43201, revision.timezone)
2128
 
        self.assertEqual('me <me@example.com>', revision.committer)
2129
 
        self.assertEqual(['Author1 <author1@example.com>',
2130
 
                          'Author2 <author2@example.com>'],
2131
 
                         revision.get_apparent_authors())
2132
 
        del revision.properties['authors']
2133
 
        self.assertEqual({'foo': 'bar',
2134
 
                          'branch-nick': 'tree'},
2135
 
                         revision.properties)
2136
 
 
2137
 
    def test_no_explicit_revprops(self):
2138
 
        branch, tt = self.get_branch_and_transform()
2139
 
        rev_id = tt.commit(branch, 'message', authors=[
2140
 
            'Author1 <author1@example.com>',
2141
 
            'Author2 <author2@example.com>', ])
2142
 
        revision = branch.repository.get_revision(rev_id)
2143
 
        self.assertEqual(['Author1 <author1@example.com>',
2144
 
                          'Author2 <author2@example.com>'],
2145
 
                         revision.get_apparent_authors())
2146
 
        self.assertEqual('tree', revision.properties['branch-nick'])
2147
 
 
2148
1975
 
2149
1976
class MockTransform(object):
2150
1977
 
2318
2145
    def create_tree(self):
2319
2146
        tree = self.make_branch_and_tree('.')
2320
2147
        self.build_tree_contents([('a', 'content 1')])
2321
 
        tree.set_root_id('TREE_ROOT')
2322
2148
        tree.add('a', 'a-id')
2323
2149
        tree.commit('rev1', rev_id='rev1')
2324
2150
        return tree.branch.repository.revision_tree('rev1')
2425
2251
    def test_ignore_pb(self):
2426
2252
        # pb could be supported, but TT.iter_changes doesn't support it.
2427
2253
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
2428
 
        preview_tree.iter_changes(revision_tree)
 
2254
        preview_tree.iter_changes(revision_tree, pb=progress.DummyProgress())
2429
2255
 
2430
2256
    def test_kind(self):
2431
2257
        revision_tree = self.create_tree()
2446
2272
        self.assertEqual(os.stat(limbo_path).st_mtime,
2447
2273
                         preview_tree.get_file_mtime('file-id'))
2448
2274
 
2449
 
    def test_get_file_mtime_renamed(self):
2450
 
        work_tree = self.make_branch_and_tree('tree')
2451
 
        self.build_tree(['tree/file'])
2452
 
        work_tree.add('file', 'file-id')
2453
 
        preview = TransformPreview(work_tree)
2454
 
        self.addCleanup(preview.finalize)
2455
 
        file_trans_id = preview.trans_id_tree_file_id('file-id')
2456
 
        preview.adjust_path('renamed', preview.root, file_trans_id)
2457
 
        preview_tree = preview.get_preview_tree()
2458
 
        preview_mtime = preview_tree.get_file_mtime('file-id', 'renamed')
2459
 
        work_mtime = work_tree.get_file_mtime('file-id', 'file')
2460
 
 
2461
2275
    def test_get_file(self):
2462
2276
        preview = self.get_empty_preview()
2463
2277
        preview.new_file('file', preview.root, 'contents', 'file-id')
2611
2425
        self.assertEqual(('missing', None, None, None), summary)
2612
2426
 
2613
2427
    def test_file_content_summary_executable(self):
 
2428
        if not osutils.supports_executable():
 
2429
            raise TestNotApplicable()
2614
2430
        preview = self.get_empty_preview()
2615
2431
        path_id = preview.new_file('path', preview.root, 'contents', 'path-id')
2616
2432
        preview.set_executability(True, path_id)
2625
2441
        self.assertIs(None, summary[3])
2626
2442
 
2627
2443
    def test_change_executability(self):
 
2444
        if not osutils.supports_executable():
 
2445
            raise TestNotApplicable()
2628
2446
        tree = self.make_branch_and_tree('tree')
2629
2447
        self.build_tree(['tree/path'])
2630
2448
        tree.add('path')
2644
2462
        # size must be known
2645
2463
        self.assertEqual(len('contents'), summary[1])
2646
2464
        # not executable
2647
 
        self.assertEqual(False, summary[2])
 
2465
        if osutils.supports_executable():
 
2466
            self.assertEqual(False, summary[2])
 
2467
        else:
 
2468
            self.assertEqual(None, summary[2])
2648
2469
        # will not have hash (not cheap to determine)
2649
2470
        self.assertIs(None, summary[3])
2650
2471
 
2791
2612
 
2792
2613
    def test_walkdirs(self):
2793
2614
        preview = self.get_empty_preview()
2794
 
        root = preview.new_directory('', ROOT_PARENT, 'tree-root')
2795
 
        # FIXME: new_directory should mark root.
2796
 
        preview.fixup_new_roots()
 
2615
        preview.version_file('tree-root', preview.root)
2797
2616
        preview_tree = preview.get_preview_tree()
2798
2617
        file_trans_id = preview.new_file('a', preview.root, 'contents',
2799
2618
                                         'a-id')
2830
2649
        self.addCleanup(work_tree.unlock)
2831
2650
        preview = TransformPreview(work_tree)
2832
2651
        self.addCleanup(preview.finalize)
 
2652
        preview_tree = preview.get_preview_tree()
2833
2653
        file_trans_id = preview.trans_id_file_id('file-id')
2834
2654
        preview.delete_contents(file_trans_id)
2835
2655
        preview.create_file('a\nb\n', file_trans_id)
2836
 
        preview_tree = preview.get_preview_tree()
2837
 
        merger = Merger.from_revision_ids(None, preview_tree,
 
2656
        pb = progress.DummyProgress()
 
2657
        merger = Merger.from_revision_ids(pb, preview_tree,
2838
2658
                                          child_tree.branch.last_revision(),
2839
2659
                                          other_branch=child_tree.branch,
2840
2660
                                          tree_branch=work_tree.branch)
2846
2666
 
2847
2667
    def test_merge_preview_into_workingtree(self):
2848
2668
        tree = self.make_branch_and_tree('tree')
2849
 
        tree.set_root_id('TREE_ROOT')
2850
2669
        tt = TransformPreview(tree)
2851
2670
        self.addCleanup(tt.finalize)
2852
2671
        tt.new_file('name', tt.root, 'content', 'file-id')
2853
2672
        tree2 = self.make_branch_and_tree('tree2')
2854
 
        tree2.set_root_id('TREE_ROOT')
 
2673
        pb = progress.DummyProgress()
2855
2674
        merger = Merger.from_uncommitted(tree2, tt.get_preview_tree(),
2856
 
                                         None, tree.basis_tree())
 
2675
                                         pb, tree.basis_tree())
2857
2676
        merger.merge_type = Merge3Merger
2858
2677
        merger.do_merge()
2859
2678
 
2869
2688
        tt.create_file('baz', trans_id)
2870
2689
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
2871
2690
        self.build_tree_contents([('tree2/foo', 'qux')])
2872
 
        pb = None
 
2691
        pb = progress.DummyProgress()
2873
2692
        merger = Merger.from_uncommitted(tree2, tt.get_preview_tree(),
2874
2693
                                         pb, tree.basis_tree())
2875
2694
        merger.merge_type = Merge3Merger
2902
2721
        rev2_tree = tree.branch.repository.revision_tree(rev2_id)
2903
2722
        self.assertEqual('contents', rev2_tree.get_file_text('file_id'))
2904
2723
 
2905
 
    def test_ascii_limbo_paths(self):
2906
 
        self.requireFeature(tests.UnicodeFilenameFeature)
2907
 
        branch = self.make_branch('any')
2908
 
        tree = branch.repository.revision_tree(_mod_revision.NULL_REVISION)
2909
 
        tt = TransformPreview(tree)
2910
 
        self.addCleanup(tt.finalize)
2911
 
        foo_id = tt.new_directory('', ROOT_PARENT)
2912
 
        bar_id = tt.new_file(u'\u1234bar', foo_id, 'contents')
2913
 
        limbo_path = tt._limbo_name(bar_id)
2914
 
        self.assertEqual(limbo_path.encode('ascii', 'replace'), limbo_path)
2915
 
 
2916
2724
 
2917
2725
class FakeSerializer(object):
2918
2726
    """Serializer implementation that simply returns the input.