/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
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
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.
28
import bzrlib
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
29
from bzrlib.errors import (NotBranchError,
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
30
                           NoSuchFile,
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
31
                           UnknownFormatError,
32
                           UnsupportedFormatError,
33
                           )
2241.1.1 by Martin Pool
Change RepositoryFormat to use a Registry rather than ad-hoc dictionary
34
from bzrlib.repository import RepositoryFormat
2535.3.41 by Andrew Bennetts
Add tests for InterRemoteToOther.is_compatible.
35
from bzrlib.smart import server
2670.3.5 by Andrew Bennetts
Remove get_stream_as_bytes from KnitVersionedFile's API, make it a function in knitrepo.py instead.
36
from bzrlib.tests import (
37
    TestCase,
38
    TestCaseWithTransport,
39
    test_knit,
40
    )
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
41
from bzrlib.transport import get_transport
42
from bzrlib.transport.memory import MemoryServer
2535.3.53 by Andrew Bennetts
Remove get_stream_as_bytes from KnitVersionedFile's API, make it a function in knitrepo.py instead.
43
from bzrlib.util import bencode
2241.1.1 by Martin Pool
Change RepositoryFormat to use a Registry rather than ad-hoc dictionary
44
from bzrlib import (
2535.3.41 by Andrew Bennetts
Add tests for InterRemoteToOther.is_compatible.
45
    bzrdir,
46
    errors,
2535.3.57 by Andrew Bennetts
Perform some sanity checking of data streams rather than blindly inserting them into our repository.
47
    inventory,
2241.1.1 by Martin Pool
Change RepositoryFormat to use a Registry rather than ad-hoc dictionary
48
    repository,
2535.3.57 by Andrew Bennetts
Perform some sanity checking of data streams rather than blindly inserting them into our repository.
49
    revision as _mod_revision,
2535.3.41 by Andrew Bennetts
Add tests for InterRemoteToOther.is_compatible.
50
    symbol_versioning,
2241.1.1 by Martin Pool
Change RepositoryFormat to use a Registry rather than ad-hoc dictionary
51
    upgrade,
52
    workingtree,
53
    )
2241.1.5 by Martin Pool
Move KnitFormat2 into repofmt
54
from bzrlib.repofmt import knitrepo, weaverepo
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
55
56
57
class TestDefaultFormat(TestCase):
58
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
59
    def test_get_set_default_format(self):
2204.5.3 by Aaron Bentley
zap old repository default handling
60
        old_default = bzrdir.format_registry.get('default')
61
        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.
62
        old_format = repository.RepositoryFormat.get_default_format()
1910.2.33 by Aaron Bentley
Fix default format test
63
        self.assertTrue(isinstance(old_format, private_default))
2204.5.3 by Aaron Bentley
zap old repository default handling
64
        def make_sample_bzrdir():
65
            my_bzrdir = bzrdir.BzrDirMetaFormat1()
66
            my_bzrdir.repository_format = SampleRepositoryFormat()
67
            return my_bzrdir
68
        bzrdir.format_registry.remove('default')
69
        bzrdir.format_registry.register('sample', make_sample_bzrdir, '')
70
        bzrdir.format_registry.set_default('sample')
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
71
        # creating a repository should now create an instrumented dir.
72
        try:
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
73
            # the default branch format is used by the meta dir format
74
            # which is not the default bzrdir format at this point
1685.1.63 by Martin Pool
Small Transport fixups
75
            dir = bzrdir.BzrDirMetaFormat1().initialize('memory:///')
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
76
            result = dir.create_repository()
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
77
            self.assertEqual(result, 'A bzr repository dir')
2241.1.1 by Martin Pool
Change RepositoryFormat to use a Registry rather than ad-hoc dictionary
78
        finally:
2204.5.3 by Aaron Bentley
zap old repository default handling
79
            bzrdir.format_registry.remove('default')
2363.5.14 by Aaron Bentley
Prevent repository.get_set_default_format from corrupting inventory
80
            bzrdir.format_registry.remove('sample')
2204.5.3 by Aaron Bentley
zap old repository default handling
81
            bzrdir.format_registry.register('default', old_default, '')
82
        self.assertIsInstance(repository.RepositoryFormat.get_default_format(),
83
                              old_format.__class__)
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
84
85
86
class SampleRepositoryFormat(repository.RepositoryFormat):
87
    """A sample format
88
89
    this format is initializable, unsupported to aid in testing the 
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
90
    open and open(unsupported=True) routines.
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
91
    """
92
93
    def get_format_string(self):
94
        """See RepositoryFormat.get_format_string()."""
95
        return "Sample .bzr repository format."
96
1534.6.1 by Robert Collins
allow API creation of shared repositories
97
    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.
98
        """Initialize a repository in a BzrDir"""
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
99
        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.
100
        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.
101
        return 'A bzr repository dir'
102
103
    def is_supported(self):
104
        return False
105
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
106
    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.
107
        return "opened repository."
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
108
109
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
110
class TestRepositoryFormat(TestCaseWithTransport):
111
    """Tests for the Repository format detection used by the bzr meta dir facility.BzrBranchFormat facility."""
112
113
    def test_find_format(self):
114
        # is the right format object found for a repository?
115
        # create a branch with a few known format objects.
116
        # this is not quite the same as 
117
        self.build_tree(["foo/", "bar/"])
118
        def check_format(format, url):
119
            dir = format._matchingbzrdir.initialize(url)
120
            format.initialize(dir)
121
            t = get_transport(url)
122
            found_format = repository.RepositoryFormat.find_format(dir)
123
            self.failUnless(isinstance(found_format, format.__class__))
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
124
        check_format(weaverepo.RepositoryFormat7(), "bar")
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
125
        
126
    def test_find_format_no_repository(self):
127
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
128
        self.assertRaises(errors.NoRepositoryPresent,
129
                          repository.RepositoryFormat.find_format,
130
                          dir)
131
132
    def test_find_format_unknown_format(self):
133
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
134
        SampleRepositoryFormat().initialize(dir)
135
        self.assertRaises(UnknownFormatError,
136
                          repository.RepositoryFormat.find_format,
137
                          dir)
138
139
    def test_register_unregister_format(self):
140
        format = SampleRepositoryFormat()
141
        # make a control dir
142
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
143
        # make a repo
144
        format.initialize(dir)
145
        # register a format for it.
146
        repository.RepositoryFormat.register_format(format)
147
        # which repository.Open will refuse (not supported)
148
        self.assertRaises(UnsupportedFormatError, repository.Repository.open, self.get_url())
149
        # but open(unsupported) will work
150
        self.assertEqual(format.open(dir), "opened repository.")
151
        # unregister the format
152
        repository.RepositoryFormat.unregister_format(format)
153
154
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
155
class TestFormat6(TestCaseWithTransport):
156
157
    def test_no_ancestry_weave(self):
158
        control = bzrdir.BzrDirFormat6().initialize(self.get_url())
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
159
        repo = weaverepo.RepositoryFormat6().initialize(control)
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
160
        # We no longer need to create the ancestry.weave file
161
        # since it is *never* used.
162
        self.assertRaises(NoSuchFile,
163
                          control.transport.get,
164
                          'ancestry.weave')
165
2818.4.2 by Robert Collins
Review feedback.
166
    def test_exposed_versioned_files_are_marked_dirty(self):
167
        control = bzrdir.BzrDirFormat6().initialize(self.get_url())
168
        repo = weaverepo.RepositoryFormat6().initialize(control)
169
        repo.lock_write()
170
        inv = repo.get_inventory_weave()
171
        repo.unlock()
172
        self.assertRaises(errors.OutSideTransaction,
173
            inv.add_lines, 'foo', [], [])
174
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
175
176
class TestFormat7(TestCaseWithTransport):
177
    
178
    def test_disk_layout(self):
179
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
180
        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.
181
        # in case of side effects of locking.
182
        repo.lock_write()
183
        repo.unlock()
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
184
        # we want:
185
        # format 'Bazaar-NG Repository format 7'
186
        # lock ''
187
        # inventory.weave == empty_weave
188
        # empty revision-store directory
189
        # empty weaves directory
190
        t = control.get_repository_transport(None)
191
        self.assertEqualDiff('Bazaar-NG Repository format 7',
192
                             t.get('format').read())
193
        self.assertTrue(S_ISDIR(t.stat('revision-store').st_mode))
194
        self.assertTrue(S_ISDIR(t.stat('weaves').st_mode))
195
        self.assertEqualDiff('# bzr weave file v5\n'
196
                             'w\n'
197
                             'W\n',
198
                             t.get('inventory.weave').read())
1534.6.1 by Robert Collins
allow API creation of shared repositories
199
200
    def test_shared_disk_layout(self):
201
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
202
        repo = weaverepo.RepositoryFormat7().initialize(control, shared=True)
1534.6.1 by Robert Collins
allow API creation of shared repositories
203
        # we want:
204
        # format 'Bazaar-NG Repository format 7'
205
        # inventory.weave == empty_weave
206
        # empty revision-store directory
207
        # empty weaves directory
208
        # a 'shared-storage' marker file.
1553.5.49 by Martin Pool
Use LockDirs for repo format 7
209
        # lock is not present when unlocked
1534.6.1 by Robert Collins
allow API creation of shared repositories
210
        t = control.get_repository_transport(None)
211
        self.assertEqualDiff('Bazaar-NG Repository format 7',
212
                             t.get('format').read())
213
        self.assertEqualDiff('', t.get('shared-storage').read())
214
        self.assertTrue(S_ISDIR(t.stat('revision-store').st_mode))
215
        self.assertTrue(S_ISDIR(t.stat('weaves').st_mode))
216
        self.assertEqualDiff('# bzr weave file v5\n'
217
                             'w\n'
218
                             'W\n',
219
                             t.get('inventory.weave').read())
1553.5.49 by Martin Pool
Use LockDirs for repo format 7
220
        self.assertFalse(t.has('branch-lock'))
221
1553.5.56 by Martin Pool
Format 7 repo now uses LockDir!
222
    def test_creates_lockdir(self):
1553.5.49 by Martin Pool
Use LockDirs for repo format 7
223
        """Make sure it appears to be controlled by a LockDir existence"""
224
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
225
        repo = weaverepo.RepositoryFormat7().initialize(control, shared=True)
1553.5.49 by Martin Pool
Use LockDirs for repo format 7
226
        t = control.get_repository_transport(None)
1553.5.58 by Martin Pool
Change LockDirs to format "lock-name/held/info"
227
        # TODO: Should check there is a 'lock' toplevel directory, 
228
        # regardless of contents
229
        self.assertFalse(t.has('lock/held/info'))
1553.5.49 by Martin Pool
Use LockDirs for repo format 7
230
        repo.lock_write()
1658.1.4 by Martin Pool
Quieten warning from TestFormat7.test_creates_lockdir about failing to unlock
231
        try:
232
            self.assertTrue(t.has('lock/held/info'))
233
        finally:
234
            # unlock so we don't get a warning about failing to do so
235
            repo.unlock()
1553.5.56 by Martin Pool
Format 7 repo now uses LockDir!
236
237
    def test_uses_lockdir(self):
238
        """repo format 7 actually locks on lockdir"""
239
        base_url = self.get_url()
240
        control = bzrdir.BzrDirMetaFormat1().initialize(base_url)
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
241
        repo = weaverepo.RepositoryFormat7().initialize(control, shared=True)
1553.5.56 by Martin Pool
Format 7 repo now uses LockDir!
242
        t = control.get_repository_transport(None)
243
        repo.lock_write()
244
        repo.unlock()
245
        del repo
246
        # make sure the same lock is created by opening it
247
        repo = repository.Repository.open(base_url)
248
        repo.lock_write()
1553.5.58 by Martin Pool
Change LockDirs to format "lock-name/held/info"
249
        self.assertTrue(t.has('lock/held/info'))
1553.5.56 by Martin Pool
Format 7 repo now uses LockDir!
250
        repo.unlock()
1553.5.58 by Martin Pool
Change LockDirs to format "lock-name/held/info"
251
        self.assertFalse(t.has('lock/held/info'))
1534.6.5 by Robert Collins
Cloning of repos preserves shared and make-working-tree attributes.
252
253
    def test_shared_no_tree_disk_layout(self):
254
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
255
        repo = weaverepo.RepositoryFormat7().initialize(control, shared=True)
1534.6.5 by Robert Collins
Cloning of repos preserves shared and make-working-tree attributes.
256
        repo.set_make_working_trees(False)
257
        # we want:
258
        # format 'Bazaar-NG Repository format 7'
259
        # lock ''
260
        # inventory.weave == empty_weave
261
        # empty revision-store directory
262
        # empty weaves directory
263
        # a 'shared-storage' marker file.
264
        t = control.get_repository_transport(None)
265
        self.assertEqualDiff('Bazaar-NG Repository format 7',
266
                             t.get('format').read())
1553.5.56 by Martin Pool
Format 7 repo now uses LockDir!
267
        ## self.assertEqualDiff('', t.get('lock').read())
1534.6.5 by Robert Collins
Cloning of repos preserves shared and make-working-tree attributes.
268
        self.assertEqualDiff('', t.get('shared-storage').read())
269
        self.assertEqualDiff('', t.get('no-working-trees').read())
270
        repo.set_make_working_trees(True)
271
        self.assertFalse(t.has('no-working-trees'))
272
        self.assertTrue(S_ISDIR(t.stat('revision-store').st_mode))
273
        self.assertTrue(S_ISDIR(t.stat('weaves').st_mode))
274
        self.assertEqualDiff('# bzr weave file v5\n'
275
                             'w\n'
276
                             'W\n',
277
                             t.get('inventory.weave').read())
1534.1.27 by Robert Collins
Start InterRepository with InterRepository.get.
278
2818.4.2 by Robert Collins
Review feedback.
279
    def test_exposed_versioned_files_are_marked_dirty(self):
280
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
281
        repo = weaverepo.RepositoryFormat7().initialize(control)
282
        repo.lock_write()
283
        inv = repo.get_inventory_weave()
284
        repo.unlock()
285
        self.assertRaises(errors.OutSideTransaction,
286
            inv.add_lines, 'foo', [], [])
287
1534.1.27 by Robert Collins
Start InterRepository with InterRepository.get.
288
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
289
class TestFormatKnit1(TestCaseWithTransport):
290
    
291
    def test_disk_layout(self):
292
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
293
        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
294
        # in case of side effects of locking.
295
        repo.lock_write()
296
        repo.unlock()
297
        # we want:
298
        # format 'Bazaar-NG Knit Repository Format 1'
1553.5.62 by Martin Pool
Add tests that MetaDir repositories use LockDirs
299
        # 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
300
        # inventory.weave == empty_weave
301
        # empty revision-store directory
302
        # empty weaves directory
303
        t = control.get_repository_transport(None)
304
        self.assertEqualDiff('Bazaar-NG Knit Repository Format 1',
305
                             t.get('format').read())
1553.5.57 by Martin Pool
[merge] sync from bzr.dev
306
        # XXX: no locks left when unlocked at the moment
307
        # 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
308
        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.
309
        self.check_knits(t)
310
1654.1.3 by Robert Collins
Refactor repository knit tests slightly to remove duplication - add a assertHasKnit method.
311
    def assertHasKnit(self, t, knit_name):
312
        """Assert that knit_name exists on t."""
1666.1.7 by Robert Collins
Update repository format check to read knit correct header
313
        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.
314
                             t.get(knit_name + '.kndx').read())
315
        # no default content
316
        self.assertTrue(t.has(knit_name + '.knit'))
317
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
318
    def check_knits(self, t):
319
        """check knit content for a repository."""
1654.1.3 by Robert Collins
Refactor repository knit tests slightly to remove duplication - add a assertHasKnit method.
320
        self.assertHasKnit(t, 'inventory')
321
        self.assertHasKnit(t, 'revisions')
322
        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
323
324
    def test_shared_disk_layout(self):
325
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
326
        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
327
        # we want:
328
        # format 'Bazaar-NG Knit Repository Format 1'
1553.5.62 by Martin Pool
Add tests that MetaDir repositories use LockDirs
329
        # 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
330
        # inventory.weave == empty_weave
331
        # empty revision-store directory
332
        # empty weaves directory
333
        # a 'shared-storage' marker file.
334
        t = control.get_repository_transport(None)
335
        self.assertEqualDiff('Bazaar-NG Knit Repository Format 1',
336
                             t.get('format').read())
1553.5.57 by Martin Pool
[merge] sync from bzr.dev
337
        # XXX: no locks left when unlocked at the moment
338
        # 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
339
        self.assertEqualDiff('', t.get('shared-storage').read())
340
        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.
341
        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
342
343
    def test_shared_no_tree_disk_layout(self):
344
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
345
        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
346
        repo.set_make_working_trees(False)
347
        # we want:
348
        # format 'Bazaar-NG Knit Repository Format 1'
349
        # lock ''
350
        # inventory.weave == empty_weave
351
        # empty revision-store directory
352
        # empty weaves directory
353
        # a 'shared-storage' marker file.
354
        t = control.get_repository_transport(None)
355
        self.assertEqualDiff('Bazaar-NG Knit Repository Format 1',
356
                             t.get('format').read())
1553.5.57 by Martin Pool
[merge] sync from bzr.dev
357
        # XXX: no locks left when unlocked at the moment
358
        # 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
359
        self.assertEqualDiff('', t.get('shared-storage').read())
360
        self.assertEqualDiff('', t.get('no-working-trees').read())
361
        repo.set_make_working_trees(True)
362
        self.assertFalse(t.has('no-working-trees'))
363
        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.
364
        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
365
2818.4.2 by Robert Collins
Review feedback.
366
    def test_exposed_versioned_files_are_marked_dirty(self):
367
        format = bzrdir.BzrDirMetaFormat1()
368
        format.repository_format = knitrepo.RepositoryFormatKnit1()
369
        repo = self.make_repository('.', format=format)
370
        repo.lock_write()
371
        inv = repo.get_inventory_weave()
372
        repo.unlock()
373
        self.assertRaises(errors.OutSideTransaction,
374
            inv.add_lines, 'foo', [], [])
375
2917.2.1 by John Arbash Meinel
Fix bug #152360. The xml5 serializer should be using
376
    def test_deserialise_sets_root_revision(self):
377
        """We must have a inventory.root.revision
378
379
        Old versions of the XML5 serializer did not set the revision_id for
380
        the whole inventory. So we grab the one from the expected text. Which
381
        is valid when the api is not being abused.
382
        """
383
        repo = self.make_repository('.',
384
                format=bzrdir.format_registry.get('knit')())
385
        inv_xml = '<inventory format="5">\n</inventory>\n'
386
        inv = repo.deserialise_inventory('test-rev-id', inv_xml)
387
        self.assertEqual('test-rev-id', inv.root.revision)
388
389
    def test_deserialise_uses_global_revision_id(self):
390
        """If it is set, then we re-use the global revision id"""
391
        repo = self.make_repository('.',
392
                format=bzrdir.format_registry.get('knit')())
393
        inv_xml = ('<inventory format="5" revision_id="other-rev-id">\n'
394
                   '</inventory>\n')
395
        # Arguably, the deserialise_inventory should detect a mismatch, and
396
        # raise an error, rather than silently using one revision_id over the
397
        # other.
398
        inv = repo.deserialise_inventory('test-rev-id', inv_xml)
399
        self.assertEqual('other-rev-id', inv.root.revision)
400
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
401
2535.3.53 by Andrew Bennetts
Remove get_stream_as_bytes from KnitVersionedFile's API, make it a function in knitrepo.py instead.
402
class KnitRepositoryStreamTests(test_knit.KnitTests):
403
    """Tests for knitrepo._get_stream_as_bytes."""
404
405
    def test_get_stream_as_bytes(self):
406
        # Make a simple knit
407
        k1 = self.make_test_knit()
408
        k1.add_lines('text-a', [], test_knit.split_lines(test_knit.TEXT_1))
409
        
410
        # Serialise it, check the output.
411
        bytes = knitrepo._get_stream_as_bytes(k1, ['text-a'])
412
        data = bencode.bdecode(bytes)
413
        format, record = data
414
        self.assertEqual('knit-plain', format)
415
        self.assertEqual(['text-a', ['fulltext'], []], record[:3])
416
        self.assertRecordContentEqual(k1, 'text-a', record[3])
417
418
    def test_get_stream_as_bytes_all(self):
419
        """Get a serialised data stream for all the records in a knit.
420
421
        Much like test_get_stream_all, except for get_stream_as_bytes.
422
        """
423
        k1 = self.make_test_knit()
424
        # Insert the same data as BasicKnitTests.test_knit_join, as they seem
425
        # to cover a range of cases (no parents, one parent, multiple parents).
426
        test_data = [
427
            ('text-a', [], test_knit.TEXT_1),
428
            ('text-b', ['text-a'], test_knit.TEXT_1),
429
            ('text-c', [], test_knit.TEXT_1),
430
            ('text-d', ['text-c'], test_knit.TEXT_1),
431
            ('text-m', ['text-b', 'text-d'], test_knit.TEXT_1),
432
           ]
433
        expected_data_list = [
434
            # version, options, parents
435
            ('text-a', ['fulltext'], []),
436
            ('text-b', ['line-delta'], ['text-a']),
437
            ('text-c', ['fulltext'], []),
438
            ('text-d', ['line-delta'], ['text-c']),
439
            ('text-m', ['line-delta'], ['text-b', 'text-d']),
440
            ]
441
        for version_id, parents, lines in test_data:
442
            k1.add_lines(version_id, parents, test_knit.split_lines(lines))
443
444
        bytes = knitrepo._get_stream_as_bytes(
445
            k1, ['text-a', 'text-b', 'text-c', 'text-d', 'text-m'])
446
447
        data = bencode.bdecode(bytes)
448
        format = data.pop(0)
449
        self.assertEqual('knit-plain', format)
450
451
        for expected, actual in zip(expected_data_list, data):
452
            expected_version = expected[0]
453
            expected_options = expected[1]
454
            expected_parents = expected[2]
455
            version, options, parents, bytes = actual
456
            self.assertEqual(expected_version, version)
457
            self.assertEqual(expected_options, options)
458
            self.assertEqual(expected_parents, parents)
459
            self.assertRecordContentEqual(k1, version, bytes)
460
461
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
462
class DummyRepository(object):
463
    """A dummy repository for testing."""
464
465
    _serializer = None
466
467
    def supports_rich_root(self):
468
        return False
469
470
471
class InterDummy(repository.InterRepository):
472
    """An inter-repository optimised code path for DummyRepository.
473
474
    This is for use during testing where we use DummyRepository as repositories
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
475
    so that none of the default regsitered inter-repository classes will
2818.4.2 by Robert Collins
Review feedback.
476
    MATCH.
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
477
    """
478
479
    @staticmethod
480
    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.
481
        """InterDummy is compatible with DummyRepository."""
482
        return (isinstance(repo_source, DummyRepository) and 
483
            isinstance(repo_target, DummyRepository))
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
484
485
1534.1.27 by Robert Collins
Start InterRepository with InterRepository.get.
486
class TestInterRepository(TestCaseWithTransport):
487
488
    def test_get_default_inter_repository(self):
489
        # test that the InterRepository.get(repo_a, repo_b) probes
490
        # for a inter_repo class where is_compatible(repo_a, repo_b) returns
491
        # true and returns a default inter_repo otherwise.
492
        # This also tests that the default registered optimised interrepository
493
        # classes do not barf inappropriately when a surprising repository type
494
        # 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.
495
        dummy_a = DummyRepository()
496
        dummy_b = DummyRepository()
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
497
        self.assertGetsDefaultInterRepository(dummy_a, dummy_b)
498
499
    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.
500
        """Asserts that InterRepository.get(repo_a, repo_b) -> the default.
501
        
502
        The effective default is now InterSameDataRepository because there is
503
        no actual sane default in the presence of incompatible data models.
504
        """
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
505
        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.
506
        self.assertEqual(repository.InterSameDataRepository,
1534.1.27 by Robert Collins
Start InterRepository with InterRepository.get.
507
                         inter_repo.__class__)
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
508
        self.assertEqual(repo_a, inter_repo.source)
509
        self.assertEqual(repo_b, inter_repo.target)
510
511
    def test_register_inter_repository_class(self):
512
        # test that a optimised code path provider - a
513
        # InterRepository subclass can be registered and unregistered
514
        # and that it is correctly selected when given a repository
515
        # pair that it returns true on for the is_compatible static method
516
        # check
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
517
        dummy_a = DummyRepository()
518
        dummy_b = DummyRepository()
519
        repo = self.make_repository('.')
520
        # hack dummies to look like repo somewhat.
521
        dummy_a._serializer = repo._serializer
522
        dummy_b._serializer = repo._serializer
523
        repository.InterRepository.register_optimiser(InterDummy)
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
524
        try:
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
525
            # we should get the default for something InterDummy returns False
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
526
            # to
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
527
            self.assertFalse(InterDummy.is_compatible(dummy_a, repo))
528
            self.assertGetsDefaultInterRepository(dummy_a, repo)
529
            # and we should get an InterDummy for a pair it 'likes'
530
            self.assertTrue(InterDummy.is_compatible(dummy_a, dummy_b))
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
531
            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.
532
            self.assertEqual(InterDummy, inter_repo.__class__)
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
533
            self.assertEqual(dummy_a, inter_repo.source)
534
            self.assertEqual(dummy_b, inter_repo.target)
535
        finally:
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
536
            repository.InterRepository.unregister_optimiser(InterDummy)
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
537
        # now we should get the default InterRepository object again.
538
        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.
539
2241.1.17 by Martin Pool
Restore old InterWeave tests
540
541
class TestInterWeaveRepo(TestCaseWithTransport):
542
543
    def test_is_compatible_and_registered(self):
544
        # InterWeaveRepo is compatible when either side
545
        # is a format 5/6/7 branch
2241.1.20 by mbp at sourcefrog
update tests for new locations of weave repos
546
        from bzrlib.repofmt import knitrepo, weaverepo
547
        formats = [weaverepo.RepositoryFormat5(),
548
                   weaverepo.RepositoryFormat6(),
549
                   weaverepo.RepositoryFormat7()]
550
        incompatible_formats = [weaverepo.RepositoryFormat4(),
551
                                knitrepo.RepositoryFormatKnit1(),
2241.1.17 by Martin Pool
Restore old InterWeave tests
552
                                ]
553
        repo_a = self.make_repository('a')
554
        repo_b = self.make_repository('b')
555
        is_compatible = repository.InterWeaveRepo.is_compatible
556
        for source in incompatible_formats:
557
            # force incompatible left then right
558
            repo_a._format = source
559
            repo_b._format = formats[0]
560
            self.assertFalse(is_compatible(repo_a, repo_b))
561
            self.assertFalse(is_compatible(repo_b, repo_a))
562
        for source in formats:
563
            repo_a._format = source
564
            for target in formats:
565
                repo_b._format = target
566
                self.assertTrue(is_compatible(repo_a, repo_b))
567
        self.assertEqual(repository.InterWeaveRepo,
568
                         repository.InterRepository.get(repo_a,
569
                                                        repo_b).__class__)
570
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.
571
2535.3.41 by Andrew Bennetts
Add tests for InterRemoteToOther.is_compatible.
572
class TestInterRemoteToOther(TestCaseWithTransport):
573
574
    def make_remote_repository(self, path, backing_format=None):
575
        """Make a RemoteRepository object backed by a real repository that will
576
        be created at the given path."""
577
        self.make_repository(path, format=backing_format)
578
        smart_server = server.SmartTCPServer_for_testing()
579
        smart_server.setUp()
580
        remote_transport = get_transport(smart_server.get_url()).clone(path)
581
        self.addCleanup(smart_server.tearDown)
582
        remote_bzrdir = bzrdir.BzrDir.open_from_transport(remote_transport)
583
        remote_repo = remote_bzrdir.open_repository()
584
        return remote_repo
585
586
    def test_is_compatible_same_format(self):
587
        """InterRemoteToOther is compatible with a remote repository and a
588
        second repository that have the same format."""
589
        local_repo = self.make_repository('local')
590
        remote_repo = self.make_remote_repository('remote')
2535.3.62 by Andrew Bennetts
Cosmetic changes.
591
        is_compatible = repository.InterRemoteToOther.is_compatible
2535.3.41 by Andrew Bennetts
Add tests for InterRemoteToOther.is_compatible.
592
        self.assertTrue(
2535.3.62 by Andrew Bennetts
Cosmetic changes.
593
            is_compatible(remote_repo, local_repo),
2535.3.41 by Andrew Bennetts
Add tests for InterRemoteToOther.is_compatible.
594
            "InterRemoteToOther(%r, %r) is false" % (remote_repo, local_repo))
595
          
596
    def test_is_incompatible_different_format(self):
597
        local_repo = self.make_repository('local', 'dirstate')
598
        remote_repo = self.make_remote_repository('a', 'dirstate-with-subtree')
2535.3.62 by Andrew Bennetts
Cosmetic changes.
599
        is_compatible = repository.InterRemoteToOther.is_compatible
2535.3.65 by Andrew Bennetts
Correct test failure caused by typo.
600
        self.assertFalse(
2535.3.62 by Andrew Bennetts
Cosmetic changes.
601
            is_compatible(remote_repo, local_repo),
2535.3.65 by Andrew Bennetts
Correct test failure caused by typo.
602
            "InterRemoteToOther(%r, %r) is true" % (local_repo, remote_repo))
2535.3.41 by Andrew Bennetts
Add tests for InterRemoteToOther.is_compatible.
603
604
    def test_is_incompatible_different_format_both_remote(self):
2535.3.66 by Andrew Bennetts
Tidy a couple more long lines.
605
        remote_repo_a = self.make_remote_repository(
606
            'a', 'dirstate-with-subtree')
2535.3.41 by Andrew Bennetts
Add tests for InterRemoteToOther.is_compatible.
607
        remote_repo_b = self.make_remote_repository('b', 'dirstate')
2535.3.62 by Andrew Bennetts
Cosmetic changes.
608
        is_compatible = repository.InterRemoteToOther.is_compatible
2535.3.41 by Andrew Bennetts
Add tests for InterRemoteToOther.is_compatible.
609
        self.assertFalse(
2535.3.62 by Andrew Bennetts
Cosmetic changes.
610
            is_compatible(remote_repo_a, remote_repo_b),
2535.3.66 by Andrew Bennetts
Tidy a couple more long lines.
611
            "InterRemoteToOther(%r, %r) is true"
612
            % (remote_repo_a, remote_repo_b))
2535.3.41 by Andrew Bennetts
Add tests for InterRemoteToOther.is_compatible.
613
614
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.
615
class TestRepositoryConverter(TestCaseWithTransport):
616
617
    def test_convert_empty(self):
618
        t = get_transport(self.get_url('.'))
619
        t.mkdir('repository')
620
        repo_dir = bzrdir.BzrDirMetaFormat1().initialize('repository')
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
621
        repo = weaverepo.RepositoryFormat7().initialize(repo_dir)
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
622
        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.
623
        converter = repository.CopyConverter(target_format)
1594.1.3 by Robert Collins
Fixup pb usage to use nested_progress_bar.
624
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
625
        try:
626
            converter.convert(repo, pb)
627
        finally:
628
            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.
629
        repo = repo_dir.open_repository()
630
        self.assertTrue(isinstance(target_format, repo._format.__class__))
1843.2.5 by Aaron Bentley
Add test of _unescape_xml
631
632
633
class TestMisc(TestCase):
634
    
635
    def test_unescape_xml(self):
636
        """We get some kind of error when malformed entities are passed"""
637
        self.assertRaises(KeyError, repository._unescape_xml, 'foo&bar;') 
1910.2.13 by Aaron Bentley
Start work on converter
638
639
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
640
class TestRepositoryFormatKnit3(TestCaseWithTransport):
1910.2.13 by Aaron Bentley
Start work on converter
641
642
    def test_convert(self):
643
        """Ensure the upgrade adds weaves for roots"""
1910.2.35 by Aaron Bentley
Better fix for convesion test
644
        format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
645
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1910.2.35 by Aaron Bentley
Better fix for convesion test
646
        tree = self.make_branch_and_tree('.', format)
1910.2.13 by Aaron Bentley
Start work on converter
647
        tree.commit("Dull commit", rev_id="dull")
648
        revision_tree = tree.branch.repository.revision_tree('dull')
649
        self.assertRaises(errors.NoSuchFile, revision_tree.get_file_lines,
650
            revision_tree.inventory.root.file_id)
651
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
652
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.13 by Aaron Bentley
Start work on converter
653
        upgrade.Convert('.', format)
1910.2.27 by Aaron Bentley
Fixed conversion test
654
        tree = workingtree.WorkingTree.open('.')
1910.2.13 by Aaron Bentley
Start work on converter
655
        revision_tree = tree.branch.repository.revision_tree('dull')
656
        revision_tree.get_file_lines(revision_tree.inventory.root.file_id)
1910.2.27 by Aaron Bentley
Fixed conversion test
657
        tree.commit("Another dull commit", rev_id='dull2')
658
        revision_tree = tree.branch.repository.revision_tree('dull2')
659
        self.assertEqual('dull', revision_tree.inventory.root.revision)
2220.2.2 by Martin Pool
Add tag command and basic implementation
660
2818.4.2 by Robert Collins
Review feedback.
661
    def test_exposed_versioned_files_are_marked_dirty(self):
662
        format = bzrdir.BzrDirMetaFormat1()
663
        format.repository_format = knitrepo.RepositoryFormatKnit3()
664
        repo = self.make_repository('.', format=format)
665
        repo.lock_write()
666
        inv = repo.get_inventory_weave()
667
        repo.unlock()
668
        self.assertRaises(errors.OutSideTransaction,
669
            inv.add_lines, 'foo', [], [])
2535.3.70 by Andrew Bennetts
Merge from bzr.dev.
670
2535.3.57 by Andrew Bennetts
Perform some sanity checking of data streams rather than blindly inserting them into our repository.
671
672
class TestWithBrokenRepo(TestCaseWithTransport):
673
674
    def make_broken_repository(self):
675
        # XXX: This function is borrowed from Aaron's "Reconcile can fix bad
676
        # parent references" branch which is due to land in bzr.dev soon.  Once
677
        # it does, this duplication should be removed.
678
        repo = self.make_repository('broken-repo')
679
        cleanups = []
680
        try:
681
            repo.lock_write()
682
            cleanups.append(repo.unlock)
683
            repo.start_write_group()
684
            cleanups.append(repo.commit_write_group)
685
            # make rev1a: A well-formed revision, containing 'file1'
686
            inv = inventory.Inventory(revision_id='rev1a')
687
            inv.root.revision = 'rev1a'
688
            self.add_file(repo, inv, 'file1', 'rev1a', [])
689
            repo.add_inventory('rev1a', inv, [])
690
            revision = _mod_revision.Revision('rev1a',
691
                committer='jrandom@example.com', timestamp=0,
692
                inventory_sha1='', timezone=0, message='foo', parent_ids=[])
693
            repo.add_revision('rev1a',revision, inv)
694
695
            # make rev1b, which has no Revision, but has an Inventory, and
696
            # file1
697
            inv = inventory.Inventory(revision_id='rev1b')
698
            inv.root.revision = 'rev1b'
699
            self.add_file(repo, inv, 'file1', 'rev1b', [])
700
            repo.add_inventory('rev1b', inv, [])
701
702
            # make rev2, with file1 and file2
703
            # file2 is sane
704
            # file1 has 'rev1b' as an ancestor, even though this is not
705
            # mentioned by 'rev1a', making it an unreferenced ancestor
706
            inv = inventory.Inventory()
707
            self.add_file(repo, inv, 'file1', 'rev2', ['rev1a', 'rev1b'])
708
            self.add_file(repo, inv, 'file2', 'rev2', [])
709
            self.add_revision(repo, 'rev2', inv, ['rev1a'])
710
711
            # make ghost revision rev1c
712
            inv = inventory.Inventory()
713
            self.add_file(repo, inv, 'file2', 'rev1c', [])
714
715
            # make rev3 with file2
716
            # file2 refers to 'rev1c', which is a ghost in this repository, so
717
            # file2 cannot have rev1c as its ancestor.
718
            inv = inventory.Inventory()
719
            self.add_file(repo, inv, 'file2', 'rev3', ['rev1c'])
720
            self.add_revision(repo, 'rev3', inv, ['rev1c'])
721
            return repo
722
        finally:
723
            for cleanup in reversed(cleanups):
724
                cleanup()
725
726
    def add_revision(self, repo, revision_id, inv, parent_ids):
727
        inv.revision_id = revision_id
728
        inv.root.revision = revision_id
729
        repo.add_inventory(revision_id, inv, parent_ids)
730
        revision = _mod_revision.Revision(revision_id,
731
            committer='jrandom@example.com', timestamp=0, inventory_sha1='',
732
            timezone=0, message='foo', parent_ids=parent_ids)
733
        repo.add_revision(revision_id,revision, inv)
734
735
    def add_file(self, repo, inv, filename, revision, parents):
736
        file_id = filename + '-id'
737
        entry = inventory.InventoryFile(file_id, filename, 'TREE_ROOT')
738
        entry.revision = revision
2535.3.70 by Andrew Bennetts
Merge from bzr.dev.
739
        entry.text_size = 0
2535.3.57 by Andrew Bennetts
Perform some sanity checking of data streams rather than blindly inserting them into our repository.
740
        inv.add(entry)
741
        vf = repo.weave_store.get_weave_or_empty(file_id,
742
                                                 repo.get_transaction())
743
        vf.add_lines(revision, parents, ['line\n'])
744
745
    def test_insert_from_broken_repo(self):
746
        """Inserting a data stream from a broken repository won't silently
747
        corrupt the target repository.
748
        """
749
        broken_repo = self.make_broken_repository()
750
        empty_repo = self.make_repository('empty-repo')
751
        stream = broken_repo.get_data_stream(['rev1a', 'rev2', 'rev3'])
752
        self.assertRaises(
753
            errors.KnitCorrupt, empty_repo.insert_data_stream, stream)
754