~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_transform.py

  • Committer: Sidnei da Silva
  • Date: 2009-05-29 14:19:29 UTC
  • mto: (4531.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 4532.
  • Revision ID: sidnei.da.silva@canonical.com-20090529141929-3heywbvj36po72a5
- Add initial config

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
 
    bencode,
24
23
    errors,
25
 
    filters,
26
24
    generate_ids,
27
25
    osutils,
28
26
    progress,
29
27
    revision as _mod_revision,
30
 
    rules,
 
28
    symbol_versioning,
31
29
    tests,
32
30
    urlutils,
33
31
    )
55
53
                              build_tree, get_backup_name,
56
54
                              _FileMover, resolve_checkout,
57
55
                              TransformPreview, create_from_tree)
 
56
from bzrlib.util import bencode
58
57
 
59
58
 
60
59
class TestTreeTransform(tests.TestCaseWithTransport):
137
136
        transform.finalize()
138
137
        transform.finalize()
139
138
 
140
 
    def test_create_files_same_timestamp(self):
141
 
        transform, root = self.get_transform()
142
 
        self.wt.lock_tree_write()
143
 
        self.addCleanup(self.wt.unlock)
144
 
        # Roll back the clock, so that we know everything is being set to the
145
 
        # exact time
146
 
        transform._creation_mtime = creation_mtime = time.time() - 20.0
147
 
        transform.create_file('content-one',
148
 
                              transform.create_path('one', root))
149
 
        time.sleep(1) # *ugly*
150
 
        transform.create_file('content-two',
151
 
                              transform.create_path('two', root))
152
 
        transform.apply()
153
 
        fo, st1 = self.wt.get_file_with_stat(None, path='one', filtered=False)
154
 
        fo.close()
155
 
        fo, st2 = self.wt.get_file_with_stat(None, path='two', filtered=False)
156
 
        fo.close()
157
 
        # We only guarantee 2s resolution
158
 
        self.assertTrue(abs(creation_mtime - st1.st_mtime) < 2.0,
159
 
            "%s != %s within 2 seconds" % (creation_mtime, st1.st_mtime))
160
 
        # But if we have more than that, all files should get the same result
161
 
        self.assertEqual(st1.st_mtime, st2.st_mtime)
162
 
 
163
 
    def test_change_root_id(self):
164
 
        transform, root = self.get_transform()
165
 
        self.assertNotEqual('new-root-id', self.wt.get_root_id())
166
 
        transform.new_directory('', ROOT_PARENT, 'new-root-id')
167
 
        transform.delete_contents(root)
168
 
        transform.unversion_file(root)
169
 
        transform.fixup_new_roots()
170
 
        transform.apply()
171
 
        self.assertEqual('new-root-id', self.wt.get_root_id())
172
 
 
173
 
    def test_change_root_id_add_files(self):
174
 
        transform, root = self.get_transform()
175
 
        self.assertNotEqual('new-root-id', self.wt.get_root_id())
176
 
        new_trans_id = transform.new_directory('', ROOT_PARENT, 'new-root-id')
177
 
        transform.new_file('file', new_trans_id, ['new-contents\n'],
178
 
                           'new-file-id')
179
 
        transform.delete_contents(root)
180
 
        transform.unversion_file(root)
181
 
        transform.fixup_new_roots()
182
 
        transform.apply()
183
 
        self.assertEqual('new-root-id', self.wt.get_root_id())
184
 
        self.assertEqual('new-file-id', self.wt.path2id('file'))
185
 
        self.assertFileEqual('new-contents\n', self.wt.abspath('file'))
186
 
 
187
 
    def test_add_two_roots(self):
188
 
        transform, root = self.get_transform()
189
 
        new_trans_id = transform.new_directory('', ROOT_PARENT, 'new-root-id')
190
 
        new_trans_id = transform.new_directory('', ROOT_PARENT, 'alt-root-id')
191
 
        self.assertRaises(ValueError, transform.fixup_new_roots)
192
 
 
193
139
    def test_hardlink(self):
194
140
        self.requireFeature(HardlinkFeature)
195
141
        transform, root = self.get_transform()
423
369
        self.assertContainsRe(transform._limbo_name(first), 'new-1/file')
424
370
        self.assertNotContainsRe(transform._limbo_name(second), 'new-1/FiLe')
425
371
 
426
 
    def test_adjust_path_updates_child_limbo_names(self):
427
 
        tree = self.make_branch_and_tree('tree')
428
 
        transform = TreeTransform(tree)
429
 
        self.addCleanup(transform.finalize)
430
 
        foo_id = transform.new_directory('foo', transform.root)
431
 
        bar_id = transform.new_directory('bar', foo_id)
432
 
        baz_id = transform.new_directory('baz', bar_id)
433
 
        qux_id = transform.new_directory('qux', baz_id)
434
 
        transform.adjust_path('quxx', foo_id, bar_id)
435
 
        self.assertStartsWith(transform._limbo_name(qux_id),
436
 
                              transform._limbo_name(bar_id))
437
 
 
438
372
    def test_add_del(self):
439
373
        start, root = self.get_transform()
440
374
        start.new_directory('a', root, 'a')
812
746
        create.apply()
813
747
        transform, root = self.get_transform()
814
748
        transform.adjust_root_path('oldroot', fun)
815
 
        new_root = transform.trans_id_tree_path('')
 
749
        new_root=transform.trans_id_tree_path('')
816
750
        transform.version_file('new-root', new_root)
817
751
        transform.apply()
818
752
 
1922
1856
        self.assertEqual([], list(target.iter_changes(revision_tree)))
1923
1857
        self.assertTrue(source.is_executable('file1-id'))
1924
1858
 
1925
 
    def install_rot13_content_filter(self, pattern):
1926
 
        # We could use
1927
 
        # self.addCleanup(filters._reset_registry, filters._reset_registry())
1928
 
        # below, but that looks a bit... hard to read even if it's exactly
1929
 
        # the same thing.
1930
 
        original_registry = filters._reset_registry()
1931
 
        def restore_registry():
1932
 
            filters._reset_registry(original_registry)
1933
 
        self.addCleanup(restore_registry)
1934
 
        def rot13(chunks, context=None):
1935
 
            return [''.join(chunks).encode('rot13')]
1936
 
        rot13filter = filters.ContentFilter(rot13, rot13)
1937
 
        filters.register_filter_stack_map('rot13', {'yes': [rot13filter]}.get)
1938
 
        os.mkdir(self.test_home_dir + '/.bazaar')
1939
 
        rules_filename = self.test_home_dir + '/.bazaar/rules'
1940
 
        f = open(rules_filename, 'wb')
1941
 
        f.write('[name %s]\nrot13=yes\n' % (pattern,))
1942
 
        f.close()
1943
 
        def uninstall_rules():
1944
 
            os.remove(rules_filename)
1945
 
            rules.reset_rules()
1946
 
        self.addCleanup(uninstall_rules)
1947
 
        rules.reset_rules()
1948
 
 
1949
 
    def test_build_tree_content_filtered_files_are_not_hardlinked(self):
1950
 
        """build_tree will not hardlink files that have content filtering rules
1951
 
        applied to them (but will still hardlink other files from the same tree
1952
 
        if it can).
1953
 
        """
1954
 
        self.requireFeature(HardlinkFeature)
1955
 
        self.install_rot13_content_filter('file1')
1956
 
        source = self.create_ab_tree()
1957
 
        target = self.make_branch_and_tree('target')
1958
 
        revision_tree = source.basis_tree()
1959
 
        revision_tree.lock_read()
1960
 
        self.addCleanup(revision_tree.unlock)
1961
 
        build_tree(revision_tree, target, source, hardlink=True)
1962
 
        target.lock_read()
1963
 
        self.addCleanup(target.unlock)
1964
 
        self.assertEqual([], list(target.iter_changes(revision_tree)))
1965
 
        source_stat = os.stat('source/file1')
1966
 
        target_stat = os.stat('target/file1')
1967
 
        self.assertNotEqual(source_stat, target_stat)
1968
 
        source_stat = os.stat('source/file2')
1969
 
        target_stat = os.stat('target/file2')
1970
 
        self.assertEqualStat(source_stat, target_stat)
1971
 
 
1972
1859
    def test_case_insensitive_build_tree_inventory(self):
1973
1860
        if (tests.CaseInsensitiveFilesystemFeature.available()
1974
1861
            or tests.CaseInsCasePresFilenameFeature.available()):
1986
1873
        self.assertEqual('FILE', target.id2path('upper-id'))
1987
1874
 
1988
1875
 
1989
 
class TestCommitTransform(tests.TestCaseWithTransport):
1990
 
 
1991
 
    def get_branch(self):
1992
 
        tree = self.make_branch_and_tree('tree')
1993
 
        tree.lock_write()
1994
 
        self.addCleanup(tree.unlock)
1995
 
        tree.commit('empty commit')
1996
 
        return tree.branch
1997
 
 
1998
 
    def get_branch_and_transform(self):
1999
 
        branch = self.get_branch()
2000
 
        tt = TransformPreview(branch.basis_tree())
2001
 
        self.addCleanup(tt.finalize)
2002
 
        return branch, tt
2003
 
 
2004
 
    def test_commit_wrong_basis(self):
2005
 
        branch = self.get_branch()
2006
 
        basis = branch.repository.revision_tree(
2007
 
            _mod_revision.NULL_REVISION)
2008
 
        tt = TransformPreview(basis)
2009
 
        self.addCleanup(tt.finalize)
2010
 
        e = self.assertRaises(ValueError, tt.commit, branch, '')
2011
 
        self.assertEqual('TreeTransform not based on branch basis: null:',
2012
 
                         str(e))
2013
 
 
2014
 
    def test_empy_commit(self):
2015
 
        branch, tt = self.get_branch_and_transform()
2016
 
        rev = tt.commit(branch, 'my message')
2017
 
        self.assertEqual(2, branch.revno())
2018
 
        repo = branch.repository
2019
 
        self.assertEqual('my message', repo.get_revision(rev).message)
2020
 
 
2021
 
    def test_merge_parents(self):
2022
 
        branch, tt = self.get_branch_and_transform()
2023
 
        rev = tt.commit(branch, 'my message', ['rev1b', 'rev1c'])
2024
 
        self.assertEqual(['rev1b', 'rev1c'],
2025
 
                         branch.basis_tree().get_parent_ids()[1:])
2026
 
 
2027
 
    def test_first_commit(self):
2028
 
        branch = self.make_branch('branch')
2029
 
        branch.lock_write()
2030
 
        self.addCleanup(branch.unlock)
2031
 
        tt = TransformPreview(branch.basis_tree())
2032
 
        self.addCleanup(tt.finalize)
2033
 
        tt.new_directory('', ROOT_PARENT, 'TREE_ROOT')
2034
 
        rev = tt.commit(branch, 'my message')
2035
 
        self.assertEqual([], branch.basis_tree().get_parent_ids())
2036
 
        self.assertNotEqual(_mod_revision.NULL_REVISION,
2037
 
                            branch.last_revision())
2038
 
 
2039
 
    def test_first_commit_with_merge_parents(self):
2040
 
        branch = self.make_branch('branch')
2041
 
        branch.lock_write()
2042
 
        self.addCleanup(branch.unlock)
2043
 
        tt = TransformPreview(branch.basis_tree())
2044
 
        self.addCleanup(tt.finalize)
2045
 
        e = self.assertRaises(ValueError, tt.commit, branch,
2046
 
                          'my message', ['rev1b-id'])
2047
 
        self.assertEqual('Cannot supply merge parents for first commit.',
2048
 
                         str(e))
2049
 
        self.assertEqual(_mod_revision.NULL_REVISION, branch.last_revision())
2050
 
 
2051
 
    def test_add_files(self):
2052
 
        branch, tt = self.get_branch_and_transform()
2053
 
        tt.new_file('file', tt.root, 'contents', 'file-id')
2054
 
        trans_id = tt.new_directory('dir', tt.root, 'dir-id')
2055
 
        if SymlinkFeature.available():
2056
 
            tt.new_symlink('symlink', trans_id, 'target', 'symlink-id')
2057
 
        rev = tt.commit(branch, 'message')
2058
 
        tree = branch.basis_tree()
2059
 
        self.assertEqual('file', tree.id2path('file-id'))
2060
 
        self.assertEqual('contents', tree.get_file_text('file-id'))
2061
 
        self.assertEqual('dir', tree.id2path('dir-id'))
2062
 
        if SymlinkFeature.available():
2063
 
            self.assertEqual('dir/symlink', tree.id2path('symlink-id'))
2064
 
            self.assertEqual('target', tree.get_symlink_target('symlink-id'))
2065
 
 
2066
 
    def test_add_unversioned(self):
2067
 
        branch, tt = self.get_branch_and_transform()
2068
 
        tt.new_file('file', tt.root, 'contents')
2069
 
        self.assertRaises(errors.StrictCommitFailed, tt.commit, branch,
2070
 
                          'message', strict=True)
2071
 
 
2072
 
    def test_modify_strict(self):
2073
 
        branch, tt = self.get_branch_and_transform()
2074
 
        tt.new_file('file', tt.root, 'contents', 'file-id')
2075
 
        tt.commit(branch, 'message', strict=True)
2076
 
        tt = TransformPreview(branch.basis_tree())
2077
 
        self.addCleanup(tt.finalize)
2078
 
        trans_id = tt.trans_id_file_id('file-id')
2079
 
        tt.delete_contents(trans_id)
2080
 
        tt.create_file('contents', trans_id)
2081
 
        tt.commit(branch, 'message', strict=True)
2082
 
 
2083
 
    def test_commit_malformed(self):
2084
 
        """Committing a malformed transform should raise an exception.
2085
 
 
2086
 
        In this case, we are adding a file without adding its parent.
2087
 
        """
2088
 
        branch, tt = self.get_branch_and_transform()
2089
 
        parent_id = tt.trans_id_file_id('parent-id')
2090
 
        tt.new_file('file', parent_id, 'contents', 'file-id')
2091
 
        self.assertRaises(errors.MalformedTransform, tt.commit, branch,
2092
 
                          'message')
2093
 
 
2094
 
 
2095
1876
class MockTransform(object):
2096
1877
 
2097
1878
    def has_named_child(self, by_parent, parent_id, name):
2264
2045
    def create_tree(self):
2265
2046
        tree = self.make_branch_and_tree('.')
2266
2047
        self.build_tree_contents([('a', 'content 1')])
2267
 
        tree.set_root_id('TREE_ROOT')
2268
2048
        tree.add('a', 'a-id')
2269
2049
        tree.commit('rev1', rev_id='rev1')
2270
2050
        return tree.branch.repository.revision_tree('rev1')
2371
2151
    def test_ignore_pb(self):
2372
2152
        # pb could be supported, but TT.iter_changes doesn't support it.
2373
2153
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
2374
 
        preview_tree.iter_changes(revision_tree)
 
2154
        preview_tree.iter_changes(revision_tree, pb=progress.DummyProgress())
2375
2155
 
2376
2156
    def test_kind(self):
2377
2157
        revision_tree = self.create_tree()
2392
2172
        self.assertEqual(os.stat(limbo_path).st_mtime,
2393
2173
                         preview_tree.get_file_mtime('file-id'))
2394
2174
 
2395
 
    def test_get_file_mtime_renamed(self):
2396
 
        work_tree = self.make_branch_and_tree('tree')
2397
 
        self.build_tree(['tree/file'])
2398
 
        work_tree.add('file', 'file-id')
2399
 
        preview = TransformPreview(work_tree)
2400
 
        self.addCleanup(preview.finalize)
2401
 
        file_trans_id = preview.trans_id_tree_file_id('file-id')
2402
 
        preview.adjust_path('renamed', preview.root, file_trans_id)
2403
 
        preview_tree = preview.get_preview_tree()
2404
 
        preview_mtime = preview_tree.get_file_mtime('file-id', 'renamed')
2405
 
        work_mtime = work_tree.get_file_mtime('file-id', 'file')
2406
 
 
2407
2175
    def test_get_file(self):
2408
2176
        preview = self.get_empty_preview()
2409
2177
        preview.new_file('file', preview.root, 'contents', 'file-id')
2557
2325
        self.assertEqual(('missing', None, None, None), summary)
2558
2326
 
2559
2327
    def test_file_content_summary_executable(self):
 
2328
        if not osutils.supports_executable():
 
2329
            raise TestNotApplicable()
2560
2330
        preview = self.get_empty_preview()
2561
2331
        path_id = preview.new_file('path', preview.root, 'contents', 'path-id')
2562
2332
        preview.set_executability(True, path_id)
2571
2341
        self.assertIs(None, summary[3])
2572
2342
 
2573
2343
    def test_change_executability(self):
 
2344
        if not osutils.supports_executable():
 
2345
            raise TestNotApplicable()
2574
2346
        tree = self.make_branch_and_tree('tree')
2575
2347
        self.build_tree(['tree/path'])
2576
2348
        tree.add('path')
2590
2362
        # size must be known
2591
2363
        self.assertEqual(len('contents'), summary[1])
2592
2364
        # not executable
2593
 
        self.assertEqual(False, summary[2])
 
2365
        if osutils.supports_executable():
 
2366
            self.assertEqual(False, summary[2])
 
2367
        else:
 
2368
            self.assertEqual(None, summary[2])
2594
2369
        # will not have hash (not cheap to determine)
2595
2370
        self.assertIs(None, summary[3])
2596
2371
 
2737
2512
 
2738
2513
    def test_walkdirs(self):
2739
2514
        preview = self.get_empty_preview()
2740
 
        root = preview.new_directory('', ROOT_PARENT, 'tree-root')
2741
 
        # FIXME: new_directory should mark root.
2742
 
        preview.fixup_new_roots()
 
2515
        preview.version_file('tree-root', preview.root)
2743
2516
        preview_tree = preview.get_preview_tree()
2744
2517
        file_trans_id = preview.new_file('a', preview.root, 'contents',
2745
2518
                                         'a-id')
2776
2549
        self.addCleanup(work_tree.unlock)
2777
2550
        preview = TransformPreview(work_tree)
2778
2551
        self.addCleanup(preview.finalize)
 
2552
        preview_tree = preview.get_preview_tree()
2779
2553
        file_trans_id = preview.trans_id_file_id('file-id')
2780
2554
        preview.delete_contents(file_trans_id)
2781
2555
        preview.create_file('a\nb\n', file_trans_id)
2782
 
        preview_tree = preview.get_preview_tree()
2783
 
        merger = Merger.from_revision_ids(None, preview_tree,
 
2556
        pb = progress.DummyProgress()
 
2557
        merger = Merger.from_revision_ids(pb, preview_tree,
2784
2558
                                          child_tree.branch.last_revision(),
2785
2559
                                          other_branch=child_tree.branch,
2786
2560
                                          tree_branch=work_tree.branch)
2792
2566
 
2793
2567
    def test_merge_preview_into_workingtree(self):
2794
2568
        tree = self.make_branch_and_tree('tree')
2795
 
        tree.set_root_id('TREE_ROOT')
2796
2569
        tt = TransformPreview(tree)
2797
2570
        self.addCleanup(tt.finalize)
2798
2571
        tt.new_file('name', tt.root, 'content', 'file-id')
2799
2572
        tree2 = self.make_branch_and_tree('tree2')
2800
 
        tree2.set_root_id('TREE_ROOT')
 
2573
        pb = progress.DummyProgress()
2801
2574
        merger = Merger.from_uncommitted(tree2, tt.get_preview_tree(),
2802
 
                                         None, tree.basis_tree())
 
2575
                                         pb, tree.basis_tree())
2803
2576
        merger.merge_type = Merge3Merger
2804
2577
        merger.do_merge()
2805
2578
 
2815
2588
        tt.create_file('baz', trans_id)
2816
2589
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
2817
2590
        self.build_tree_contents([('tree2/foo', 'qux')])
2818
 
        pb = None
 
2591
        pb = progress.DummyProgress()
2819
2592
        merger = Merger.from_uncommitted(tree2, tt.get_preview_tree(),
2820
2593
                                         pb, tree.basis_tree())
2821
2594
        merger.merge_type = Merge3Merger
2848
2621
        rev2_tree = tree.branch.repository.revision_tree(rev2_id)
2849
2622
        self.assertEqual('contents', rev2_tree.get_file_text('file_id'))
2850
2623
 
2851
 
    def test_ascii_limbo_paths(self):
2852
 
        self.requireFeature(tests.UnicodeFilenameFeature)
2853
 
        branch = self.make_branch('any')
2854
 
        tree = branch.repository.revision_tree(_mod_revision.NULL_REVISION)
2855
 
        tt = TransformPreview(tree)
2856
 
        self.addCleanup(tt.finalize)
2857
 
        foo_id = tt.new_directory('', ROOT_PARENT)
2858
 
        bar_id = tt.new_file(u'\u1234bar', foo_id, 'contents')
2859
 
        limbo_path = tt._limbo_name(bar_id)
2860
 
        self.assertEqual(limbo_path.encode('ascii', 'replace'), limbo_path)
2861
 
 
2862
2624
 
2863
2625
class FakeSerializer(object):
2864
2626
    """Serializer implementation that simply returns the input.