/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
1711.7.18 by John Arbash Meinel
Old repository formats didn't support double locking on win32, don't raise errors
19
import sys
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
20
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.
21
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.
22
import bzrlib.bzrdir as bzrdir
23
from bzrlib.branch import Branch, needs_read_lock, needs_write_lock
24
import bzrlib.errors as errors
25
from bzrlib.errors import (FileExists,
26
                           NoSuchRevision,
27
                           NoSuchFile,
28
                           UninitializableFormat,
29
                           NotBranchError,
30
                           )
31
import bzrlib.repository as repository
1694.2.6 by Martin Pool
[merge] bzr.dev
32
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.
33
from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
34
from bzrlib.tests.bzrdir_implementations.test_bzrdir import TestCaseWithBzrDir
35
from bzrlib.transport import get_transport
36
37
38
class TestCaseWithInterRepository(TestCaseWithBzrDir):
39
40
    def setUp(self):
41
        super(TestCaseWithInterRepository, self).setUp()
42
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
43
    def make_branch(self, relpath, format=None):
44
        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.
45
        return repo.bzrdir.create_branch()
46
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
47
    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.
48
        try:
49
            url = self.get_url(relpath)
50
            segments = url.split('/')
51
            if segments and segments[-1] not in ('', '.'):
52
                parent = '/'.join(segments[:-1])
53
                t = get_transport(parent)
54
                try:
55
                    t.mkdir(segments[-1])
56
                except FileExists:
57
                    pass
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
58
            if format is None:
59
                format = self.repository_format._matchingbzrdir
60
            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.
61
        except UninitializableFormat:
1684.1.4 by Martin Pool
(patch) better warnings when tests are skipped (Alexander)
62
            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.
63
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
64
    def make_repository(self, relpath, format=None):
65
        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.
66
        return self.repository_format.initialize(made_control)
67
68
    def make_to_repository(self, relpath):
69
        made_control = self.make_bzrdir(relpath,
70
            self.repository_format_to._matchingbzrdir)
1534.1.30 by Robert Collins
Test that we get the right optimiser back in the InterRepository tests.
71
        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.
72
73
1711.7.18 by John Arbash Meinel
Old repository formats didn't support double locking on win32, don't raise errors
74
def check_old_format_lock_error(repository_format):
75
    """Potentially ignore LockError on old formats.
76
77
    On win32, with the old OS locks, we get a failure of double-lock when
78
    we open a object in 2 objects and try to lock both.
79
80
    On new formats, LockError would be invalid, but for old formats
81
    this was not supported on Win32.
82
    """
83
    if sys.platform != 'win32':
84
        raise
85
86
    description = repository_format.get_format_description()
87
    if description in ("Repository format 4",
88
                       "Weave repository format 5",
89
                       "Weave repository format 6"):
1711.7.30 by John Arbash Meinel
Switch to using TestSkipped for old win32 problems
90
        # jam 20060701
91
        # win32 OS locks are not re-entrant. So one process cannot
92
        # open the same repository twice and lock them both.
93
        raise TestSkipped('%s on win32 cannot open the same'
94
                          ' repository twice in different objects'
95
                          % description)
1711.7.18 by John Arbash Meinel
Old repository formats didn't support double locking on win32, don't raise errors
96
    raise
97
98
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
99
class TestInterRepository(TestCaseWithInterRepository):
100
1534.1.30 by Robert Collins
Test that we get the right optimiser back in the InterRepository tests.
101
    def test_interrepository_get_returns_correct_optimiser(self):
102
        # we assume the optimising code paths are triggered
103
        # by the type of the repo not the transport - at this point.
104
        # we may need to update this test if this changes.
105
        source_repo = self.make_repository("source")
106
        target_repo = self.make_to_repository("target")
107
        interrepo = repository.InterRepository.get(source_repo, target_repo)
108
        self.assertEqual(self.interrepo_class, interrepo.__class__)
109
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
110
    def test_fetch(self):
111
        tree_a = self.make_branch_and_tree('a')
112
        self.build_tree(['a/foo'])
113
        tree_a.add('foo', 'file1')
114
        tree_a.commit('rev1', rev_id='rev1')
115
        def check_push_rev1(repo):
116
            # ensure the revision is missing.
117
            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.
118
            # fetch with a limit of NULL_REVISION and an explicit progress bar.
119
            repo.fetch(tree_a.branch.repository,
120
                       revision_id=NULL_REVISION,
121
                       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.
122
            # nothing should have been pushed
123
            self.assertFalse(repo.has_revision('rev1'))
124
            # fetch with a default limit (grab everything)
125
            repo.fetch(tree_a.branch.repository)
126
            # check that b now has all the data from a's first commit.
127
            rev = repo.get_revision('rev1')
128
            tree = repo.revision_tree('rev1')
129
            tree.get_file_text('file1')
130
            for file_id in tree:
131
                if tree.inventory[file_id].kind == "file":
132
                    tree.get_file(file_id).read()
133
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.
134
        # makes a target version repo 
135
        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.
136
        check_push_rev1(repo_b)
137
        
138
    def test_fetch_missing_revision_same_location_fails(self):
139
        repo_a = self.make_repository('.')
140
        repo_b = repository.Repository.open('.')
1711.7.18 by John Arbash Meinel
Old repository formats didn't support double locking on win32, don't raise errors
141
        try:
142
            self.assertRaises(errors.NoSuchRevision, repo_b.fetch, repo_a, revision_id='XXX')
143
        except errors.LockError, e:
144
            check_old_format_lock_error(self.repository_format)
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
145
146
    def test_fetch_same_location_trivial_works(self):
147
        repo_a = self.make_repository('.')
148
        repo_b = repository.Repository.open('.')
1711.7.18 by John Arbash Meinel
Old repository formats didn't support double locking on win32, don't raise errors
149
        try:
150
            repo_a.fetch(repo_b)
151
        except errors.LockError, e:
152
            check_old_format_lock_error(self.repository_format)
1534.1.34 by Robert Collins
Move missing_revision_ids from Repository to InterRepository, and eliminate the now unused Repository._compatible_formats method.
153
1694.2.6 by Martin Pool
[merge] bzr.dev
154
    def test_fetch_missing_text_other_location_fails(self):
155
        source_tree = self.make_branch_and_tree('source')
156
        source = source_tree.branch.repository
157
        target = self.make_to_repository('target')
158
    
159
        # start by adding a file so the data for hte file exists.
160
        self.build_tree(['source/id'])
161
        source_tree.add(['id'], ['id'])
162
        source_tree.commit('a', rev_id='a')
163
        # now we manually insert a revision with an inventory referencing
164
        # 'id' at revision 'b', but we do not insert revision b.
165
        # this should ensure that the new versions of files are being checked
166
        # for during pull operations
167
        inv = source.get_inventory('a')
168
        inv['id'].revision = 'b'
1740.2.6 by Aaron Bentley
Update test for new interface
169
        inv.revision_id = 'b'
1694.2.6 by Martin Pool
[merge] bzr.dev
170
        sha1 = source.add_inventory('b', inv, ['a'])
171
        rev = Revision(timestamp=0,
172
                       timezone=None,
173
                       committer="Foo Bar <foo@example.com>",
174
                       message="Message",
175
                       inventory_sha1=sha1,
176
                       revision_id='b')
177
        rev.parent_ids = ['a']
178
        source.add_revision('b', rev)
179
        self.assertRaises(errors.RevisionNotPresent, target.fetch, source)
180
        self.assertFalse(target.has_revision('b'))
181
1843.2.1 by Aaron Bentley
Add failing tests for funky ids
182
    def test_fetch_funky_file_id(self):
183
        from_tree = self.make_branch_and_tree('tree')
184
        self.build_tree(['tree/filename'])
185
        from_tree.add('filename', 'funky-chars<>%&;"\'')
186
        from_tree.commit('commit filename')
187
        to_repo = self.make_to_repository('to')
188
        to_repo.fetch(from_tree.branch.repository, from_tree.last_revision())
189
1534.1.34 by Robert Collins
Move missing_revision_ids from Repository to InterRepository, and eliminate the now unused Repository._compatible_formats method.
190
191
class TestCaseWithComplexRepository(TestCaseWithInterRepository):
192
193
    def setUp(self):
194
        super(TestCaseWithComplexRepository, self).setUp()
195
        tree_a = self.make_branch_and_tree('a')
196
        self.bzrdir = tree_a.branch.bzrdir
197
        # 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.
198
        inv_file = tree_a.branch.repository.control_weaves.get_weave(
199
            'inventory', 
1534.1.34 by Robert Collins
Move missing_revision_ids from Repository to InterRepository, and eliminate the now unused Repository._compatible_formats method.
200
            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.
201
        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.
202
        # add a real revision 'rev1'
203
        tree_a.commit('rev1', rev_id='rev1', allow_pointless=True)
204
        # add a real revision 'rev2' based on rev1
205
        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.
206
        # and sign 'rev2'
207
        tree_a.branch.repository.sign_revision('rev2',
208
            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.
209
210
    def test_missing_revision_ids(self):
211
        # revision ids in repository A but not B are returned, fake ones
212
        # are stripped. (fake meaning no revision object, but an inventory 
213
        # as some formats keyed off inventory data in the past.
214
        # make a repository to compare against that claims to have rev1
215
        repo_b = self.make_to_repository('rev1_only')
216
        repo_a = self.bzrdir.open_repository()
217
        repo_b.fetch(repo_a, 'rev1')
218
        # check the test will be valid
219
        self.assertFalse(repo_b.has_revision('rev2'))
220
        self.assertEqual(['rev2'],
221
                         repo_b.missing_revision_ids(repo_a))
222
223
    def test_missing_revision_ids_revision_limited(self):
224
        # revision ids in repository A that are not referenced by the
225
        # requested revision are not returned.
226
        # make a repository to compare against that is empty
227
        repo_b = self.make_to_repository('empty')
228
        repo_a = self.bzrdir.open_repository()
229
        self.assertEqual(['rev1'],
230
                         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.
231
        
232
    def test_fetch_preserves_signatures(self):
233
        from_repo = self.bzrdir.open_repository()
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
234
        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.
235
        to_repo = self.make_to_repository('target')
236
        to_repo.fetch(from_repo)
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
237
        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.
238
        self.assertEqual(from_signature, to_signature)
239
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
240
241
class TestCaseWithGhosts(TestCaseWithInterRepository):
242
243
    def setUp(self):
244
        super(TestCaseWithGhosts, self).setUp()
245
        # we want two repositories at this point
246
        # one with a revision that is a ghost in the other
247
        # repository.
248
249
        # 'ghost' is a ghost in missing_ghost and not in with_ghost_rev
250
        inv = bzrlib.tree.EmptyTree().inventory
251
        repo = self.make_repository('with_ghost_rev')
252
        sha1 = repo.add_inventory('ghost', inv, [])
253
        rev = bzrlib.revision.Revision(timestamp=0,
254
                                       timezone=None,
255
                                       committer="Foo Bar <foo@example.com>",
256
                                       message="Message",
257
                                       inventory_sha1=sha1,
258
                                       revision_id='ghost')
259
        rev.parent_ids = []
260
        repo.add_revision('ghost', rev)
261
         
262
        repo = self.make_to_repository('missing_ghost')
263
        sha1 = repo.add_inventory('with_ghost', inv, [])
264
        rev = bzrlib.revision.Revision(timestamp=0,
265
                                       timezone=None,
266
                                       committer="Foo Bar <foo@example.com>",
267
                                       message="Message",
268
                                       inventory_sha1=sha1,
269
                                       revision_id='with_ghost')
270
        rev.parent_ids = ['ghost']
271
        repo.add_revision('with_ghost', rev)
272
273
    def test_fetch_all_fixes_up_ghost(self):
274
        # fetching from a repo with a current ghost unghosts it in referencing
275
        # revisions.
276
        repo = repository.Repository.open('missing_ghost')
277
        rev = repo.get_revision('with_ghost')
278
        from_repo = repository.Repository.open('with_ghost_rev')
279
        repo.fetch(from_repo)
280
        # rev must not be corrupt now
281
        rev = repo.get_revision('with_ghost')
282
        self.assertEqual([None, 'ghost', 'with_ghost'], repo.get_ancestry('with_ghost'))