/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)
80
            tree.get_file_text('file1')
5837.2.2 by Jelmer Vernooij
Fix more uses of Tree.__iter__
81
            for file_id in tree.all_file_ids():
6405.2.10 by Jelmer Vernooij
Fix more tests.
82
                if tree.kind(file_id) == "file":
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
83
                    tree.get_file(file_id).read()
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()
154
        builder.build_snapshot('first', None, [
155
            ('add', ('', 'root-id', 'directory', '')),
156
            ('add', ('file', 'file-id', 'file', 'content\n'))])
157
        builder.build_snapshot('second', ['first'], [
158
            ('modify', ('file-id', 'second content\n'))])
159
        builder.build_snapshot('third', ['second'], [
160
            ('modify', ('file-id', 'third content\n'))])
161
        builder.finish_series()
162
        branch = builder.get_branch()
163
        repo = self.make_repository('stacking-base')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
164
        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.
165
        trunk.repository.fetch(branch.repository, 'second')
166
        repo = self.make_repository('stacked')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
167
        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.
168
        stacked_branch.set_stacked_on_url(trunk.base)
169
        stacked_branch.repository.fetch(branch.repository, 'third')
170
        target = self.make_to_repository('target')
171
        target.fetch(stacked_branch.repository, 'third')
172
        target.lock_read()
173
        self.addCleanup(target.unlock)
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
174
        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.
175
        self.assertEqual(all_revs, set(target.get_parent_map(all_revs)))
176
4476.3.15 by Andrew Bennetts
Partially working fallback for pre-1.17 servers.
177
    def test_fetch_parent_inventories_at_stacking_boundary_smart(self):
178
        self.setup_smart_server_with_call_log()
179
        self.test_fetch_parent_inventories_at_stacking_boundary()
180
181
    def test_fetch_parent_inventories_at_stacking_boundary_smart_old(self):
182
        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.
183
        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
184
        try:
185
            self.test_fetch_parent_inventories_at_stacking_boundary()
186
        except errors.ConnectionReset:
187
            self.knownFailure("Random spurious failure, see bug 874153")
4476.3.15 by Andrew Bennetts
Partially working fallback for pre-1.17 servers.
188
4257.3.1 by Andrew Bennetts
Add failing test.
189
    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.
190
        """Fetch to a stacked branch copies inventories for parents of
191
        revisions at the stacking boundary.
192
193
        This is necessary so that the server is able to determine the file-ids
194
        altered by all revisions it contains, which means that it needs both
195
        the inventory for any revision it has, and the inventories of all that
196
        revision's parents.
4597.1.2 by John Arbash Meinel
Fix the second half of bug #402778
197
198
        However, we should also skip any revisions which are ghosts in the
199
        parents.
4257.3.9 by Andrew Bennetts
Add fix to InterDifferingSerializer too, although it's pretty ugly.
200
        """
4597.1.5 by John Arbash Meinel
Split the 'ghost' test into a second test.
201
        if not self.repository_format_to.supports_external_lookups:
4257.3.1 by Andrew Bennetts
Add failing test.
202
            raise TestNotApplicable("Need stacking support in the target.")
203
        builder = self.make_branch_builder('branch')
204
        builder.start_series()
205
        builder.build_snapshot('base', None, [
4597.1.1 by John Arbash Meinel
fix a critical bug #402778
206
            ('add', ('', 'root-id', 'directory', '')),
207
            ('add', ('file', 'file-id', 'file', 'content\n'))])
208
        builder.build_snapshot('left', ['base'], [
209
            ('modify', ('file-id', 'left content\n'))])
210
        builder.build_snapshot('right', ['base'], [
211
            ('modify', ('file-id', 'right content\n'))])
4597.1.5 by John Arbash Meinel
Split the 'ghost' test into a second test.
212
        builder.build_snapshot('merge', ['left', 'right'], [
4597.1.1 by John Arbash Meinel
fix a critical bug #402778
213
            ('modify', ('file-id', 'left and right content\n'))])
4257.3.1 by Andrew Bennetts
Add failing test.
214
        builder.finish_series()
215
        branch = builder.get_branch()
216
        repo = self.make_to_repository('trunk')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
217
        trunk = repo.controldir.create_branch()
4257.3.1 by Andrew Bennetts
Add failing test.
218
        trunk.repository.fetch(branch.repository, 'left')
219
        trunk.repository.fetch(branch.repository, 'right')
220
        repo = self.make_to_repository('stacked')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
221
        stacked_branch = repo.controldir.create_branch()
4257.3.1 by Andrew Bennetts
Add failing test.
222
        stacked_branch.set_stacked_on_url(trunk.base)
223
        stacked_branch.repository.fetch(branch.repository, 'merge')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
224
        unstacked_repo = stacked_branch.controldir.open_repository()
4257.3.1 by Andrew Bennetts
Add failing test.
225
        unstacked_repo.lock_read()
226
        self.addCleanup(unstacked_repo.unlock)
4476.3.73 by Andrew Bennetts
Remove smelly if guard from interrepo fetch stacking test, it's not necessary.
227
        self.assertFalse(unstacked_repo.has_revision('left'))
228
        self.assertFalse(unstacked_repo.has_revision('right'))
4257.3.1 by Andrew Bennetts
Add failing test.
229
        self.assertEqual(
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
230
            {('left',), ('right',), ('merge',)},
4257.3.1 by Andrew Bennetts
Add failing test.
231
            unstacked_repo.inventories.keys())
4597.1.1 by John Arbash Meinel
fix a critical bug #402778
232
        # And the basis inventories have been copied correctly
233
        trunk.lock_read()
234
        self.addCleanup(trunk.unlock)
235
        left_tree, right_tree = trunk.repository.revision_trees(
236
            ['left', 'right'])
237
        stacked_branch.lock_read()
238
        self.addCleanup(stacked_branch.unlock)
239
        (stacked_left_tree,
240
         stacked_right_tree) = stacked_branch.repository.revision_trees(
241
            ['left', 'right'])
6405.2.7 by Jelmer Vernooij
Fix more tests.
242
        self.assertEqual(
243
            left_tree.root_inventory, stacked_left_tree.root_inventory)
244
        self.assertEqual(
245
            right_tree.root_inventory, stacked_right_tree.root_inventory)
4257.3.1 by Andrew Bennetts
Add failing test.
246
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.
247
        # Finally, it's not enough to see that the basis inventories are
248
        # present.  The texts introduced in merge (and only those) should be
249
        # present, and also generating a stream should succeed without blowing
250
        # up.
4476.3.11 by Andrew Bennetts
All fetch and interrepo tests passing.
251
        self.assertTrue(unstacked_repo.has_revision('merge'))
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
252
        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.
253
        if stacked_branch.repository.texts.get_parent_map([('root-id',
254
            'merge')]):
255
            # If a (root-id,merge) text exists, it should be in the stacked
256
            # repo.
257
            expected_texts.add(('root-id', 'merge'))
258
        self.assertEqual(expected_texts, unstacked_repo.texts.keys())
4476.3.11 by Andrew Bennetts
All fetch and interrepo tests passing.
259
        self.assertCanStreamRevision(unstacked_repo, 'merge')
260
261
    def assertCanStreamRevision(self, repo, revision_id):
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
262
        exclude_keys = set(repo.all_revision_ids()) - {revision_id}
4476.3.11 by Andrew Bennetts
All fetch and interrepo tests passing.
263
        search = SearchResult([revision_id], exclude_keys, 1, [revision_id])
264
        source = repo._get_source(repo._format)
265
        for substream_kind, substream in source.get_stream(search):
266
            # Consume the substream
267
            list(substream)
4257.3.1 by Andrew Bennetts
Add failing test.
268
4597.1.5 by John Arbash Meinel
Split the 'ghost' test into a second test.
269
    def test_fetch_across_stacking_boundary_ignores_ghost(self):
270
        if not self.repository_format_to.supports_external_lookups:
271
            raise TestNotApplicable("Need stacking support in the target.")
272
        to_repo = self.make_to_repository('to')
273
        builder = self.make_branch_builder('branch')
274
        builder.start_series()
275
        builder.build_snapshot('base', None, [
276
            ('add', ('', 'root-id', 'directory', '')),
277
            ('add', ('file', 'file-id', 'file', 'content\n'))])
278
        builder.build_snapshot('second', ['base'], [
279
            ('modify', ('file-id', 'second content\n'))])
280
        builder.build_snapshot('third', ['second', 'ghost'], [
281
            ('modify', ('file-id', 'third content\n'))])
282
        builder.finish_series()
283
        branch = builder.get_branch()
284
        repo = self.make_to_repository('trunk')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
285
        trunk = repo.controldir.create_branch()
4597.1.5 by John Arbash Meinel
Split the 'ghost' test into a second test.
286
        trunk.repository.fetch(branch.repository, 'second')
287
        repo = self.make_to_repository('stacked')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
288
        stacked_branch = repo.controldir.create_branch()
4597.1.5 by John Arbash Meinel
Split the 'ghost' test into a second test.
289
        stacked_branch.set_stacked_on_url(trunk.base)
290
        stacked_branch.repository.fetch(branch.repository, 'third')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
291
        unstacked_repo = stacked_branch.controldir.open_repository()
4597.1.5 by John Arbash Meinel
Split the 'ghost' test into a second test.
292
        unstacked_repo.lock_read()
293
        self.addCleanup(unstacked_repo.unlock)
294
        self.assertFalse(unstacked_repo.has_revision('second'))
295
        self.assertFalse(unstacked_repo.has_revision('ghost'))
296
        self.assertEqual(
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
297
            {('second',), ('third',)},
4597.1.5 by John Arbash Meinel
Split the 'ghost' test into a second test.
298
            unstacked_repo.inventories.keys())
299
        # And the basis inventories have been copied correctly
300
        trunk.lock_read()
301
        self.addCleanup(trunk.unlock)
302
        second_tree = trunk.repository.revision_tree('second')
303
        stacked_branch.lock_read()
304
        self.addCleanup(stacked_branch.unlock)
305
        stacked_second_tree = stacked_branch.repository.revision_tree('second')
6471.1.5 by Jelmer Vernooij
Compare trees rather than inventories.
306
        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.
307
        # Finally, it's not enough to see that the basis inventories are
308
        # present.  The texts introduced in merge (and only those) should be
309
        # present, and also generating a stream should succeed without blowing
310
        # up.
311
        self.assertTrue(unstacked_repo.has_revision('third'))
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
312
        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.
313
        if stacked_branch.repository.texts.get_parent_map([('root-id',
314
            'third')]):
315
            # If a (root-id,third) text exists, it should be in the stacked
316
            # repo.
317
            expected_texts.add(('root-id', 'third'))
318
        self.assertEqual(expected_texts, unstacked_repo.texts.keys())
319
        self.assertCanStreamRevision(unstacked_repo, 'third')
4597.1.5 by John Arbash Meinel
Split the 'ghost' test into a second test.
320
4627.3.4 by Andrew Bennetts
Add a (long) test that fails without the fix.
321
    def test_fetch_from_stacked_to_stacked_copies_parent_inventories(self):
322
        """Fetch from a stacked branch copies inventories for parents of
323
        revisions at the stacking boundary.
324
325
        Specifically, fetch will copy the parent inventories from the
326
        source for which the corresponding revisions are not present.  This
327
        will happen even when the source repository has no fallbacks configured
328
        (as is the case during upgrade).
329
        """
330
        if not self.repository_format.supports_external_lookups:
331
            raise TestNotApplicable("Need stacking support in the source.")
332
        if not self.repository_format_to.supports_external_lookups:
333
            raise TestNotApplicable("Need stacking support in the target.")
334
        builder = self.make_branch_builder('branch')
335
        builder.start_series()
336
        builder.build_snapshot('base', None, [
337
            ('add', ('', 'root-id', 'directory', '')),
338
            ('add', ('file', 'file-id', 'file', 'content\n'))])
339
        builder.build_snapshot('left', ['base'], [
340
            ('modify', ('file-id', 'left content\n'))])
341
        builder.build_snapshot('right', ['base'], [
342
            ('modify', ('file-id', 'right content\n'))])
343
        builder.build_snapshot('merge', ['left', 'right'], [
344
            ('modify', ('file-id', 'left and right content\n'))])
345
        builder.finish_series()
346
        branch = builder.get_branch()
347
        repo = self.make_repository('old-trunk')
348
        # 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.
349
        old_trunk = repo.controldir.create_branch()
4627.3.4 by Andrew Bennetts
Add a (long) test that fails without the fix.
350
        old_trunk.repository.fetch(branch.repository, 'left')
351
        old_trunk.repository.fetch(branch.repository, 'right')
352
        repo = self.make_to_repository('new-trunk')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
353
        new_trunk = repo.controldir.create_branch()
4627.3.4 by Andrew Bennetts
Add a (long) test that fails without the fix.
354
        new_trunk.repository.fetch(branch.repository, 'left')
355
        new_trunk.repository.fetch(branch.repository, 'right')
356
        # Make the source; a repo stacked on old_trunk contained just the data
357
        # for 'merge'.
358
        repo = self.make_repository('old-stacked')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
359
        old_stacked_branch = repo.controldir.create_branch()
4627.3.4 by Andrew Bennetts
Add a (long) test that fails without the fix.
360
        old_stacked_branch.set_stacked_on_url(old_trunk.base)
361
        old_stacked_branch.repository.fetch(branch.repository, 'merge')
362
        # Make the target, a repo stacked on new_trunk.
363
        repo = self.make_to_repository('new-stacked')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
364
        new_stacked_branch = repo.controldir.create_branch()
4627.3.4 by Andrew Bennetts
Add a (long) test that fails without the fix.
365
        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.
366
        old_unstacked_repo = old_stacked_branch.controldir.open_repository()
367
        new_unstacked_repo = new_stacked_branch.controldir.open_repository()
4627.3.4 by Andrew Bennetts
Add a (long) test that fails without the fix.
368
        # Reopen the source and target repos without any fallbacks, and fetch
369
        # 'merge'.
370
        new_unstacked_repo.fetch(old_unstacked_repo, 'merge')
371
        # Now check the results.  new_unstacked_repo should contain all the
372
        # data necessary to stream 'merge' (i.e. the parent inventories).
373
        new_unstacked_repo.lock_read()
374
        self.addCleanup(new_unstacked_repo.unlock)
375
        self.assertFalse(new_unstacked_repo.has_revision('left'))
376
        self.assertFalse(new_unstacked_repo.has_revision('right'))
377
        self.assertEqual(
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
378
            {('left',), ('right',), ('merge',)},
4627.3.4 by Andrew Bennetts
Add a (long) test that fails without the fix.
379
            new_unstacked_repo.inventories.keys())
380
        # And the basis inventories have been copied correctly
381
        new_trunk.lock_read()
382
        self.addCleanup(new_trunk.unlock)
383
        left_tree, right_tree = new_trunk.repository.revision_trees(
384
            ['left', 'right'])
385
        new_stacked_branch.lock_read()
386
        self.addCleanup(new_stacked_branch.unlock)
387
        (stacked_left_tree,
388
         stacked_right_tree) = new_stacked_branch.repository.revision_trees(
389
            ['left', 'right'])
6470.1.1 by Jelmer Vernooij
Use inventories directly in fewer places.
390
        self.assertEqual(left_tree, stacked_left_tree)
391
        self.assertEqual(right_tree, stacked_right_tree)
4627.3.4 by Andrew Bennetts
Add a (long) test that fails without the fix.
392
        # Finally, it's not enough to see that the basis inventories are
393
        # present.  The texts introduced in merge (and only those) should be
394
        # present, and also generating a stream should succeed without blowing
395
        # up.
396
        self.assertTrue(new_unstacked_repo.has_revision('merge'))
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
397
        expected_texts = {('file-id', 'merge')}
4627.3.4 by Andrew Bennetts
Add a (long) test that fails without the fix.
398
        if new_stacked_branch.repository.texts.get_parent_map([('root-id',
399
            'merge')]):
400
            # If a (root-id,merge) text exists, it should be in the stacked
401
            # repo.
402
            expected_texts.add(('root-id', 'merge'))
403
        self.assertEqual(expected_texts, new_unstacked_repo.texts.keys())
404
        self.assertCanStreamRevision(new_unstacked_repo, 'merge')
405
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
406
    def test_fetch_missing_basis_text(self):
407
        """If fetching a delta, we should die if a basis is not present."""
408
        tree = self.make_branch_and_tree('tree')
409
        self.build_tree(['tree/a'])
410
        tree.add(['a'], ['a-id'])
411
        tree.commit('one', rev_id='rev-one')
412
        self.build_tree_contents([('tree/a', 'new contents\n')])
413
        tree.commit('two', rev_id='rev-two')
414
415
        to_repo = self.make_to_repository('to_repo')
416
        # We build a broken revision so that we can test the fetch code dies
417
        # properly. So copy the inventory and revision, but not the text.
418
        to_repo.lock_write()
419
        try:
420
            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.
421
            try:
422
                inv = tree.branch.repository.get_inventory('rev-one')
423
                to_repo.add_inventory('rev-one', inv, [])
424
                rev = tree.branch.repository.get_revision('rev-one')
425
                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.
426
                self.disable_commit_write_group_paranoia(to_repo)
427
                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.
428
            except:
429
                to_repo.abort_write_group(suppress_errors=True)
430
                raise
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
431
        finally:
432
            to_repo.unlock()
433
3350.3.21 by Robert Collins
Merge bzr.dev.
434
        # Implementations can either ensure that the target of the delta is
435
        # reconstructable, or raise an exception (which stream based copies
436
        # generally do).
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
437
        try:
438
            to_repo.fetch(tree.branch.repository, 'rev-two')
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
439
        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
440
            # If an exception is raised, the revision should not be in the
441
            # target.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
442
            #
3830.3.9 by Martin Pool
Simplify kvf insert_record_stream; add has_key shorthand methods; update stacking effort tests
443
            # Can also just raise a generic check errors; stream insertion
444
            # does this to include all the missing data
445
            self.assertRaises((errors.NoSuchRevision, errors.RevisionNotPresent),
446
                              to_repo.revision_tree, 'rev-two')
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
447
        else:
3350.3.21 by Robert Collins
Merge bzr.dev.
448
            # If not exception is raised, then the text should be
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
449
            # available.
450
            to_repo.lock_read()
451
            try:
3350.3.21 by Robert Collins
Merge bzr.dev.
452
                rt = to_repo.revision_tree('rev-two')
453
                self.assertEqual('new contents\n',
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
454
                                 rt.get_file_text('a-id'))
455
            finally:
456
                to_repo.unlock()
457
458
    def test_fetch_missing_revision_same_location_fails(self):
459
        repo_a = self.make_repository('.')
460
        repo_b = repository.Repository.open('.')
5728.3.1 by Martin Pool
Remove apparently no-longer-called check_old_format_lock_error
461
        self.assertRaises(errors.NoSuchRevision,
462
            repo_b.fetch, repo_a, revision_id='XXX')
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
463
464
    def test_fetch_same_location_trivial_works(self):
465
        repo_a = self.make_repository('.')
466
        repo_b = repository.Repository.open('.')
5728.3.1 by Martin Pool
Remove apparently no-longer-called check_old_format_lock_error
467
        repo_a.fetch(repo_b)
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
468
469
    def test_fetch_missing_text_other_location_fails(self):
470
        source_tree = self.make_branch_and_tree('source')
471
        source = source_tree.branch.repository
472
        target = self.make_to_repository('target')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
473
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
474
        # start by adding a file so the data knit for the file exists in
475
        # repositories that have specific files for each fileid.
476
        self.build_tree(['source/id'])
477
        source_tree.add(['id'], ['id'])
478
        source_tree.commit('a', rev_id='a')
479
        # 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.
480
        # 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
481
        # this should ensure that the new versions of files are being checked
482
        # for during pull operations
483
        inv = source.get_inventory('a')
484
        source.lock_write()
3380.1.5 by Aaron Bentley
Merge with make-it-work
485
        self.addCleanup(source.unlock)
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
486
        source.start_write_group()
487
        inv['id'].revision = 'b'
488
        inv.revision_id = 'b'
489
        sha1 = source.add_inventory('b', inv, ['a'])
490
        rev = Revision(timestamp=0,
491
                       timezone=None,
492
                       committer="Foo Bar <foo@example.com>",
493
                       message="Message",
494
                       inventory_sha1=sha1,
495
                       revision_id='b')
496
        rev.parent_ids = ['a']
497
        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.
498
        self.disable_commit_write_group_paranoia(source)
499
        source.commit_write_group()
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
500
        self.assertRaises(errors.RevisionNotPresent, target.fetch, source)
501
        self.assertFalse(target.has_revision('b'))
502
503
    def test_fetch_funky_file_id(self):
504
        from_tree = self.make_branch_and_tree('tree')
505
        if sys.platform == 'win32':
506
            from_repo = from_tree.branch.repository
507
            check_repo_format_for_funky_id_on_win32(from_repo)
508
        self.build_tree(['tree/filename'])
509
        from_tree.add('filename', 'funky-chars<>%&;"\'')
510
        from_tree.commit('commit filename')
511
        to_repo = self.make_to_repository('to')
3350.3.21 by Robert Collins
Merge bzr.dev.
512
        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
513
3380.1.6 by Aaron Bentley
Ensure fetching munges sha1s
514
    def test_fetch_revision_hash(self):
515
        """Ensure that inventory hashes are updated by fetch"""
516
        from_tree = self.make_branch_and_tree('tree')
517
        from_tree.commit('foo', rev_id='foo-id')
518
        to_repo = self.make_to_repository('to')
519
        to_repo.fetch(from_tree.branch.repository)
4988.3.2 by Jelmer Vernooij
Call get_revision on the right object.
520
        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.
521
        to_repo.lock_read()
522
        self.addCleanup(to_repo.unlock)
523
        stream = to_repo.inventories.get_record_stream([('foo-id',)],
524
                                                       'unordered', True)
525
        bytes = stream.next().get_bytes_as('fulltext')
526
        computed_inv_sha1 = osutils.sha_string(bytes)
3380.1.6 by Aaron Bentley
Ensure fetching munges sha1s
527
        self.assertEqual(computed_inv_sha1, recorded_inv_sha1)
528
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
529
530
class TestFetchDependentData(TestCaseWithInterRepository):
531
532
    def test_reference(self):
533
        from_tree = self.make_branch_and_tree('tree')
534
        to_repo = self.make_to_repository('to')
535
        if (not from_tree.supports_tree_reference() or
536
            not from_tree.branch.repository._format.supports_tree_reference or
537
            not to_repo._format.supports_tree_reference):
538
            raise TestNotApplicable("Need subtree support.")
539
        subtree = self.make_branch_and_tree('tree/subtree')
540
        subtree.commit('subrev 1')
541
        from_tree.add_reference(subtree)
542
        tree_rev = from_tree.commit('foo')
543
        # now from_tree has a last-modified of subtree of the rev id of the
544
        # commit for foo, and a reference revision of the rev id of the commit
545
        # for subrev 1
546
        to_repo.fetch(from_tree.branch.repository, tree_rev)
547
        # to_repo should have a file_graph for from_tree.path2id('subtree') and
548
        # 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.
549
        file_id = from_tree.path2id('subtree')
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
550
        to_repo.lock_read()
551
        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.
552
            self.assertEqual({(file_id, tree_rev):()},
553
                to_repo.texts.get_parent_map([(file_id, tree_rev)]))
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
554
        finally:
555
            to_repo.unlock()