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