~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_repository.py

MergeĀ inĀ upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2007, 2008 Canonical Ltd
2
 
#
 
1
# (C) 2006 Canonical Ltd
 
2
 
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
#
 
7
 
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
22
also see this file.
23
23
"""
24
24
 
25
 
import md5
26
 
from stat import S_ISDIR
 
25
from stat import *
27
26
from StringIO import StringIO
28
27
 
29
28
import bzrlib
 
29
import bzrlib.bzrdir as bzrdir
 
30
import bzrlib.errors as errors
30
31
from bzrlib.errors import (NotBranchError,
31
32
                           NoSuchFile,
32
33
                           UnknownFormatError,
33
34
                           UnsupportedFormatError,
34
35
                           )
35
 
from bzrlib import graph
36
 
from bzrlib.index import GraphIndex, InMemoryGraphIndex
37
 
from bzrlib.repository import RepositoryFormat
38
 
from bzrlib.smart import server
39
 
from bzrlib.tests import (
40
 
    TestCase,
41
 
    TestCaseWithTransport,
42
 
    TestSkipped,
43
 
    test_knit,
44
 
    )
45
 
from bzrlib.transport import (
46
 
    fakenfs,
47
 
    get_transport,
48
 
    )
 
36
import bzrlib.repository as repository
 
37
from bzrlib.tests import TestCase, TestCaseWithTransport
 
38
from bzrlib.transport import get_transport
 
39
from bzrlib.transport.http import HttpServer
49
40
from bzrlib.transport.memory import MemoryServer
50
 
from bzrlib.util import bencode
51
 
from bzrlib import (
52
 
    bzrdir,
53
 
    errors,
54
 
    inventory,
55
 
    progress,
56
 
    repository,
57
 
    revision as _mod_revision,
58
 
    symbol_versioning,
59
 
    upgrade,
60
 
    workingtree,
61
 
    )
62
 
from bzrlib.repofmt import knitrepo, weaverepo, pack_repo
63
41
 
64
42
 
65
43
class TestDefaultFormat(TestCase):
66
44
 
67
45
    def test_get_set_default_format(self):
68
 
        old_default = bzrdir.format_registry.get('default')
69
 
        private_default = old_default().repository_format.__class__
70
46
        old_format = repository.RepositoryFormat.get_default_format()
71
 
        self.assertTrue(isinstance(old_format, private_default))
72
 
        def make_sample_bzrdir():
73
 
            my_bzrdir = bzrdir.BzrDirMetaFormat1()
74
 
            my_bzrdir.repository_format = SampleRepositoryFormat()
75
 
            return my_bzrdir
76
 
        bzrdir.format_registry.remove('default')
77
 
        bzrdir.format_registry.register('sample', make_sample_bzrdir, '')
78
 
        bzrdir.format_registry.set_default('sample')
 
47
        # default is None - we cannot create a Repository independently yet
 
48
        self.assertTrue(isinstance(old_format, repository.RepositoryFormat7))
 
49
        repository.RepositoryFormat.set_default_format(SampleRepositoryFormat())
79
50
        # creating a repository should now create an instrumented dir.
80
51
        try:
81
52
            # the default branch format is used by the meta dir format
82
53
            # which is not the default bzrdir format at this point
83
 
            dir = bzrdir.BzrDirMetaFormat1().initialize('memory:///')
 
54
            dir = bzrdir.BzrDirMetaFormat1().initialize('memory:/')
84
55
            result = dir.create_repository()
85
56
            self.assertEqual(result, 'A bzr repository dir')
86
57
        finally:
87
 
            bzrdir.format_registry.remove('default')
88
 
            bzrdir.format_registry.remove('sample')
89
 
            bzrdir.format_registry.register('default', old_default, '')
90
 
        self.assertIsInstance(repository.RepositoryFormat.get_default_format(),
91
 
                              old_format.__class__)
 
58
            repository.RepositoryFormat.set_default_format(old_format)
 
59
        self.assertEqual(old_format, repository.RepositoryFormat.get_default_format())
92
60
 
93
61
 
94
62
class SampleRepositoryFormat(repository.RepositoryFormat):
105
73
    def initialize(self, a_bzrdir, shared=False):
106
74
        """Initialize a repository in a BzrDir"""
107
75
        t = a_bzrdir.get_repository_transport(self)
108
 
        t.put_bytes('format', self.get_format_string())
 
76
        t.put('format', StringIO(self.get_format_string()))
109
77
        return 'A bzr repository dir'
110
78
 
111
79
    def is_supported(self):
129
97
            t = get_transport(url)
130
98
            found_format = repository.RepositoryFormat.find_format(dir)
131
99
            self.failUnless(isinstance(found_format, format.__class__))
132
 
        check_format(weaverepo.RepositoryFormat7(), "bar")
 
100
        check_format(repository.RepositoryFormat7(), "bar")
133
101
        
134
102
    def test_find_format_no_repository(self):
135
103
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
162
130
 
163
131
class TestFormat6(TestCaseWithTransport):
164
132
 
165
 
    def test_attribute__fetch_order(self):
166
 
        """Weaves need topological data insertion."""
167
 
        control = bzrdir.BzrDirFormat6().initialize(self.get_url())
168
 
        repo = weaverepo.RepositoryFormat6().initialize(control)
169
 
        self.assertEqual('topological', repo._fetch_order)
170
 
 
171
 
    def test_attribute__fetch_uses_deltas(self):
172
 
        """Weaves do not reuse deltas."""
173
 
        control = bzrdir.BzrDirFormat6().initialize(self.get_url())
174
 
        repo = weaverepo.RepositoryFormat6().initialize(control)
175
 
        self.assertEqual(False, repo._fetch_uses_deltas)
176
 
 
177
 
    def test_attribute__fetch_reconcile(self):
178
 
        """Weave repositories need a reconcile after fetch."""
179
 
        control = bzrdir.BzrDirFormat6().initialize(self.get_url())
180
 
        repo = weaverepo.RepositoryFormat6().initialize(control)
181
 
        self.assertEqual(True, repo._fetch_reconcile)
182
 
 
183
133
    def test_no_ancestry_weave(self):
184
134
        control = bzrdir.BzrDirFormat6().initialize(self.get_url())
185
 
        repo = weaverepo.RepositoryFormat6().initialize(control)
 
135
        repo = repository.RepositoryFormat6().initialize(control)
186
136
        # We no longer need to create the ancestry.weave file
187
137
        # since it is *never* used.
188
138
        self.assertRaises(NoSuchFile,
189
139
                          control.transport.get,
190
140
                          'ancestry.weave')
191
141
 
192
 
    def test_supports_external_lookups(self):
193
 
        control = bzrdir.BzrDirFormat6().initialize(self.get_url())
194
 
        repo = weaverepo.RepositoryFormat6().initialize(control)
195
 
        self.assertFalse(repo._format.supports_external_lookups)
196
 
 
197
142
 
198
143
class TestFormat7(TestCaseWithTransport):
199
 
 
200
 
    def test_attribute__fetch_order(self):
201
 
        """Weaves need topological data insertion."""
202
 
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
203
 
        repo = weaverepo.RepositoryFormat7().initialize(control)
204
 
        self.assertEqual('topological', repo._fetch_order)
205
 
 
206
 
    def test_attribute__fetch_uses_deltas(self):
207
 
        """Weaves do not reuse deltas."""
208
 
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
209
 
        repo = weaverepo.RepositoryFormat7().initialize(control)
210
 
        self.assertEqual(False, repo._fetch_uses_deltas)
211
 
 
212
 
    def test_attribute__fetch_reconcile(self):
213
 
        """Weave repositories need a reconcile after fetch."""
214
 
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
215
 
        repo = weaverepo.RepositoryFormat7().initialize(control)
216
 
        self.assertEqual(True, repo._fetch_reconcile)
217
 
 
 
144
    
218
145
    def test_disk_layout(self):
219
146
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
220
 
        repo = weaverepo.RepositoryFormat7().initialize(control)
 
147
        repo = repository.RepositoryFormat7().initialize(control)
221
148
        # in case of side effects of locking.
222
149
        repo.lock_write()
223
150
        repo.unlock()
230
157
        t = control.get_repository_transport(None)
231
158
        self.assertEqualDiff('Bazaar-NG Repository format 7',
232
159
                             t.get('format').read())
 
160
        self.assertEqualDiff('', t.get('lock').read())
233
161
        self.assertTrue(S_ISDIR(t.stat('revision-store').st_mode))
234
162
        self.assertTrue(S_ISDIR(t.stat('weaves').st_mode))
235
163
        self.assertEqualDiff('# bzr weave file v5\n'
236
164
                             'w\n'
237
165
                             'W\n',
238
166
                             t.get('inventory.weave').read())
239
 
        # Creating a file with id Foo:Bar results in a non-escaped file name on
240
 
        # disk.
241
 
        control.create_branch()
242
 
        tree = control.create_workingtree()
243
 
        tree.add(['foo'], ['Foo:Bar'], ['file'])
244
 
        tree.put_file_bytes_non_atomic('Foo:Bar', 'content\n')
245
 
        tree.commit('first post', rev_id='first')
246
 
        self.assertEqualDiff(
247
 
            '# bzr weave file v5\n'
248
 
            'i\n'
249
 
            '1 7fe70820e08a1aac0ef224d9c66ab66831cc4ab1\n'
250
 
            'n first\n'
251
 
            '\n'
252
 
            'w\n'
253
 
            '{ 0\n'
254
 
            '. content\n'
255
 
            '}\n'
256
 
            'W\n',
257
 
            t.get('weaves/74/Foo%3ABar.weave').read())
258
167
 
259
168
    def test_shared_disk_layout(self):
260
169
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
261
 
        repo = weaverepo.RepositoryFormat7().initialize(control, shared=True)
 
170
        repo = repository.RepositoryFormat7().initialize(control, shared=True)
262
171
        # we want:
263
172
        # format 'Bazaar-NG Repository format 7'
 
173
        # lock ''
264
174
        # inventory.weave == empty_weave
265
175
        # empty revision-store directory
266
176
        # empty weaves directory
267
177
        # a 'shared-storage' marker file.
268
 
        # lock is not present when unlocked
269
178
        t = control.get_repository_transport(None)
270
179
        self.assertEqualDiff('Bazaar-NG Repository format 7',
271
180
                             t.get('format').read())
 
181
        self.assertEqualDiff('', t.get('lock').read())
272
182
        self.assertEqualDiff('', t.get('shared-storage').read())
273
183
        self.assertTrue(S_ISDIR(t.stat('revision-store').st_mode))
274
184
        self.assertTrue(S_ISDIR(t.stat('weaves').st_mode))
276
186
                             'w\n'
277
187
                             'W\n',
278
188
                             t.get('inventory.weave').read())
279
 
        self.assertFalse(t.has('branch-lock'))
280
 
 
281
 
    def test_creates_lockdir(self):
282
 
        """Make sure it appears to be controlled by a LockDir existence"""
283
 
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
284
 
        repo = weaverepo.RepositoryFormat7().initialize(control, shared=True)
285
 
        t = control.get_repository_transport(None)
286
 
        # TODO: Should check there is a 'lock' toplevel directory, 
287
 
        # regardless of contents
288
 
        self.assertFalse(t.has('lock/held/info'))
289
 
        repo.lock_write()
290
 
        try:
291
 
            self.assertTrue(t.has('lock/held/info'))
292
 
        finally:
293
 
            # unlock so we don't get a warning about failing to do so
294
 
            repo.unlock()
295
 
 
296
 
    def test_uses_lockdir(self):
297
 
        """repo format 7 actually locks on lockdir"""
298
 
        base_url = self.get_url()
299
 
        control = bzrdir.BzrDirMetaFormat1().initialize(base_url)
300
 
        repo = weaverepo.RepositoryFormat7().initialize(control, shared=True)
301
 
        t = control.get_repository_transport(None)
302
 
        repo.lock_write()
303
 
        repo.unlock()
304
 
        del repo
305
 
        # make sure the same lock is created by opening it
306
 
        repo = repository.Repository.open(base_url)
307
 
        repo.lock_write()
308
 
        self.assertTrue(t.has('lock/held/info'))
309
 
        repo.unlock()
310
 
        self.assertFalse(t.has('lock/held/info'))
311
189
 
312
190
    def test_shared_no_tree_disk_layout(self):
313
191
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
314
 
        repo = weaverepo.RepositoryFormat7().initialize(control, shared=True)
 
192
        repo = repository.RepositoryFormat7().initialize(control, shared=True)
315
193
        repo.set_make_working_trees(False)
316
194
        # we want:
317
195
        # format 'Bazaar-NG Repository format 7'
323
201
        t = control.get_repository_transport(None)
324
202
        self.assertEqualDiff('Bazaar-NG Repository format 7',
325
203
                             t.get('format').read())
326
 
        ## self.assertEqualDiff('', t.get('lock').read())
 
204
        self.assertEqualDiff('', t.get('lock').read())
327
205
        self.assertEqualDiff('', t.get('shared-storage').read())
328
206
        self.assertEqualDiff('', t.get('no-working-trees').read())
329
207
        repo.set_make_working_trees(True)
335
213
                             'W\n',
336
214
                             t.get('inventory.weave').read())
337
215
 
338
 
    def test_supports_external_lookups(self):
339
 
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
340
 
        repo = weaverepo.RepositoryFormat7().initialize(control)
341
 
        self.assertFalse(repo._format.supports_external_lookups)
342
 
 
343
216
 
344
217
class TestFormatKnit1(TestCaseWithTransport):
345
218
    
346
 
    def test_attribute__fetch_order(self):
347
 
        """Knits need topological data insertion."""
348
 
        repo = self.make_repository('.',
349
 
                format=bzrdir.format_registry.get('knit')())
350
 
        self.assertEqual('topological', repo._fetch_order)
351
 
 
352
 
    def test_attribute__fetch_uses_deltas(self):
353
 
        """Knits reuse deltas."""
354
 
        repo = self.make_repository('.',
355
 
                format=bzrdir.format_registry.get('knit')())
356
 
        self.assertEqual(True, repo._fetch_uses_deltas)
357
 
 
358
219
    def test_disk_layout(self):
359
220
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
360
 
        repo = knitrepo.RepositoryFormatKnit1().initialize(control)
 
221
        repo = repository.RepositoryFormatKnit1().initialize(control)
361
222
        # in case of side effects of locking.
362
223
        repo.lock_write()
363
224
        repo.unlock()
364
225
        # we want:
365
226
        # format 'Bazaar-NG Knit Repository Format 1'
366
 
        # lock: is a directory
 
227
        # lock ''
367
228
        # inventory.weave == empty_weave
368
229
        # empty revision-store directory
369
230
        # empty weaves directory
370
231
        t = control.get_repository_transport(None)
371
232
        self.assertEqualDiff('Bazaar-NG Knit Repository Format 1',
372
233
                             t.get('format').read())
373
 
        # XXX: no locks left when unlocked at the moment
374
 
        # self.assertEqualDiff('', t.get('lock').read())
 
234
        self.assertEqualDiff('', t.get('lock').read())
 
235
        self.assertTrue(S_ISDIR(t.stat('revision-store').st_mode))
375
236
        self.assertTrue(S_ISDIR(t.stat('knits').st_mode))
376
 
        self.check_knits(t)
377
 
        # Check per-file knits.
378
 
        branch = control.create_branch()
379
 
        tree = control.create_workingtree()
380
 
        tree.add(['foo'], ['Nasty-IdC:'], ['file'])
381
 
        tree.put_file_bytes_non_atomic('Nasty-IdC:', '')
382
 
        tree.commit('1st post', rev_id='foo')
383
 
        self.assertHasKnit(t, 'knits/e8/%254easty-%2549d%2543%253a',
384
 
            '\nfoo fulltext 0 81  :')
385
 
 
386
 
    def assertHasKnit(self, t, knit_name, extra_content=''):
387
 
        """Assert that knit_name exists on t."""
388
 
        self.assertEqualDiff('# bzr knit index 8\n' + extra_content,
389
 
                             t.get(knit_name + '.kndx').read())
390
 
 
391
 
    def check_knits(self, t):
392
 
        """check knit content for a repository."""
393
 
        self.assertHasKnit(t, 'inventory')
394
 
        self.assertHasKnit(t, 'revisions')
395
 
        self.assertHasKnit(t, 'signatures')
 
237
        # cheating and using a weave for now.
 
238
        self.assertEqualDiff('# bzr weave file v5\n'
 
239
                             'w\n'
 
240
                             'W\n',
 
241
                             t.get('control/inventory.weave').read())
396
242
 
397
243
    def test_shared_disk_layout(self):
398
244
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
399
 
        repo = knitrepo.RepositoryFormatKnit1().initialize(control, shared=True)
 
245
        repo = repository.RepositoryFormatKnit1().initialize(control, shared=True)
400
246
        # we want:
401
247
        # format 'Bazaar-NG Knit Repository Format 1'
402
 
        # lock: is a directory
 
248
        # lock ''
403
249
        # inventory.weave == empty_weave
404
250
        # empty revision-store directory
405
251
        # empty weaves directory
407
253
        t = control.get_repository_transport(None)
408
254
        self.assertEqualDiff('Bazaar-NG Knit Repository Format 1',
409
255
                             t.get('format').read())
410
 
        # XXX: no locks left when unlocked at the moment
411
 
        # self.assertEqualDiff('', t.get('lock').read())
 
256
        self.assertEqualDiff('', t.get('lock').read())
412
257
        self.assertEqualDiff('', t.get('shared-storage').read())
 
258
        self.assertTrue(S_ISDIR(t.stat('revision-store').st_mode))
413
259
        self.assertTrue(S_ISDIR(t.stat('knits').st_mode))
414
 
        self.check_knits(t)
 
260
        # cheating and using a weave for now.
 
261
        self.assertEqualDiff('# bzr weave file v5\n'
 
262
                             'w\n'
 
263
                             'W\n',
 
264
                             t.get('control/inventory.weave').read())
415
265
 
416
266
    def test_shared_no_tree_disk_layout(self):
417
267
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
418
 
        repo = knitrepo.RepositoryFormatKnit1().initialize(control, shared=True)
 
268
        repo = repository.RepositoryFormatKnit1().initialize(control, shared=True)
419
269
        repo.set_make_working_trees(False)
420
270
        # we want:
421
271
        # format 'Bazaar-NG Knit Repository Format 1'
427
277
        t = control.get_repository_transport(None)
428
278
        self.assertEqualDiff('Bazaar-NG Knit Repository Format 1',
429
279
                             t.get('format').read())
430
 
        # XXX: no locks left when unlocked at the moment
431
 
        # self.assertEqualDiff('', t.get('lock').read())
 
280
        self.assertEqualDiff('', t.get('lock').read())
432
281
        self.assertEqualDiff('', t.get('shared-storage').read())
433
282
        self.assertEqualDiff('', t.get('no-working-trees').read())
434
283
        repo.set_make_working_trees(True)
435
284
        self.assertFalse(t.has('no-working-trees'))
 
285
        self.assertTrue(S_ISDIR(t.stat('revision-store').st_mode))
436
286
        self.assertTrue(S_ISDIR(t.stat('knits').st_mode))
437
 
        self.check_knits(t)
438
 
 
439
 
    def test_deserialise_sets_root_revision(self):
440
 
        """We must have a inventory.root.revision
441
 
 
442
 
        Old versions of the XML5 serializer did not set the revision_id for
443
 
        the whole inventory. So we grab the one from the expected text. Which
444
 
        is valid when the api is not being abused.
445
 
        """
446
 
        repo = self.make_repository('.',
447
 
                format=bzrdir.format_registry.get('knit')())
448
 
        inv_xml = '<inventory format="5">\n</inventory>\n'
449
 
        inv = repo.deserialise_inventory('test-rev-id', inv_xml)
450
 
        self.assertEqual('test-rev-id', inv.root.revision)
451
 
 
452
 
    def test_deserialise_uses_global_revision_id(self):
453
 
        """If it is set, then we re-use the global revision id"""
454
 
        repo = self.make_repository('.',
455
 
                format=bzrdir.format_registry.get('knit')())
456
 
        inv_xml = ('<inventory format="5" revision_id="other-rev-id">\n'
457
 
                   '</inventory>\n')
458
 
        # Arguably, the deserialise_inventory should detect a mismatch, and
459
 
        # raise an error, rather than silently using one revision_id over the
460
 
        # other.
461
 
        self.assertRaises(AssertionError, repo.deserialise_inventory,
462
 
            'test-rev-id', inv_xml)
463
 
        inv = repo.deserialise_inventory('other-rev-id', inv_xml)
464
 
        self.assertEqual('other-rev-id', inv.root.revision)
465
 
 
466
 
    def test_supports_external_lookups(self):
467
 
        repo = self.make_repository('.',
468
 
                format=bzrdir.format_registry.get('knit')())
469
 
        self.assertFalse(repo._format.supports_external_lookups)
470
 
 
471
 
 
472
 
class DummyRepository(object):
473
 
    """A dummy repository for testing."""
474
 
 
475
 
    _serializer = None
476
 
 
477
 
    def supports_rich_root(self):
478
 
        return False
479
 
 
480
 
 
481
 
class InterDummy(repository.InterRepository):
482
 
    """An inter-repository optimised code path for DummyRepository.
483
 
 
484
 
    This is for use during testing where we use DummyRepository as repositories
 
287
        # cheating and using a weave for now.
 
288
        self.assertEqualDiff('# bzr weave file v5\n'
 
289
                             'w\n'
 
290
                             'W\n',
 
291
                             t.get('control/inventory.weave').read())
 
292
 
 
293
 
 
294
class InterString(repository.InterRepository):
 
295
    """An inter-repository optimised code path for strings.
 
296
 
 
297
    This is for use during testing where we use strings as repositories
485
298
    so that none of the default regsitered inter-repository classes will
486
 
    MATCH.
 
299
    match.
487
300
    """
488
301
 
489
302
    @staticmethod
490
303
    def is_compatible(repo_source, repo_target):
491
 
        """InterDummy is compatible with DummyRepository."""
492
 
        return (isinstance(repo_source, DummyRepository) and 
493
 
            isinstance(repo_target, DummyRepository))
 
304
        """InterString is compatible with strings-as-repos."""
 
305
        return isinstance(repo_source, str) and isinstance(repo_target, str)
494
306
 
495
307
 
496
308
class TestInterRepository(TestCaseWithTransport):
502
314
        # This also tests that the default registered optimised interrepository
503
315
        # classes do not barf inappropriately when a surprising repository type
504
316
        # is handed to them.
505
 
        dummy_a = DummyRepository()
506
 
        dummy_b = DummyRepository()
 
317
        dummy_a = "Repository 1."
 
318
        dummy_b = "Repository 2."
507
319
        self.assertGetsDefaultInterRepository(dummy_a, dummy_b)
508
320
 
509
321
    def assertGetsDefaultInterRepository(self, repo_a, repo_b):
510
 
        """Asserts that InterRepository.get(repo_a, repo_b) -> the default.
511
 
        
512
 
        The effective default is now InterSameDataRepository because there is
513
 
        no actual sane default in the presence of incompatible data models.
514
 
        """
 
322
        """Asserts that InterRepository.get(repo_a, repo_b) -> the default."""
515
323
        inter_repo = repository.InterRepository.get(repo_a, repo_b)
516
 
        self.assertEqual(repository.InterSameDataRepository,
 
324
        self.assertEqual(repository.InterRepository,
517
325
                         inter_repo.__class__)
518
326
        self.assertEqual(repo_a, inter_repo.source)
519
327
        self.assertEqual(repo_b, inter_repo.target)
524
332
        # and that it is correctly selected when given a repository
525
333
        # pair that it returns true on for the is_compatible static method
526
334
        # check
527
 
        dummy_a = DummyRepository()
528
 
        dummy_b = DummyRepository()
529
 
        repo = self.make_repository('.')
530
 
        # hack dummies to look like repo somewhat.
531
 
        dummy_a._serializer = repo._serializer
532
 
        dummy_b._serializer = repo._serializer
533
 
        repository.InterRepository.register_optimiser(InterDummy)
 
335
        dummy_a = "Repository 1."
 
336
        dummy_b = "Repository 2."
 
337
        repository.InterRepository.register_optimiser(InterString)
534
338
        try:
535
 
            # we should get the default for something InterDummy returns False
 
339
            # we should get the default for something InterString returns False
536
340
            # to
537
 
            self.assertFalse(InterDummy.is_compatible(dummy_a, repo))
538
 
            self.assertGetsDefaultInterRepository(dummy_a, repo)
539
 
            # and we should get an InterDummy for a pair it 'likes'
540
 
            self.assertTrue(InterDummy.is_compatible(dummy_a, dummy_b))
 
341
            self.assertFalse(InterString.is_compatible(dummy_a, None))
 
342
            self.assertGetsDefaultInterRepository(dummy_a, None)
 
343
            # and we should get an InterString for a pair it 'likes'
 
344
            self.assertTrue(InterString.is_compatible(dummy_a, dummy_b))
541
345
            inter_repo = repository.InterRepository.get(dummy_a, dummy_b)
542
 
            self.assertEqual(InterDummy, inter_repo.__class__)
 
346
            self.assertEqual(InterString, inter_repo.__class__)
543
347
            self.assertEqual(dummy_a, inter_repo.source)
544
348
            self.assertEqual(dummy_b, inter_repo.target)
545
349
        finally:
546
 
            repository.InterRepository.unregister_optimiser(InterDummy)
 
350
            repository.InterRepository.unregister_optimiser(InterString)
547
351
        # now we should get the default InterRepository object again.
548
352
        self.assertGetsDefaultInterRepository(dummy_a, dummy_b)
549
353
 
553
357
    def test_is_compatible_and_registered(self):
554
358
        # InterWeaveRepo is compatible when either side
555
359
        # is a format 5/6/7 branch
556
 
        from bzrlib.repofmt import knitrepo, weaverepo
557
 
        formats = [weaverepo.RepositoryFormat5(),
558
 
                   weaverepo.RepositoryFormat6(),
559
 
                   weaverepo.RepositoryFormat7()]
560
 
        incompatible_formats = [weaverepo.RepositoryFormat4(),
561
 
                                knitrepo.RepositoryFormatKnit1(),
 
360
        formats = [repository.RepositoryFormat5(),
 
361
                   repository.RepositoryFormat6(),
 
362
                   repository.RepositoryFormat7()]
 
363
        incompatible_formats = [repository.RepositoryFormat4(),
 
364
                                repository.RepositoryFormatKnit1(),
562
365
                                ]
563
366
        repo_a = self.make_repository('a')
564
367
        repo_b = self.make_repository('b')
585
388
        t = get_transport(self.get_url('.'))
586
389
        t.mkdir('repository')
587
390
        repo_dir = bzrdir.BzrDirMetaFormat1().initialize('repository')
588
 
        repo = weaverepo.RepositoryFormat7().initialize(repo_dir)
589
 
        target_format = knitrepo.RepositoryFormatKnit1()
 
391
        repo = repository.RepositoryFormat7().initialize(repo_dir)
 
392
        target_format = repository.RepositoryFormatKnit1()
 
393
        pb = bzrlib.ui.ui_factory.progress_bar()
 
394
 
590
395
        converter = repository.CopyConverter(target_format)
591
 
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
592
 
        try:
593
 
            converter.convert(repo, pb)
594
 
        finally:
595
 
            pb.finished()
 
396
        converter.convert(repo, pb)
596
397
        repo = repo_dir.open_repository()
597
398
        self.assertTrue(isinstance(target_format, repo._format.__class__))
598
 
 
599
 
 
600
 
class TestMisc(TestCase):
601
 
    
602
 
    def test_unescape_xml(self):
603
 
        """We get some kind of error when malformed entities are passed"""
604
 
        self.assertRaises(KeyError, repository._unescape_xml, 'foo&bar;') 
605
 
 
606
 
 
607
 
class TestRepositoryFormatKnit3(TestCaseWithTransport):
608
 
 
609
 
    def test_attribute__fetch_order(self):
610
 
        """Knits need topological data insertion."""
611
 
        format = bzrdir.BzrDirMetaFormat1()
612
 
        format.repository_format = knitrepo.RepositoryFormatKnit3()
613
 
        repo = self.make_repository('.', format=format)
614
 
        self.assertEqual('topological', repo._fetch_order)
615
 
 
616
 
    def test_attribute__fetch_uses_deltas(self):
617
 
        """Knits reuse deltas."""
618
 
        format = bzrdir.BzrDirMetaFormat1()
619
 
        format.repository_format = knitrepo.RepositoryFormatKnit3()
620
 
        repo = self.make_repository('.', format=format)
621
 
        self.assertEqual(True, repo._fetch_uses_deltas)
622
 
 
623
 
    def test_convert(self):
624
 
        """Ensure the upgrade adds weaves for roots"""
625
 
        format = bzrdir.BzrDirMetaFormat1()
626
 
        format.repository_format = knitrepo.RepositoryFormatKnit1()
627
 
        tree = self.make_branch_and_tree('.', format)
628
 
        tree.commit("Dull commit", rev_id="dull")
629
 
        revision_tree = tree.branch.repository.revision_tree('dull')
630
 
        revision_tree.lock_read()
631
 
        try:
632
 
            self.assertRaises(errors.NoSuchFile, revision_tree.get_file_lines,
633
 
                revision_tree.inventory.root.file_id)
634
 
        finally:
635
 
            revision_tree.unlock()
636
 
        format = bzrdir.BzrDirMetaFormat1()
637
 
        format.repository_format = knitrepo.RepositoryFormatKnit3()
638
 
        upgrade.Convert('.', format)
639
 
        tree = workingtree.WorkingTree.open('.')
640
 
        revision_tree = tree.branch.repository.revision_tree('dull')
641
 
        revision_tree.lock_read()
642
 
        try:
643
 
            revision_tree.get_file_lines(revision_tree.inventory.root.file_id)
644
 
        finally:
645
 
            revision_tree.unlock()
646
 
        tree.commit("Another dull commit", rev_id='dull2')
647
 
        revision_tree = tree.branch.repository.revision_tree('dull2')
648
 
        revision_tree.lock_read()
649
 
        self.addCleanup(revision_tree.unlock)
650
 
        self.assertEqual('dull', revision_tree.inventory.root.revision)
651
 
 
652
 
    def test_supports_external_lookups(self):
653
 
        format = bzrdir.BzrDirMetaFormat1()
654
 
        format.repository_format = knitrepo.RepositoryFormatKnit3()
655
 
        repo = self.make_repository('.', format=format)
656
 
        self.assertFalse(repo._format.supports_external_lookups)
657
 
 
658
 
 
659
 
class TestWithBrokenRepo(TestCaseWithTransport):
660
 
    """These tests seem to be more appropriate as interface tests?"""
661
 
 
662
 
    def make_broken_repository(self):
663
 
        # XXX: This function is borrowed from Aaron's "Reconcile can fix bad
664
 
        # parent references" branch which is due to land in bzr.dev soon.  Once
665
 
        # it does, this duplication should be removed.
666
 
        repo = self.make_repository('broken-repo')
667
 
        cleanups = []
668
 
        try:
669
 
            repo.lock_write()
670
 
            cleanups.append(repo.unlock)
671
 
            repo.start_write_group()
672
 
            cleanups.append(repo.commit_write_group)
673
 
            # make rev1a: A well-formed revision, containing 'file1'
674
 
            inv = inventory.Inventory(revision_id='rev1a')
675
 
            inv.root.revision = 'rev1a'
676
 
            self.add_file(repo, inv, 'file1', 'rev1a', [])
677
 
            repo.add_inventory('rev1a', inv, [])
678
 
            revision = _mod_revision.Revision('rev1a',
679
 
                committer='jrandom@example.com', timestamp=0,
680
 
                inventory_sha1='', timezone=0, message='foo', parent_ids=[])
681
 
            repo.add_revision('rev1a',revision, inv)
682
 
 
683
 
            # make rev1b, which has no Revision, but has an Inventory, and
684
 
            # file1
685
 
            inv = inventory.Inventory(revision_id='rev1b')
686
 
            inv.root.revision = 'rev1b'
687
 
            self.add_file(repo, inv, 'file1', 'rev1b', [])
688
 
            repo.add_inventory('rev1b', inv, [])
689
 
 
690
 
            # make rev2, with file1 and file2
691
 
            # file2 is sane
692
 
            # file1 has 'rev1b' as an ancestor, even though this is not
693
 
            # mentioned by 'rev1a', making it an unreferenced ancestor
694
 
            inv = inventory.Inventory()
695
 
            self.add_file(repo, inv, 'file1', 'rev2', ['rev1a', 'rev1b'])
696
 
            self.add_file(repo, inv, 'file2', 'rev2', [])
697
 
            self.add_revision(repo, 'rev2', inv, ['rev1a'])
698
 
 
699
 
            # make ghost revision rev1c
700
 
            inv = inventory.Inventory()
701
 
            self.add_file(repo, inv, 'file2', 'rev1c', [])
702
 
 
703
 
            # make rev3 with file2
704
 
            # file2 refers to 'rev1c', which is a ghost in this repository, so
705
 
            # file2 cannot have rev1c as its ancestor.
706
 
            inv = inventory.Inventory()
707
 
            self.add_file(repo, inv, 'file2', 'rev3', ['rev1c'])
708
 
            self.add_revision(repo, 'rev3', inv, ['rev1c'])
709
 
            return repo
710
 
        finally:
711
 
            for cleanup in reversed(cleanups):
712
 
                cleanup()
713
 
 
714
 
    def add_revision(self, repo, revision_id, inv, parent_ids):
715
 
        inv.revision_id = revision_id
716
 
        inv.root.revision = revision_id
717
 
        repo.add_inventory(revision_id, inv, parent_ids)
718
 
        revision = _mod_revision.Revision(revision_id,
719
 
            committer='jrandom@example.com', timestamp=0, inventory_sha1='',
720
 
            timezone=0, message='foo', parent_ids=parent_ids)
721
 
        repo.add_revision(revision_id,revision, inv)
722
 
 
723
 
    def add_file(self, repo, inv, filename, revision, parents):
724
 
        file_id = filename + '-id'
725
 
        entry = inventory.InventoryFile(file_id, filename, 'TREE_ROOT')
726
 
        entry.revision = revision
727
 
        entry.text_size = 0
728
 
        inv.add(entry)
729
 
        text_key = (file_id, revision)
730
 
        parent_keys = [(file_id, parent) for parent in parents]
731
 
        repo.texts.add_lines(text_key, parent_keys, ['line\n'])
732
 
 
733
 
    def test_insert_from_broken_repo(self):
734
 
        """Inserting a data stream from a broken repository won't silently
735
 
        corrupt the target repository.
736
 
        """
737
 
        broken_repo = self.make_broken_repository()
738
 
        empty_repo = self.make_repository('empty-repo')
739
 
        self.assertRaises(errors.RevisionNotPresent, empty_repo.fetch, broken_repo)
740
 
 
741
 
 
742
 
class TestRepositoryPackCollection(TestCaseWithTransport):
743
 
 
744
 
    def get_format(self):
745
 
        return bzrdir.format_registry.make_bzrdir('pack-0.92')
746
 
 
747
 
    def test__max_pack_count(self):
748
 
        """The maximum pack count is a function of the number of revisions."""
749
 
        format = self.get_format()
750
 
        repo = self.make_repository('.', format=format)
751
 
        packs = repo._pack_collection
752
 
        # no revisions - one pack, so that we can have a revision free repo
753
 
        # without it blowing up
754
 
        self.assertEqual(1, packs._max_pack_count(0))
755
 
        # after that the sum of the digits, - check the first 1-9
756
 
        self.assertEqual(1, packs._max_pack_count(1))
757
 
        self.assertEqual(2, packs._max_pack_count(2))
758
 
        self.assertEqual(3, packs._max_pack_count(3))
759
 
        self.assertEqual(4, packs._max_pack_count(4))
760
 
        self.assertEqual(5, packs._max_pack_count(5))
761
 
        self.assertEqual(6, packs._max_pack_count(6))
762
 
        self.assertEqual(7, packs._max_pack_count(7))
763
 
        self.assertEqual(8, packs._max_pack_count(8))
764
 
        self.assertEqual(9, packs._max_pack_count(9))
765
 
        # check the boundary cases with two digits for the next decade
766
 
        self.assertEqual(1, packs._max_pack_count(10))
767
 
        self.assertEqual(2, packs._max_pack_count(11))
768
 
        self.assertEqual(10, packs._max_pack_count(19))
769
 
        self.assertEqual(2, packs._max_pack_count(20))
770
 
        self.assertEqual(3, packs._max_pack_count(21))
771
 
        # check some arbitrary big numbers
772
 
        self.assertEqual(25, packs._max_pack_count(112894))
773
 
 
774
 
    def test_pack_distribution_zero(self):
775
 
        format = self.get_format()
776
 
        repo = self.make_repository('.', format=format)
777
 
        packs = repo._pack_collection
778
 
        self.assertEqual([0], packs.pack_distribution(0))
779
 
 
780
 
    def test_ensure_loaded_unlocked(self):
781
 
        format = self.get_format()
782
 
        repo = self.make_repository('.', format=format)
783
 
        self.assertRaises(errors.ObjectNotLocked,
784
 
                          repo._pack_collection.ensure_loaded)
785
 
 
786
 
    def test_pack_distribution_one_to_nine(self):
787
 
        format = self.get_format()
788
 
        repo = self.make_repository('.', format=format)
789
 
        packs = repo._pack_collection
790
 
        self.assertEqual([1],
791
 
            packs.pack_distribution(1))
792
 
        self.assertEqual([1, 1],
793
 
            packs.pack_distribution(2))
794
 
        self.assertEqual([1, 1, 1],
795
 
            packs.pack_distribution(3))
796
 
        self.assertEqual([1, 1, 1, 1],
797
 
            packs.pack_distribution(4))
798
 
        self.assertEqual([1, 1, 1, 1, 1],
799
 
            packs.pack_distribution(5))
800
 
        self.assertEqual([1, 1, 1, 1, 1, 1],
801
 
            packs.pack_distribution(6))
802
 
        self.assertEqual([1, 1, 1, 1, 1, 1, 1],
803
 
            packs.pack_distribution(7))
804
 
        self.assertEqual([1, 1, 1, 1, 1, 1, 1, 1],
805
 
            packs.pack_distribution(8))
806
 
        self.assertEqual([1, 1, 1, 1, 1, 1, 1, 1, 1],
807
 
            packs.pack_distribution(9))
808
 
 
809
 
    def test_pack_distribution_stable_at_boundaries(self):
810
 
        """When there are multi-rev packs the counts are stable."""
811
 
        format = self.get_format()
812
 
        repo = self.make_repository('.', format=format)
813
 
        packs = repo._pack_collection
814
 
        # in 10s:
815
 
        self.assertEqual([10], packs.pack_distribution(10))
816
 
        self.assertEqual([10, 1], packs.pack_distribution(11))
817
 
        self.assertEqual([10, 10], packs.pack_distribution(20))
818
 
        self.assertEqual([10, 10, 1], packs.pack_distribution(21))
819
 
        # 100s
820
 
        self.assertEqual([100], packs.pack_distribution(100))
821
 
        self.assertEqual([100, 1], packs.pack_distribution(101))
822
 
        self.assertEqual([100, 10, 1], packs.pack_distribution(111))
823
 
        self.assertEqual([100, 100], packs.pack_distribution(200))
824
 
        self.assertEqual([100, 100, 1], packs.pack_distribution(201))
825
 
        self.assertEqual([100, 100, 10, 1], packs.pack_distribution(211))
826
 
 
827
 
    def test_plan_pack_operations_2009_revisions_skip_all_packs(self):
828
 
        format = self.get_format()
829
 
        repo = self.make_repository('.', format=format)
830
 
        packs = repo._pack_collection
831
 
        existing_packs = [(2000, "big"), (9, "medium")]
832
 
        # rev count - 2009 -> 2x1000 + 9x1
833
 
        pack_operations = packs.plan_autopack_combinations(
834
 
            existing_packs, [1000, 1000, 1, 1, 1, 1, 1, 1, 1, 1, 1])
835
 
        self.assertEqual([], pack_operations)
836
 
 
837
 
    def test_plan_pack_operations_2010_revisions_skip_all_packs(self):
838
 
        format = self.get_format()
839
 
        repo = self.make_repository('.', format=format)
840
 
        packs = repo._pack_collection
841
 
        existing_packs = [(2000, "big"), (9, "medium"), (1, "single")]
842
 
        # rev count - 2010 -> 2x1000 + 1x10
843
 
        pack_operations = packs.plan_autopack_combinations(
844
 
            existing_packs, [1000, 1000, 10])
845
 
        self.assertEqual([], pack_operations)
846
 
 
847
 
    def test_plan_pack_operations_2010_combines_smallest_two(self):
848
 
        format = self.get_format()
849
 
        repo = self.make_repository('.', format=format)
850
 
        packs = repo._pack_collection
851
 
        existing_packs = [(1999, "big"), (9, "medium"), (1, "single2"),
852
 
            (1, "single1")]
853
 
        # rev count - 2010 -> 2x1000 + 1x10 (3)
854
 
        pack_operations = packs.plan_autopack_combinations(
855
 
            existing_packs, [1000, 1000, 10])
856
 
        self.assertEqual([[2, ["single2", "single1"]], [0, []]], pack_operations)
857
 
 
858
 
    def test_all_packs_none(self):
859
 
        format = self.get_format()
860
 
        tree = self.make_branch_and_tree('.', format=format)
861
 
        tree.lock_read()
862
 
        self.addCleanup(tree.unlock)
863
 
        packs = tree.branch.repository._pack_collection
864
 
        packs.ensure_loaded()
865
 
        self.assertEqual([], packs.all_packs())
866
 
 
867
 
    def test_all_packs_one(self):
868
 
        format = self.get_format()
869
 
        tree = self.make_branch_and_tree('.', format=format)
870
 
        tree.commit('start')
871
 
        tree.lock_read()
872
 
        self.addCleanup(tree.unlock)
873
 
        packs = tree.branch.repository._pack_collection
874
 
        packs.ensure_loaded()
875
 
        self.assertEqual([
876
 
            packs.get_pack_by_name(packs.names()[0])],
877
 
            packs.all_packs())
878
 
 
879
 
    def test_all_packs_two(self):
880
 
        format = self.get_format()
881
 
        tree = self.make_branch_and_tree('.', format=format)
882
 
        tree.commit('start')
883
 
        tree.commit('continue')
884
 
        tree.lock_read()
885
 
        self.addCleanup(tree.unlock)
886
 
        packs = tree.branch.repository._pack_collection
887
 
        packs.ensure_loaded()
888
 
        self.assertEqual([
889
 
            packs.get_pack_by_name(packs.names()[0]),
890
 
            packs.get_pack_by_name(packs.names()[1]),
891
 
            ], packs.all_packs())
892
 
 
893
 
    def test_get_pack_by_name(self):
894
 
        format = self.get_format()
895
 
        tree = self.make_branch_and_tree('.', format=format)
896
 
        tree.commit('start')
897
 
        tree.lock_read()
898
 
        self.addCleanup(tree.unlock)
899
 
        packs = tree.branch.repository._pack_collection
900
 
        packs.ensure_loaded()
901
 
        name = packs.names()[0]
902
 
        pack_1 = packs.get_pack_by_name(name)
903
 
        # the pack should be correctly initialised
904
 
        sizes = packs._names[name]
905
 
        rev_index = GraphIndex(packs._index_transport, name + '.rix', sizes[0])
906
 
        inv_index = GraphIndex(packs._index_transport, name + '.iix', sizes[1])
907
 
        txt_index = GraphIndex(packs._index_transport, name + '.tix', sizes[2])
908
 
        sig_index = GraphIndex(packs._index_transport, name + '.six', sizes[3])
909
 
        self.assertEqual(pack_repo.ExistingPack(packs._pack_transport,
910
 
            name, rev_index, inv_index, txt_index, sig_index), pack_1)
911
 
        # and the same instance should be returned on successive calls.
912
 
        self.assertTrue(pack_1 is packs.get_pack_by_name(name))
913
 
 
914
 
 
915
 
class TestPack(TestCaseWithTransport):
916
 
    """Tests for the Pack object."""
917
 
 
918
 
    def assertCurrentlyEqual(self, left, right):
919
 
        self.assertTrue(left == right)
920
 
        self.assertTrue(right == left)
921
 
        self.assertFalse(left != right)
922
 
        self.assertFalse(right != left)
923
 
 
924
 
    def assertCurrentlyNotEqual(self, left, right):
925
 
        self.assertFalse(left == right)
926
 
        self.assertFalse(right == left)
927
 
        self.assertTrue(left != right)
928
 
        self.assertTrue(right != left)
929
 
 
930
 
    def test___eq____ne__(self):
931
 
        left = pack_repo.ExistingPack('', '', '', '', '', '')
932
 
        right = pack_repo.ExistingPack('', '', '', '', '', '')
933
 
        self.assertCurrentlyEqual(left, right)
934
 
        # change all attributes and ensure equality changes as we do.
935
 
        left.revision_index = 'a'
936
 
        self.assertCurrentlyNotEqual(left, right)
937
 
        right.revision_index = 'a'
938
 
        self.assertCurrentlyEqual(left, right)
939
 
        left.inventory_index = 'a'
940
 
        self.assertCurrentlyNotEqual(left, right)
941
 
        right.inventory_index = 'a'
942
 
        self.assertCurrentlyEqual(left, right)
943
 
        left.text_index = 'a'
944
 
        self.assertCurrentlyNotEqual(left, right)
945
 
        right.text_index = 'a'
946
 
        self.assertCurrentlyEqual(left, right)
947
 
        left.signature_index = 'a'
948
 
        self.assertCurrentlyNotEqual(left, right)
949
 
        right.signature_index = 'a'
950
 
        self.assertCurrentlyEqual(left, right)
951
 
        left.name = 'a'
952
 
        self.assertCurrentlyNotEqual(left, right)
953
 
        right.name = 'a'
954
 
        self.assertCurrentlyEqual(left, right)
955
 
        left.transport = 'a'
956
 
        self.assertCurrentlyNotEqual(left, right)
957
 
        right.transport = 'a'
958
 
        self.assertCurrentlyEqual(left, right)
959
 
 
960
 
    def test_file_name(self):
961
 
        pack = pack_repo.ExistingPack('', 'a_name', '', '', '', '')
962
 
        self.assertEqual('a_name.pack', pack.file_name())
963
 
 
964
 
 
965
 
class TestNewPack(TestCaseWithTransport):
966
 
    """Tests for pack_repo.NewPack."""
967
 
 
968
 
    def test_new_instance_attributes(self):
969
 
        upload_transport = self.get_transport('upload')
970
 
        pack_transport = self.get_transport('pack')
971
 
        index_transport = self.get_transport('index')
972
 
        upload_transport.mkdir('.')
973
 
        pack = pack_repo.NewPack(upload_transport, index_transport,
974
 
            pack_transport)
975
 
        self.assertIsInstance(pack.revision_index, InMemoryGraphIndex)
976
 
        self.assertIsInstance(pack.inventory_index, InMemoryGraphIndex)
977
 
        self.assertIsInstance(pack._hash, type(md5.new()))
978
 
        self.assertTrue(pack.upload_transport is upload_transport)
979
 
        self.assertTrue(pack.index_transport is index_transport)
980
 
        self.assertTrue(pack.pack_transport is pack_transport)
981
 
        self.assertEqual(None, pack.index_sizes)
982
 
        self.assertEqual(20, len(pack.random_name))
983
 
        self.assertIsInstance(pack.random_name, str)
984
 
        self.assertIsInstance(pack.start_time, float)
985
 
 
986
 
 
987
 
class TestPacker(TestCaseWithTransport):
988
 
    """Tests for the packs repository Packer class."""
989
 
 
990
 
    # To date, this class has been factored out and nothing new added to it;
991
 
    # thus there are not yet any tests.
992
 
 
993
 
 
994
 
class TestInterDifferingSerializer(TestCaseWithTransport):
995
 
 
996
 
    def test_progress_bar(self):
997
 
        tree = self.make_branch_and_tree('tree')
998
 
        tree.commit('rev1', rev_id='rev-1')
999
 
        tree.commit('rev2', rev_id='rev-2')
1000
 
        tree.commit('rev3', rev_id='rev-3')
1001
 
        repo = self.make_repository('repo')
1002
 
        inter_repo = repository.InterDifferingSerializer(
1003
 
            tree.branch.repository, repo)
1004
 
        pb = progress.InstrumentedProgress(to_file=StringIO())
1005
 
        pb.never_throttle = True
1006
 
        inter_repo.fetch('rev-1', pb)
1007
 
        self.assertEqual('Transferring revisions', pb.last_msg)
1008
 
        self.assertEqual(1, pb.last_cnt)
1009
 
        self.assertEqual(1, pb.last_total)
1010
 
        inter_repo.fetch('rev-3', pb)
1011
 
        self.assertEqual(2, pb.last_cnt)
1012
 
        self.assertEqual(2, pb.last_total)