~bzr-pqm/bzr/bzr.dev

2220.2.2 by Martin Pool
Add tag command and basic implementation
1
# Copyright (C) 2006, 2007 Canonical Ltd
1685.1.63 by Martin Pool
Small Transport fixups
2
#
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
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.
1685.1.63 by Martin Pool
Small Transport fixups
7
#
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
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.
1685.1.63 by Martin Pool
Small Transport fixups
12
#
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Tests for the Repository facility that are not interface tests.
18
19
For interface tests see tests/repository_implementations/*.py.
20
21
For concrete class tests see this file, and for storage formats tests
22
also see this file.
23
"""
24
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
25
from stat import S_ISDIR
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
26
from StringIO import StringIO
27
2204.4.11 by Aaron Bentley
deprecate Repository.set_default_format, update upgrade tests
28
from bzrlib import symbol_versioning
1556.1.4 by Robert Collins
Add a new format for what will become knit, and the surrounding logic to upgrade repositories within metadirs, and tests for the same.
29
import bzrlib
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
30
import bzrlib.bzrdir as bzrdir
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
31
import bzrlib.errors as errors
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
32
from bzrlib.errors import (NotBranchError,
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
33
                           NoSuchFile,
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
34
                           UnknownFormatError,
35
                           UnsupportedFormatError,
36
                           )
2241.1.1 by Martin Pool
Change RepositoryFormat to use a Registry rather than ad-hoc dictionary
37
from bzrlib.repository import RepositoryFormat
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
38
from bzrlib.tests import TestCase, TestCaseWithTransport
39
from bzrlib.transport import get_transport
40
from bzrlib.transport.memory import MemoryServer
2241.1.1 by Martin Pool
Change RepositoryFormat to use a Registry rather than ad-hoc dictionary
41
from bzrlib import (
42
    repository,
43
    upgrade,
44
    workingtree,
45
    )
2241.1.5 by Martin Pool
Move KnitFormat2 into repofmt
46
from bzrlib.repofmt import knitrepo, weaverepo
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
47
48
49
class TestDefaultFormat(TestCase):
50
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
51
    def test_get_set_default_format(self):
2204.5.3 by Aaron Bentley
zap old repository default handling
52
        old_default = bzrdir.format_registry.get('default')
53
        private_default = old_default().repository_format.__class__
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
54
        old_format = repository.RepositoryFormat.get_default_format()
1910.2.33 by Aaron Bentley
Fix default format test
55
        self.assertTrue(isinstance(old_format, private_default))
2204.5.3 by Aaron Bentley
zap old repository default handling
56
        def make_sample_bzrdir():
57
            my_bzrdir = bzrdir.BzrDirMetaFormat1()
58
            my_bzrdir.repository_format = SampleRepositoryFormat()
59
            return my_bzrdir
60
        bzrdir.format_registry.remove('default')
61
        bzrdir.format_registry.register('sample', make_sample_bzrdir, '')
62
        bzrdir.format_registry.set_default('sample')
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
63
        # creating a repository should now create an instrumented dir.
64
        try:
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
65
            # the default branch format is used by the meta dir format
66
            # which is not the default bzrdir format at this point
1685.1.63 by Martin Pool
Small Transport fixups
67
            dir = bzrdir.BzrDirMetaFormat1().initialize('memory:///')
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
68
            result = dir.create_repository()
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
69
            self.assertEqual(result, 'A bzr repository dir')
2241.1.1 by Martin Pool
Change RepositoryFormat to use a Registry rather than ad-hoc dictionary
70
        finally:
2204.5.3 by Aaron Bentley
zap old repository default handling
71
            bzrdir.format_registry.remove('default')
2363.5.14 by Aaron Bentley
Prevent repository.get_set_default_format from corrupting inventory
72
            bzrdir.format_registry.remove('sample')
2204.5.3 by Aaron Bentley
zap old repository default handling
73
            bzrdir.format_registry.register('default', old_default, '')
74
        self.assertIsInstance(repository.RepositoryFormat.get_default_format(),
75
                              old_format.__class__)
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
76
77
78
class SampleRepositoryFormat(repository.RepositoryFormat):
79
    """A sample format
80
81
    this format is initializable, unsupported to aid in testing the 
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
82
    open and open(unsupported=True) routines.
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
83
    """
84
85
    def get_format_string(self):
86
        """See RepositoryFormat.get_format_string()."""
87
        return "Sample .bzr repository format."
88
1534.6.1 by Robert Collins
allow API creation of shared repositories
89
    def initialize(self, a_bzrdir, shared=False):
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
90
        """Initialize a repository in a BzrDir"""
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
91
        t = a_bzrdir.get_repository_transport(self)
1955.3.13 by John Arbash Meinel
Run the full test suite, and fix up any deprecation warnings.
92
        t.put_bytes('format', self.get_format_string())
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
93
        return 'A bzr repository dir'
94
95
    def is_supported(self):
96
        return False
97
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
98
    def open(self, a_bzrdir, _found=False):
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
99
        return "opened repository."
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
100
101
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
102
class TestRepositoryFormat(TestCaseWithTransport):
103
    """Tests for the Repository format detection used by the bzr meta dir facility.BzrBranchFormat facility."""
104
105
    def test_find_format(self):
106
        # is the right format object found for a repository?
107
        # create a branch with a few known format objects.
108
        # this is not quite the same as 
109
        self.build_tree(["foo/", "bar/"])
110
        def check_format(format, url):
111
            dir = format._matchingbzrdir.initialize(url)
112
            format.initialize(dir)
113
            t = get_transport(url)
114
            found_format = repository.RepositoryFormat.find_format(dir)
115
            self.failUnless(isinstance(found_format, format.__class__))
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
116
        check_format(weaverepo.RepositoryFormat7(), "bar")
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
117
        
118
    def test_find_format_no_repository(self):
119
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
120
        self.assertRaises(errors.NoRepositoryPresent,
121
                          repository.RepositoryFormat.find_format,
122
                          dir)
123
124
    def test_find_format_unknown_format(self):
125
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
126
        SampleRepositoryFormat().initialize(dir)
127
        self.assertRaises(UnknownFormatError,
128
                          repository.RepositoryFormat.find_format,
129
                          dir)
130
131
    def test_register_unregister_format(self):
132
        format = SampleRepositoryFormat()
133
        # make a control dir
134
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
135
        # make a repo
136
        format.initialize(dir)
137
        # register a format for it.
138
        repository.RepositoryFormat.register_format(format)
139
        # which repository.Open will refuse (not supported)
140
        self.assertRaises(UnsupportedFormatError, repository.Repository.open, self.get_url())
141
        # but open(unsupported) will work
142
        self.assertEqual(format.open(dir), "opened repository.")
143
        # unregister the format
144
        repository.RepositoryFormat.unregister_format(format)
145
146
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
147
class TestFormat6(TestCaseWithTransport):
148
149
    def test_no_ancestry_weave(self):
150
        control = bzrdir.BzrDirFormat6().initialize(self.get_url())
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
151
        repo = weaverepo.RepositoryFormat6().initialize(control)
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
152
        # We no longer need to create the ancestry.weave file
153
        # since it is *never* used.
154
        self.assertRaises(NoSuchFile,
155
                          control.transport.get,
156
                          'ancestry.weave')
157
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
158
159
class TestFormat7(TestCaseWithTransport):
160
    
161
    def test_disk_layout(self):
162
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
163
        repo = weaverepo.RepositoryFormat7().initialize(control)
1534.5.3 by Robert Collins
Make format 4/5/6 branches share a single LockableFiles instance across wt/branch/repository.
164
        # in case of side effects of locking.
165
        repo.lock_write()
166
        repo.unlock()
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
167
        # we want:
168
        # format 'Bazaar-NG Repository format 7'
169
        # lock ''
170
        # inventory.weave == empty_weave
171
        # empty revision-store directory
172
        # empty weaves directory
173
        t = control.get_repository_transport(None)
174
        self.assertEqualDiff('Bazaar-NG Repository format 7',
175
                             t.get('format').read())
176
        self.assertTrue(S_ISDIR(t.stat('revision-store').st_mode))
177
        self.assertTrue(S_ISDIR(t.stat('weaves').st_mode))
178
        self.assertEqualDiff('# bzr weave file v5\n'
179
                             'w\n'
180
                             'W\n',
181
                             t.get('inventory.weave').read())
1534.6.1 by Robert Collins
allow API creation of shared repositories
182
183
    def test_shared_disk_layout(self):
184
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
185
        repo = weaverepo.RepositoryFormat7().initialize(control, shared=True)
1534.6.1 by Robert Collins
allow API creation of shared repositories
186
        # we want:
187
        # format 'Bazaar-NG Repository format 7'
188
        # inventory.weave == empty_weave
189
        # empty revision-store directory
190
        # empty weaves directory
191
        # a 'shared-storage' marker file.
1553.5.49 by Martin Pool
Use LockDirs for repo format 7
192
        # lock is not present when unlocked
1534.6.1 by Robert Collins
allow API creation of shared repositories
193
        t = control.get_repository_transport(None)
194
        self.assertEqualDiff('Bazaar-NG Repository format 7',
195
                             t.get('format').read())
196
        self.assertEqualDiff('', t.get('shared-storage').read())
197
        self.assertTrue(S_ISDIR(t.stat('revision-store').st_mode))
198
        self.assertTrue(S_ISDIR(t.stat('weaves').st_mode))
199
        self.assertEqualDiff('# bzr weave file v5\n'
200
                             'w\n'
201
                             'W\n',
202
                             t.get('inventory.weave').read())
1553.5.49 by Martin Pool
Use LockDirs for repo format 7
203
        self.assertFalse(t.has('branch-lock'))
204
1553.5.56 by Martin Pool
Format 7 repo now uses LockDir!
205
    def test_creates_lockdir(self):
1553.5.49 by Martin Pool
Use LockDirs for repo format 7
206
        """Make sure it appears to be controlled by a LockDir existence"""
207
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
208
        repo = weaverepo.RepositoryFormat7().initialize(control, shared=True)
1553.5.49 by Martin Pool
Use LockDirs for repo format 7
209
        t = control.get_repository_transport(None)
1553.5.58 by Martin Pool
Change LockDirs to format "lock-name/held/info"
210
        # TODO: Should check there is a 'lock' toplevel directory, 
211
        # regardless of contents
212
        self.assertFalse(t.has('lock/held/info'))
1553.5.49 by Martin Pool
Use LockDirs for repo format 7
213
        repo.lock_write()
1658.1.4 by Martin Pool
Quieten warning from TestFormat7.test_creates_lockdir about failing to unlock
214
        try:
215
            self.assertTrue(t.has('lock/held/info'))
216
        finally:
217
            # unlock so we don't get a warning about failing to do so
218
            repo.unlock()
1553.5.56 by Martin Pool
Format 7 repo now uses LockDir!
219
220
    def test_uses_lockdir(self):
221
        """repo format 7 actually locks on lockdir"""
222
        base_url = self.get_url()
223
        control = bzrdir.BzrDirMetaFormat1().initialize(base_url)
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
224
        repo = weaverepo.RepositoryFormat7().initialize(control, shared=True)
1553.5.56 by Martin Pool
Format 7 repo now uses LockDir!
225
        t = control.get_repository_transport(None)
226
        repo.lock_write()
227
        repo.unlock()
228
        del repo
229
        # make sure the same lock is created by opening it
230
        repo = repository.Repository.open(base_url)
231
        repo.lock_write()
1553.5.58 by Martin Pool
Change LockDirs to format "lock-name/held/info"
232
        self.assertTrue(t.has('lock/held/info'))
1553.5.56 by Martin Pool
Format 7 repo now uses LockDir!
233
        repo.unlock()
1553.5.58 by Martin Pool
Change LockDirs to format "lock-name/held/info"
234
        self.assertFalse(t.has('lock/held/info'))
1534.6.5 by Robert Collins
Cloning of repos preserves shared and make-working-tree attributes.
235
236
    def test_shared_no_tree_disk_layout(self):
237
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
238
        repo = weaverepo.RepositoryFormat7().initialize(control, shared=True)
1534.6.5 by Robert Collins
Cloning of repos preserves shared and make-working-tree attributes.
239
        repo.set_make_working_trees(False)
240
        # we want:
241
        # format 'Bazaar-NG Repository format 7'
242
        # lock ''
243
        # inventory.weave == empty_weave
244
        # empty revision-store directory
245
        # empty weaves directory
246
        # a 'shared-storage' marker file.
247
        t = control.get_repository_transport(None)
248
        self.assertEqualDiff('Bazaar-NG Repository format 7',
249
                             t.get('format').read())
1553.5.56 by Martin Pool
Format 7 repo now uses LockDir!
250
        ## self.assertEqualDiff('', t.get('lock').read())
1534.6.5 by Robert Collins
Cloning of repos preserves shared and make-working-tree attributes.
251
        self.assertEqualDiff('', t.get('shared-storage').read())
252
        self.assertEqualDiff('', t.get('no-working-trees').read())
253
        repo.set_make_working_trees(True)
254
        self.assertFalse(t.has('no-working-trees'))
255
        self.assertTrue(S_ISDIR(t.stat('revision-store').st_mode))
256
        self.assertTrue(S_ISDIR(t.stat('weaves').st_mode))
257
        self.assertEqualDiff('# bzr weave file v5\n'
258
                             'w\n'
259
                             'W\n',
260
                             t.get('inventory.weave').read())
1534.1.27 by Robert Collins
Start InterRepository with InterRepository.get.
261
262
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
263
class TestFormatKnit1(TestCaseWithTransport):
264
    
265
    def test_disk_layout(self):
266
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
267
        repo = knitrepo.RepositoryFormatKnit1().initialize(control)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
268
        # in case of side effects of locking.
269
        repo.lock_write()
270
        repo.unlock()
271
        # we want:
272
        # format 'Bazaar-NG Knit Repository Format 1'
1553.5.62 by Martin Pool
Add tests that MetaDir repositories use LockDirs
273
        # lock: is a directory
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
274
        # inventory.weave == empty_weave
275
        # empty revision-store directory
276
        # empty weaves directory
277
        t = control.get_repository_transport(None)
278
        self.assertEqualDiff('Bazaar-NG Knit Repository Format 1',
279
                             t.get('format').read())
1553.5.57 by Martin Pool
[merge] sync from bzr.dev
280
        # XXX: no locks left when unlocked at the moment
281
        # self.assertEqualDiff('', t.get('lock').read())
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
282
        self.assertTrue(S_ISDIR(t.stat('knits').st_mode))
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
283
        self.check_knits(t)
284
1654.1.3 by Robert Collins
Refactor repository knit tests slightly to remove duplication - add a assertHasKnit method.
285
    def assertHasKnit(self, t, knit_name):
286
        """Assert that knit_name exists on t."""
1666.1.7 by Robert Collins
Update repository format check to read knit correct header
287
        self.assertEqualDiff('# bzr knit index 8\n',
1654.1.3 by Robert Collins
Refactor repository knit tests slightly to remove duplication - add a assertHasKnit method.
288
                             t.get(knit_name + '.kndx').read())
289
        # no default content
290
        self.assertTrue(t.has(knit_name + '.knit'))
291
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
292
    def check_knits(self, t):
293
        """check knit content for a repository."""
1654.1.3 by Robert Collins
Refactor repository knit tests slightly to remove duplication - add a assertHasKnit method.
294
        self.assertHasKnit(t, 'inventory')
295
        self.assertHasKnit(t, 'revisions')
296
        self.assertHasKnit(t, 'signatures')
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
297
298
    def test_shared_disk_layout(self):
299
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
300
        repo = knitrepo.RepositoryFormatKnit1().initialize(control, shared=True)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
301
        # we want:
302
        # format 'Bazaar-NG Knit Repository Format 1'
1553.5.62 by Martin Pool
Add tests that MetaDir repositories use LockDirs
303
        # lock: is a directory
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
304
        # inventory.weave == empty_weave
305
        # empty revision-store directory
306
        # empty weaves directory
307
        # a 'shared-storage' marker file.
308
        t = control.get_repository_transport(None)
309
        self.assertEqualDiff('Bazaar-NG Knit Repository Format 1',
310
                             t.get('format').read())
1553.5.57 by Martin Pool
[merge] sync from bzr.dev
311
        # XXX: no locks left when unlocked at the moment
312
        # self.assertEqualDiff('', t.get('lock').read())
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
313
        self.assertEqualDiff('', t.get('shared-storage').read())
314
        self.assertTrue(S_ISDIR(t.stat('knits').st_mode))
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
315
        self.check_knits(t)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
316
317
    def test_shared_no_tree_disk_layout(self):
318
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
319
        repo = knitrepo.RepositoryFormatKnit1().initialize(control, shared=True)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
320
        repo.set_make_working_trees(False)
321
        # we want:
322
        # format 'Bazaar-NG Knit Repository Format 1'
323
        # lock ''
324
        # inventory.weave == empty_weave
325
        # empty revision-store directory
326
        # empty weaves directory
327
        # a 'shared-storage' marker file.
328
        t = control.get_repository_transport(None)
329
        self.assertEqualDiff('Bazaar-NG Knit Repository Format 1',
330
                             t.get('format').read())
1553.5.57 by Martin Pool
[merge] sync from bzr.dev
331
        # XXX: no locks left when unlocked at the moment
332
        # self.assertEqualDiff('', t.get('lock').read())
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
333
        self.assertEqualDiff('', t.get('shared-storage').read())
334
        self.assertEqualDiff('', t.get('no-working-trees').read())
335
        repo.set_make_working_trees(True)
336
        self.assertFalse(t.has('no-working-trees'))
337
        self.assertTrue(S_ISDIR(t.stat('knits').st_mode))
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
338
        self.check_knits(t)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
339
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
340
341
class DummyRepository(object):
342
    """A dummy repository for testing."""
343
344
    _serializer = None
345
346
    def supports_rich_root(self):
347
        return False
348
349
350
class InterDummy(repository.InterRepository):
351
    """An inter-repository optimised code path for DummyRepository.
352
353
    This is for use during testing where we use DummyRepository as repositories
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
354
    so that none of the default regsitered inter-repository classes will
355
    match.
356
    """
357
358
    @staticmethod
359
    def is_compatible(repo_source, repo_target):
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
360
        """InterDummy is compatible with DummyRepository."""
361
        return (isinstance(repo_source, DummyRepository) and 
362
            isinstance(repo_target, DummyRepository))
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
363
364
1534.1.27 by Robert Collins
Start InterRepository with InterRepository.get.
365
class TestInterRepository(TestCaseWithTransport):
366
367
    def test_get_default_inter_repository(self):
368
        # test that the InterRepository.get(repo_a, repo_b) probes
369
        # for a inter_repo class where is_compatible(repo_a, repo_b) returns
370
        # true and returns a default inter_repo otherwise.
371
        # This also tests that the default registered optimised interrepository
372
        # classes do not barf inappropriately when a surprising repository type
373
        # is handed to them.
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
374
        dummy_a = DummyRepository()
375
        dummy_b = DummyRepository()
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
376
        self.assertGetsDefaultInterRepository(dummy_a, dummy_b)
377
378
    def assertGetsDefaultInterRepository(self, repo_a, repo_b):
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
379
        """Asserts that InterRepository.get(repo_a, repo_b) -> the default.
380
        
381
        The effective default is now InterSameDataRepository because there is
382
        no actual sane default in the presence of incompatible data models.
383
        """
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
384
        inter_repo = repository.InterRepository.get(repo_a, repo_b)
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
385
        self.assertEqual(repository.InterSameDataRepository,
1534.1.27 by Robert Collins
Start InterRepository with InterRepository.get.
386
                         inter_repo.__class__)
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
387
        self.assertEqual(repo_a, inter_repo.source)
388
        self.assertEqual(repo_b, inter_repo.target)
389
390
    def test_register_inter_repository_class(self):
391
        # test that a optimised code path provider - a
392
        # InterRepository subclass can be registered and unregistered
393
        # and that it is correctly selected when given a repository
394
        # pair that it returns true on for the is_compatible static method
395
        # check
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
396
        dummy_a = DummyRepository()
397
        dummy_b = DummyRepository()
398
        repo = self.make_repository('.')
399
        # hack dummies to look like repo somewhat.
400
        dummy_a._serializer = repo._serializer
401
        dummy_b._serializer = repo._serializer
402
        repository.InterRepository.register_optimiser(InterDummy)
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
403
        try:
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
404
            # we should get the default for something InterDummy returns False
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
405
            # to
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
406
            self.assertFalse(InterDummy.is_compatible(dummy_a, repo))
407
            self.assertGetsDefaultInterRepository(dummy_a, repo)
408
            # and we should get an InterDummy for a pair it 'likes'
409
            self.assertTrue(InterDummy.is_compatible(dummy_a, dummy_b))
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
410
            inter_repo = repository.InterRepository.get(dummy_a, dummy_b)
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
411
            self.assertEqual(InterDummy, inter_repo.__class__)
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
412
            self.assertEqual(dummy_a, inter_repo.source)
413
            self.assertEqual(dummy_b, inter_repo.target)
414
        finally:
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
415
            repository.InterRepository.unregister_optimiser(InterDummy)
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
416
        # now we should get the default InterRepository object again.
417
        self.assertGetsDefaultInterRepository(dummy_a, dummy_b)
1534.1.33 by Robert Collins
Move copy_content_into into InterRepository and InterWeaveRepo, and disable the default codepath test as we have optimised paths for all current combinations.
418
2241.1.17 by Martin Pool
Restore old InterWeave tests
419
420
class TestInterWeaveRepo(TestCaseWithTransport):
421
422
    def test_is_compatible_and_registered(self):
423
        # InterWeaveRepo is compatible when either side
424
        # is a format 5/6/7 branch
2241.1.20 by mbp at sourcefrog
update tests for new locations of weave repos
425
        from bzrlib.repofmt import knitrepo, weaverepo
426
        formats = [weaverepo.RepositoryFormat5(),
427
                   weaverepo.RepositoryFormat6(),
428
                   weaverepo.RepositoryFormat7()]
429
        incompatible_formats = [weaverepo.RepositoryFormat4(),
430
                                knitrepo.RepositoryFormatKnit1(),
2241.1.17 by Martin Pool
Restore old InterWeave tests
431
                                ]
432
        repo_a = self.make_repository('a')
433
        repo_b = self.make_repository('b')
434
        is_compatible = repository.InterWeaveRepo.is_compatible
435
        for source in incompatible_formats:
436
            # force incompatible left then right
437
            repo_a._format = source
438
            repo_b._format = formats[0]
439
            self.assertFalse(is_compatible(repo_a, repo_b))
440
            self.assertFalse(is_compatible(repo_b, repo_a))
441
        for source in formats:
442
            repo_a._format = source
443
            for target in formats:
444
                repo_b._format = target
445
                self.assertTrue(is_compatible(repo_a, repo_b))
446
        self.assertEqual(repository.InterWeaveRepo,
447
                         repository.InterRepository.get(repo_a,
448
                                                        repo_b).__class__)
449
1556.1.4 by Robert Collins
Add a new format for what will become knit, and the surrounding logic to upgrade repositories within metadirs, and tests for the same.
450
451
class TestRepositoryConverter(TestCaseWithTransport):
452
453
    def test_convert_empty(self):
454
        t = get_transport(self.get_url('.'))
455
        t.mkdir('repository')
456
        repo_dir = bzrdir.BzrDirMetaFormat1().initialize('repository')
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
457
        repo = weaverepo.RepositoryFormat7().initialize(repo_dir)
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
458
        target_format = knitrepo.RepositoryFormatKnit1()
1556.1.4 by Robert Collins
Add a new format for what will become knit, and the surrounding logic to upgrade repositories within metadirs, and tests for the same.
459
        converter = repository.CopyConverter(target_format)
1594.1.3 by Robert Collins
Fixup pb usage to use nested_progress_bar.
460
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
461
        try:
462
            converter.convert(repo, pb)
463
        finally:
464
            pb.finished()
1556.1.4 by Robert Collins
Add a new format for what will become knit, and the surrounding logic to upgrade repositories within metadirs, and tests for the same.
465
        repo = repo_dir.open_repository()
466
        self.assertTrue(isinstance(target_format, repo._format.__class__))
1843.2.5 by Aaron Bentley
Add test of _unescape_xml
467
468
469
class TestMisc(TestCase):
470
    
471
    def test_unescape_xml(self):
472
        """We get some kind of error when malformed entities are passed"""
473
        self.assertRaises(KeyError, repository._unescape_xml, 'foo&bar;') 
1910.2.13 by Aaron Bentley
Start work on converter
474
475
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
476
class TestRepositoryFormatKnit3(TestCaseWithTransport):
1910.2.13 by Aaron Bentley
Start work on converter
477
478
    def test_convert(self):
479
        """Ensure the upgrade adds weaves for roots"""
1910.2.35 by Aaron Bentley
Better fix for convesion test
480
        format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
481
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1910.2.35 by Aaron Bentley
Better fix for convesion test
482
        tree = self.make_branch_and_tree('.', format)
1910.2.13 by Aaron Bentley
Start work on converter
483
        tree.commit("Dull commit", rev_id="dull")
484
        revision_tree = tree.branch.repository.revision_tree('dull')
485
        self.assertRaises(errors.NoSuchFile, revision_tree.get_file_lines,
486
            revision_tree.inventory.root.file_id)
487
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
488
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.13 by Aaron Bentley
Start work on converter
489
        upgrade.Convert('.', format)
1910.2.27 by Aaron Bentley
Fixed conversion test
490
        tree = workingtree.WorkingTree.open('.')
1910.2.13 by Aaron Bentley
Start work on converter
491
        revision_tree = tree.branch.repository.revision_tree('dull')
492
        revision_tree.get_file_lines(revision_tree.inventory.root.file_id)
1910.2.27 by Aaron Bentley
Fixed conversion test
493
        tree.commit("Another dull commit", rev_id='dull2')
494
        revision_tree = tree.branch.repository.revision_tree('dull2')
495
        self.assertEqual('dull', revision_tree.inventory.root.revision)
2220.2.2 by Martin Pool
Add tag command and basic implementation
496