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