/brz/remove-bazaar

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