/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5273.1.7 by Vincent Ladeuil
No more use of the get_transport imported *symbol*, all uses are through
1
# Copyright (C) 2007-2010 Canonical Ltd
2696.3.2 by Martin Pool
Move some per-repository tests from big test_repository to test_fetch
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
2696.3.2 by Martin Pool
Move some per-repository tests from big test_repository to test_fetch
16
17
"""Tests for fetch between repositories of the same type."""
18
19
from bzrlib import (
20
    bzrdir,
21
    errors,
2696.3.10 by Martin Pool
Add missing import
22
    gpg,
4324.3.1 by Robert Collins
When adding rich root data follow the standard revision graph rules, so it does not create 'inconstent parents'.
23
    remote,
2948.3.1 by John Arbash Meinel
Fix bug #158333, make sure that Repository.fetch(self) is properly a no-op for all Repository implementations.
24
    repository,
2696.3.2 by Martin Pool
Move some per-repository tests from big test_repository to test_fetch
25
    )
4324.3.1 by Robert Collins
When adding rich root data follow the standard revision graph rules, so it does not create 'inconstent parents'.
26
from bzrlib.inventory import ROOT_ID
5751.2.3 by Jelmer Vernooij
More tests
27
from bzrlib.tests import (
28
    TestNotApplicable,
29
    TestSkipped,
30
    )
3689.1.1 by John Arbash Meinel
Rename repository_implementations tests into per_repository tests
31
from bzrlib.tests.per_repository import TestCaseWithRepository
2696.3.2 by Martin Pool
Move some per-repository tests from big test_repository to test_fetch
32
33
34
class TestFetchSameRepository(TestCaseWithRepository):
35
36
    def test_fetch(self):
37
        # smoke test fetch to ensure that the convenience function works.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
38
        # it is defined as a convenience function with the underlying
2696.3.2 by Martin Pool
Move some per-repository tests from big test_repository to test_fetch
39
        # functionality provided by an InterRepository
40
        tree_a = self.make_branch_and_tree('a')
41
        self.build_tree(['a/foo'])
42
        tree_a.add('foo', 'file1')
43
        tree_a.commit('rev1', rev_id='rev1')
44
        # fetch with a default limit (grab everything)
2711.2.6 by Martin Pool
Fix up conversion of create_repository to make_repository in test_fetch
45
        repo = self.make_repository('b')
2696.3.2 by Martin Pool
Move some per-repository tests from big test_repository to test_fetch
46
        if (tree_a.branch.repository.supports_rich_root() and not
47
            repo.supports_rich_root()):
48
            raise TestSkipped('Cannot fetch from model2 to model1')
49
        repo.fetch(tree_a.branch.repository,
50
                   revision_id=None)
51
4145.1.1 by Robert Collins
Explicitly prevent fetching while the target repository is in a write group.
52
    def test_fetch_fails_in_write_group(self):
53
        # fetch() manages a write group itself, fetching within one isn't safe.
54
        repo = self.make_repository('a')
55
        repo.lock_write()
56
        self.addCleanup(repo.unlock)
57
        repo.start_write_group()
58
        self.addCleanup(repo.abort_write_group)
59
        # Don't need a specific class - not expecting flow control based on
60
        # this.
61
        self.assertRaises(errors.BzrError, repo.fetch, repo)
62
4060.1.4 by Robert Collins
Streaming fetch from remote servers.
63
    def test_fetch_to_knit3(self):
2696.3.2 by Martin Pool
Move some per-repository tests from big test_repository to test_fetch
64
        # create a repository of the sort we are testing.
3242.2.17 by Aaron Bentley
Fix broken tests
65
        tree_a = self.make_branch_and_tree('a')
2696.3.2 by Martin Pool
Move some per-repository tests from big test_repository to test_fetch
66
        self.build_tree(['a/foo'])
67
        tree_a.add('foo', 'file1')
68
        tree_a.commit('rev1', rev_id='rev1')
69
        # create a knit-3 based format to fetch into
6437.14.2 by Jelmer Vernooij
Run subtree tests with development-subtree rather than deprecated dirstate-with-subtree.
70
        f = bzrdir.format_registry.make_bzrdir('development-subtree')
2696.3.2 by Martin Pool
Move some per-repository tests from big test_repository to test_fetch
71
        try:
72
            format = tree_a.branch.repository._format
73
            format.check_conversion_target(f.repository_format)
74
            # if we cannot convert data to knit3, skip the test.
75
        except errors.BadConversionTarget, e:
76
            raise TestSkipped(str(e))
77
        self.get_transport().mkdir('b')
78
        b_bzrdir = f.initialize(self.get_url('b'))
79
        knit3_repo = b_bzrdir.create_repository()
80
        # fetch with a default limit (grab everything)
81
        knit3_repo.fetch(tree_a.branch.repository, revision_id=None)
2592.3.96 by Robert Collins
Merge index improvements (includes bzr.dev).
82
        # Reopen to avoid any in-memory caching - ensure its reading from
83
        # disk.
84
        knit3_repo = b_bzrdir.open_repository()
2696.3.2 by Martin Pool
Move some per-repository tests from big test_repository to test_fetch
85
        rev1_tree = knit3_repo.revision_tree('rev1')
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.
86
        rev1_tree.lock_read()
87
        try:
88
            lines = rev1_tree.get_file_lines(rev1_tree.get_root_id())
89
        finally:
90
            rev1_tree.unlock()
2696.3.2 by Martin Pool
Move some per-repository tests from big test_repository to test_fetch
91
        self.assertEqual([], lines)
92
        b_branch = b_bzrdir.create_branch()
93
        b_branch.pull(tree_a.branch)
94
        try:
95
            tree_b = b_bzrdir.create_workingtree()
96
        except errors.NotLocalUrl:
4060.1.4 by Robert Collins
Streaming fetch from remote servers.
97
            try:
98
                tree_b = b_branch.create_checkout('b', lightweight=True)
99
            except errors.NotLocalUrl:
100
                raise TestSkipped("cannot make working tree with transport %r"
2696.3.2 by Martin Pool
Move some per-repository tests from big test_repository to test_fetch
101
                              % b_bzrdir.transport)
102
        tree_b.commit('no change', rev_id='rev2')
103
        rev2_tree = knit3_repo.revision_tree('rev2')
6405.2.7 by Jelmer Vernooij
Fix more tests.
104
        self.assertEqual(
105
            'rev1',
106
            rev2_tree.get_file_revision(rev2_tree.get_root_id()))
2696.3.9 by Martin Pool
merge trunk
107
4324.3.1 by Robert Collins
When adding rich root data follow the standard revision graph rules, so it does not create 'inconstent parents'.
108
    def do_test_fetch_to_rich_root_sets_parents_correctly(self, result,
109
        snapshots, root_id=ROOT_ID, allow_lefthand_ghost=False):
110
        """Assert that result is the parents of 'tip' after fetching snapshots.
111
112
        This helper constructs a 1.9 format source, and a test-format target
113
        and fetches the result of building snapshots in the source, then
114
        asserts that the parents of tip are result.
115
116
        :param result: A parents list for the inventories.get_parent_map call.
117
        :param snapshots: An iterable of snapshot parameters for
118
            BranchBuilder.build_snapshot.
119
        '"""
120
        # This overlaps slightly with the tests for commit builder about graph
121
        # consistency.
122
        # Cases:
123
        repo = self.make_repository('target')
4324.3.3 by Robert Collins
Fix silly typo.
124
        remote_format = isinstance(repo, remote.RemoteRepository)
4324.3.1 by Robert Collins
When adding rich root data follow the standard revision graph rules, so it does not create 'inconstent parents'.
125
        if not repo._format.rich_root_data and not remote_format:
126
            return # not relevant
127
        builder = self.make_branch_builder('source', format='1.9')
128
        builder.start_series()
129
        for revision_id, parent_ids, actions in snapshots:
130
            builder.build_snapshot(revision_id, parent_ids, actions,
131
            allow_leftmost_as_ghost=allow_lefthand_ghost)
132
        builder.finish_series()
133
        source = builder.get_branch()
134
        if remote_format and not repo._format.rich_root_data:
135
            # use a manual rich root format to ensure the code path is tested.
136
            repo = self.make_repository('remote-target',
137
                format='1.9-rich-root')
138
        repo.lock_write()
139
        self.addCleanup(repo.unlock)
140
        repo.fetch(source.repository)
5815.5.10 by Jelmer Vernooij
Fix two issues pointed out by John.
141
        graph = repo.get_file_graph()
4324.3.1 by Robert Collins
When adding rich root data follow the standard revision graph rules, so it does not create 'inconstent parents'.
142
        self.assertEqual(result,
5815.5.10 by Jelmer Vernooij
Fix two issues pointed out by John.
143
            graph.get_parent_map([(root_id, 'tip')])[(root_id, 'tip')])
4324.3.1 by Robert Collins
When adding rich root data follow the standard revision graph rules, so it does not create 'inconstent parents'.
144
145
    def test_fetch_to_rich_root_set_parent_no_parents(self):
146
        # No parents rev -> No parents
147
        self.do_test_fetch_to_rich_root_sets_parents_correctly((),
148
            [('tip', None, [('add', ('', ROOT_ID, 'directory', ''))]),
149
            ])
150
151
    def test_fetch_to_rich_root_set_parent_1_parent(self):
4392.2.2 by John Arbash Meinel
Add tests that ensure we can fetch branches with ghosts in their ancestry.
152
        # 1 parent rev -> 1 parent
4324.3.1 by Robert Collins
When adding rich root data follow the standard revision graph rules, so it does not create 'inconstent parents'.
153
        self.do_test_fetch_to_rich_root_sets_parents_correctly(
154
            ((ROOT_ID, 'base'),),
155
            [('base', None, [('add', ('', ROOT_ID, 'directory', ''))]),
156
             ('tip', None, []),
157
            ])
158
159
    def test_fetch_to_rich_root_set_parent_1_ghost_parent(self):
160
        # 1 ghost parent -> No parents
6162.2.1 by Jelmer Vernooij
Skip tests that require ghosts on repositories that don't support ghosts.
161
        if not self.repository_format.supports_ghosts:
162
            raise TestNotApplicable("repository format does not support "
163
                 "ghosts")
4324.3.1 by Robert Collins
When adding rich root data follow the standard revision graph rules, so it does not create 'inconstent parents'.
164
        self.do_test_fetch_to_rich_root_sets_parents_correctly((),
165
            [('tip', ['ghost'], [('add', ('', ROOT_ID, 'directory', ''))]),
166
            ], allow_lefthand_ghost=True)
167
168
    def test_fetch_to_rich_root_set_parent_2_head_parents(self):
169
        # 2 parents both heads -> 2 parents
170
        self.do_test_fetch_to_rich_root_sets_parents_correctly(
171
            ((ROOT_ID, 'left'), (ROOT_ID, 'right')),
172
            [('base', None, [('add', ('', ROOT_ID, 'directory', ''))]),
173
             ('left', None, []),
174
             ('right', ['base'], []),
175
             ('tip', ['left', 'right'], []),
176
            ])
177
178
    def test_fetch_to_rich_root_set_parent_2_parents_1_head(self):
179
        # 2 parents one head -> 1 parent
180
        self.do_test_fetch_to_rich_root_sets_parents_correctly(
181
            ((ROOT_ID, 'right'),),
182
            [('left', None, [('add', ('', ROOT_ID, 'directory', ''))]),
183
             ('right', None, []),
184
             ('tip', ['left', 'right'], []),
185
            ])
186
187
    def test_fetch_to_rich_root_set_parent_1_parent_different_id_gone(self):
188
        # 1 parent different fileid, ours missing -> no parents
189
        self.do_test_fetch_to_rich_root_sets_parents_correctly(
190
            (),
191
            [('base', None, [('add', ('', ROOT_ID, 'directory', ''))]),
192
             ('tip', None, [('unversion', ROOT_ID),
193
                            ('add', ('', 'my-root', 'directory', '')),
194
                            ]),
195
            ], root_id='my-root')
196
197
    def test_fetch_to_rich_root_set_parent_1_parent_different_id_moved(self):
198
        # 1 parent different fileid, ours moved -> 1 parent
199
        # (and that parent honours the changing revid of the other location)
200
        self.do_test_fetch_to_rich_root_sets_parents_correctly(
201
            (('my-root', 'origin'),),
202
            [('origin', None, [('add', ('', ROOT_ID, 'directory', '')),
203
                             ('add', ('child', 'my-root', 'directory', ''))]),
204
             ('base', None, []),
205
             ('tip', None, [('unversion', 'my-root'),
206
                            ('unversion', ROOT_ID),
6008.2.5 by Andrew Bennetts
Rename 'checkpoint' to 'flush', add some unit tests and more comments.
207
                            ('flush', None),
4324.3.1 by Robert Collins
When adding rich root data follow the standard revision graph rules, so it does not create 'inconstent parents'.
208
                            ('add', ('', 'my-root', 'directory', '')),
209
                            ]),
210
            ], root_id='my-root')
211
212
    def test_fetch_to_rich_root_set_parent_2_parent_1_different_id_gone(self):
213
        # 2 parents, 1 different fileid, our second missing -> 1 parent
214
        self.do_test_fetch_to_rich_root_sets_parents_correctly(
215
            (('my-root', 'right'),),
216
            [('base', None, [('add', ('', ROOT_ID, 'directory', ''))]),
217
             ('right', None, [('unversion', ROOT_ID),
218
                              ('add', ('', 'my-root', 'directory', ''))]),
219
             ('tip', ['base', 'right'], [('unversion', ROOT_ID),
220
                            ('add', ('', 'my-root', 'directory', '')),
221
                            ]),
222
            ], root_id='my-root')
223
224
    def test_fetch_to_rich_root_set_parent_2_parent_2_different_id_moved(self):
225
        # 2 parents, 1 different fileid, our second moved -> 2 parent
226
        # (and that parent honours the changing revid of the other location)
227
        self.do_test_fetch_to_rich_root_sets_parents_correctly(
228
            (('my-root', 'right'),),
229
            # 'my-root' at 'child'.
230
            [('origin', None, [('add', ('', ROOT_ID, 'directory', '')),
231
                             ('add', ('child', 'my-root', 'directory', ''))]),
232
             ('base', None, []),
233
            # 'my-root' at root
234
             ('right', None, [('unversion', 'my-root'),
235
                              ('unversion', ROOT_ID),
6008.2.5 by Andrew Bennetts
Rename 'checkpoint' to 'flush', add some unit tests and more comments.
236
                              ('flush', None),
4324.3.1 by Robert Collins
When adding rich root data follow the standard revision graph rules, so it does not create 'inconstent parents'.
237
                              ('add', ('', 'my-root', 'directory', ''))]),
238
             ('tip', ['base', 'right'], [('unversion', 'my-root'),
239
                            ('unversion', ROOT_ID),
6008.2.5 by Andrew Bennetts
Rename 'checkpoint' to 'flush', add some unit tests and more comments.
240
                            ('flush', None),
4324.3.1 by Robert Collins
When adding rich root data follow the standard revision graph rules, so it does not create 'inconstent parents'.
241
                            ('add', ('', 'my-root', 'directory', '')),
242
                            ]),
243
            ], root_id='my-root')
244
2948.3.1 by John Arbash Meinel
Fix bug #158333, make sure that Repository.fetch(self) is properly a no-op for all Repository implementations.
245
    def test_fetch_all_from_self(self):
246
        tree = self.make_branch_and_tree('.')
247
        rev_id = tree.commit('one')
248
        # This needs to be a new copy of the repository, if this changes, the
249
        # test needs to be rewritten
250
        repo = tree.branch.repository.bzrdir.open_repository()
251
        # This fetch should be a no-op see bug #158333
252
        tree.branch.repository.fetch(repo, None)
253
254
    def test_fetch_from_self(self):
255
        tree = self.make_branch_and_tree('.')
256
        rev_id = tree.commit('one')
257
        repo = tree.branch.repository.bzrdir.open_repository()
258
        # This fetch should be a no-op see bug #158333
259
        tree.branch.repository.fetch(repo, rev_id)
260
261
    def test_fetch_missing_from_self(self):
262
        tree = self.make_branch_and_tree('.')
263
        rev_id = tree.commit('one')
264
        # Even though the fetch() is a NO-OP it should assert the revision id
265
        # is present
266
        repo = tree.branch.repository.bzrdir.open_repository()
267
        self.assertRaises(errors.NoSuchRevision, tree.branch.repository.fetch,
268
                          repo, 'no-such-revision')
269
2696.3.9 by Martin Pool
merge trunk
270
    def makeARepoWithSignatures(self):
271
        wt = self.make_branch_and_tree('a-repo-with-sigs')
272
        wt.commit('rev1', allow_pointless=True, rev_id='rev1')
273
        repo = wt.branch.repository
2592.3.96 by Robert Collins
Merge index improvements (includes bzr.dev).
274
        repo.lock_write()
275
        repo.start_write_group()
5751.2.3 by Jelmer Vernooij
More tests
276
        try:
277
            repo.sign_revision('rev1', gpg.LoopbackGPGStrategy(None))
278
        except errors.UnsupportedOperation:
279
            self.assertFalse(repo._format.supports_revision_signatures)
280
            raise TestNotApplicable("repository format does not support signatures")
2592.3.96 by Robert Collins
Merge index improvements (includes bzr.dev).
281
        repo.commit_write_group()
282
        repo.unlock()
2696.3.9 by Martin Pool
merge trunk
283
        return repo
284
285
    def test_fetch_copies_signatures(self):
286
        source_repo = self.makeARepoWithSignatures()
287
        target_repo = self.make_repository('target')
288
        target_repo.fetch(source_repo, revision_id=None)
289
        self.assertEqual(
290
            source_repo.get_signature_text('rev1'),
291
            target_repo.get_signature_text('rev1'))
2535.3.48 by Andrew Bennetts
Merge from bzr.dev.
292
293
    def make_repository_with_one_revision(self):
3242.2.17 by Aaron Bentley
Fix broken tests
294
        wt = self.make_branch_and_tree('source')
2535.3.48 by Andrew Bennetts
Merge from bzr.dev.
295
        wt.commit('rev1', allow_pointless=True, rev_id='rev1')
296
        return wt.branch.repository
297
298
    def test_fetch_revision_already_exists(self):
299
        # Make a repository with one revision.
300
        source_repo = self.make_repository_with_one_revision()
301
        # Fetch that revision into a second repository.
302
        target_repo = self.make_repository('target')
303
        target_repo.fetch(source_repo, revision_id='rev1')
304
        # Now fetch again; there will be nothing to do.  This should work
305
        # without causing any errors.
306
        target_repo.fetch(source_repo, revision_id='rev1')
307
1551.19.36 by Aaron Bentley
Prevent fetch all from causing pack collisions
308
    def test_fetch_all_same_revisions_twice(self):
309
        # Blind-fetching all the same revisions twice should succeed and be a
310
        # no-op the second time.
311
        repo = self.make_repository('repo')
312
        tree = self.make_branch_and_tree('tree')
313
        revision_id = tree.commit('test')
314
        repo.fetch(tree.branch.repository)
315
        repo.fetch(tree.branch.repository)
4360.2.1 by Robert Collins
Don't return ghosts in the keyset for PendingAncestryResult.
316
4392.2.2 by John Arbash Meinel
Add tests that ensure we can fetch branches with ghosts in their ancestry.
317
    def make_simple_branch_with_ghost(self):
4476.3.59 by Andrew Bennetts
Undo changes that aren't needed anymore.
318
        builder = self.make_branch_builder('source')
4392.2.2 by John Arbash Meinel
Add tests that ensure we can fetch branches with ghosts in their ancestry.
319
        builder.start_series()
320
        builder.build_snapshot('A-id', None, [
4476.3.59 by Andrew Bennetts
Undo changes that aren't needed anymore.
321
            ('add', ('', 'root-id', 'directory', None)),
4392.2.2 by John Arbash Meinel
Add tests that ensure we can fetch branches with ghosts in their ancestry.
322
            ('add', ('file', 'file-id', 'file', 'content\n'))])
323
        builder.build_snapshot('B-id', ['A-id', 'ghost-id'], [])
324
        builder.finish_series()
325
        source_b = builder.get_branch()
326
        source_b.lock_read()
327
        self.addCleanup(source_b.unlock)
328
        return source_b
329
330
    def test_fetch_with_ghost(self):
331
        source_b = self.make_simple_branch_with_ghost()
332
        target = self.make_repository('target')
333
        target.lock_write()
334
        self.addCleanup(target.unlock)
335
        target.fetch(source_b.repository, revision_id='B-id')
336
337
    def test_fetch_into_smart_with_ghost(self):
338
        trans = self.make_smart_server('target')
339
        source_b = self.make_simple_branch_with_ghost()
6205.3.1 by Jelmer Vernooij
Add ControlDirFormat.supports_transport.
340
        if not source_b.bzrdir._format.supports_transport(trans):
341
            raise TestNotApplicable("format does not support transport")
4392.2.2 by John Arbash Meinel
Add tests that ensure we can fetch branches with ghosts in their ancestry.
342
        target = self.make_repository('target')
343
        # Re-open the repository over the smart protocol
344
        target = repository.Repository.open(trans.base)
345
        target.lock_write()
346
        self.addCleanup(target.unlock)
347
        try:
348
            target.fetch(source_b.repository, revision_id='B-id')
349
        except errors.TokenLockingNotSupported:
350
            # The code inside fetch() that tries to lock and then fails, also
351
            # causes weird problems with 'lock_not_held' later on...
352
            target.lock_read()
6050.1.2 by Martin
Make tests raising KnownFailure use the knownFailure method instead
353
            self.knownFailure('some repositories fail to fetch'
4392.2.2 by John Arbash Meinel
Add tests that ensure we can fetch branches with ghosts in their ancestry.
354
                ' via the smart server because of locking issues.')
355
356
    def test_fetch_from_smart_with_ghost(self):
357
        trans = self.make_smart_server('source')
358
        source_b = self.make_simple_branch_with_ghost()
6205.3.1 by Jelmer Vernooij
Add ControlDirFormat.supports_transport.
359
        if not source_b.bzrdir._format.supports_transport(trans):
360
            raise TestNotApplicable("format does not support transport")
4392.2.2 by John Arbash Meinel
Add tests that ensure we can fetch branches with ghosts in their ancestry.
361
        target = self.make_repository('target')
362
        target.lock_write()
363
        self.addCleanup(target.unlock)
364
        # Re-open the repository over the smart protocol
365
        source = repository.Repository.open(trans.base)
366
        source.lock_read()
367
        self.addCleanup(source.unlock)
368
        target.fetch(source, revision_id='B-id')
369