/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
1
# Copyright (C) 2005, 2006, 2008 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
16
17
18
import sys
19
20
import bzrlib
21
from bzrlib import (
22
    errors,
3735.2.135 by Robert Collins
Permit fetching bzr.dev [deal with inconsistent inventories.]
23
    inventory,
24
    osutils,
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
25
    repository,
3735.2.135 by Robert Collins
Permit fetching bzr.dev [deal with inconsistent inventories.]
26
    versionedfile,
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
27
    )
28
from bzrlib.errors import (
29
    NoSuchRevision,
30
    )
31
from bzrlib.revision import (
32
    NULL_REVISION,
33
    Revision,
34
    )
35
from bzrlib.tests import (
36
    TestNotApplicable,
37
    )
4523.1.3 by Martin Pool
Rename to per_interrepository
38
from bzrlib.tests.per_interrepository import (
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
39
    TestCaseWithInterRepository,
40
    )
4523.1.3 by Martin Pool
Rename to per_interrepository
41
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
42
    check_repo_format_for_funky_id_on_win32
43
    )
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
44
45
46
class TestInterRepository(TestCaseWithInterRepository):
47
48
    def test_fetch(self):
49
        tree_a = self.make_branch_and_tree('a')
50
        self.build_tree(['a/foo'])
51
        tree_a.add('foo', 'file1')
52
        tree_a.commit('rev1', rev_id='rev1')
53
        def check_push_rev1(repo):
54
            # ensure the revision is missing.
55
            self.assertRaises(NoSuchRevision, repo.get_revision, 'rev1')
4110.2.5 by Martin Pool
Deprecate passing pbs in to fetch()
56
            # fetch with a limit of NULL_REVISION
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
57
            repo.fetch(tree_a.branch.repository,
4110.2.5 by Martin Pool
Deprecate passing pbs in to fetch()
58
                       revision_id=NULL_REVISION)
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
59
            # nothing should have been pushed
60
            self.assertFalse(repo.has_revision('rev1'))
61
            # fetch with a default limit (grab everything)
62
            repo.fetch(tree_a.branch.repository)
63
            # check that b now has all the data from a's first commit.
64
            rev = repo.get_revision('rev1')
65
            tree = repo.revision_tree('rev1')
66
            tree.lock_read()
67
            self.addCleanup(tree.unlock)
68
            tree.get_file_text('file1')
69
            for file_id in tree:
70
                if tree.inventory[file_id].kind == "file":
71
                    tree.get_file(file_id).read()
72
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
73
        # makes a target version repo
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
74
        repo_b = self.make_to_repository('b')
75
        check_push_rev1(repo_b)
76
3735.2.135 by Robert Collins
Permit fetching bzr.dev [deal with inconsistent inventories.]
77
    def test_fetch_inconsistent_last_changed_entries(self):
78
        """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.
79
3735.2.135 by Robert Collins
Permit fetching bzr.dev [deal with inconsistent inventories.]
80
        This test tests that we do fetch a file text created in a revision not
81
        being fetched, but referenced from the revision we are fetching when the
82
        adjacent revisions to the one being fetched do not reference that text.
83
        """
84
        tree = self.make_branch_and_tree('source')
85
        revid = tree.commit('old')
86
        to_repo = self.make_to_repository('to_repo')
87
        to_repo.fetch(tree.branch.repository, revid)
88
        # Make a broken revision and fetch it.
89
        source = tree.branch.repository
90
        source.lock_write()
91
        self.addCleanup(source.unlock)
92
        source.start_write_group()
93
        try:
94
            # We need two revisions: OLD and NEW. NEW will claim to need a file
95
            # 'FOO' changed in 'OLD'. OLD will not have that file at all.
96
            source.texts.insert_record_stream([
97
                versionedfile.FulltextContentFactory(('foo', revid), (), None,
98
                'contents')])
99
            basis = source.revision_tree(revid)
100
            parent_id = basis.path2id('')
101
            entry = inventory.make_entry('file', 'foo-path', parent_id, 'foo')
102
            entry.revision = revid
103
            entry.text_size = len('contents')
104
            entry.text_sha1 = osutils.sha_string('contents')
105
            inv_sha1, _ = source.add_inventory_by_delta(revid, [
106
                (None, 'foo-path', 'foo', entry)], 'new', [revid])
107
            rev = Revision(timestamp=0,
108
                           timezone=None,
109
                           committer="Foo Bar <foo@example.com>",
110
                           message="Message",
111
                           inventory_sha1=inv_sha1,
112
                           revision_id='new',
113
                           parent_ids=[revid])
114
            source.add_revision(rev.revision_id, rev)
115
        except:
116
            source.abort_write_group()
117
            raise
118
        else:
119
            source.commit_write_group()
120
        to_repo.fetch(source, 'new')
121
        to_repo.lock_read()
122
        self.addCleanup(to_repo.unlock)
123
        self.assertEqual('contents',
124
            to_repo.texts.get_record_stream([('foo', revid)],
125
            'unordered', True).next().get_bytes_as('fulltext'))
126
4257.3.1 by Andrew Bennetts
Add failing test.
127
    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.
128
        """Fetch to a stacked branch copies inventories for parents of
129
        revisions at the stacking boundary.
130
131
        This is necessary so that the server is able to determine the file-ids
132
        altered by all revisions it contains, which means that it needs both
133
        the inventory for any revision it has, and the inventories of all that
134
        revision's parents.
4597.1.2 by John Arbash Meinel
Fix the second half of bug #402778
135
136
        However, we should also skip any revisions which are ghosts in the
137
        parents.
4257.3.9 by Andrew Bennetts
Add fix to InterDifferingSerializer too, although it's pretty ugly.
138
        """
4597.1.5 by John Arbash Meinel
Split the 'ghost' test into a second test.
139
        if not self.repository_format_to.supports_external_lookups:
4257.3.1 by Andrew Bennetts
Add failing test.
140
            raise TestNotApplicable("Need stacking support in the target.")
141
        builder = self.make_branch_builder('branch')
142
        builder.start_series()
143
        builder.build_snapshot('base', None, [
4597.1.1 by John Arbash Meinel
fix a critical bug #402778
144
            ('add', ('', 'root-id', 'directory', '')),
145
            ('add', ('file', 'file-id', 'file', 'content\n'))])
146
        builder.build_snapshot('left', ['base'], [
147
            ('modify', ('file-id', 'left content\n'))])
148
        builder.build_snapshot('right', ['base'], [
149
            ('modify', ('file-id', 'right content\n'))])
4597.1.5 by John Arbash Meinel
Split the 'ghost' test into a second test.
150
        builder.build_snapshot('merge', ['left', 'right'], [
4597.1.1 by John Arbash Meinel
fix a critical bug #402778
151
            ('modify', ('file-id', 'left and right content\n'))])
4257.3.1 by Andrew Bennetts
Add failing test.
152
        builder.finish_series()
153
        branch = builder.get_branch()
154
        repo = self.make_to_repository('trunk')
155
        trunk = repo.bzrdir.create_branch()
156
        trunk.repository.fetch(branch.repository, 'left')
157
        trunk.repository.fetch(branch.repository, 'right')
158
        repo = self.make_to_repository('stacked')
159
        stacked_branch = repo.bzrdir.create_branch()
160
        stacked_branch.set_stacked_on_url(trunk.base)
161
        stacked_branch.repository.fetch(branch.repository, 'merge')
162
        unstacked_repo = stacked_branch.bzrdir.open_repository()
163
        unstacked_repo.lock_read()
164
        self.addCleanup(unstacked_repo.unlock)
165
        self.assertFalse(unstacked_repo.has_revision('left'))
166
        self.assertFalse(unstacked_repo.has_revision('right'))
167
        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.
168
            set([('left',), ('right',), ('merge',)]),
4257.3.1 by Andrew Bennetts
Add failing test.
169
            unstacked_repo.inventories.keys())
4597.1.1 by John Arbash Meinel
fix a critical bug #402778
170
        # And the basis inventories have been copied correctly
171
        trunk.lock_read()
172
        self.addCleanup(trunk.unlock)
173
        left_tree, right_tree = trunk.repository.revision_trees(
174
            ['left', 'right'])
175
        stacked_branch.lock_read()
176
        self.addCleanup(stacked_branch.unlock)
177
        (stacked_left_tree,
178
         stacked_right_tree) = stacked_branch.repository.revision_trees(
179
            ['left', 'right'])
180
        self.assertEqual(left_tree.inventory, stacked_left_tree.inventory)
181
        self.assertEqual(right_tree.inventory, stacked_right_tree.inventory)
4257.3.1 by Andrew Bennetts
Add failing test.
182
4597.1.5 by John Arbash Meinel
Split the 'ghost' test into a second test.
183
    def test_fetch_across_stacking_boundary_ignores_ghost(self):
184
        if not self.repository_format_to.supports_external_lookups:
185
            raise TestNotApplicable("Need stacking support in the target.")
186
        to_repo = self.make_to_repository('to')
187
        builder = self.make_branch_builder('branch')
188
        builder.start_series()
189
        builder.build_snapshot('base', None, [
190
            ('add', ('', 'root-id', 'directory', '')),
191
            ('add', ('file', 'file-id', 'file', 'content\n'))])
192
        builder.build_snapshot('second', ['base'], [
193
            ('modify', ('file-id', 'second content\n'))])
194
        builder.build_snapshot('third', ['second', 'ghost'], [
195
            ('modify', ('file-id', 'third content\n'))])
196
        builder.finish_series()
197
        branch = builder.get_branch()
198
        repo = self.make_to_repository('trunk')
199
        trunk = repo.bzrdir.create_branch()
200
        trunk.repository.fetch(branch.repository, 'second')
201
        repo = self.make_to_repository('stacked')
202
        stacked_branch = repo.bzrdir.create_branch()
203
        stacked_branch.set_stacked_on_url(trunk.base)
204
        stacked_branch.repository.fetch(branch.repository, 'third')
205
        unstacked_repo = stacked_branch.bzrdir.open_repository()
206
        unstacked_repo.lock_read()
207
        self.addCleanup(unstacked_repo.unlock)
208
        self.assertFalse(unstacked_repo.has_revision('second'))
209
        self.assertFalse(unstacked_repo.has_revision('ghost'))
210
        self.assertEqual(
211
            set([('second',), ('third',)]),
212
            unstacked_repo.inventories.keys())
213
        # And the basis inventories have been copied correctly
214
        trunk.lock_read()
215
        self.addCleanup(trunk.unlock)
216
        second_tree = trunk.repository.revision_tree('second')
217
        stacked_branch.lock_read()
218
        self.addCleanup(stacked_branch.unlock)
219
        stacked_second_tree = stacked_branch.repository.revision_tree('second')
220
        self.assertEqual(second_tree.inventory, stacked_second_tree.inventory)
221
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
222
    def test_fetch_missing_basis_text(self):
223
        """If fetching a delta, we should die if a basis is not present."""
224
        tree = self.make_branch_and_tree('tree')
225
        self.build_tree(['tree/a'])
226
        tree.add(['a'], ['a-id'])
227
        tree.commit('one', rev_id='rev-one')
228
        self.build_tree_contents([('tree/a', 'new contents\n')])
229
        tree.commit('two', rev_id='rev-two')
230
231
        to_repo = self.make_to_repository('to_repo')
232
        # We build a broken revision so that we can test the fetch code dies
233
        # properly. So copy the inventory and revision, but not the text.
234
        to_repo.lock_write()
235
        try:
236
            to_repo.start_write_group()
237
            inv = tree.branch.repository.get_inventory('rev-one')
238
            to_repo.add_inventory('rev-one', inv, [])
239
            rev = tree.branch.repository.get_revision('rev-one')
240
            to_repo.add_revision('rev-one', rev, inv=inv)
241
            to_repo.commit_write_group()
242
        finally:
243
            to_repo.unlock()
244
3350.3.21 by Robert Collins
Merge bzr.dev.
245
        # Implementations can either ensure that the target of the delta is
246
        # reconstructable, or raise an exception (which stream based copies
247
        # generally do).
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
248
        try:
249
            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
250
        except (errors.BzrCheckError, errors.RevisionNotPresent), e:
251
            # If an exception is raised, the revision should not be in the
252
            # target.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
253
            #
3830.3.9 by Martin Pool
Simplify kvf insert_record_stream; add has_key shorthand methods; update stacking effort tests
254
            # Can also just raise a generic check errors; stream insertion
255
            # does this to include all the missing data
256
            self.assertRaises((errors.NoSuchRevision, errors.RevisionNotPresent),
257
                              to_repo.revision_tree, 'rev-two')
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
258
        else:
3350.3.21 by Robert Collins
Merge bzr.dev.
259
            # If not exception is raised, then the text should be
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
260
            # available.
261
            to_repo.lock_read()
262
            try:
3350.3.21 by Robert Collins
Merge bzr.dev.
263
                rt = to_repo.revision_tree('rev-two')
264
                self.assertEqual('new contents\n',
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
265
                                 rt.get_file_text('a-id'))
266
            finally:
267
                to_repo.unlock()
268
269
    def test_fetch_missing_revision_same_location_fails(self):
270
        repo_a = self.make_repository('.')
271
        repo_b = repository.Repository.open('.')
272
        try:
3350.3.21 by Robert Collins
Merge bzr.dev.
273
            self.assertRaises(errors.NoSuchRevision, repo_b.fetch, repo_a, revision_id='XXX')
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
274
        except errors.LockError, e:
275
            check_old_format_lock_error(self.repository_format)
276
277
    def test_fetch_same_location_trivial_works(self):
278
        repo_a = self.make_repository('.')
279
        repo_b = repository.Repository.open('.')
280
        try:
281
            repo_a.fetch(repo_b)
282
        except errors.LockError, e:
283
            check_old_format_lock_error(self.repository_format)
284
285
    def test_fetch_missing_text_other_location_fails(self):
286
        source_tree = self.make_branch_and_tree('source')
287
        source = source_tree.branch.repository
288
        target = self.make_to_repository('target')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
289
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
290
        # start by adding a file so the data knit for the file exists in
291
        # repositories that have specific files for each fileid.
292
        self.build_tree(['source/id'])
293
        source_tree.add(['id'], ['id'])
294
        source_tree.commit('a', rev_id='a')
295
        # now we manually insert a revision with an inventory referencing
296
        # 'id' at revision 'b', but we do not insert revision b.
297
        # this should ensure that the new versions of files are being checked
298
        # for during pull operations
299
        inv = source.get_inventory('a')
300
        source.lock_write()
3380.1.5 by Aaron Bentley
Merge with make-it-work
301
        self.addCleanup(source.unlock)
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
302
        source.start_write_group()
303
        inv['id'].revision = 'b'
304
        inv.revision_id = 'b'
305
        sha1 = source.add_inventory('b', inv, ['a'])
306
        rev = Revision(timestamp=0,
307
                       timezone=None,
308
                       committer="Foo Bar <foo@example.com>",
309
                       message="Message",
310
                       inventory_sha1=sha1,
311
                       revision_id='b')
312
        rev.parent_ids = ['a']
313
        source.add_revision('b', rev)
314
        source.commit_write_group()
315
        self.assertRaises(errors.RevisionNotPresent, target.fetch, source)
316
        self.assertFalse(target.has_revision('b'))
317
318
    def test_fetch_funky_file_id(self):
319
        from_tree = self.make_branch_and_tree('tree')
320
        if sys.platform == 'win32':
321
            from_repo = from_tree.branch.repository
322
            check_repo_format_for_funky_id_on_win32(from_repo)
323
        self.build_tree(['tree/filename'])
324
        from_tree.add('filename', 'funky-chars<>%&;"\'')
325
        from_tree.commit('commit filename')
326
        to_repo = self.make_to_repository('to')
3350.3.21 by Robert Collins
Merge bzr.dev.
327
        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
328
3380.1.6 by Aaron Bentley
Ensure fetching munges sha1s
329
    def test_fetch_revision_hash(self):
330
        """Ensure that inventory hashes are updated by fetch"""
331
        from_tree = self.make_branch_and_tree('tree')
332
        from_tree.commit('foo', rev_id='foo-id')
333
        to_repo = self.make_to_repository('to')
334
        to_repo.fetch(from_tree.branch.repository)
335
        recorded_inv_sha1 = to_repo.get_inventory_sha1('foo-id')
4597.1.4 by John Arbash Meinel
Fix one test that assumed get_inventory_xml worked.
336
        to_repo.lock_read()
337
        self.addCleanup(to_repo.unlock)
338
        stream = to_repo.inventories.get_record_stream([('foo-id',)],
339
                                                       'unordered', True)
340
        bytes = stream.next().get_bytes_as('fulltext')
341
        computed_inv_sha1 = osutils.sha_string(bytes)
3380.1.6 by Aaron Bentley
Ensure fetching munges sha1s
342
        self.assertEqual(computed_inv_sha1, recorded_inv_sha1)
343
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
344
345
class TestFetchDependentData(TestCaseWithInterRepository):
346
347
    def test_reference(self):
348
        from_tree = self.make_branch_and_tree('tree')
349
        to_repo = self.make_to_repository('to')
350
        if (not from_tree.supports_tree_reference() or
351
            not from_tree.branch.repository._format.supports_tree_reference or
352
            not to_repo._format.supports_tree_reference):
353
            raise TestNotApplicable("Need subtree support.")
354
        subtree = self.make_branch_and_tree('tree/subtree')
355
        subtree.commit('subrev 1')
356
        from_tree.add_reference(subtree)
357
        tree_rev = from_tree.commit('foo')
358
        # now from_tree has a last-modified of subtree of the rev id of the
359
        # commit for foo, and a reference revision of the rev id of the commit
360
        # for subrev 1
361
        to_repo.fetch(from_tree.branch.repository, tree_rev)
362
        # to_repo should have a file_graph for from_tree.path2id('subtree') and
363
        # 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.
364
        file_id = from_tree.path2id('subtree')
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
365
        to_repo.lock_read()
366
        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.
367
            self.assertEqual({(file_id, tree_rev):()},
368
                to_repo.texts.get_parent_map([(file_id, tree_rev)]))
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
369
        finally:
370
            to_repo.unlock()