/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
1
# Copyright (C) 2005, 2006, 2008 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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
16
17
18
import sys
19
20
import bzrlib
21
from bzrlib import (
22
    errors,
3735.2.135 by Robert Collins
Permit fetching bzr.dev [deal with inconsistent inventories.]
23
    inventory,
24
    osutils,
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
25
    repository,
3735.2.135 by Robert Collins
Permit fetching bzr.dev [deal with inconsistent inventories.]
26
    versionedfile,
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
27
    )
28
from bzrlib.errors import (
29
    NoSuchRevision,
30
    )
4476.3.11 by Andrew Bennetts
All fetch and interrepo tests passing.
31
from bzrlib.graph import (
32
    SearchResult,
33
    )
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
34
from bzrlib.revision import (
35
    NULL_REVISION,
36
    Revision,
37
    )
38
from bzrlib.tests import (
39
    TestNotApplicable,
40
    )
41
from bzrlib.tests.interrepository_implementations import (
42
    TestCaseWithInterRepository,
43
    )
3616.2.3 by Mark Hammond
Fix test failures due to missing check_repo_format_for_funky_id_on_win32
44
from bzrlib.tests.interrepository_implementations.test_interrepository import (
45
    check_repo_format_for_funky_id_on_win32
46
    )
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
47
48
49
class TestInterRepository(TestCaseWithInterRepository):
50
51
    def test_fetch(self):
52
        tree_a = self.make_branch_and_tree('a')
53
        self.build_tree(['a/foo'])
54
        tree_a.add('foo', 'file1')
55
        tree_a.commit('rev1', rev_id='rev1')
56
        def check_push_rev1(repo):
57
            # ensure the revision is missing.
58
            self.assertRaises(NoSuchRevision, repo.get_revision, 'rev1')
4110.2.5 by Martin Pool
Deprecate passing pbs in to fetch()
59
            # fetch with a limit of NULL_REVISION
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
60
            repo.fetch(tree_a.branch.repository,
4110.2.5 by Martin Pool
Deprecate passing pbs in to fetch()
61
                       revision_id=NULL_REVISION)
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
62
            # nothing should have been pushed
63
            self.assertFalse(repo.has_revision('rev1'))
64
            # fetch with a default limit (grab everything)
65
            repo.fetch(tree_a.branch.repository)
66
            # check that b now has all the data from a's first commit.
67
            rev = repo.get_revision('rev1')
68
            tree = repo.revision_tree('rev1')
69
            tree.lock_read()
70
            self.addCleanup(tree.unlock)
71
            tree.get_file_text('file1')
72
            for file_id in tree:
73
                if tree.inventory[file_id].kind == "file":
74
                    tree.get_file(file_id).read()
75
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
76
        # makes a target version repo
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
77
        repo_b = self.make_to_repository('b')
78
        check_push_rev1(repo_b)
79
3735.2.135 by Robert Collins
Permit fetching bzr.dev [deal with inconsistent inventories.]
80
    def test_fetch_inconsistent_last_changed_entries(self):
81
        """If an inventory has odd data we should still get what it references.
3735.31.2 by John Arbash Meinel
Cleanup trailing whitespace, get test_source to pass by removing asserts.
82
3735.2.135 by Robert Collins
Permit fetching bzr.dev [deal with inconsistent inventories.]
83
        This test tests that we do fetch a file text created in a revision not
84
        being fetched, but referenced from the revision we are fetching when the
85
        adjacent revisions to the one being fetched do not reference that text.
86
        """
87
        tree = self.make_branch_and_tree('source')
88
        revid = tree.commit('old')
89
        to_repo = self.make_to_repository('to_repo')
90
        to_repo.fetch(tree.branch.repository, revid)
91
        # Make a broken revision and fetch it.
92
        source = tree.branch.repository
93
        source.lock_write()
94
        self.addCleanup(source.unlock)
95
        source.start_write_group()
96
        try:
97
            # We need two revisions: OLD and NEW. NEW will claim to need a file
98
            # 'FOO' changed in 'OLD'. OLD will not have that file at all.
99
            source.texts.insert_record_stream([
100
                versionedfile.FulltextContentFactory(('foo', revid), (), None,
101
                'contents')])
102
            basis = source.revision_tree(revid)
103
            parent_id = basis.path2id('')
104
            entry = inventory.make_entry('file', 'foo-path', parent_id, 'foo')
105
            entry.revision = revid
106
            entry.text_size = len('contents')
107
            entry.text_sha1 = osutils.sha_string('contents')
108
            inv_sha1, _ = source.add_inventory_by_delta(revid, [
109
                (None, 'foo-path', 'foo', entry)], 'new', [revid])
110
            rev = Revision(timestamp=0,
111
                           timezone=None,
112
                           committer="Foo Bar <foo@example.com>",
113
                           message="Message",
114
                           inventory_sha1=inv_sha1,
115
                           revision_id='new',
116
                           parent_ids=[revid])
117
            source.add_revision(rev.revision_id, rev)
118
        except:
119
            source.abort_write_group()
120
            raise
121
        else:
122
            source.commit_write_group()
123
        to_repo.fetch(source, 'new')
124
        to_repo.lock_read()
125
        self.addCleanup(to_repo.unlock)
126
        self.assertEqual('contents',
127
            to_repo.texts.get_record_stream([('foo', revid)],
128
            'unordered', True).next().get_bytes_as('fulltext'))
129
4476.3.15 by Andrew Bennetts
Partially working fallback for pre-1.17 servers.
130
    def test_fetch_parent_inventories_at_stacking_boundary_smart(self):
131
        self.setup_smart_server_with_call_log()
132
        self.test_fetch_parent_inventories_at_stacking_boundary()
133
134
    def disable_verb(self, verb):
135
        """Disable a verb for one test."""
136
        from bzrlib.smart import request
137
        request_handlers = request.request_handlers
138
        orig_method = request_handlers.get(verb)
139
        request_handlers.remove(verb)
140
        def restoreVerb():
141
            request_handlers.register(verb, orig_method)
142
        self.addCleanup(restoreVerb)
143
144
    def test_fetch_parent_inventories_at_stacking_boundary_smart_old(self):
145
        self.setup_smart_server_with_call_log()
146
        self.disable_verb('Repository.insert_stream_1.17')
147
        self.test_fetch_parent_inventories_at_stacking_boundary()
148
4257.3.1 by Andrew Bennetts
Add failing test.
149
    def test_fetch_parent_inventories_at_stacking_boundary(self):
4257.3.9 by Andrew Bennetts
Add fix to InterDifferingSerializer too, although it's pretty ugly.
150
        """Fetch to a stacked branch copies inventories for parents of
151
        revisions at the stacking boundary.
152
153
        This is necessary so that the server is able to determine the file-ids
154
        altered by all revisions it contains, which means that it needs both
155
        the inventory for any revision it has, and the inventories of all that
156
        revision's parents.
157
        """
4257.3.1 by Andrew Bennetts
Add failing test.
158
        to_repo = self.make_to_repository('to')
159
        if not to_repo._format.supports_external_lookups:
160
            raise TestNotApplicable("Need stacking support in the target.")
161
        builder = self.make_branch_builder('branch')
162
        builder.start_series()
163
        builder.build_snapshot('base', None, [
164
            ('add', ('', 'root-id', 'directory', ''))])
165
        builder.build_snapshot('left', ['base'], [])
166
        builder.build_snapshot('right', ['base'], [])
167
        builder.build_snapshot('merge', ['left', 'right'], [])
168
        builder.finish_series()
169
        branch = builder.get_branch()
170
        repo = self.make_to_repository('trunk')
171
        trunk = repo.bzrdir.create_branch()
172
        trunk.repository.fetch(branch.repository, 'left')
173
        trunk.repository.fetch(branch.repository, 'right')
174
        repo = self.make_to_repository('stacked')
175
        stacked_branch = repo.bzrdir.create_branch()
176
        stacked_branch.set_stacked_on_url(trunk.base)
177
        stacked_branch.repository.fetch(branch.repository, 'merge')
178
        unstacked_repo = stacked_branch.bzrdir.open_repository()
179
        unstacked_repo.lock_read()
180
        self.addCleanup(unstacked_repo.unlock)
4476.3.16 by Andrew Bennetts
Only make inv deltas against bases we've already sent, and other tweaks.
181
        if not unstacked_repo._format.supports_chks:
182
            # these assertions aren't valid for groupcompress repos, which may
183
            # transfer data than strictly necessary to avoid breaking up an
184
            # already-compressed block of data.
185
            self.assertFalse(unstacked_repo.has_revision('left'))
186
            self.assertFalse(unstacked_repo.has_revision('right'))
4476.3.11 by Andrew Bennetts
All fetch and interrepo tests passing.
187
        self.assertTrue(unstacked_repo.has_revision('merge'))
188
        # We used to check for the presence of parent invs here, but what
189
        # really matters is that the repo can stream the new revision without
190
        # the help of any fallback repos.
191
        self.assertCanStreamRevision(unstacked_repo, 'merge')
192
193
    def assertCanStreamRevision(self, repo, revision_id):
194
        exclude_keys = set(repo.all_revision_ids()) - set([revision_id])
195
        search = SearchResult([revision_id], exclude_keys, 1, [revision_id])
196
        source = repo._get_source(repo._format)
197
        for substream_kind, substream in source.get_stream(search):
198
            # Consume the substream
199
            list(substream)
4257.3.1 by Andrew Bennetts
Add failing test.
200
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
201
    def test_fetch_missing_basis_text(self):
202
        """If fetching a delta, we should die if a basis is not present."""
203
        tree = self.make_branch_and_tree('tree')
204
        self.build_tree(['tree/a'])
205
        tree.add(['a'], ['a-id'])
206
        tree.commit('one', rev_id='rev-one')
207
        self.build_tree_contents([('tree/a', 'new contents\n')])
208
        tree.commit('two', rev_id='rev-two')
209
210
        to_repo = self.make_to_repository('to_repo')
211
        # We build a broken revision so that we can test the fetch code dies
212
        # properly. So copy the inventory and revision, but not the text.
213
        to_repo.lock_write()
214
        try:
215
            to_repo.start_write_group()
216
            inv = tree.branch.repository.get_inventory('rev-one')
217
            to_repo.add_inventory('rev-one', inv, [])
218
            rev = tree.branch.repository.get_revision('rev-one')
219
            to_repo.add_revision('rev-one', rev, inv=inv)
220
            to_repo.commit_write_group()
221
        finally:
222
            to_repo.unlock()
223
3350.3.21 by Robert Collins
Merge bzr.dev.
224
        # Implementations can either ensure that the target of the delta is
225
        # reconstructable, or raise an exception (which stream based copies
226
        # generally do).
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
227
        try:
228
            to_repo.fetch(tree.branch.repository, 'rev-two')
3830.3.12 by Martin Pool
Review cleanups: unify has_key impls, add missing_keys(), clean up exception blocks
229
        except (errors.BzrCheckError, errors.RevisionNotPresent), e:
230
            # If an exception is raised, the revision should not be in the
231
            # target.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
232
            #
3830.3.9 by Martin Pool
Simplify kvf insert_record_stream; add has_key shorthand methods; update stacking effort tests
233
            # Can also just raise a generic check errors; stream insertion
234
            # does this to include all the missing data
235
            self.assertRaises((errors.NoSuchRevision, errors.RevisionNotPresent),
236
                              to_repo.revision_tree, 'rev-two')
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
237
        else:
3350.3.21 by Robert Collins
Merge bzr.dev.
238
            # If not exception is raised, then the text should be
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
239
            # available.
240
            to_repo.lock_read()
241
            try:
3350.3.21 by Robert Collins
Merge bzr.dev.
242
                rt = to_repo.revision_tree('rev-two')
243
                self.assertEqual('new contents\n',
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
244
                                 rt.get_file_text('a-id'))
245
            finally:
246
                to_repo.unlock()
247
248
    def test_fetch_missing_revision_same_location_fails(self):
249
        repo_a = self.make_repository('.')
250
        repo_b = repository.Repository.open('.')
251
        try:
3350.3.21 by Robert Collins
Merge bzr.dev.
252
            self.assertRaises(errors.NoSuchRevision, repo_b.fetch, repo_a, revision_id='XXX')
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
253
        except errors.LockError, e:
254
            check_old_format_lock_error(self.repository_format)
255
256
    def test_fetch_same_location_trivial_works(self):
257
        repo_a = self.make_repository('.')
258
        repo_b = repository.Repository.open('.')
259
        try:
260
            repo_a.fetch(repo_b)
261
        except errors.LockError, e:
262
            check_old_format_lock_error(self.repository_format)
263
264
    def test_fetch_missing_text_other_location_fails(self):
265
        source_tree = self.make_branch_and_tree('source')
266
        source = source_tree.branch.repository
267
        target = self.make_to_repository('target')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
268
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
269
        # start by adding a file so the data knit for the file exists in
270
        # repositories that have specific files for each fileid.
271
        self.build_tree(['source/id'])
272
        source_tree.add(['id'], ['id'])
273
        source_tree.commit('a', rev_id='a')
274
        # now we manually insert a revision with an inventory referencing
275
        # 'id' at revision 'b', but we do not insert revision b.
276
        # this should ensure that the new versions of files are being checked
277
        # for during pull operations
278
        inv = source.get_inventory('a')
279
        source.lock_write()
3380.1.5 by Aaron Bentley
Merge with make-it-work
280
        self.addCleanup(source.unlock)
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
281
        source.start_write_group()
282
        inv['id'].revision = 'b'
283
        inv.revision_id = 'b'
284
        sha1 = source.add_inventory('b', inv, ['a'])
285
        rev = Revision(timestamp=0,
286
                       timezone=None,
287
                       committer="Foo Bar <foo@example.com>",
288
                       message="Message",
289
                       inventory_sha1=sha1,
290
                       revision_id='b')
291
        rev.parent_ids = ['a']
292
        source.add_revision('b', rev)
293
        source.commit_write_group()
294
        self.assertRaises(errors.RevisionNotPresent, target.fetch, source)
295
        self.assertFalse(target.has_revision('b'))
296
297
    def test_fetch_funky_file_id(self):
298
        from_tree = self.make_branch_and_tree('tree')
299
        if sys.platform == 'win32':
300
            from_repo = from_tree.branch.repository
301
            check_repo_format_for_funky_id_on_win32(from_repo)
302
        self.build_tree(['tree/filename'])
303
        from_tree.add('filename', 'funky-chars<>%&;"\'')
304
        from_tree.commit('commit filename')
305
        to_repo = self.make_to_repository('to')
3350.3.21 by Robert Collins
Merge bzr.dev.
306
        to_repo.fetch(from_tree.branch.repository, from_tree.get_parent_ids()[0])
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
307
3380.1.6 by Aaron Bentley
Ensure fetching munges sha1s
308
    def test_fetch_revision_hash(self):
309
        """Ensure that inventory hashes are updated by fetch"""
310
        from_tree = self.make_branch_and_tree('tree')
311
        from_tree.commit('foo', rev_id='foo-id')
312
        to_repo = self.make_to_repository('to')
313
        to_repo.fetch(from_tree.branch.repository)
314
        recorded_inv_sha1 = to_repo.get_inventory_sha1('foo-id')
4476.3.4 by Andrew Bennetts
Network serialisation, and most tests passing with InterDifferingSerializer commented out.
315
        try:
316
            xml = to_repo.get_inventory_xml('foo-id')
317
        except NotImplementedError:
318
            raise TestNotApplicable('repo does not provide get_inventory_xml')
3380.1.6 by Aaron Bentley
Ensure fetching munges sha1s
319
        computed_inv_sha1 = osutils.sha_string(xml)
320
        self.assertEqual(computed_inv_sha1, recorded_inv_sha1)
321
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
322
323
class TestFetchDependentData(TestCaseWithInterRepository):
324
325
    def test_reference(self):
326
        from_tree = self.make_branch_and_tree('tree')
327
        to_repo = self.make_to_repository('to')
328
        if (not from_tree.supports_tree_reference() or
329
            not from_tree.branch.repository._format.supports_tree_reference or
330
            not to_repo._format.supports_tree_reference):
331
            raise TestNotApplicable("Need subtree support.")
332
        subtree = self.make_branch_and_tree('tree/subtree')
333
        subtree.commit('subrev 1')
334
        from_tree.add_reference(subtree)
335
        tree_rev = from_tree.commit('foo')
336
        # now from_tree has a last-modified of subtree of the rev id of the
337
        # commit for foo, and a reference revision of the rev id of the commit
338
        # for subrev 1
339
        to_repo.fetch(from_tree.branch.repository, tree_rev)
340
        # to_repo should have a file_graph for from_tree.path2id('subtree') and
341
        # revid tree_rev.
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
342
        file_id = from_tree.path2id('subtree')
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
343
        to_repo.lock_read()
344
        try:
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
345
            self.assertEqual({(file_id, tree_rev):()},
346
                to_repo.texts.get_parent_map([(file_id, tree_rev)]))
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
347
        finally:
348
            to_repo.unlock()