~lifeless/ubuntu/lucid/bzr/2.1.2-sru

« back to all changes in this revision

Viewing changes to bzrlib/tests/per_repository/test_fetch.py

  • Committer: Bazaar Package Importer
  • Author(s): Jelmer Vernooij
  • Date: 2009-06-27 15:23:34 UTC
  • mfrom: (1.3.1 upstream) (3.1.78 karmic)
  • Revision ID: james.westby@ubuntu.com-20090627152334-u3smexjpaolh96qd
* New upstream release.
* Bump standards version to 3.8.2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Tests for fetch between repositories of the same type."""
18
18
 
20
20
    bzrdir,
21
21
    errors,
22
22
    gpg,
 
23
    graph,
 
24
    remote,
23
25
    repository,
 
26
    tests,
24
27
    )
 
28
from bzrlib.inventory import ROOT_ID
25
29
from bzrlib.tests import TestSkipped
26
30
from bzrlib.tests.per_repository import TestCaseWithRepository
27
31
from bzrlib.transport import get_transport
44
48
            raise TestSkipped('Cannot fetch from model2 to model1')
45
49
        repo.fetch(tree_a.branch.repository,
46
50
                   revision_id=None)
47
 
                   ## pb=bzrlib.progress.DummyProgress())
 
51
 
 
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)
48
62
 
49
63
    def test_fetch_to_knit3(self):
50
64
        # create a repository of the sort we are testing.
89
103
        rev2_tree = knit3_repo.revision_tree('rev2')
90
104
        self.assertEqual('rev1', rev2_tree.inventory.root.revision)
91
105
 
 
106
    def do_test_fetch_to_rich_root_sets_parents_correctly(self, result,
 
107
        snapshots, root_id=ROOT_ID, allow_lefthand_ghost=False):
 
108
        """Assert that result is the parents of 'tip' after fetching snapshots.
 
109
 
 
110
        This helper constructs a 1.9 format source, and a test-format target
 
111
        and fetches the result of building snapshots in the source, then
 
112
        asserts that the parents of tip are result.
 
113
 
 
114
        :param result: A parents list for the inventories.get_parent_map call.
 
115
        :param snapshots: An iterable of snapshot parameters for
 
116
            BranchBuilder.build_snapshot.
 
117
        '"""
 
118
        # This overlaps slightly with the tests for commit builder about graph
 
119
        # consistency.
 
120
        # Cases:
 
121
        repo = self.make_repository('target')
 
122
        remote_format = isinstance(repo, remote.RemoteRepository)
 
123
        if not repo._format.rich_root_data and not remote_format:
 
124
            return # not relevant
 
125
        builder = self.make_branch_builder('source', format='1.9')
 
126
        builder.start_series()
 
127
        for revision_id, parent_ids, actions in snapshots:
 
128
            builder.build_snapshot(revision_id, parent_ids, actions,
 
129
            allow_leftmost_as_ghost=allow_lefthand_ghost)
 
130
        builder.finish_series()
 
131
        source = builder.get_branch()
 
132
        if remote_format and not repo._format.rich_root_data:
 
133
            # use a manual rich root format to ensure the code path is tested.
 
134
            repo = self.make_repository('remote-target',
 
135
                format='1.9-rich-root')
 
136
        repo.lock_write()
 
137
        self.addCleanup(repo.unlock)
 
138
        repo.fetch(source.repository)
 
139
        self.assertEqual(result,
 
140
            repo.texts.get_parent_map([(root_id, 'tip')])[(root_id, 'tip')])
 
141
 
 
142
    def test_fetch_to_rich_root_set_parent_no_parents(self):
 
143
        # No parents rev -> No parents
 
144
        self.do_test_fetch_to_rich_root_sets_parents_correctly((),
 
145
            [('tip', None, [('add', ('', ROOT_ID, 'directory', ''))]),
 
146
            ])
 
147
 
 
148
    def test_fetch_to_rich_root_set_parent_1_parent(self):
 
149
        # 1 parent rev -> 1 parent
 
150
        self.do_test_fetch_to_rich_root_sets_parents_correctly(
 
151
            ((ROOT_ID, 'base'),),
 
152
            [('base', None, [('add', ('', ROOT_ID, 'directory', ''))]),
 
153
             ('tip', None, []),
 
154
            ])
 
155
 
 
156
    def test_fetch_to_rich_root_set_parent_1_ghost_parent(self):
 
157
        # 1 ghost parent -> No parents
 
158
        self.do_test_fetch_to_rich_root_sets_parents_correctly((),
 
159
            [('tip', ['ghost'], [('add', ('', ROOT_ID, 'directory', ''))]),
 
160
            ], allow_lefthand_ghost=True)
 
161
 
 
162
    def test_fetch_to_rich_root_set_parent_2_head_parents(self):
 
163
        # 2 parents both heads -> 2 parents
 
164
        self.do_test_fetch_to_rich_root_sets_parents_correctly(
 
165
            ((ROOT_ID, 'left'), (ROOT_ID, 'right')),
 
166
            [('base', None, [('add', ('', ROOT_ID, 'directory', ''))]),
 
167
             ('left', None, []),
 
168
             ('right', ['base'], []),
 
169
             ('tip', ['left', 'right'], []),
 
170
            ])
 
171
 
 
172
    def test_fetch_to_rich_root_set_parent_2_parents_1_head(self):
 
173
        # 2 parents one head -> 1 parent
 
174
        self.do_test_fetch_to_rich_root_sets_parents_correctly(
 
175
            ((ROOT_ID, 'right'),),
 
176
            [('left', None, [('add', ('', ROOT_ID, 'directory', ''))]),
 
177
             ('right', None, []),
 
178
             ('tip', ['left', 'right'], []),
 
179
            ])
 
180
 
 
181
    def test_fetch_to_rich_root_set_parent_1_parent_different_id_gone(self):
 
182
        # 1 parent different fileid, ours missing -> no parents
 
183
        self.do_test_fetch_to_rich_root_sets_parents_correctly(
 
184
            (),
 
185
            [('base', None, [('add', ('', ROOT_ID, 'directory', ''))]),
 
186
             ('tip', None, [('unversion', ROOT_ID),
 
187
                            ('add', ('', 'my-root', 'directory', '')),
 
188
                            ]),
 
189
            ], root_id='my-root')
 
190
 
 
191
    def test_fetch_to_rich_root_set_parent_1_parent_different_id_moved(self):
 
192
        # 1 parent different fileid, ours moved -> 1 parent
 
193
        # (and that parent honours the changing revid of the other location)
 
194
        self.do_test_fetch_to_rich_root_sets_parents_correctly(
 
195
            (('my-root', 'origin'),),
 
196
            [('origin', None, [('add', ('', ROOT_ID, 'directory', '')),
 
197
                             ('add', ('child', 'my-root', 'directory', ''))]),
 
198
             ('base', None, []),
 
199
             ('tip', None, [('unversion', 'my-root'),
 
200
                            ('unversion', ROOT_ID),
 
201
                            ('add', ('', 'my-root', 'directory', '')),
 
202
                            ]),
 
203
            ], root_id='my-root')
 
204
 
 
205
    def test_fetch_to_rich_root_set_parent_2_parent_1_different_id_gone(self):
 
206
        # 2 parents, 1 different fileid, our second missing -> 1 parent
 
207
        self.do_test_fetch_to_rich_root_sets_parents_correctly(
 
208
            (('my-root', 'right'),),
 
209
            [('base', None, [('add', ('', ROOT_ID, 'directory', ''))]),
 
210
             ('right', None, [('unversion', ROOT_ID),
 
211
                              ('add', ('', 'my-root', 'directory', ''))]),
 
212
             ('tip', ['base', 'right'], [('unversion', ROOT_ID),
 
213
                            ('add', ('', 'my-root', 'directory', '')),
 
214
                            ]),
 
215
            ], root_id='my-root')
 
216
 
 
217
    def test_fetch_to_rich_root_set_parent_2_parent_2_different_id_moved(self):
 
218
        # 2 parents, 1 different fileid, our second moved -> 2 parent
 
219
        # (and that parent honours the changing revid of the other location)
 
220
        self.do_test_fetch_to_rich_root_sets_parents_correctly(
 
221
            (('my-root', 'right'),),
 
222
            # 'my-root' at 'child'.
 
223
            [('origin', None, [('add', ('', ROOT_ID, 'directory', '')),
 
224
                             ('add', ('child', 'my-root', 'directory', ''))]),
 
225
             ('base', None, []),
 
226
            # 'my-root' at root
 
227
             ('right', None, [('unversion', 'my-root'),
 
228
                              ('unversion', ROOT_ID),
 
229
                              ('add', ('', 'my-root', 'directory', ''))]),
 
230
             ('tip', ['base', 'right'], [('unversion', 'my-root'),
 
231
                            ('unversion', ROOT_ID),
 
232
                            ('add', ('', 'my-root', 'directory', '')),
 
233
                            ]),
 
234
            ], root_id='my-root')
 
235
 
92
236
    def test_fetch_all_from_self(self):
93
237
        tree = self.make_branch_and_tree('.')
94
238
        rev_id = tree.commit('one')
156
300
        revision_id = tree.commit('test')
157
301
        repo.fetch(tree.branch.repository)
158
302
        repo.fetch(tree.branch.repository)
 
303
 
 
304
    def make_simple_branch_with_ghost(self):
 
305
        builder = self.make_branch_builder('source')
 
306
        builder.start_series()
 
307
        builder.build_snapshot('A-id', None, [
 
308
            ('add', ('', 'root-id', 'directory', None)),
 
309
            ('add', ('file', 'file-id', 'file', 'content\n'))])
 
310
        builder.build_snapshot('B-id', ['A-id', 'ghost-id'], [])
 
311
        builder.finish_series()
 
312
        source_b = builder.get_branch()
 
313
        source_b.lock_read()
 
314
        self.addCleanup(source_b.unlock)
 
315
        return source_b
 
316
 
 
317
    def test_fetch_with_ghost(self):
 
318
        source_b = self.make_simple_branch_with_ghost()
 
319
        target = self.make_repository('target')
 
320
        target.lock_write()
 
321
        self.addCleanup(target.unlock)
 
322
        target.fetch(source_b.repository, revision_id='B-id')
 
323
 
 
324
    def test_fetch_into_smart_with_ghost(self):
 
325
        trans = self.make_smart_server('target')
 
326
        source_b = self.make_simple_branch_with_ghost()
 
327
        target = self.make_repository('target')
 
328
        # Re-open the repository over the smart protocol
 
329
        target = repository.Repository.open(trans.base)
 
330
        target.lock_write()
 
331
        self.addCleanup(target.unlock)
 
332
        try:
 
333
            target.fetch(source_b.repository, revision_id='B-id')
 
334
        except errors.TokenLockingNotSupported:
 
335
            # The code inside fetch() that tries to lock and then fails, also
 
336
            # causes weird problems with 'lock_not_held' later on...
 
337
            target.lock_read()
 
338
            raise tests.KnownFailure('some repositories fail to fetch'
 
339
                ' via the smart server because of locking issues.')
 
340
 
 
341
    def test_fetch_from_smart_with_ghost(self):
 
342
        trans = self.make_smart_server('source')
 
343
        source_b = self.make_simple_branch_with_ghost()
 
344
        target = self.make_repository('target')
 
345
        target.lock_write()
 
346
        self.addCleanup(target.unlock)
 
347
        # Re-open the repository over the smart protocol
 
348
        source = repository.Repository.open(trans.base)
 
349
        source.lock_read()
 
350
        self.addCleanup(source.unlock)
 
351
        target.fetch(source, revision_id='B-id')
 
352
 
 
353
 
 
354
class TestSource(TestCaseWithRepository):
 
355
    """Tests for/about the results of Repository._get_source."""
 
356
 
 
357
    def test_no_absent_records_in_stream_with_ghosts(self):
 
358
        # XXX: Arguably should be in interrepository_implementations but
 
359
        # doesn't actually gain coverage there; need a specific set of
 
360
        # permutations to cover it.
 
361
        # bug lp:376255 was reported about this.
 
362
        builder = self.make_branch_builder('repo')
 
363
        builder.start_series()
 
364
        builder.build_snapshot('tip', ['ghost'],
 
365
            [('add', ('', 'ROOT_ID', 'directory', ''))],
 
366
            allow_leftmost_as_ghost=True)
 
367
        builder.finish_series()
 
368
        b = builder.get_branch()
 
369
        b.lock_read()
 
370
        self.addCleanup(b.unlock)
 
371
        repo = b.repository
 
372
        source = repo._get_source(repo._format)
 
373
        search = graph.PendingAncestryResult(['tip'], repo)
 
374
        stream = source.get_stream(search)
 
375
        for substream_type, substream in stream:
 
376
            for record in substream:
 
377
                self.assertNotEqual('absent', record.storage_kind,
 
378
                    "Absent record for %s" % (((substream_type,) + record.key),))