/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
#        self.assertEqual(
170
#            set([('left',), ('right',), ('merge',)]),
171
#            unstacked_repo.inventories.keys())
172
173
    def assertCanStreamRevision(self, repo, revision_id):
174
        exclude_keys = set(repo.all_revision_ids()) - set([revision_id])
175
        search = SearchResult([revision_id], exclude_keys, 1, [revision_id])
176
        source = repo._get_source(repo._format)
177
        for substream_kind, substream in source.get_stream(search):
178
            # Consume the substream
179
            list(substream)
4257.3.1 by Andrew Bennetts
Add failing test.
180
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
181
    def test_fetch_missing_basis_text(self):
182
        """If fetching a delta, we should die if a basis is not present."""
183
        tree = self.make_branch_and_tree('tree')
184
        self.build_tree(['tree/a'])
185
        tree.add(['a'], ['a-id'])
186
        tree.commit('one', rev_id='rev-one')
187
        self.build_tree_contents([('tree/a', 'new contents\n')])
188
        tree.commit('two', rev_id='rev-two')
189
190
        to_repo = self.make_to_repository('to_repo')
191
        # We build a broken revision so that we can test the fetch code dies
192
        # properly. So copy the inventory and revision, but not the text.
193
        to_repo.lock_write()
194
        try:
195
            to_repo.start_write_group()
196
            inv = tree.branch.repository.get_inventory('rev-one')
197
            to_repo.add_inventory('rev-one', inv, [])
198
            rev = tree.branch.repository.get_revision('rev-one')
199
            to_repo.add_revision('rev-one', rev, inv=inv)
200
            to_repo.commit_write_group()
201
        finally:
202
            to_repo.unlock()
203
3350.3.21 by Robert Collins
Merge bzr.dev.
204
        # Implementations can either ensure that the target of the delta is
205
        # reconstructable, or raise an exception (which stream based copies
206
        # generally do).
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
207
        try:
208
            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
209
        except (errors.BzrCheckError, errors.RevisionNotPresent), e:
210
            # If an exception is raised, the revision should not be in the
211
            # target.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
212
            #
3830.3.9 by Martin Pool
Simplify kvf insert_record_stream; add has_key shorthand methods; update stacking effort tests
213
            # Can also just raise a generic check errors; stream insertion
214
            # does this to include all the missing data
215
            self.assertRaises((errors.NoSuchRevision, errors.RevisionNotPresent),
216
                              to_repo.revision_tree, 'rev-two')
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
217
        else:
3350.3.21 by Robert Collins
Merge bzr.dev.
218
            # If not exception is raised, then the text should be
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
219
            # available.
220
            to_repo.lock_read()
221
            try:
3350.3.21 by Robert Collins
Merge bzr.dev.
222
                rt = to_repo.revision_tree('rev-two')
223
                self.assertEqual('new contents\n',
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
224
                                 rt.get_file_text('a-id'))
225
            finally:
226
                to_repo.unlock()
227
228
    def test_fetch_missing_revision_same_location_fails(self):
229
        repo_a = self.make_repository('.')
230
        repo_b = repository.Repository.open('.')
231
        try:
3350.3.21 by Robert Collins
Merge bzr.dev.
232
            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
233
        except errors.LockError, e:
234
            check_old_format_lock_error(self.repository_format)
235
236
    def test_fetch_same_location_trivial_works(self):
237
        repo_a = self.make_repository('.')
238
        repo_b = repository.Repository.open('.')
239
        try:
240
            repo_a.fetch(repo_b)
241
        except errors.LockError, e:
242
            check_old_format_lock_error(self.repository_format)
243
244
    def test_fetch_missing_text_other_location_fails(self):
245
        source_tree = self.make_branch_and_tree('source')
246
        source = source_tree.branch.repository
247
        target = self.make_to_repository('target')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
248
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
249
        # start by adding a file so the data knit for the file exists in
250
        # repositories that have specific files for each fileid.
251
        self.build_tree(['source/id'])
252
        source_tree.add(['id'], ['id'])
253
        source_tree.commit('a', rev_id='a')
254
        # now we manually insert a revision with an inventory referencing
255
        # 'id' at revision 'b', but we do not insert revision b.
256
        # this should ensure that the new versions of files are being checked
257
        # for during pull operations
258
        inv = source.get_inventory('a')
259
        source.lock_write()
3380.1.5 by Aaron Bentley
Merge with make-it-work
260
        self.addCleanup(source.unlock)
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
261
        source.start_write_group()
262
        inv['id'].revision = 'b'
263
        inv.revision_id = 'b'
264
        sha1 = source.add_inventory('b', inv, ['a'])
265
        rev = Revision(timestamp=0,
266
                       timezone=None,
267
                       committer="Foo Bar <foo@example.com>",
268
                       message="Message",
269
                       inventory_sha1=sha1,
270
                       revision_id='b')
271
        rev.parent_ids = ['a']
272
        source.add_revision('b', rev)
273
        source.commit_write_group()
274
        self.assertRaises(errors.RevisionNotPresent, target.fetch, source)
275
        self.assertFalse(target.has_revision('b'))
276
277
    def test_fetch_funky_file_id(self):
278
        from_tree = self.make_branch_and_tree('tree')
279
        if sys.platform == 'win32':
280
            from_repo = from_tree.branch.repository
281
            check_repo_format_for_funky_id_on_win32(from_repo)
282
        self.build_tree(['tree/filename'])
283
        from_tree.add('filename', 'funky-chars<>%&;"\'')
284
        from_tree.commit('commit filename')
285
        to_repo = self.make_to_repository('to')
3350.3.21 by Robert Collins
Merge bzr.dev.
286
        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
287
3380.1.6 by Aaron Bentley
Ensure fetching munges sha1s
288
    def test_fetch_revision_hash(self):
289
        """Ensure that inventory hashes are updated by fetch"""
290
        from_tree = self.make_branch_and_tree('tree')
291
        from_tree.commit('foo', rev_id='foo-id')
292
        to_repo = self.make_to_repository('to')
293
        to_repo.fetch(from_tree.branch.repository)
294
        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.
295
        try:
296
            xml = to_repo.get_inventory_xml('foo-id')
297
        except NotImplementedError:
298
            raise TestNotApplicable('repo does not provide get_inventory_xml')
3380.1.6 by Aaron Bentley
Ensure fetching munges sha1s
299
        computed_inv_sha1 = osutils.sha_string(xml)
300
        self.assertEqual(computed_inv_sha1, recorded_inv_sha1)
301
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
302
303
class TestFetchDependentData(TestCaseWithInterRepository):
304
305
    def test_reference(self):
306
        from_tree = self.make_branch_and_tree('tree')
307
        to_repo = self.make_to_repository('to')
308
        if (not from_tree.supports_tree_reference() or
309
            not from_tree.branch.repository._format.supports_tree_reference or
310
            not to_repo._format.supports_tree_reference):
311
            raise TestNotApplicable("Need subtree support.")
312
        subtree = self.make_branch_and_tree('tree/subtree')
313
        subtree.commit('subrev 1')
314
        from_tree.add_reference(subtree)
315
        tree_rev = from_tree.commit('foo')
316
        # now from_tree has a last-modified of subtree of the rev id of the
317
        # commit for foo, and a reference revision of the rev id of the commit
318
        # for subrev 1
319
        to_repo.fetch(from_tree.branch.repository, tree_rev)
320
        # to_repo should have a file_graph for from_tree.path2id('subtree') and
321
        # 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.
322
        file_id = from_tree.path2id('subtree')
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
323
        to_repo.lock_read()
324
        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.
325
            self.assertEqual({(file_id, tree_rev):()},
326
                to_repo.texts.get_parent_map([(file_id, tree_rev)]))
3380.1.4 by Aaron Bentley
Split interrepository fetch tests into their own file
327
        finally:
328
            to_repo.unlock()