/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
1
# (C) 2005, 2006 Canonical Ltd
2
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Tests for InterRepository implementastions."""
18
19
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
20
import bzrlib
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
21
import bzrlib.bzrdir as bzrdir
22
from bzrlib.branch import Branch, needs_read_lock, needs_write_lock
23
import bzrlib.errors as errors
24
from bzrlib.errors import (FileExists,
25
                           NoSuchRevision,
26
                           NoSuchFile,
27
                           UninitializableFormat,
28
                           NotBranchError,
29
                           )
30
import bzrlib.repository as repository
1694.2.6 by Martin Pool
[merge] bzr.dev
31
from bzrlib.revision import NULL_REVISION, Revision
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
32
from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
33
from bzrlib.tests.bzrdir_implementations.test_bzrdir import TestCaseWithBzrDir
34
from bzrlib.transport import get_transport
35
36
37
class TestCaseWithInterRepository(TestCaseWithBzrDir):
38
39
    def setUp(self):
40
        super(TestCaseWithInterRepository, self).setUp()
41
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
42
    def make_branch(self, relpath, format=None):
43
        repo = self.make_repository(relpath, format=format)
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
44
        return repo.bzrdir.create_branch()
45
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
46
    def make_bzrdir(self, relpath, format=None):
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
47
        try:
48
            url = self.get_url(relpath)
49
            segments = url.split('/')
50
            if segments and segments[-1] not in ('', '.'):
51
                parent = '/'.join(segments[:-1])
52
                t = get_transport(parent)
53
                try:
54
                    t.mkdir(segments[-1])
55
                except FileExists:
56
                    pass
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
57
            if format is None:
58
                format = self.repository_format._matchingbzrdir
59
            return format.initialize(url)
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
60
        except UninitializableFormat:
1684.1.4 by Martin Pool
(patch) better warnings when tests are skipped (Alexander)
61
            raise TestSkipped("Format %s is not initializable." % format)
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
62
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
63
    def make_repository(self, relpath, format=None):
64
        made_control = self.make_bzrdir(relpath, format=format)
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
65
        return self.repository_format.initialize(made_control)
66
67
    def make_to_repository(self, relpath):
68
        made_control = self.make_bzrdir(relpath,
69
            self.repository_format_to._matchingbzrdir)
1534.1.30 by Robert Collins
Test that we get the right optimiser back in the InterRepository tests.
70
        return self.repository_format_to.initialize(made_control)
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
71
72
73
class TestInterRepository(TestCaseWithInterRepository):
74
1534.1.30 by Robert Collins
Test that we get the right optimiser back in the InterRepository tests.
75
    def test_interrepository_get_returns_correct_optimiser(self):
76
        # we assume the optimising code paths are triggered
77
        # by the type of the repo not the transport - at this point.
78
        # we may need to update this test if this changes.
79
        source_repo = self.make_repository("source")
80
        target_repo = self.make_to_repository("target")
81
        interrepo = repository.InterRepository.get(source_repo, target_repo)
82
        self.assertEqual(self.interrepo_class, interrepo.__class__)
83
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
84
    def test_fetch(self):
85
        tree_a = self.make_branch_and_tree('a')
86
        self.build_tree(['a/foo'])
87
        tree_a.add('foo', 'file1')
88
        tree_a.commit('rev1', rev_id='rev1')
89
        def check_push_rev1(repo):
90
            # ensure the revision is missing.
91
            self.assertRaises(NoSuchRevision, repo.get_revision, 'rev1')
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
92
            # fetch with a limit of NULL_REVISION and an explicit progress bar.
93
            repo.fetch(tree_a.branch.repository,
94
                       revision_id=NULL_REVISION,
95
                       pb=bzrlib.progress.DummyProgress())
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
96
            # nothing should have been pushed
97
            self.assertFalse(repo.has_revision('rev1'))
98
            # fetch with a default limit (grab everything)
99
            repo.fetch(tree_a.branch.repository)
100
            # check that b now has all the data from a's first commit.
101
            rev = repo.get_revision('rev1')
102
            tree = repo.revision_tree('rev1')
103
            tree.get_file_text('file1')
104
            for file_id in tree:
105
                if tree.inventory[file_id].kind == "file":
106
                    tree.get_file(file_id).read()
107
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
108
        # makes a target version repo 
109
        repo_b = self.make_to_repository('b')
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
110
        check_push_rev1(repo_b)
111
        
112
    def test_fetch_missing_revision_same_location_fails(self):
113
        repo_a = self.make_repository('.')
114
        repo_b = repository.Repository.open('.')
115
        self.assertRaises(errors.NoSuchRevision, repo_b.fetch, repo_a, revision_id='XXX')
116
117
    def test_fetch_same_location_trivial_works(self):
118
        repo_a = self.make_repository('.')
119
        repo_b = repository.Repository.open('.')
120
        repo_a.fetch(repo_b)
1534.1.34 by Robert Collins
Move missing_revision_ids from Repository to InterRepository, and eliminate the now unused Repository._compatible_formats method.
121
1694.2.6 by Martin Pool
[merge] bzr.dev
122
    def test_fetch_missing_text_other_location_fails(self):
123
        source_tree = self.make_branch_and_tree('source')
124
        source = source_tree.branch.repository
125
        target = self.make_to_repository('target')
126
    
127
        # start by adding a file so the data for hte file exists.
128
        self.build_tree(['source/id'])
129
        source_tree.add(['id'], ['id'])
130
        source_tree.commit('a', rev_id='a')
131
        # now we manually insert a revision with an inventory referencing
132
        # 'id' at revision 'b', but we do not insert revision b.
133
        # this should ensure that the new versions of files are being checked
134
        # for during pull operations
135
        inv = source.get_inventory('a')
136
        inv['id'].revision = 'b'
1740.2.6 by Aaron Bentley
Update test for new interface
137
        inv.revision_id = 'b'
1694.2.6 by Martin Pool
[merge] bzr.dev
138
        sha1 = source.add_inventory('b', inv, ['a'])
139
        rev = Revision(timestamp=0,
140
                       timezone=None,
141
                       committer="Foo Bar <foo@example.com>",
142
                       message="Message",
143
                       inventory_sha1=sha1,
144
                       revision_id='b')
145
        rev.parent_ids = ['a']
146
        source.add_revision('b', rev)
147
        self.assertRaises(errors.RevisionNotPresent, target.fetch, source)
148
        self.assertFalse(target.has_revision('b'))
149
1534.1.34 by Robert Collins
Move missing_revision_ids from Repository to InterRepository, and eliminate the now unused Repository._compatible_formats method.
150
151
class TestCaseWithComplexRepository(TestCaseWithInterRepository):
152
153
    def setUp(self):
154
        super(TestCaseWithComplexRepository, self).setUp()
155
        tree_a = self.make_branch_and_tree('a')
156
        self.bzrdir = tree_a.branch.bzrdir
157
        # add a corrupt inventory 'orphan'
1563.2.10 by Robert Collins
Change weave store to be a versioned store, using WeaveFiles which maintain integrity without needing explicit 'put' operations.
158
        inv_file = tree_a.branch.repository.control_weaves.get_weave(
159
            'inventory', 
1534.1.34 by Robert Collins
Move missing_revision_ids from Repository to InterRepository, and eliminate the now unused Repository._compatible_formats method.
160
            tree_a.branch.repository.get_transaction())
1563.2.10 by Robert Collins
Change weave store to be a versioned store, using WeaveFiles which maintain integrity without needing explicit 'put' operations.
161
        inv_file.add_lines('orphan', [], [])
1534.1.34 by Robert Collins
Move missing_revision_ids from Repository to InterRepository, and eliminate the now unused Repository._compatible_formats method.
162
        # add a real revision 'rev1'
163
        tree_a.commit('rev1', rev_id='rev1', allow_pointless=True)
164
        # add a real revision 'rev2' based on rev1
165
        tree_a.commit('rev2', rev_id='rev2', allow_pointless=True)
1556.1.4 by Robert Collins
Add a new format for what will become knit, and the surrounding logic to upgrade repositories within metadirs, and tests for the same.
166
        # and sign 'rev2'
167
        tree_a.branch.repository.sign_revision('rev2',
168
            bzrlib.gpg.LoopbackGPGStrategy(None))
1534.1.34 by Robert Collins
Move missing_revision_ids from Repository to InterRepository, and eliminate the now unused Repository._compatible_formats method.
169
170
    def test_missing_revision_ids(self):
171
        # revision ids in repository A but not B are returned, fake ones
172
        # are stripped. (fake meaning no revision object, but an inventory 
173
        # as some formats keyed off inventory data in the past.
174
        # make a repository to compare against that claims to have rev1
175
        repo_b = self.make_to_repository('rev1_only')
176
        repo_a = self.bzrdir.open_repository()
177
        repo_b.fetch(repo_a, 'rev1')
178
        # check the test will be valid
179
        self.assertFalse(repo_b.has_revision('rev2'))
180
        self.assertEqual(['rev2'],
181
                         repo_b.missing_revision_ids(repo_a))
182
183
    def test_missing_revision_ids_revision_limited(self):
184
        # revision ids in repository A that are not referenced by the
185
        # requested revision are not returned.
186
        # make a repository to compare against that is empty
187
        repo_b = self.make_to_repository('empty')
188
        repo_a = self.bzrdir.open_repository()
189
        self.assertEqual(['rev1'],
190
                         repo_b.missing_revision_ids(repo_a, revision_id='rev1'))
1556.1.4 by Robert Collins
Add a new format for what will become knit, and the surrounding logic to upgrade repositories within metadirs, and tests for the same.
191
        
192
    def test_fetch_preserves_signatures(self):
193
        from_repo = self.bzrdir.open_repository()
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
194
        from_signature = from_repo.get_signature_text('rev2')
1556.1.4 by Robert Collins
Add a new format for what will become knit, and the surrounding logic to upgrade repositories within metadirs, and tests for the same.
195
        to_repo = self.make_to_repository('target')
196
        to_repo.fetch(from_repo)
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
197
        to_signature = to_repo.get_signature_text('rev2')
1556.1.4 by Robert Collins
Add a new format for what will become knit, and the surrounding logic to upgrade repositories within metadirs, and tests for the same.
198
        self.assertEqual(from_signature, to_signature)
199
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
200
201
class TestCaseWithGhosts(TestCaseWithInterRepository):
202
203
    def setUp(self):
204
        super(TestCaseWithGhosts, self).setUp()
205
        # we want two repositories at this point
206
        # one with a revision that is a ghost in the other
207
        # repository.
208
209
        # 'ghost' is a ghost in missing_ghost and not in with_ghost_rev
210
        inv = bzrlib.tree.EmptyTree().inventory
211
        repo = self.make_repository('with_ghost_rev')
212
        sha1 = repo.add_inventory('ghost', inv, [])
213
        rev = bzrlib.revision.Revision(timestamp=0,
214
                                       timezone=None,
215
                                       committer="Foo Bar <foo@example.com>",
216
                                       message="Message",
217
                                       inventory_sha1=sha1,
218
                                       revision_id='ghost')
219
        rev.parent_ids = []
220
        repo.add_revision('ghost', rev)
221
         
222
        repo = self.make_to_repository('missing_ghost')
223
        sha1 = repo.add_inventory('with_ghost', inv, [])
224
        rev = bzrlib.revision.Revision(timestamp=0,
225
                                       timezone=None,
226
                                       committer="Foo Bar <foo@example.com>",
227
                                       message="Message",
228
                                       inventory_sha1=sha1,
229
                                       revision_id='with_ghost')
230
        rev.parent_ids = ['ghost']
231
        repo.add_revision('with_ghost', rev)
232
233
    def test_fetch_all_fixes_up_ghost(self):
234
        # fetching from a repo with a current ghost unghosts it in referencing
235
        # revisions.
236
        repo = repository.Repository.open('missing_ghost')
237
        rev = repo.get_revision('with_ghost')
238
        from_repo = repository.Repository.open('with_ghost_rev')
239
        repo.fetch(from_repo)
240
        # rev must not be corrupt now
241
        rev = repo.get_revision('with_ghost')
242
        self.assertEqual([None, 'ghost', 'with_ghost'], repo.get_ancestry('with_ghost'))