/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
4988.10.3 by John Arbash Meinel
Merge bzr.dev 5007, resolve conflict, update NEWS
1
# Copyright (C) 2008, 2009, 2010 Canonical Ltd
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
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
from bzrlib import (
21
    errors,
3735.2.135 by Robert Collins
Permit fetching bzr.dev [deal with inconsistent inventories.]
22
    inventory,
23
    osutils,
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
24
    repository,
3735.2.135 by Robert Collins
Permit fetching bzr.dev [deal with inconsistent inventories.]
25
    versionedfile,
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
26
    )
27
from bzrlib.errors import (
28
    NoSuchRevision,
29
    )
6341.1.4 by Jelmer Vernooij
Move more functionality to vf_search.
30
from bzrlib.vf_search import (
4476.3.11 by Andrew Bennetts
All fetch and interrepo tests passing.
31
    SearchResult,
32
    )
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
33
from bzrlib.revision import (
34
    NULL_REVISION,
35
    Revision,
36
    )
37
from bzrlib.tests import (
38
    TestNotApplicable,
39
    )
4523.1.3 by Martin Pool
Rename to per_interrepository
40
from bzrlib.tests.per_interrepository import (
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
41
    TestCaseWithInterRepository,
42
    )
4523.1.3 by Martin Pool
Rename to per_interrepository
43
from bzrlib.tests.per_interrepository.test_interrepository import (
3616.2.3 by Mark Hammond
Fix test failures due to missing check_repo_format_for_funky_id_on_win32
44
    check_repo_format_for_funky_id_on_win32
45
    )
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
46
47
4634.35.22 by Andrew Bennetts
Use monkey patching to avoid skipping (mostly) tests that try to create damaged repos on 2a.
48
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
49
class TestInterRepository(TestCaseWithInterRepository):
50
4634.35.22 by Andrew Bennetts
Use monkey patching to avoid skipping (mostly) tests that try to create damaged repos on 2a.
51
    def disable_commit_write_group_paranoia(self, repo):
52
        pack_coll = getattr(repo, '_pack_collection', None)
53
        if pack_coll is not None:
54
            # Monkey-patch the pack collection instance to allow storing
55
            # incomplete revisions.
56
            pack_coll._check_new_inventories = lambda: []
57
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
58
    def test_fetch(self):
59
        tree_a = self.make_branch_and_tree('a')
60
        self.build_tree(['a/foo'])
61
        tree_a.add('foo', 'file1')
62
        tree_a.commit('rev1', rev_id='rev1')
63
        def check_push_rev1(repo):
64
            # ensure the revision is missing.
65
            self.assertRaises(NoSuchRevision, repo.get_revision, 'rev1')
4110.2.5 by Martin Pool
Deprecate passing pbs in to fetch()
66
            # fetch with a limit of NULL_REVISION
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
67
            repo.fetch(tree_a.branch.repository,
4110.2.5 by Martin Pool
Deprecate passing pbs in to fetch()
68
                       revision_id=NULL_REVISION)
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
69
            # nothing should have been pushed
70
            self.assertFalse(repo.has_revision('rev1'))
71
            # fetch with a default limit (grab everything)
72
            repo.fetch(tree_a.branch.repository)
73
            # check that b now has all the data from a's first commit.
74
            rev = repo.get_revision('rev1')
75
            tree = repo.revision_tree('rev1')
76
            tree.lock_read()
77
            self.addCleanup(tree.unlock)
78
            tree.get_file_text('file1')
5837.2.2 by Jelmer Vernooij
Fix more uses of Tree.__iter__
79
            for file_id in tree.all_file_ids():
6405.2.10 by Jelmer Vernooij
Fix more tests.
80
                if tree.kind(file_id) == "file":
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
81
                    tree.get_file(file_id).read()
82
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
83
        # makes a target version repo
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
84
        repo_b = self.make_to_repository('b')
85
        check_push_rev1(repo_b)
86
3735.2.135 by Robert Collins
Permit fetching bzr.dev [deal with inconsistent inventories.]
87
    def test_fetch_inconsistent_last_changed_entries(self):
88
        """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.
89
3735.2.135 by Robert Collins
Permit fetching bzr.dev [deal with inconsistent inventories.]
90
        This test tests that we do fetch a file text created in a revision not
91
        being fetched, but referenced from the revision we are fetching when the
92
        adjacent revisions to the one being fetched do not reference that text.
93
        """
94
        tree = self.make_branch_and_tree('source')
95
        revid = tree.commit('old')
96
        to_repo = self.make_to_repository('to_repo')
97
        to_repo.fetch(tree.branch.repository, revid)
98
        # Make a broken revision and fetch it.
99
        source = tree.branch.repository
100
        source.lock_write()
101
        self.addCleanup(source.unlock)
102
        source.start_write_group()
103
        try:
104
            # We need two revisions: OLD and NEW. NEW will claim to need a file
105
            # 'FOO' changed in 'OLD'. OLD will not have that file at all.
106
            source.texts.insert_record_stream([
107
                versionedfile.FulltextContentFactory(('foo', revid), (), None,
108
                'contents')])
109
            basis = source.revision_tree(revid)
110
            parent_id = basis.path2id('')
111
            entry = inventory.make_entry('file', 'foo-path', parent_id, 'foo')
112
            entry.revision = revid
113
            entry.text_size = len('contents')
114
            entry.text_sha1 = osutils.sha_string('contents')
115
            inv_sha1, _ = source.add_inventory_by_delta(revid, [
116
                (None, 'foo-path', 'foo', entry)], 'new', [revid])
117
            rev = Revision(timestamp=0,
118
                           timezone=None,
119
                           committer="Foo Bar <foo@example.com>",
120
                           message="Message",
121
                           inventory_sha1=inv_sha1,
122
                           revision_id='new',
123
                           parent_ids=[revid])
124
            source.add_revision(rev.revision_id, rev)
125
        except:
126
            source.abort_write_group()
127
            raise
128
        else:
129
            source.commit_write_group()
130
        to_repo.fetch(source, 'new')
131
        to_repo.lock_read()
132
        self.addCleanup(to_repo.unlock)
133
        self.assertEqual('contents',
134
            to_repo.texts.get_record_stream([('foo', revid)],
135
            'unordered', True).next().get_bytes_as('fulltext'))
136
4634.61.1 by Andrew Bennetts
Fix cross-format pulls from stacked branches via smart server, add tests for same.
137
    def test_fetch_from_stacked_smart(self):
138
        self.setup_smart_server_with_call_log()
139
        self.test_fetch_from_stacked()
140
141
    def test_fetch_from_stacked_smart_old(self):
142
        self.setup_smart_server_with_call_log()
143
        self.disable_verb('Repository.get_stream_1.19')
144
        self.test_fetch_from_stacked()
145
146
    def test_fetch_from_stacked(self):
147
        """Fetch from a stacked branch succeeds."""
148
        if not self.repository_format.supports_external_lookups:
149
            raise TestNotApplicable("Need stacking support in the source.")
150
        builder = self.make_branch_builder('full-branch')
151
        builder.start_series()
152
        builder.build_snapshot('first', None, [
153
            ('add', ('', 'root-id', 'directory', '')),
154
            ('add', ('file', 'file-id', 'file', 'content\n'))])
155
        builder.build_snapshot('second', ['first'], [
156
            ('modify', ('file-id', 'second content\n'))])
157
        builder.build_snapshot('third', ['second'], [
158
            ('modify', ('file-id', 'third content\n'))])
159
        builder.finish_series()
160
        branch = builder.get_branch()
161
        repo = self.make_repository('stacking-base')
162
        trunk = repo.bzrdir.create_branch()
163
        trunk.repository.fetch(branch.repository, 'second')
164
        repo = self.make_repository('stacked')
165
        stacked_branch = repo.bzrdir.create_branch()
166
        stacked_branch.set_stacked_on_url(trunk.base)
167
        stacked_branch.repository.fetch(branch.repository, 'third')
168
        target = self.make_to_repository('target')
169
        target.fetch(stacked_branch.repository, 'third')
170
        target.lock_read()
171
        self.addCleanup(target.unlock)
172
        all_revs = set(['first', 'second', 'third'])
173
        self.assertEqual(all_revs, set(target.get_parent_map(all_revs)))
174
4476.3.15 by Andrew Bennetts
Partially working fallback for pre-1.17 servers.
175
    def test_fetch_parent_inventories_at_stacking_boundary_smart(self):
176
        self.setup_smart_server_with_call_log()
177
        self.test_fetch_parent_inventories_at_stacking_boundary()
178
179
    def test_fetch_parent_inventories_at_stacking_boundary_smart_old(self):
180
        self.setup_smart_server_with_call_log()
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
181
        self.disable_verb('Repository.insert_stream_1.19')
6437.59.1 by Martin Packman
Mark randomly failing test in per_interrepository using knownFailure when ConnectionReset is raised
182
        try:
183
            self.test_fetch_parent_inventories_at_stacking_boundary()
184
        except errors.ConnectionReset:
185
            self.knownFailure("Random spurious failure, see bug 874153")
4476.3.15 by Andrew Bennetts
Partially working fallback for pre-1.17 servers.
186
4257.3.1 by Andrew Bennetts
Add failing test.
187
    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.
188
        """Fetch to a stacked branch copies inventories for parents of
189
        revisions at the stacking boundary.
190
191
        This is necessary so that the server is able to determine the file-ids
192
        altered by all revisions it contains, which means that it needs both
193
        the inventory for any revision it has, and the inventories of all that
194
        revision's parents.
4597.1.2 by John Arbash Meinel
Fix the second half of bug #402778
195
196
        However, we should also skip any revisions which are ghosts in the
197
        parents.
4257.3.9 by Andrew Bennetts
Add fix to InterDifferingSerializer too, although it's pretty ugly.
198
        """
4597.1.5 by John Arbash Meinel
Split the 'ghost' test into a second test.
199
        if not self.repository_format_to.supports_external_lookups:
4257.3.1 by Andrew Bennetts
Add failing test.
200
            raise TestNotApplicable("Need stacking support in the target.")
201
        builder = self.make_branch_builder('branch')
202
        builder.start_series()
203
        builder.build_snapshot('base', None, [
4597.1.1 by John Arbash Meinel
fix a critical bug #402778
204
            ('add', ('', 'root-id', 'directory', '')),
205
            ('add', ('file', 'file-id', 'file', 'content\n'))])
206
        builder.build_snapshot('left', ['base'], [
207
            ('modify', ('file-id', 'left content\n'))])
208
        builder.build_snapshot('right', ['base'], [
209
            ('modify', ('file-id', 'right content\n'))])
4597.1.5 by John Arbash Meinel
Split the 'ghost' test into a second test.
210
        builder.build_snapshot('merge', ['left', 'right'], [
4597.1.1 by John Arbash Meinel
fix a critical bug #402778
211
            ('modify', ('file-id', 'left and right content\n'))])
4257.3.1 by Andrew Bennetts
Add failing test.
212
        builder.finish_series()
213
        branch = builder.get_branch()
214
        repo = self.make_to_repository('trunk')
215
        trunk = repo.bzrdir.create_branch()
216
        trunk.repository.fetch(branch.repository, 'left')
217
        trunk.repository.fetch(branch.repository, 'right')
218
        repo = self.make_to_repository('stacked')
219
        stacked_branch = repo.bzrdir.create_branch()
220
        stacked_branch.set_stacked_on_url(trunk.base)
221
        stacked_branch.repository.fetch(branch.repository, 'merge')
222
        unstacked_repo = stacked_branch.bzrdir.open_repository()
223
        unstacked_repo.lock_read()
224
        self.addCleanup(unstacked_repo.unlock)
4476.3.73 by Andrew Bennetts
Remove smelly if guard from interrepo fetch stacking test, it's not necessary.
225
        self.assertFalse(unstacked_repo.has_revision('left'))
226
        self.assertFalse(unstacked_repo.has_revision('right'))
4257.3.1 by Andrew Bennetts
Add failing test.
227
        self.assertEqual(
4257.3.2 by Andrew Bennetts
Check during fetch if we are going to be missing data necessary to calculate altered fileids for stacked revisions.
228
            set([('left',), ('right',), ('merge',)]),
4257.3.1 by Andrew Bennetts
Add failing test.
229
            unstacked_repo.inventories.keys())
4597.1.1 by John Arbash Meinel
fix a critical bug #402778
230
        # And the basis inventories have been copied correctly
231
        trunk.lock_read()
232
        self.addCleanup(trunk.unlock)
233
        left_tree, right_tree = trunk.repository.revision_trees(
234
            ['left', 'right'])
235
        stacked_branch.lock_read()
236
        self.addCleanup(stacked_branch.unlock)
237
        (stacked_left_tree,
238
         stacked_right_tree) = stacked_branch.repository.revision_trees(
239
            ['left', 'right'])
6405.2.7 by Jelmer Vernooij
Fix more tests.
240
        self.assertEqual(
241
            left_tree.root_inventory, stacked_left_tree.root_inventory)
242
        self.assertEqual(
243
            right_tree.root_inventory, stacked_right_tree.root_inventory)
4257.3.1 by Andrew Bennetts
Add failing test.
244
4476.3.81 by Andrew Bennetts
Merge bzr.dev. Fix some minor fallout. per_interrepository/test_fetch.py has some duplicated assertions as a first pass at resolving conflicts.
245
        # Finally, it's not enough to see that the basis inventories are
246
        # present.  The texts introduced in merge (and only those) should be
247
        # present, and also generating a stream should succeed without blowing
248
        # up.
4476.3.11 by Andrew Bennetts
All fetch and interrepo tests passing.
249
        self.assertTrue(unstacked_repo.has_revision('merge'))
4476.3.81 by Andrew Bennetts
Merge bzr.dev. Fix some minor fallout. per_interrepository/test_fetch.py has some duplicated assertions as a first pass at resolving conflicts.
250
        expected_texts = set([('file-id', 'merge')])
251
        if stacked_branch.repository.texts.get_parent_map([('root-id',
252
            'merge')]):
253
            # If a (root-id,merge) text exists, it should be in the stacked
254
            # repo.
255
            expected_texts.add(('root-id', 'merge'))
256
        self.assertEqual(expected_texts, unstacked_repo.texts.keys())
4476.3.11 by Andrew Bennetts
All fetch and interrepo tests passing.
257
        self.assertCanStreamRevision(unstacked_repo, 'merge')
258
259
    def assertCanStreamRevision(self, repo, revision_id):
260
        exclude_keys = set(repo.all_revision_ids()) - set([revision_id])
261
        search = SearchResult([revision_id], exclude_keys, 1, [revision_id])
262
        source = repo._get_source(repo._format)
263
        for substream_kind, substream in source.get_stream(search):
264
            # Consume the substream
265
            list(substream)
4257.3.1 by Andrew Bennetts
Add failing test.
266
4597.1.5 by John Arbash Meinel
Split the 'ghost' test into a second test.
267
    def test_fetch_across_stacking_boundary_ignores_ghost(self):
268
        if not self.repository_format_to.supports_external_lookups:
269
            raise TestNotApplicable("Need stacking support in the target.")
270
        to_repo = self.make_to_repository('to')
271
        builder = self.make_branch_builder('branch')
272
        builder.start_series()
273
        builder.build_snapshot('base', None, [
274
            ('add', ('', 'root-id', 'directory', '')),
275
            ('add', ('file', 'file-id', 'file', 'content\n'))])
276
        builder.build_snapshot('second', ['base'], [
277
            ('modify', ('file-id', 'second content\n'))])
278
        builder.build_snapshot('third', ['second', 'ghost'], [
279
            ('modify', ('file-id', 'third content\n'))])
280
        builder.finish_series()
281
        branch = builder.get_branch()
282
        repo = self.make_to_repository('trunk')
283
        trunk = repo.bzrdir.create_branch()
284
        trunk.repository.fetch(branch.repository, 'second')
285
        repo = self.make_to_repository('stacked')
286
        stacked_branch = repo.bzrdir.create_branch()
287
        stacked_branch.set_stacked_on_url(trunk.base)
288
        stacked_branch.repository.fetch(branch.repository, 'third')
289
        unstacked_repo = stacked_branch.bzrdir.open_repository()
290
        unstacked_repo.lock_read()
291
        self.addCleanup(unstacked_repo.unlock)
292
        self.assertFalse(unstacked_repo.has_revision('second'))
293
        self.assertFalse(unstacked_repo.has_revision('ghost'))
294
        self.assertEqual(
295
            set([('second',), ('third',)]),
296
            unstacked_repo.inventories.keys())
297
        # And the basis inventories have been copied correctly
298
        trunk.lock_read()
299
        self.addCleanup(trunk.unlock)
300
        second_tree = trunk.repository.revision_tree('second')
301
        stacked_branch.lock_read()
302
        self.addCleanup(stacked_branch.unlock)
303
        stacked_second_tree = stacked_branch.repository.revision_tree('second')
6471.1.5 by Jelmer Vernooij
Compare trees rather than inventories.
304
        self.assertEqual(second_tree, stacked_second_tree)
4476.3.81 by Andrew Bennetts
Merge bzr.dev. Fix some minor fallout. per_interrepository/test_fetch.py has some duplicated assertions as a first pass at resolving conflicts.
305
        # Finally, it's not enough to see that the basis inventories are
306
        # present.  The texts introduced in merge (and only those) should be
307
        # present, and also generating a stream should succeed without blowing
308
        # up.
309
        self.assertTrue(unstacked_repo.has_revision('third'))
310
        expected_texts = set([('file-id', 'third')])
311
        if stacked_branch.repository.texts.get_parent_map([('root-id',
312
            'third')]):
313
            # If a (root-id,third) text exists, it should be in the stacked
314
            # repo.
315
            expected_texts.add(('root-id', 'third'))
316
        self.assertEqual(expected_texts, unstacked_repo.texts.keys())
317
        self.assertCanStreamRevision(unstacked_repo, 'third')
4597.1.5 by John Arbash Meinel
Split the 'ghost' test into a second test.
318
4627.3.4 by Andrew Bennetts
Add a (long) test that fails without the fix.
319
    def test_fetch_from_stacked_to_stacked_copies_parent_inventories(self):
320
        """Fetch from a stacked branch copies inventories for parents of
321
        revisions at the stacking boundary.
322
323
        Specifically, fetch will copy the parent inventories from the
324
        source for which the corresponding revisions are not present.  This
325
        will happen even when the source repository has no fallbacks configured
326
        (as is the case during upgrade).
327
        """
328
        if not self.repository_format.supports_external_lookups:
329
            raise TestNotApplicable("Need stacking support in the source.")
330
        if not self.repository_format_to.supports_external_lookups:
331
            raise TestNotApplicable("Need stacking support in the target.")
332
        builder = self.make_branch_builder('branch')
333
        builder.start_series()
334
        builder.build_snapshot('base', None, [
335
            ('add', ('', 'root-id', 'directory', '')),
336
            ('add', ('file', 'file-id', 'file', 'content\n'))])
337
        builder.build_snapshot('left', ['base'], [
338
            ('modify', ('file-id', 'left content\n'))])
339
        builder.build_snapshot('right', ['base'], [
340
            ('modify', ('file-id', 'right content\n'))])
341
        builder.build_snapshot('merge', ['left', 'right'], [
342
            ('modify', ('file-id', 'left and right content\n'))])
343
        builder.finish_series()
344
        branch = builder.get_branch()
345
        repo = self.make_repository('old-trunk')
346
        # Make a pair of equivalent trunk repos in the from and to formats.
347
        old_trunk = repo.bzrdir.create_branch()
348
        old_trunk.repository.fetch(branch.repository, 'left')
349
        old_trunk.repository.fetch(branch.repository, 'right')
350
        repo = self.make_to_repository('new-trunk')
351
        new_trunk = repo.bzrdir.create_branch()
352
        new_trunk.repository.fetch(branch.repository, 'left')
353
        new_trunk.repository.fetch(branch.repository, 'right')
354
        # Make the source; a repo stacked on old_trunk contained just the data
355
        # for 'merge'.
356
        repo = self.make_repository('old-stacked')
357
        old_stacked_branch = repo.bzrdir.create_branch()
358
        old_stacked_branch.set_stacked_on_url(old_trunk.base)
359
        old_stacked_branch.repository.fetch(branch.repository, 'merge')
360
        # Make the target, a repo stacked on new_trunk.
361
        repo = self.make_to_repository('new-stacked')
362
        new_stacked_branch = repo.bzrdir.create_branch()
363
        new_stacked_branch.set_stacked_on_url(new_trunk.base)
364
        old_unstacked_repo = old_stacked_branch.bzrdir.open_repository()
365
        new_unstacked_repo = new_stacked_branch.bzrdir.open_repository()
366
        # Reopen the source and target repos without any fallbacks, and fetch
367
        # 'merge'.
368
        new_unstacked_repo.fetch(old_unstacked_repo, 'merge')
369
        # Now check the results.  new_unstacked_repo should contain all the
370
        # data necessary to stream 'merge' (i.e. the parent inventories).
371
        new_unstacked_repo.lock_read()
372
        self.addCleanup(new_unstacked_repo.unlock)
373
        self.assertFalse(new_unstacked_repo.has_revision('left'))
374
        self.assertFalse(new_unstacked_repo.has_revision('right'))
375
        self.assertEqual(
376
            set([('left',), ('right',), ('merge',)]),
377
            new_unstacked_repo.inventories.keys())
378
        # And the basis inventories have been copied correctly
379
        new_trunk.lock_read()
380
        self.addCleanup(new_trunk.unlock)
381
        left_tree, right_tree = new_trunk.repository.revision_trees(
382
            ['left', 'right'])
383
        new_stacked_branch.lock_read()
384
        self.addCleanup(new_stacked_branch.unlock)
385
        (stacked_left_tree,
386
         stacked_right_tree) = new_stacked_branch.repository.revision_trees(
387
            ['left', 'right'])
6470.1.1 by Jelmer Vernooij
Use inventories directly in fewer places.
388
        self.assertEqual(left_tree, stacked_left_tree)
389
        self.assertEqual(right_tree, stacked_right_tree)
4627.3.4 by Andrew Bennetts
Add a (long) test that fails without the fix.
390
        # Finally, it's not enough to see that the basis inventories are
391
        # present.  The texts introduced in merge (and only those) should be
392
        # present, and also generating a stream should succeed without blowing
393
        # up.
394
        self.assertTrue(new_unstacked_repo.has_revision('merge'))
395
        expected_texts = set([('file-id', 'merge')])
396
        if new_stacked_branch.repository.texts.get_parent_map([('root-id',
397
            'merge')]):
398
            # If a (root-id,merge) text exists, it should be in the stacked
399
            # repo.
400
            expected_texts.add(('root-id', 'merge'))
401
        self.assertEqual(expected_texts, new_unstacked_repo.texts.keys())
402
        self.assertCanStreamRevision(new_unstacked_repo, 'merge')
403
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
404
    def test_fetch_missing_basis_text(self):
405
        """If fetching a delta, we should die if a basis is not present."""
406
        tree = self.make_branch_and_tree('tree')
407
        self.build_tree(['tree/a'])
408
        tree.add(['a'], ['a-id'])
409
        tree.commit('one', rev_id='rev-one')
410
        self.build_tree_contents([('tree/a', 'new contents\n')])
411
        tree.commit('two', rev_id='rev-two')
412
413
        to_repo = self.make_to_repository('to_repo')
414
        # We build a broken revision so that we can test the fetch code dies
415
        # properly. So copy the inventory and revision, but not the text.
416
        to_repo.lock_write()
417
        try:
418
            to_repo.start_write_group()
4634.35.13 by Andrew Bennetts
Fix test_fetch_missing_basis_text to skip if commit_write_group on the target repo prevents making a broken revision.
419
            try:
420
                inv = tree.branch.repository.get_inventory('rev-one')
421
                to_repo.add_inventory('rev-one', inv, [])
422
                rev = tree.branch.repository.get_revision('rev-one')
423
                to_repo.add_revision('rev-one', rev, inv=inv)
4634.35.22 by Andrew Bennetts
Use monkey patching to avoid skipping (mostly) tests that try to create damaged repos on 2a.
424
                self.disable_commit_write_group_paranoia(to_repo)
425
                to_repo.commit_write_group()
4634.35.13 by Andrew Bennetts
Fix test_fetch_missing_basis_text to skip if commit_write_group on the target repo prevents making a broken revision.
426
            except:
427
                to_repo.abort_write_group(suppress_errors=True)
428
                raise
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
429
        finally:
430
            to_repo.unlock()
431
3350.3.21 by Robert Collins
Merge bzr.dev.
432
        # Implementations can either ensure that the target of the delta is
433
        # reconstructable, or raise an exception (which stream based copies
434
        # generally do).
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
435
        try:
436
            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
437
        except (errors.BzrCheckError, errors.RevisionNotPresent), e:
438
            # If an exception is raised, the revision should not be in the
439
            # target.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
440
            #
3830.3.9 by Martin Pool
Simplify kvf insert_record_stream; add has_key shorthand methods; update stacking effort tests
441
            # Can also just raise a generic check errors; stream insertion
442
            # does this to include all the missing data
443
            self.assertRaises((errors.NoSuchRevision, errors.RevisionNotPresent),
444
                              to_repo.revision_tree, 'rev-two')
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
445
        else:
3350.3.21 by Robert Collins
Merge bzr.dev.
446
            # If not exception is raised, then the text should be
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
447
            # available.
448
            to_repo.lock_read()
449
            try:
3350.3.21 by Robert Collins
Merge bzr.dev.
450
                rt = to_repo.revision_tree('rev-two')
451
                self.assertEqual('new contents\n',
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
452
                                 rt.get_file_text('a-id'))
453
            finally:
454
                to_repo.unlock()
455
456
    def test_fetch_missing_revision_same_location_fails(self):
457
        repo_a = self.make_repository('.')
458
        repo_b = repository.Repository.open('.')
5728.3.1 by Martin Pool
Remove apparently no-longer-called check_old_format_lock_error
459
        self.assertRaises(errors.NoSuchRevision,
460
            repo_b.fetch, repo_a, revision_id='XXX')
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
461
462
    def test_fetch_same_location_trivial_works(self):
463
        repo_a = self.make_repository('.')
464
        repo_b = repository.Repository.open('.')
5728.3.1 by Martin Pool
Remove apparently no-longer-called check_old_format_lock_error
465
        repo_a.fetch(repo_b)
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
466
467
    def test_fetch_missing_text_other_location_fails(self):
468
        source_tree = self.make_branch_and_tree('source')
469
        source = source_tree.branch.repository
470
        target = self.make_to_repository('target')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
471
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
472
        # start by adding a file so the data knit for the file exists in
473
        # repositories that have specific files for each fileid.
474
        self.build_tree(['source/id'])
475
        source_tree.add(['id'], ['id'])
476
        source_tree.commit('a', rev_id='a')
477
        # now we manually insert a revision with an inventory referencing
4634.35.14 by Andrew Bennetts
Fix more tests to cope with new commit_write_group strictness.
478
        # file 'id' at revision 'b', but we do not insert revision b.
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
479
        # this should ensure that the new versions of files are being checked
480
        # for during pull operations
481
        inv = source.get_inventory('a')
482
        source.lock_write()
3380.1.5 by Aaron Bentley
Merge with make-it-work
483
        self.addCleanup(source.unlock)
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
484
        source.start_write_group()
485
        inv['id'].revision = 'b'
486
        inv.revision_id = 'b'
487
        sha1 = source.add_inventory('b', inv, ['a'])
488
        rev = Revision(timestamp=0,
489
                       timezone=None,
490
                       committer="Foo Bar <foo@example.com>",
491
                       message="Message",
492
                       inventory_sha1=sha1,
493
                       revision_id='b')
494
        rev.parent_ids = ['a']
495
        source.add_revision('b', rev)
4634.35.22 by Andrew Bennetts
Use monkey patching to avoid skipping (mostly) tests that try to create damaged repos on 2a.
496
        self.disable_commit_write_group_paranoia(source)
497
        source.commit_write_group()
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
498
        self.assertRaises(errors.RevisionNotPresent, target.fetch, source)
499
        self.assertFalse(target.has_revision('b'))
500
501
    def test_fetch_funky_file_id(self):
502
        from_tree = self.make_branch_and_tree('tree')
503
        if sys.platform == 'win32':
504
            from_repo = from_tree.branch.repository
505
            check_repo_format_for_funky_id_on_win32(from_repo)
506
        self.build_tree(['tree/filename'])
507
        from_tree.add('filename', 'funky-chars<>%&;"\'')
508
        from_tree.commit('commit filename')
509
        to_repo = self.make_to_repository('to')
3350.3.21 by Robert Collins
Merge bzr.dev.
510
        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
511
3380.1.6 by Aaron Bentley
Ensure fetching munges sha1s
512
    def test_fetch_revision_hash(self):
513
        """Ensure that inventory hashes are updated by fetch"""
514
        from_tree = self.make_branch_and_tree('tree')
515
        from_tree.commit('foo', rev_id='foo-id')
516
        to_repo = self.make_to_repository('to')
517
        to_repo.fetch(from_tree.branch.repository)
4988.3.2 by Jelmer Vernooij
Call get_revision on the right object.
518
        recorded_inv_sha1 = to_repo.get_revision('foo-id').inventory_sha1
4597.1.4 by John Arbash Meinel
Fix one test that assumed get_inventory_xml worked.
519
        to_repo.lock_read()
520
        self.addCleanup(to_repo.unlock)
521
        stream = to_repo.inventories.get_record_stream([('foo-id',)],
522
                                                       'unordered', True)
523
        bytes = stream.next().get_bytes_as('fulltext')
524
        computed_inv_sha1 = osutils.sha_string(bytes)
3380.1.6 by Aaron Bentley
Ensure fetching munges sha1s
525
        self.assertEqual(computed_inv_sha1, recorded_inv_sha1)
526
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
527
528
class TestFetchDependentData(TestCaseWithInterRepository):
529
530
    def test_reference(self):
531
        from_tree = self.make_branch_and_tree('tree')
532
        to_repo = self.make_to_repository('to')
533
        if (not from_tree.supports_tree_reference() or
534
            not from_tree.branch.repository._format.supports_tree_reference or
535
            not to_repo._format.supports_tree_reference):
536
            raise TestNotApplicable("Need subtree support.")
537
        subtree = self.make_branch_and_tree('tree/subtree')
538
        subtree.commit('subrev 1')
539
        from_tree.add_reference(subtree)
540
        tree_rev = from_tree.commit('foo')
541
        # now from_tree has a last-modified of subtree of the rev id of the
542
        # commit for foo, and a reference revision of the rev id of the commit
543
        # for subrev 1
544
        to_repo.fetch(from_tree.branch.repository, tree_rev)
545
        # to_repo should have a file_graph for from_tree.path2id('subtree') and
546
        # 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.
547
        file_id = from_tree.path2id('subtree')
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
548
        to_repo.lock_read()
549
        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.
550
            self.assertEqual({(file_id, tree_rev):()},
551
                to_repo.texts.get_parent_map([(file_id, tree_rev)]))
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
552
        finally:
553
            to_repo.unlock()