/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2241.1.5 by Martin Pool
Move KnitFormat2 into repofmt
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
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 bzrdir implementations - tests a bzrdir format."""
18
2520.4.54 by Aaron Bentley
Hang a create_bundle method off repository
19
from cStringIO import StringIO
1666.1.6 by Robert Collins
Make knit the default format.
20
import re
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
21
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
22
import bzrlib
1752.2.87 by Andrew Bennetts
Make tests pass.
23
from bzrlib import (
24
    bzrdir,
25
    errors,
3184.1.9 by Robert Collins
* ``Repository.get_data_stream`` is now deprecated in favour of
26
    graph,
3305.1.1 by Jelmer Vernooij
Make sure that specifying the inv= argument to add_revision() sets the
27
    osutils,
1752.2.87 by Andrew Bennetts
Make tests pass.
28
    remote,
29
    repository,
30
    )
1852.10.3 by Robert Collins
Remove all uses of compare_trees and replace with Tree.changes_from throughout bzrlib.
31
from bzrlib.delta import TreeDelta
1731.1.33 by Aaron Bentley
Revert no-special-root changes
32
from bzrlib.inventory import Inventory, InventoryDirectory
3047.1.2 by Andrew Bennetts
Directly test that sprouting branches from a HPSS preserves the repository format.
33
from bzrlib.repofmt.weaverepo import (
34
    RepositoryFormat5,
35
    RepositoryFormat6,
36
    RepositoryFormat7,
37
    )
2996.2.3 by Aaron Bentley
Add tests for install_revisions and add_signature
38
from bzrlib.revision import NULL_REVISION, Revision
3047.1.1 by Andrew Bennetts
Fix for bug 164626, add test that Repository.sprout preserves format.
39
from bzrlib.smart import server
3287.6.1 by Robert Collins
* ``VersionedFile.get_graph`` is deprecated, with no replacement method.
40
from bzrlib.symbol_versioning import one_two, one_three, one_four
3023.2.1 by Martin Pool
test_get_data_stream should indicate NotApplicable rather than silently passing
41
from bzrlib.tests import (
3047.1.1 by Andrew Bennetts
Fix for bug 164626, add test that Repository.sprout preserves format.
42
    KnownFailure,
3023.2.1 by Martin Pool
test_get_data_stream should indicate NotApplicable rather than silently passing
43
    TestCaseWithTransport,
44
    TestNotApplicable,
45
    TestSkipped,
46
    )
2485.7.1 by Robert Collins
Relocate TestCaseWithRepository to be more central.
47
from bzrlib.tests.repository_implementations import TestCaseWithRepository
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
48
from bzrlib.transport import get_transport
49
from bzrlib.upgrade import upgrade
50
from bzrlib.workingtree import WorkingTree
51
52
2018.5.66 by Wouter van Heyst
Fix repository test parameterization for RemoteRepository.
53
class TestRepositoryMakeBranchAndTree(TestCaseWithRepository):
54
55
    def test_repository_format(self):
2018.5.119 by Robert Collins
Unbreak TestRepositoryMakeBranchAndTree.
56
        # make sure the repository on tree.branch is of the desired format,
57
        # because developers use this api to setup the tree, branch and 
58
        # repository for their tests: having it now give the right repository
59
        # type would invalidate the tests.
2018.5.66 by Wouter van Heyst
Fix repository test parameterization for RemoteRepository.
60
        tree = self.make_branch_and_tree('repo')
61
        self.assertIsInstance(tree.branch.repository._format,
62
            self.repository_format.__class__)
2381.1.1 by Robert Collins
Split out hpss test fixes which dont depend on new or altered API's.
63
64
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
65
class TestRepository(TestCaseWithRepository):
66
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
67
    def test_clone_to_default_format(self):
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
68
        #TODO: Test that cloning a repository preserves all the information
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
69
        # such as signatures[not tested yet] etc etc.
70
        # when changing to the current default format.
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
71
        tree_a = self.make_branch_and_tree('a')
2381.1.3 by Robert Collins
Review feedback.
72
        self.build_tree(['a/foo'])
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
73
        tree_a.add('foo', 'file1')
74
        tree_a.commit('rev1', rev_id='rev1')
75
        bzrdirb = self.make_bzrdir('b')
76
        repo_b = tree_a.branch.repository.clone(bzrdirb)
77
        tree_b = repo_b.revision_tree('rev1')
2592.3.214 by Robert Collins
Merge bzr.dev.
78
        tree_b.lock_read()
79
        self.addCleanup(tree_b.unlock)
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
80
        tree_b.get_file_text('file1')
81
        rev1 = repo_b.get_revision('rev1')
82
3169.2.1 by Robert Collins
New method ``iter_inventories`` on Repository for access to many
83
    def test_iter_inventories_is_ordered(self):
84
        # just a smoke test
85
        tree = self.make_branch_and_tree('a')
86
        first_revision = tree.commit('')
87
        second_revision = tree.commit('')
88
        tree.lock_read()
89
        self.addCleanup(tree.unlock)
90
        revs = (first_revision, second_revision)
91
        invs = tree.branch.repository.iter_inventories(revs)
92
        for rev_id, inv in zip(revs, invs):
93
            self.assertEqual(rev_id, inv.revision_id)
94
            self.assertIsInstance(inv, Inventory)
95
1910.2.63 by Aaron Bentley
Add supports_rich_root member to repository
96
    def test_supports_rich_root(self):
97
        tree = self.make_branch_and_tree('a')
98
        tree.commit('')
99
        second_revision = tree.commit('')
100
        inv = tree.branch.repository.revision_tree(second_revision).inventory
101
        rich_root = (inv.root.revision != second_revision)
2018.5.113 by Robert Collins
Test only fixes from the ported-to-bzr.dev test-correctness branch.
102
        self.assertEqual(rich_root,
1910.2.63 by Aaron Bentley
Add supports_rich_root member to repository
103
                         tree.branch.repository.supports_rich_root())
104
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
105
    def test_clone_specific_format(self):
106
        """todo"""
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
107
108
    def test_format_initialize_find_open(self):
109
        # loopback test to check the current format initializes to itself.
110
        if not self.repository_format.is_supported():
111
            # unsupported formats are not loopback testable
112
            # because the default open will not open them and
113
            # they may not be initializable.
114
            return
115
        # supported formats must be able to init and open
116
        t = get_transport(self.get_url())
117
        readonly_t = get_transport(self.get_readonly_url())
118
        made_control = self.bzrdir_format.initialize(t.base)
119
        made_repo = self.repository_format.initialize(made_control)
120
        self.assertEqual(made_control, made_repo.bzrdir)
121
122
        # find it via bzrdir opening:
123
        opened_control = bzrdir.BzrDir.open(readonly_t.base)
124
        direct_opened_repo = opened_control.open_repository()
125
        self.assertEqual(direct_opened_repo.__class__, made_repo.__class__)
126
        self.assertEqual(opened_control, direct_opened_repo.bzrdir)
127
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
128
        self.assertIsInstance(direct_opened_repo._format,
129
                              self.repository_format.__class__)
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
130
        # find it via Repository.open
131
        opened_repo = repository.Repository.open(readonly_t.base)
132
        self.failUnless(isinstance(opened_repo, made_repo.__class__))
133
        self.assertEqual(made_repo._format.__class__,
134
                         opened_repo._format.__class__)
135
        # if it has a unique id string, can we probe for it ?
136
        try:
137
            self.repository_format.get_format_string()
138
        except NotImplementedError:
139
            return
140
        self.assertEqual(self.repository_format,
141
                         repository.RepositoryFormat.find_format(opened_control))
142
143
    def test_create_repository(self):
1534.6.1 by Robert Collins
allow API creation of shared repositories
144
        # bzrdir can construct a repository for itself.
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
145
        if not self.bzrdir_format.is_supported():
146
            # unsupported formats are not loopback testable
147
            # because the default open will not open them and
148
            # they may not be initializable.
149
            return
150
        t = get_transport(self.get_url())
151
        made_control = self.bzrdir_format.initialize(t.base)
152
        made_repo = made_control.create_repository()
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
153
        # Check that we have a repository object.
154
        made_repo.has_revision('foo')
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
155
        self.assertEqual(made_control, made_repo.bzrdir)
1534.6.1 by Robert Collins
allow API creation of shared repositories
156
        
157
    def test_create_repository_shared(self):
158
        # bzrdir can construct a shared repository.
159
        if not self.bzrdir_format.is_supported():
160
            # unsupported formats are not loopback testable
161
            # because the default open will not open them and
162
            # they may not be initializable.
163
            return
164
        t = get_transport(self.get_url())
165
        made_control = self.bzrdir_format.initialize(t.base)
166
        try:
167
            made_repo = made_control.create_repository(shared=True)
168
        except errors.IncompatibleFormat:
169
            # not all repository formats understand being shared, or
170
            # may only be shared in some circumstances.
171
            return
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
172
        # Check that we have a repository object.
173
        made_repo.has_revision('foo')
1534.6.1 by Robert Collins
allow API creation of shared repositories
174
        self.assertEqual(made_control, made_repo.bzrdir)
1534.6.3 by Robert Collins
find_repository sufficiently robust.
175
        self.assertTrue(made_repo.is_shared())
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
176
177
    def test_revision_tree(self):
178
        wt = self.make_branch_and_tree('.')
1731.1.33 by Aaron Bentley
Revert no-special-root changes
179
        wt.set_root_id('fixed-root')
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
180
        wt.commit('lala!', rev_id='revision-1', allow_pointless=True)
181
        tree = wt.branch.repository.revision_tree('revision-1')
1731.1.45 by Aaron Bentley
Merge bzr.dev
182
        self.assertEqual('revision-1', tree.inventory.root.revision) 
183
        expected = InventoryDirectory('fixed-root', '', None)
184
        expected.revision = 'revision-1'
185
        self.assertEqual([('', 'V', 'directory', 'fixed-root', expected)],
1731.1.54 by Aaron Bentley
Fix revision_tree tests
186
                         list(tree.list_files(include_root=True)))
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
187
        tree = wt.branch.repository.revision_tree(None)
1731.1.54 by Aaron Bentley
Fix revision_tree tests
188
        self.assertEqual([], list(tree.list_files(include_root=True)))
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
189
        tree = wt.branch.repository.revision_tree(NULL_REVISION)
1731.1.54 by Aaron Bentley
Fix revision_tree tests
190
        self.assertEqual([], list(tree.list_files(include_root=True)))
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
191
1770.3.3 by Jelmer Vernooij
Add tests for Branch.get_revision_delta() and Repository.get_revision_delta().
192
    def test_get_revision_delta(self):
193
        tree_a = self.make_branch_and_tree('a')
2381.1.3 by Robert Collins
Review feedback.
194
        self.build_tree(['a/foo'])
1770.3.3 by Jelmer Vernooij
Add tests for Branch.get_revision_delta() and Repository.get_revision_delta().
195
        tree_a.add('foo', 'file1')
196
        tree_a.commit('rev1', rev_id='rev1')
2381.1.3 by Robert Collins
Review feedback.
197
        self.build_tree(['a/vla'])
1770.3.3 by Jelmer Vernooij
Add tests for Branch.get_revision_delta() and Repository.get_revision_delta().
198
        tree_a.add('vla', 'file2')
199
        tree_a.commit('rev2', rev_id='rev2')
200
201
        delta = tree_a.branch.repository.get_revision_delta('rev1')
202
        self.assertIsInstance(delta, TreeDelta)
203
        self.assertEqual([('foo', 'file1', 'file')], delta.added)
204
        delta = tree_a.branch.repository.get_revision_delta('rev2')
205
        self.assertIsInstance(delta, TreeDelta)
206
        self.assertEqual([('vla', 'file2', 'file')], delta.added)
207
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
208
    def test_clone_bzrdir_repository_revision(self):
209
        # make a repository with some revisions,
210
        # and clone it, this should not have unreferenced revisions.
211
        # also: test cloning with a revision id of NULL_REVISION -> empty repo.
212
        raise TestSkipped('revision limiting is not implemented yet.')
213
214
    def test_clone_repository_basis_revision(self):
215
        raise TestSkipped('the use of a basis should not add noise data to the result.')
216
1534.6.5 by Robert Collins
Cloning of repos preserves shared and make-working-tree attributes.
217
    def test_clone_shared_no_tree(self):
218
        # cloning a shared repository keeps it shared
219
        # and preserves the make_working_tree setting.
220
        made_control = self.make_bzrdir('source')
221
        try:
222
            made_repo = made_control.create_repository(shared=True)
223
        except errors.IncompatibleFormat:
224
            # not all repository formats understand being shared, or
225
            # may only be shared in some circumstances.
226
            return
2018.14.2 by Andrew Bennetts
All but one repository_implementation tests for RemoteRepository passing.
227
        try:
228
            made_repo.set_make_working_trees(False)
229
        except NotImplementedError:
2018.5.120 by Robert Collins
The Repository API ``make_working_trees`` is now permitted to return
230
            # the repository does not support having its tree-making flag
231
            # toggled.
232
            return
1534.6.5 by Robert Collins
Cloning of repos preserves shared and make-working-tree attributes.
233
        result = made_control.clone(self.get_url('target'))
1752.2.55 by Andrew Bennetts
Replace another isinstance(made_repo, Repository) check.
234
        # Check that we have a repository object.
235
        made_repo.has_revision('foo')
236
1534.6.5 by Robert Collins
Cloning of repos preserves shared and make-working-tree attributes.
237
        self.assertEqual(made_control, made_repo.bzrdir)
238
        self.assertTrue(result.open_repository().is_shared())
239
        self.assertFalse(result.open_repository().make_working_trees())
240
2018.5.90 by Andrew Bennetts
Fix test_upgrade_preserves_signatures; it incorrectly assumed that upgrade(wt, ...) would necessarily affect the repository.
241
    def test_upgrade_preserves_signatures(self):
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.
242
        wt = self.make_branch_and_tree('source')
243
        wt.commit('A', allow_pointless=True, rev_id='A')
2018.5.90 by Andrew Bennetts
Fix test_upgrade_preserves_signatures; it incorrectly assumed that upgrade(wt, ...) would necessarily affect the repository.
244
        repo = wt.branch.repository
2592.3.39 by Robert Collins
Fugly version to remove signatures.kndx
245
        repo.lock_write()
246
        repo.start_write_group()
2018.5.90 by Andrew Bennetts
Fix test_upgrade_preserves_signatures; it incorrectly assumed that upgrade(wt, ...) would necessarily affect the repository.
247
        repo.sign_revision('A', bzrlib.gpg.LoopbackGPGStrategy(None))
2592.3.39 by Robert Collins
Fugly version to remove signatures.kndx
248
        repo.commit_write_group()
249
        repo.unlock()
2018.5.90 by Andrew Bennetts
Fix test_upgrade_preserves_signatures; it incorrectly assumed that upgrade(wt, ...) would necessarily affect the repository.
250
        old_signature = repo.get_signature_text('A')
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.
251
        try:
252
            old_format = bzrdir.BzrDirFormat.get_default_format()
253
            # This gives metadir branches something they can convert to.
254
            # it would be nice to have a 'latest' vs 'default' concept.
2255.2.208 by Robert Collins
Remove more references to 'experimental' formats.
255
            format = bzrdir.format_registry.make_bzrdir('dirstate-with-subtree')
2018.5.90 by Andrew Bennetts
Fix test_upgrade_preserves_signatures; it incorrectly assumed that upgrade(wt, ...) would necessarily affect the repository.
256
            upgrade(repo.bzrdir.root_transport.base, format=format)
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.
257
        except errors.UpToDateFormat:
258
            # this is in the most current format already.
259
            return
1910.2.12 by Aaron Bentley
Implement knit repo format 2
260
        except errors.BadConversionTarget, e:
261
            raise TestSkipped(str(e))
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.
262
        wt = WorkingTree.open(wt.basedir)
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
263
        new_signature = wt.branch.repository.get_signature_text('A')
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.
264
        self.assertEqual(old_signature, new_signature)
265
1624.3.19 by Olaf Conradi
New call get_format_description to give a user-friendly description of a
266
    def test_format_description(self):
267
        repo = self.make_repository('.')
268
        text = repo._format.get_format_description()
269
        self.failUnless(len(text))
270
3221.3.1 by Robert Collins
* Repository formats have a new supported-feature attribute
271
    def test_format_supports_external_lookups(self):
272
        repo = self.make_repository('.')
273
        self.assertSubset(
274
            [repo._format.supports_external_lookups], (True, False))
275
1666.1.6 by Robert Collins
Make knit the default format.
276
    def assertMessageRoundtrips(self, message):
277
        """Assert that message roundtrips to a repository and back intact."""
278
        tree = self.make_branch_and_tree('.')
279
        tree.commit(message, rev_id='a', allow_pointless=True)
280
        rev = tree.branch.repository.get_revision('a')
281
        # we have to manually escape this as we dont try to
282
        # roundtrip xml invalid characters at this point.
283
        # when escaping is moved to the serialiser, this test
284
        # can check against the literal message rather than
285
        # this escaped version.
286
        escaped_message, escape_count = re.subn(
287
            u'[^\x09\x0A\x0D\u0020-\uD7FF\uE000-\uFFFD]+',
288
            lambda match: match.group(0).encode('unicode_escape'),
289
            message)
290
        escaped_message= re.sub('\r', '\n', escaped_message)
291
        self.assertEqual(rev.message, escaped_message)
292
        # insist the class is unicode no matter what came in for 
293
        # consistency.
294
        self.assertIsInstance(rev.message, unicode)
295
296
    def test_commit_unicode_message(self):
297
        # a siple unicode message should be preserved
298
        self.assertMessageRoundtrips(u'foo bar gamm\xae plop')
299
300
    def test_commit_unicode_control_characters(self):
301
        # a unicode message with control characters should roundtrip too.
302
        self.assertMessageRoundtrips(
303
            "All 8-bit chars: " +  ''.join([unichr(x) for x in range(256)]))
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
304
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
305
    def test_check_repository(self):
306
        """Check a fairly simple repository's history"""
307
        tree = self.make_branch_and_tree('.')
308
        tree.commit('initial empty commit', rev_id='a-rev',
309
                    allow_pointless=True)
2745.6.39 by Andrew Bennetts
Use scenario in test_check too, and make check actually report inconsistent parents to the end user.
310
        result = tree.branch.repository.check()
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
311
        # writes to log; should accept both verbose or non-verbose
312
        result.report_results(verbose=True)
313
        result.report_results(verbose=False)
314
1756.1.5 by Aaron Bentley
Test get_revisions with all repository types (and fix bug...)
315
    def test_get_revisions(self):
316
        tree = self.make_branch_and_tree('.')
317
        tree.commit('initial empty commit', rev_id='a-rev',
318
                    allow_pointless=True)
319
        tree.commit('second empty commit', rev_id='b-rev',
320
                    allow_pointless=True)
321
        tree.commit('third empty commit', rev_id='c-rev',
322
                    allow_pointless=True)
323
        repo = tree.branch.repository
324
        revision_ids = ['a-rev', 'b-rev', 'c-rev']
325
        revisions = repo.get_revisions(revision_ids)
326
        assert len(revisions) == 3, repr(revisions)
327
        zipped = zip(revisions, revision_ids)
328
        self.assertEqual(len(zipped), 3)
329
        for revision, revision_id in zipped:
330
            self.assertEqual(revision.revision_id, revision_id)
331
            self.assertEqual(revision, repo.get_revision(revision_id))
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
332
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
333
    def test_root_entry_has_revision(self):
334
        tree = self.make_branch_and_tree('.')
335
        tree.commit('message', rev_id='rev_id')
2255.7.65 by Robert Collins
Split test_root_revision_entry into tree and repository portions.
336
        rev_tree = tree.branch.repository.revision_tree(tree.last_revision())
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
337
        self.assertEqual('rev_id', rev_tree.inventory.root.revision)
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
338
2255.7.64 by Robert Collins
Disabled test_repository.test_create_basis_inventory, a test that tests tree behaviour in the wrong place - its future is being discussed.
339
    def DISABLED_DELETE_OR_FIX_BEFORE_MERGE_test_create_basis_inventory(self):
1910.2.31 by Aaron Bentley
Fix bugs in basis inventory handling, change filename
340
        # Needs testing here because differences between repo and working tree
341
        # basis inventory formats can lead to bugs.
342
        t = self.make_branch_and_tree('.')
343
        b = t.branch
344
        open('a', 'wb').write('a\n')
345
        t.add('a')
346
        t.commit('a', rev_id='r1')
347
348
        t._control_files.get_utf8('basis-inventory-cache')
349
350
        basis_inv = t.basis_tree().inventory
351
        self.assertEquals('r1', basis_inv.revision_id)
352
        
353
        store_inv = b.repository.get_inventory('r1')
354
        self.assertEquals(store_inv._byid, basis_inv._byid)
355
356
        open('b', 'wb').write('b\n')
357
        t.add('b')
358
        t.commit('b', rev_id='r2')
359
360
        t._control_files.get_utf8('basis-inventory-cache')
361
362
        basis_inv_txt = t.read_basis_inventory()
2100.3.15 by Aaron Bentley
get test suite passing
363
        basis_inv = bzrlib.xml7.serializer_v7.read_inventory_from_string(basis_inv_txt)
1910.2.31 by Aaron Bentley
Fix bugs in basis inventory handling, change filename
364
        self.assertEquals('r2', basis_inv.revision_id)
365
        store_inv = b.repository.get_inventory('r2')
366
367
        self.assertEquals(store_inv._byid, basis_inv._byid)
368
1910.2.36 by Aaron Bentley
Get upgrade from format4 under test and fixed for all formats
369
    def test_upgrade_from_format4(self):
370
        from bzrlib.tests.test_upgrade import _upgrade_dir_template
2241.1.4 by Martin Pool
Moved old weave-based repository formats into bzrlib.repofmt.weaverepo.
371
        if self.repository_format.get_format_description() \
372
            == "Repository format 4":
1910.2.36 by Aaron Bentley
Get upgrade from format4 under test and fixed for all formats
373
            raise TestSkipped('Cannot convert format-4 to itself')
1752.2.89 by Andrew Bennetts
Skip test_upgrade_from_format4 for RemoteRepositoryFormat.
374
        if isinstance(self.repository_format, remote.RemoteRepositoryFormat):
375
            return # local conversion to/from RemoteObjects is irrelevant.
1910.2.36 by Aaron Bentley
Get upgrade from format4 under test and fixed for all formats
376
        self.build_tree_contents(_upgrade_dir_template)
377
        old_repodir = bzrlib.bzrdir.BzrDir.open_unsupported('.')
378
        old_repo_format = old_repodir.open_repository()._format
379
        format = self.repository_format._matchingbzrdir
380
        try:
381
            format.repository_format = self.repository_format
382
        except AttributeError:
383
            pass
384
        upgrade('.', format)
385
1910.2.37 by Aaron Bentley
Handle empty commits, fix test
386
    def test_pointless_commit(self):
387
        tree = self.make_branch_and_tree('.')
388
        self.assertRaises(errors.PointlessCommit, tree.commit, 'pointless',
389
                          allow_pointless=False)
390
        tree.commit('pointless', allow_pointless=True)
391
2323.5.17 by Martin Pool
Add supports_tree_reference to all repo formats (robert)
392
    def test_format_attributes(self):
393
        """All repository formats should have some basic attributes."""
394
        # create a repository to get a real format instance, not the 
3128.1.3 by Vincent Ladeuil
Since we are there s/parameteris.*/parameteriz&/.
395
        # template from the test suite parameterization.
2323.5.17 by Martin Pool
Add supports_tree_reference to all repo formats (robert)
396
        repo = self.make_repository('.')
397
        repo._format.rich_root_data
398
        repo._format.supports_tree_reference
399
3184.1.9 by Robert Collins
* ``Repository.get_data_stream`` is now deprecated in favour of
400
    def test_get_data_stream_deprecated(self):
401
        # If get_data_stream is present it must be deprecated
402
        tree = self.make_branch_and_tree('t')
403
        self.build_tree(['t/foo'])
404
        tree.add('foo', 'file1')
405
        tree.commit('message', rev_id='rev_id')
406
        repo = tree.branch.repository
3381.1.1 by Aaron Bentley
Fix lock-taking iterators
407
        repo.lock_read()
408
        self.addCleanup(repo.unlock)
3184.1.9 by Robert Collins
* ``Repository.get_data_stream`` is now deprecated in favour of
409
        try:
410
            stream = self.applyDeprecated(one_two, repo.get_data_stream,
411
                ['rev_id'])
412
        except NotImplementedError:
413
            raise TestNotApplicable("%s doesn't support get_data_stream"
414
                % repo._format)
415
        except AttributeError:
416
            pass
417
418
    def test_get_data_stream_for_search(self):
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
419
        # Make a repo with a revision
420
        tree = self.make_branch_and_tree('t')
421
        self.build_tree(['t/foo'])
422
        tree.add('foo', 'file1')
423
        tree.commit('message', rev_id='rev_id')
424
        repo = tree.branch.repository
425
426
        # Get a data stream (a file-like object) for that revision
3184.1.9 by Robert Collins
* ``Repository.get_data_stream`` is now deprecated in favour of
427
        search = graph.SearchResult(set(['rev_id']), set([NULL_REVISION]), 1,
428
            set(['rev_id']))
3381.1.3 by Aaron Bentley
Stop locking in get_data_stream_for_search
429
        repo.lock_read()
430
        self.addCleanup(repo.unlock)
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
431
        try:
3184.1.9 by Robert Collins
* ``Repository.get_data_stream`` is now deprecated in favour of
432
            stream = repo.get_data_stream_for_search(search)
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
433
        except NotImplementedError:
3023.2.1 by Martin Pool
test_get_data_stream should indicate NotApplicable rather than silently passing
434
            raise TestNotApplicable("%s doesn't support get_data_stream"
435
                % repo._format)
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
436
2535.3.14 by Andrew Bennetts
Move serialising repo data stream to bytes into smart protocol.
437
        # The data stream is a iterator that yields (name, versioned_file)
438
        # pairs for:
2535.3.62 by Andrew Bennetts
Cosmetic changes.
439
        #   * the file knit (or knits; if this repo has rich roots there will
440
        #     be a file knit for that as well as for 'file1').
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
441
        #   * the inventory knit
442
        #   * the revisions knit
443
        # in that order.
2535.3.50 by Andrew Bennetts
Use tuple names in data streams rather than concatenated strings.
444
        expected_record_names = [
445
            ('file', 'file1'),
446
            ('inventory',),
447
            ('signatures',),
448
            ('revisions',)]
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
449
        streamed_names = []
2535.3.15 by Andrew Bennetts
Add KnitVersionedFile.get_stream_as_bytes, start smart implementation of RemoteRepository.get_data_stream.
450
        for name, bytes in stream:
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
451
            streamed_names.append(name)
452
453
        if repo.supports_rich_root():
2535.3.14 by Andrew Bennetts
Move serialising repo data stream to bytes into smart protocol.
454
            # Check for the root versioned file in the stream, then remove it
455
            # from streamed_names so we can compare that with
456
            # expected_record_names.
457
            # Note that the file knits can be in any order, so this test is
458
            # written to allow that.
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
459
            inv = repo.get_inventory('rev_id')
2535.3.50 by Andrew Bennetts
Use tuple names in data streams rather than concatenated strings.
460
            expected_record_name = ('file', inv.root.file_id)
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
461
            self.assertTrue(expected_record_name in streamed_names)
462
            streamed_names.remove(expected_record_name)
463
464
        self.assertEqual(expected_record_names, streamed_names)
465
2535.3.17 by Andrew Bennetts
[broken] Closer to a working Repository.fetch_revisions smart request.
466
    def test_insert_data_stream(self):
467
        tree = self.make_branch_and_tree('source')
468
        self.build_tree(['source/foo'])
469
        tree.add('foo', 'file1')
470
        tree.commit('message', rev_id='rev_id')
471
        source_repo = tree.branch.repository
472
        dest_repo = self.make_repository('dest')
3204.1.2 by Ian Clatworthy
Fix error handling in insert_data_stream (Lukas Lalinsky)
473
        search = dest_repo.search_missing_revision_ids(source_repo,
474
            revision_id='rev_id')
3381.1.3 by Aaron Bentley
Stop locking in get_data_stream_for_search
475
        source_repo.lock_read()
476
        self.addCleanup(source_repo.unlock)
2535.3.17 by Andrew Bennetts
[broken] Closer to a working Repository.fetch_revisions smart request.
477
        try:
3204.1.2 by Ian Clatworthy
Fix error handling in insert_data_stream (Lukas Lalinsky)
478
            stream = source_repo.get_data_stream_for_search(search)
2535.3.17 by Andrew Bennetts
[broken] Closer to a working Repository.fetch_revisions smart request.
479
        except NotImplementedError, e:
480
            # Not all repositories support streaming.
3184.1.9 by Robert Collins
* ``Repository.get_data_stream`` is now deprecated in favour of
481
            self.assertContainsRe(str(e), 'get_data_stream_for_search')
2535.3.17 by Andrew Bennetts
[broken] Closer to a working Repository.fetch_revisions smart request.
482
            raise TestSkipped('This format does not support streaming.')
483
2592.3.214 by Robert Collins
Merge bzr.dev.
484
        dest_repo.lock_write()
485
        try:
486
            dest_repo.start_write_group()
487
            try:
488
                dest_repo.insert_data_stream(stream)
489
            except:
490
                dest_repo.abort_write_group()
491
                raise
492
            else:
493
                dest_repo.commit_write_group()
494
        finally:
495
            dest_repo.unlock()
496
        # reopen to be sure it was added.
497
        dest_repo = dest_repo.bzrdir.open_repository()
2535.3.17 by Andrew Bennetts
[broken] Closer to a working Repository.fetch_revisions smart request.
498
        self.assertTrue(dest_repo.has_revision('rev_id'))
499
3184.5.1 by Lukáš Lalinský
Fix handling of some error cases in insert_data_stream
500
        # insert the same data stream again, should be no-op
3204.1.2 by Ian Clatworthy
Fix error handling in insert_data_stream (Lukas Lalinsky)
501
        stream = source_repo.get_data_stream_for_search(search)
3184.5.1 by Lukáš Lalinský
Fix handling of some error cases in insert_data_stream
502
        dest_repo.lock_write()
503
        try:
504
            dest_repo.start_write_group()
505
            try:
506
                dest_repo.insert_data_stream(stream)
507
            except:
508
                dest_repo.abort_write_group()
509
                raise
510
            else:
511
                dest_repo.commit_write_group()
512
        finally:
513
            dest_repo.unlock()
514
515
        # try to insert data stream with invalid key
516
        stream = [[('bogus-key',), '']]
517
        self.assertRaises(errors.RepositoryDataStreamError,
518
                          dest_repo.insert_data_stream, stream)
519
2520.4.113 by Aaron Bentley
Avoid peeking at Repository._serializer
520
    def test_get_serializer_format(self):
521
        repo = self.make_repository('.')
522
        format = repo.get_serializer_format()
523
        self.assertEqual(repo._serializer.format_num, format)
524
2708.1.7 by Aaron Bentley
Rename extract_files_bytes to iter_files_bytes
525
    def test_iter_files_bytes(self):
2708.1.3 by Aaron Bentley
Implement extract_files_bytes on Repository
526
        tree = self.make_branch_and_tree('tree')
527
        self.build_tree_contents([('tree/file1', 'foo'),
528
                                  ('tree/file2', 'bar')])
529
        tree.add(['file1', 'file2'], ['file1-id', 'file2-id'])
530
        tree.commit('rev1', rev_id='rev1')
531
        self.build_tree_contents([('tree/file1', 'baz')])
532
        tree.commit('rev2', rev_id='rev2')
2708.1.11 by Aaron Bentley
Test and tweak error handling
533
        repository = tree.branch.repository
2592.3.214 by Robert Collins
Merge bzr.dev.
534
        repository.lock_read()
535
        self.addCleanup(repository.unlock)
2708.1.6 by Aaron Bentley
Turn extract_files_bytes into an iterator
536
        extracted = dict((i, ''.join(b)) for i, b in
2708.1.11 by Aaron Bentley
Test and tweak error handling
537
                         repository.iter_files_bytes(
2708.1.6 by Aaron Bentley
Turn extract_files_bytes into an iterator
538
                         [('file1-id', 'rev1', 'file1-old'),
539
                          ('file1-id', 'rev2', 'file1-new'),
540
                          ('file2-id', 'rev1', 'file2'),
541
                         ]))
542
        self.assertEqual('foo', extracted['file1-old'])
543
        self.assertEqual('bar', extracted['file2'])
544
        self.assertEqual('baz', extracted['file1-new'])
2708.1.11 by Aaron Bentley
Test and tweak error handling
545
        self.assertRaises(errors.RevisionNotPresent, list,
546
                          repository.iter_files_bytes(
547
                          [('file1-id', 'rev3', 'file1-notpresent')]))
2592.3.102 by Robert Collins
Change the iter_files_bytes error to allow either RevisionNotPresent or NoSuchId when requesting a file that was not in the repository at all.
548
        self.assertRaises((errors.RevisionNotPresent, errors.NoSuchId), list,
2708.1.11 by Aaron Bentley
Test and tweak error handling
549
                          repository.iter_files_bytes(
550
                          [('file3-id', 'rev3', 'file1-notpresent')]))
2708.1.3 by Aaron Bentley
Implement extract_files_bytes on Repository
551
2535.3.63 by Andrew Bennetts
Add repository implementations test for item_keys_introduced_by.
552
    def test_item_keys_introduced_by(self):
553
        # Make a repo with one revision and one versioned file.
554
        tree = self.make_branch_and_tree('t')
555
        self.build_tree(['t/foo'])
556
        tree.add('foo', 'file1')
557
        tree.commit('message', rev_id='rev_id')
558
        repo = tree.branch.repository
3381.1.3 by Aaron Bentley
Stop locking in get_data_stream_for_search
559
        repo.lock_read()
560
        self.addCleanup(repo.unlock)
2535.3.63 by Andrew Bennetts
Add repository implementations test for item_keys_introduced_by.
561
562
        # Item keys will be in this order, for maximum convenience for
563
        # generating data to insert into knit repository:
564
        #   * files
565
        #   * inventory
566
        #   * signatures
567
        #   * revisions
568
        expected_item_keys = [
569
            ('file', 'file1', ['rev_id']),
570
            ('inventory', None, ['rev_id']),
571
            ('signatures', None, []),
572
            ('revisions', None, ['rev_id'])]
573
        item_keys = list(repo.item_keys_introduced_by(['rev_id']))
574
        item_keys = [
575
            (kind, file_id, list(versions))
576
            for (kind, file_id, versions) in item_keys]
577
578
        if repo.supports_rich_root():
579
            # Check for the root versioned file in the item_keys, then remove
580
            # it from streamed_names so we can compare that with
581
            # expected_record_names.
582
            # Note that the file keys can be in any order, so this test is
583
            # written to allow that.
584
            inv = repo.get_inventory('rev_id')
585
            root_item_key = ('file', inv.root.file_id, ['rev_id'])
586
            self.assertTrue(root_item_key in item_keys)
587
            item_keys.remove(root_item_key)
588
589
        self.assertEqual(expected_item_keys, item_keys)
590
2850.4.1 by Andrew Bennetts
Add smoketest for repo.get_graph, and fix bug in RemoteRepository.get_graph that it reveals.
591
    def test_get_graph(self):
592
        """Bare-bones smoketest that all repositories implement get_graph."""
593
        repo = self.make_repository('repo')
2592.3.214 by Robert Collins
Merge bzr.dev.
594
        repo.lock_read()
595
        self.addCleanup(repo.unlock)
2850.4.1 by Andrew Bennetts
Add smoketest for repo.get_graph, and fix bug in RemoteRepository.get_graph that it reveals.
596
        repo.get_graph()
597
3146.1.1 by Aaron Bentley
Fix bad ghost handling in KnitParentsProvider
598
    def test_graph_ghost_handling(self):
599
        tree = self.make_branch_and_tree('here')
600
        tree.lock_write()
601
        self.addCleanup(tree.unlock)
602
        tree.commit('initial commit', rev_id='rev1')
603
        tree.add_parent_tree_id('ghost')
604
        tree.commit('commit-with-ghost', rev_id='rev2')
605
        graph = tree.branch.repository.get_graph()
606
        parents = graph.get_parent_map(['ghost', 'rev2'])
607
        self.assertTrue('ghost' not in parents)
3146.1.2 by Aaron Bentley
ParentsProviders now provide tuples of parents, never lists
608
        self.assertEqual(parents['rev2'], ('rev1', 'ghost'))
609
610
    def test_parent_map_type(self):
611
        tree = self.make_branch_and_tree('here')
612
        tree.lock_write()
613
        self.addCleanup(tree.unlock)
614
        tree.commit('initial commit', rev_id='rev1')
615
        tree.commit('next commit', rev_id='rev2')
616
        graph = tree.branch.repository.get_graph()
617
        parents = graph.get_parent_map([NULL_REVISION, 'rev1', 'rev2'])
618
        for value in parents.values():
619
            self.assertIsInstance(value, tuple)
3146.1.1 by Aaron Bentley
Fix bad ghost handling in KnitParentsProvider
620
2819.2.4 by Andrew Bennetts
Add a 'revision_graph_can_have_wrong_parents' method to repository.
621
    def test_implements_revision_graph_can_have_wrong_parents(self):
622
        """All repositories should implement
623
        revision_graph_can_have_wrong_parents, so that check and reconcile can
624
        work correctly.
625
        """
626
        repo = self.make_repository('.')
627
        # This should work, not raise NotImplementedError:
2592.3.214 by Robert Collins
Merge bzr.dev.
628
        if not repo.revision_graph_can_have_wrong_parents():
629
            return
630
        repo.lock_read()
631
        self.addCleanup(repo.unlock)
632
        # This repo must also implement
633
        # _find_inconsistent_revision_parents and
634
        # _check_for_inconsistent_revision_parents.  So calling these
635
        # should not raise NotImplementedError.
636
        list(repo._find_inconsistent_revision_parents())
637
        repo._check_for_inconsistent_revision_parents()
2819.2.4 by Andrew Bennetts
Add a 'revision_graph_can_have_wrong_parents' method to repository.
638
2996.2.4 by Aaron Bentley
Rename function to add_signature_text
639
    def test_add_signature_text(self):
2996.2.3 by Aaron Bentley
Add tests for install_revisions and add_signature
640
        repo = self.make_repository('repo')
641
        repo.lock_write()
642
        self.addCleanup(repo.unlock)
643
        self.addCleanup(repo.commit_write_group)
644
        repo.start_write_group()
645
        inv = Inventory(revision_id='A')
646
        inv.root.revision = 'A'
647
        repo.add_inventory('A', inv, [])
648
        repo.add_revision('A', Revision('A', committer='A', timestamp=0,
649
                          inventory_sha1='', timezone=0, message='A'))
2996.2.4 by Aaron Bentley
Rename function to add_signature_text
650
        repo.add_signature_text('A', 'This might be a signature')
2996.2.3 by Aaron Bentley
Add tests for install_revisions and add_signature
651
        self.assertEqual('This might be a signature',
652
                         repo.get_signature_text('A'))
653
3305.1.1 by Jelmer Vernooij
Make sure that specifying the inv= argument to add_revision() sets the
654
    def test_add_revision_inventory_sha1(self):
655
        repo = self.make_repository('repo')
656
        inv = Inventory(revision_id='A')
657
        inv.root.revision = 'A'
658
        inv.root.file_id = 'fixed-root'
659
        repo.lock_write()
660
        repo.start_write_group()
661
        repo.add_revision('A', Revision('A', committer='B', timestamp=0,
662
                          timezone=0, message='C'), inv=inv)
663
        repo.commit_write_group()
664
        repo.unlock()
665
        repo.lock_read()
666
        self.assertEquals(osutils.sha_string(
667
            repo._serializer.write_inventory_to_string(inv)),
668
            repo.get_revision('A').inventory_sha1)
669
        repo.unlock()
670
2996.2.3 by Aaron Bentley
Add tests for install_revisions and add_signature
671
    def test_install_revisions(self):
672
        wt = self.make_branch_and_tree('source')
673
        wt.commit('A', allow_pointless=True, rev_id='A')
674
        repo = wt.branch.repository
675
        repo.lock_write()
676
        repo.start_write_group()
677
        repo.sign_revision('A', bzrlib.gpg.LoopbackGPGStrategy(None))
678
        repo.commit_write_group()
679
        repo.unlock()
680
        repo.lock_read()
681
        self.addCleanup(repo.unlock)
682
        repo2 = self.make_repository('repo2')
683
        revision = repo.get_revision('A')
684
        tree = repo.revision_tree('A')
685
        signature = repo.get_signature_text('A')
686
        repo2.lock_write()
687
        self.addCleanup(repo2.unlock)
688
        repository.install_revisions(repo2, [(revision, tree, signature)])
689
        self.assertEqual(revision, repo2.get_revision('A'))
690
        self.assertEqual(signature, repo2.get_signature_text('A'))
1852.9.6 by Robert Collins
Merge the change from Tree.compare to Tree.changes_from.
691
3047.1.1 by Andrew Bennetts
Fix for bug 164626, add test that Repository.sprout preserves format.
692
    # XXX: this helper duplicated from tests.test_repository
693
    def make_remote_repository(self, path):
694
        """Make a RemoteRepository object backed by a real repository that will
695
        be created at the given path."""
696
        repo = self.make_repository(path)
697
        smart_server = server.SmartTCPServer_for_testing()
698
        smart_server.setUp(self.get_server())
699
        remote_transport = get_transport(smart_server.get_url()).clone(path)
700
        self.addCleanup(smart_server.tearDown)
701
        remote_bzrdir = bzrdir.BzrDir.open_from_transport(remote_transport)
702
        remote_repo = remote_bzrdir.open_repository()
703
        return remote_repo
704
3047.1.2 by Andrew Bennetts
Directly test that sprouting branches from a HPSS preserves the repository format.
705
    def test_sprout_from_hpss_preserves_format(self):
706
        """repo.sprout from a smart server preserves the repository format."""
3047.1.1 by Andrew Bennetts
Fix for bug 164626, add test that Repository.sprout preserves format.
707
        if self.repository_format == RepositoryFormat7():
708
            raise KnownFailure(
709
                "Cannot fetch weaves over smart protocol.")
710
        remote_repo = self.make_remote_repository('remote')
711
        local_bzrdir = self.make_bzrdir('local')
712
        try:
713
            local_repo = remote_repo.sprout(local_bzrdir)
714
        except errors.TransportNotPossible:
715
            raise TestNotApplicable(
716
                "Cannot lock_read old formats like AllInOne over HPSS.")
717
        remote_backing_repo = bzrdir.BzrDir.open(
718
            self.get_vfs_only_url('remote')).open_repository()
719
        self.assertEqual(remote_backing_repo._format, local_repo._format)
720
3047.1.2 by Andrew Bennetts
Directly test that sprouting branches from a HPSS preserves the repository format.
721
    def test_sprout_branch_from_hpss_preserves_repo_format(self):
722
        """branch.sprout from a smart server preserves the repository format.
723
        """
724
        weave_formats = [RepositoryFormat5(), RepositoryFormat6(),
725
                         RepositoryFormat7()]
726
        if self.repository_format in weave_formats:
727
            raise KnownFailure(
728
                "Cannot fetch weaves over smart protocol.")
729
        remote_repo = self.make_remote_repository('remote')
730
        remote_branch = remote_repo.bzrdir.create_branch()
731
        try:
732
            local_bzrdir = remote_branch.bzrdir.sprout('local')
733
        except errors.TransportNotPossible:
734
            raise TestNotApplicable(
735
                "Cannot lock_read old formats like AllInOne over HPSS.")
736
        local_repo = local_bzrdir.open_repository()
737
        remote_backing_repo = bzrdir.BzrDir.open(
738
            self.get_vfs_only_url('remote')).open_repository()
739
        self.assertEqual(remote_backing_repo._format, local_repo._format)
740
3089.2.1 by Andrew Bennetts
Implement RemoteRepository._make_parents_provider.
741
    def test__make_parents_provider(self):
742
        """Repositories must have a _make_parents_provider method that returns
3099.3.5 by John Arbash Meinel
Update the last couple of places that referred to Provider.get_parents() directly.
743
        an object with a get_parent_map method.
3089.2.1 by Andrew Bennetts
Implement RemoteRepository._make_parents_provider.
744
        """
745
        repo = self.make_repository('repo')
3099.3.5 by John Arbash Meinel
Update the last couple of places that referred to Provider.get_parents() directly.
746
        repo._make_parents_provider().get_parent_map
3089.2.1 by Andrew Bennetts
Implement RemoteRepository._make_parents_provider.
747
3140.1.2 by Aaron Bentley
Add ability to find branches inside repositories
748
    def make_repository_and_foo_bar(self, shared):
749
        made_control = self.make_bzrdir('repository')
750
        repo = made_control.create_repository(shared=shared)
751
        bzrdir.BzrDir.create_branch_convenience(self.get_url('repository/foo'),
752
                                                force_new_repo=False)
753
        bzrdir.BzrDir.create_branch_convenience(self.get_url('repository/bar'),
754
                                                force_new_repo=True)
3140.1.3 by Aaron Bentley
Add support for finding branches to BzrDir
755
        baz = self.make_bzrdir('repository/baz')
756
        qux = self.make_branch('repository/baz/qux')
3140.1.6 by Aaron Bentley
Add test that nested branches are returned
757
        quxx = self.make_branch('repository/baz/qux/quxx')
3140.1.2 by Aaron Bentley
Add ability to find branches inside repositories
758
        return repo
759
760
    def test_find_branches(self):
761
        repo = self.make_repository_and_foo_bar(shared=False)
762
        branches = repo.find_branches()
763
        self.assertContainsRe(branches[-1].base, 'repository/foo/$')
3140.1.6 by Aaron Bentley
Add test that nested branches are returned
764
        self.assertContainsRe(branches[-3].base, 'repository/baz/qux/$')
765
        self.assertContainsRe(branches[-2].base, 'repository/baz/qux/quxx/$')
3140.1.2 by Aaron Bentley
Add ability to find branches inside repositories
766
        # in some formats, creating a repo creates a branch
3140.1.6 by Aaron Bentley
Add test that nested branches are returned
767
        if len(branches) == 6:
768
            self.assertContainsRe(branches[-4].base, 'repository/baz/$')
769
            self.assertContainsRe(branches[-5].base, 'repository/bar/$')
770
            self.assertContainsRe(branches[-6].base, 'repository/$')
771
        else:
772
            self.assertEqual(4, len(branches))
3140.1.3 by Aaron Bentley
Add support for finding branches to BzrDir
773
            self.assertContainsRe(branches[-4].base, 'repository/bar/$')
3140.1.2 by Aaron Bentley
Add ability to find branches inside repositories
774
775
    def test_find_branches_using(self):
776
        try:
777
            repo = self.make_repository_and_foo_bar(shared=True)
778
        except errors.IncompatibleFormat:
779
            raise TestNotApplicable
780
        branches = repo.find_branches(using=True)
781
        self.assertContainsRe(branches[-1].base, 'repository/foo/$')
782
        # in some formats, creating a repo creates a branch
783
        if len(branches) == 2:
784
            self.assertContainsRe(branches[-2].base, 'repository/$')
785
        else:
786
            self.assertEqual(1, len(branches))
787
3140.1.9 by Aaron Bentley
Optimize find_branches for standalone repositories
788
    def test_find_branches_using_standalone(self):
789
        branch = self.make_branch('branch')
790
        contained = self.make_branch('branch/contained')
791
        branches = branch.repository.find_branches(using=True)
792
        self.assertEqual([branch.base], [b.base for b in branches])
793
        branches = branch.repository.find_branches(using=False)
794
        self.assertEqual([branch.base, contained.base],
795
                         [b.base for b in branches])
796
797
    def test_find_branches_using_empty_standalone_repo(self):
798
        repo = self.make_repository('repo')
799
        self.assertFalse(repo.is_shared())
800
        try:
801
            repo.bzrdir.open_branch()
802
        except errors.NotBranchError:
803
            self.assertEqual([], repo.find_branches(using=True))
804
        else:
805
            self.assertEqual([repo.bzrdir.root_transport.base],
806
                             [b.base for b in repo.find_branches(using=True)])
807
3349.1.1 by Aaron Bentley
Enable setting and getting make_working_trees for all repositories
808
    def test_set_get_make_working_trees_true(self):
809
        repo = self.make_repository('repo')
3349.1.2 by Aaron Bentley
Change ValueError to RepositoryUpgradeRequired
810
        try:
811
            repo.set_make_working_trees(True)
812
        except errors.RepositoryUpgradeRequired, e:
813
            raise TestNotApplicable('Format does not support this flag.')
3349.1.1 by Aaron Bentley
Enable setting and getting make_working_trees for all repositories
814
        self.assertTrue(repo.make_working_trees())
815
816
    def test_set_get_make_working_trees_false(self):
817
        repo = self.make_repository('repo')
818
        try:
819
            repo.set_make_working_trees(False)
3349.1.2 by Aaron Bentley
Change ValueError to RepositoryUpgradeRequired
820
        except errors.RepositoryUpgradeRequired, e:
821
            raise TestNotApplicable('Format does not support this flag.')
822
        self.assertFalse(repo.make_working_trees())
3349.1.1 by Aaron Bentley
Enable setting and getting make_working_trees for all repositories
823
3047.1.1 by Andrew Bennetts
Fix for bug 164626, add test that Repository.sprout preserves format.
824
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
825
class TestRepositoryLocking(TestCaseWithRepository):
826
827
    def test_leave_lock_in_place(self):
828
        repo = self.make_repository('r')
829
        # Lock the repository, then use leave_lock_in_place so that when we
830
        # unlock the repository the lock is still held on disk.
2018.5.76 by Andrew Bennetts
Testing that repository.{dont_,}leave_lock_in_place raises NotImplementedError if lock_write returns None.
831
        token = repo.lock_write()
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
832
        try:
2018.5.76 by Andrew Bennetts
Testing that repository.{dont_,}leave_lock_in_place raises NotImplementedError if lock_write returns None.
833
            if token is None:
834
                # This test does not apply, because this repository refuses lock
835
                # tokens.
836
                self.assertRaises(NotImplementedError, repo.leave_lock_in_place)
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
837
                return
2018.5.76 by Andrew Bennetts
Testing that repository.{dont_,}leave_lock_in_place raises NotImplementedError if lock_write returns None.
838
            repo.leave_lock_in_place()
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
839
        finally:
840
            repo.unlock()
841
        # We should be unable to relock the repo.
842
        self.assertRaises(errors.LockContention, repo.lock_write)
843
844
    def test_dont_leave_lock_in_place(self):
845
        repo = self.make_repository('r')
846
        # Create a lock on disk.
847
        token = repo.lock_write()
848
        try:
849
            if token is None:
850
                # This test does not apply, because this repository refuses lock
851
                # tokens.
2018.5.76 by Andrew Bennetts
Testing that repository.{dont_,}leave_lock_in_place raises NotImplementedError if lock_write returns None.
852
                self.assertRaises(NotImplementedError,
853
                                  repo.dont_leave_lock_in_place)
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
854
                return
855
            try:
856
                repo.leave_lock_in_place()
857
            except NotImplementedError:
858
                # This repository doesn't support this API.
859
                return
860
        finally:
861
            repo.unlock()
862
        # Reacquire the lock (with a different repository object) by using the
863
        # token.
864
        new_repo = repo.bzrdir.open_repository()
865
        new_repo.lock_write(token=token)
866
        # Call dont_leave_lock_in_place, so that the lock will be released by
867
        # this instance, even though the lock wasn't originally acquired by it.
868
        new_repo.dont_leave_lock_in_place()
869
        new_repo.unlock()
870
        # Now the repository is unlocked.  Test this by locking it (without a
871
        # token).
872
        repo.lock_write()
873
        repo.unlock()
874
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
875
    def test_lock_read_then_unlock(self):
876
        # Calling lock_read then unlocking should work without errors.
877
        repo = self.make_repository('r')
878
        repo.lock_read()
879
        repo.unlock()
880
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
881
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
882
class TestCaseWithComplexRepository(TestCaseWithRepository):
883
884
    def setUp(self):
885
        super(TestCaseWithComplexRepository, self).setUp()
886
        tree_a = self.make_branch_and_tree('a')
887
        self.bzrdir = tree_a.branch.bzrdir
888
        # add a corrupt inventory 'orphan'
1534.1.34 by Robert Collins
Move missing_revision_ids from Repository to InterRepository, and eliminate the now unused Repository._compatible_formats method.
889
        # this may need some generalising for knits.
2592.3.74 by Robert Collins
Test setup fix to use get_inventory_weave rather than control_store.get_weave.
890
        tree_a.lock_write()
891
        try:
892
            tree_a.branch.repository.start_write_group()
893
            inv_file = tree_a.branch.repository.get_inventory_weave()
894
            try:
895
                inv_file.add_lines('orphan', [], [])
896
            except:
897
                tree_a.branch.repository.commit_write_group()
898
                raise
899
            else:
900
                tree_a.branch.repository.abort_write_group()
901
        finally:
902
            tree_a.unlock()
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
903
        # add a real revision 'rev1'
904
        tree_a.commit('rev1', rev_id='rev1', allow_pointless=True)
905
        # add a real revision 'rev2' based on rev1
906
        tree_a.commit('rev2', rev_id='rev2', allow_pointless=True)
1594.2.3 by Robert Collins
bugfix revision.MultipleRevisionSources.get_revision_graph to integrate ghosts between sources. [slow on weaves, fast on knits.
907
        # add a reference to a ghost
1908.6.7 by Robert Collins
Remove all users of set_pending_merges and add_pending_merge except tests that they work correctly.
908
        tree_a.add_parent_tree_id('ghost1')
1594.2.3 by Robert Collins
bugfix revision.MultipleRevisionSources.get_revision_graph to integrate ghosts between sources. [slow on weaves, fast on knits.
909
        tree_a.commit('rev3', rev_id='rev3', allow_pointless=True)
910
        # add another reference to a ghost, and a second ghost.
1908.6.7 by Robert Collins
Remove all users of set_pending_merges and add_pending_merge except tests that they work correctly.
911
        tree_a.add_parent_tree_id('ghost1')
912
        tree_a.add_parent_tree_id('ghost2')
1594.2.3 by Robert Collins
bugfix revision.MultipleRevisionSources.get_revision_graph to integrate ghosts between sources. [slow on weaves, fast on knits.
913
        tree_a.commit('rev4', rev_id='rev4', allow_pointless=True)
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
914
1756.3.20 by Aaron Bentley
Tests for get_revision_deltas and revisions_trees
915
    def test_revision_trees(self):
916
        revision_ids = ['rev1', 'rev2', 'rev3', 'rev4']
917
        repository = self.bzrdir.open_repository()
2592.3.214 by Robert Collins
Merge bzr.dev.
918
        repository.lock_read()
919
        self.addCleanup(repository.unlock)
1756.3.20 by Aaron Bentley
Tests for get_revision_deltas and revisions_trees
920
        trees1 = list(repository.revision_trees(revision_ids))
921
        trees2 = [repository.revision_tree(t) for t in revision_ids]
922
        assert len(trees1) == len(trees2)
923
        for tree1, tree2 in zip(trees1, trees2):
1852.10.3 by Robert Collins
Remove all uses of compare_trees and replace with Tree.changes_from throughout bzrlib.
924
            assert not tree2.changes_from(tree1).has_changed()
1756.3.20 by Aaron Bentley
Tests for get_revision_deltas and revisions_trees
925
1756.3.22 by Aaron Bentley
Tweaks from review
926
    def test_get_deltas_for_revisions(self):
1756.3.20 by Aaron Bentley
Tests for get_revision_deltas and revisions_trees
927
        repository = self.bzrdir.open_repository()
2592.3.214 by Robert Collins
Merge bzr.dev.
928
        repository.lock_read()
929
        self.addCleanup(repository.unlock)
1756.3.20 by Aaron Bentley
Tests for get_revision_deltas and revisions_trees
930
        revisions = [repository.get_revision(r) for r in 
931
                     ['rev1', 'rev2', 'rev3', 'rev4']]
1756.3.22 by Aaron Bentley
Tweaks from review
932
        deltas1 = list(repository.get_deltas_for_revisions(revisions))
1756.3.20 by Aaron Bentley
Tests for get_revision_deltas and revisions_trees
933
        deltas2 = [repository.get_revision_delta(r.revision_id) for r in
934
                   revisions]
935
        assert deltas1 == deltas2
936
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
937
    def test_all_revision_ids(self):
938
        # all_revision_ids -> all revisions
1594.2.3 by Robert Collins
bugfix revision.MultipleRevisionSources.get_revision_graph to integrate ghosts between sources. [slow on weaves, fast on knits.
939
        self.assertEqual(['rev1', 'rev2', 'rev3', 'rev4'],
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
940
                         self.bzrdir.open_repository().all_revision_ids())
941
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
942
    def test_get_ancestry_missing_revision(self):
1534.1.34 by Robert Collins
Move missing_revision_ids from Repository to InterRepository, and eliminate the now unused Repository._compatible_formats method.
943
        # get_ancestry(revision that is in some data but not fully installed
944
        # -> NoSuchRevision
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
945
        self.assertRaises(errors.NoSuchRevision,
946
                          self.bzrdir.open_repository().get_ancestry, 'orphan')
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
947
2530.1.1 by Aaron Bentley
Make topological sorting optional for get_ancestry
948
    def test_get_unsorted_ancestry(self):
949
        repo = self.bzrdir.open_repository()
950
        self.assertEqual(set(repo.get_ancestry('rev3')),
951
                         set(repo.get_ancestry('rev3', topo_sorted=False)))
952
1590.1.1 by Robert Collins
Improve common_ancestor performance.
953
    def test_get_revision_graph(self):
954
        # we can get a mapping of id->parents for the entire revision graph or bits thereof.
2625.8.1 by Robert Collins
LIBRARY API BREAKS:
955
        self.assertEqual({'rev1':(),
956
                          'rev2':('rev1', ),
957
                          'rev3':('rev2', ),
958
                          'rev4':('rev3', ),
1594.2.3 by Robert Collins
bugfix revision.MultipleRevisionSources.get_revision_graph to integrate ghosts between sources. [slow on weaves, fast on knits.
959
                          },
3287.6.1 by Robert Collins
* ``VersionedFile.get_graph`` is deprecated, with no replacement method.
960
            self.applyDeprecated(one_four,
961
                self.bzrdir.open_repository().get_revision_graph, None))
2625.8.1 by Robert Collins
LIBRARY API BREAKS:
962
        self.assertEqual({'rev1':()},
3287.6.1 by Robert Collins
* ``VersionedFile.get_graph`` is deprecated, with no replacement method.
963
            self.applyDeprecated(one_four,
964
                self.bzrdir.open_repository().get_revision_graph, 'rev1'))
2625.8.1 by Robert Collins
LIBRARY API BREAKS:
965
        self.assertEqual({'rev1':(),
966
                          'rev2':('rev1', )},
3287.6.1 by Robert Collins
* ``VersionedFile.get_graph`` is deprecated, with no replacement method.
967
            self.applyDeprecated(one_four,
968
                self.bzrdir.open_repository().get_revision_graph, 'rev2'))
969
        self.assertRaises(errors.NoSuchRevision, self.applyDeprecated, one_four,
970
            self.bzrdir.open_repository().get_revision_graph, 'orphan')
1594.2.3 by Robert Collins
bugfix revision.MultipleRevisionSources.get_revision_graph to integrate ghosts between sources. [slow on weaves, fast on knits.
971
        # and ghosts are not mentioned
2625.8.1 by Robert Collins
LIBRARY API BREAKS:
972
        self.assertEqual({'rev1':(),
973
                          'rev2':('rev1', ),
974
                          'rev3':('rev2', ),
1594.2.3 by Robert Collins
bugfix revision.MultipleRevisionSources.get_revision_graph to integrate ghosts between sources. [slow on weaves, fast on knits.
975
                          },
3287.6.1 by Robert Collins
* ``VersionedFile.get_graph`` is deprecated, with no replacement method.
976
            self.applyDeprecated(one_four,
977
                self.bzrdir.open_repository().get_revision_graph, 'rev3'))
1836.3.1 by Robert Collins
(robertc) Teach repository.get_revision_graph, and revision.common_ancestor, about NULL_REVISION.
978
        # and we can ask for the NULLREVISION graph
979
        self.assertEqual({},
3287.6.1 by Robert Collins
* ``VersionedFile.get_graph`` is deprecated, with no replacement method.
980
            self.applyDeprecated(one_four,
981
                self.bzrdir.open_repository().get_revision_graph, NULL_REVISION))
1594.2.3 by Robert Collins
bugfix revision.MultipleRevisionSources.get_revision_graph to integrate ghosts between sources. [slow on weaves, fast on knits.
982
983
    def test_get_revision_graph_with_ghosts(self):
984
        # we can get a graph object with roots, ghosts, ancestors and
985
        # descendants.
986
        repo = self.bzrdir.open_repository()
3228.4.11 by John Arbash Meinel
Deprecations abound.
987
        graph = self.applyDeprecated(one_three,
988
                                     repo.get_revision_graph_with_ghosts, [])
1594.2.3 by Robert Collins
bugfix revision.MultipleRevisionSources.get_revision_graph to integrate ghosts between sources. [slow on weaves, fast on knits.
989
        self.assertEqual(set(['rev1']), graph.roots)
990
        self.assertEqual(set(['ghost1', 'ghost2']), graph.ghosts)
991
        self.assertEqual({'rev1':[],
992
                          'rev2':['rev1'],
993
                          'rev3':['rev2', 'ghost1'],
994
                          'rev4':['rev3', 'ghost1', 'ghost2'],
995
                          },
996
                          graph.get_ancestors())
997
        self.assertEqual({'ghost1':{'rev3':1, 'rev4':1},
998
                          'ghost2':{'rev4':1},
999
                          'rev1':{'rev2':1},
1000
                          'rev2':{'rev3':1},
1001
                          'rev3':{'rev4':1},
1002
                          'rev4':{},
1003
                          },
1004
                          graph.get_descendants())
1836.3.1 by Robert Collins
(robertc) Teach repository.get_revision_graph, and revision.common_ancestor, about NULL_REVISION.
1005
        # and we can ask for the NULLREVISION graph
3228.4.11 by John Arbash Meinel
Deprecations abound.
1006
        graph = self.applyDeprecated(one_three, 
1007
                    repo.get_revision_graph_with_ghosts, [NULL_REVISION])
1836.3.1 by Robert Collins
(robertc) Teach repository.get_revision_graph, and revision.common_ancestor, about NULL_REVISION.
1008
        self.assertEqual({}, graph.get_ancestors())
1009
        self.assertEqual({}, graph.get_descendants())
1590.1.1 by Robert Collins
Improve common_ancestor performance.
1010
2229.2.1 by Aaron Bentley
Reject reserved ids in versiondfile, tree, branch and repository
1011
    def test_reserved_id(self):
1012
        repo = self.make_repository('repository')
2592.3.61 by Robert Collins
Remove inventory.kndx.
1013
        repo.lock_write()
1014
        repo.start_write_group()
1015
        try:
1016
            self.assertRaises(errors.ReservedId, repo.add_inventory, 'reserved:',
1017
                              None, None)
1018
            self.assertRaises(errors.ReservedId, repo.add_revision, 'reserved:',
1019
                              None)
1020
        finally:
1021
            repo.abort_write_group()
1022
            repo.unlock()
2229.2.3 by Aaron Bentley
change reserved_id to is_reserved_id, add check_not_reserved for DRY
1023
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
1024
1025
class TestCaseWithCorruptRepository(TestCaseWithRepository):
1026
1027
    def setUp(self):
1028
        super(TestCaseWithCorruptRepository, self).setUp()
1029
        # a inventory with no parents and the revision has parents..
1030
        # i.e. a ghost.
1031
        repo = self.make_repository('inventory_with_unnecessary_ghost')
2592.3.38 by Robert Collins
All experimental format tests passing again.
1032
        repo.lock_write()
1033
        repo.start_write_group()
1910.2.23 by Aaron Bentley
Fix up test cases that manually construct inventories
1034
        inv = Inventory(revision_id = 'ghost')
1035
        inv.root.revision = 'ghost'
1907.1.1 by Aaron Bentley
Unshelved all changes except those related to removing RootEntry
1036
        sha1 = repo.add_inventory('ghost', inv, [])
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
1037
        rev = bzrlib.revision.Revision(timestamp=0,
1038
                                       timezone=None,
1039
                                       committer="Foo Bar <foo@example.com>",
1040
                                       message="Message",
1041
                                       inventory_sha1=sha1,
1042
                                       revision_id='ghost')
1043
        rev.parent_ids = ['the_ghost']
1044
        repo.add_revision('ghost', rev)
1045
         
1910.2.23 by Aaron Bentley
Fix up test cases that manually construct inventories
1046
        inv = Inventory(revision_id = 'the_ghost')
1047
        inv.root.revision = 'the_ghost'
1907.1.1 by Aaron Bentley
Unshelved all changes except those related to removing RootEntry
1048
        sha1 = repo.add_inventory('the_ghost', inv, [])
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
1049
        rev = bzrlib.revision.Revision(timestamp=0,
1050
                                       timezone=None,
1051
                                       committer="Foo Bar <foo@example.com>",
1052
                                       message="Message",
1053
                                       inventory_sha1=sha1,
1054
                                       revision_id='the_ghost')
1055
        rev.parent_ids = []
1056
        repo.add_revision('the_ghost', rev)
1057
        # check its setup usefully
1058
        inv_weave = repo.get_inventory_weave()
1563.2.30 by Robert Collins
Remove all but fetch references to revision_store, making the repository references that are weave specific use the RevisionTextStore.text_store attribute.
1059
        self.assertEqual(['ghost'], inv_weave.get_ancestry(['ghost']))
2592.3.38 by Robert Collins
All experimental format tests passing again.
1060
        repo.commit_write_group()
1061
        repo.unlock()
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
1062
1594.2.10 by Robert Collins
Teach knit fetching and branching to only duplicate relevant data avoiding unnecessary reconciles.
1063
    def test_corrupt_revision_access_asserts_if_reported_wrong(self):
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1064
        repo_url = self.get_url('inventory_with_unnecessary_ghost')
1065
        repo = repository.Repository.open(repo_url)
1594.2.10 by Robert Collins
Teach knit fetching and branching to only duplicate relevant data avoiding unnecessary reconciles.
1066
        reported_wrong = False
1067
        try:
1068
            if repo.get_ancestry('ghost') != [None, 'the_ghost', 'ghost']:
1069
                reported_wrong = True
1070
        except errors.CorruptRepository:
1071
            # caught the bad data:
1072
            return
1073
        if not reported_wrong:
1074
            return
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
1075
        self.assertRaises(errors.CorruptRepository, repo.get_revision, 'ghost')
1076
1594.2.3 by Robert Collins
bugfix revision.MultipleRevisionSources.get_revision_graph to integrate ghosts between sources. [slow on weaves, fast on knits.
1077
    def test_corrupt_revision_get_revision_reconcile(self):
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
1078
        repo_url = self.get_url('inventory_with_unnecessary_ghost')
1079
        repo = repository.Repository.open(repo_url)
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
1080
        repo.get_revision_reconcile('ghost')
1986.1.1 by Robert Collins
Move test_branch_on_vfat into a repository implementation test, to ensure that all repository formats are safe on vfat.
1081
1082
2018.5.29 by Robert Collins
Dont run the vfat repository test on RemoteRepositories as there is no point.
1083
# FIXME: document why this is a TestCaseWithTransport rather than a
1084
#        TestCaseWithRepository
1986.1.1 by Robert Collins
Move test_branch_on_vfat into a repository implementation test, to ensure that all repository formats are safe on vfat.
1085
class TestEscaping(TestCaseWithTransport):
1086
    """Test that repositories can be stored correctly on VFAT transports.
1087
    
1088
    Makes sure we have proper escaping of invalid characters, etc.
1089
1090
    It'd be better to test all operations on the FakeVFATTransportDecorator,
1091
    but working trees go straight to the os not through the Transport layer.
1092
    Therefore we build some history first in the regular way and then 
1093
    check it's safe to access for vfat.
1094
    """
1095
1096
    def test_on_vfat(self):
2018.5.29 by Robert Collins
Dont run the vfat repository test on RemoteRepositories as there is no point.
1097
        # dont bother with remote repository testing, because this test is
1098
        # about local disk layout/support.
1099
        from bzrlib.remote import RemoteRepositoryFormat
1100
        if isinstance(self.repository_format, RemoteRepositoryFormat):
1101
            return
1986.1.1 by Robert Collins
Move test_branch_on_vfat into a repository implementation test, to ensure that all repository formats are safe on vfat.
1102
        FOO_ID = 'foo<:>ID'
2018.5.29 by Robert Collins
Dont run the vfat repository test on RemoteRepositories as there is no point.
1103
        REV_ID = 'revid-1' 
1104
        # this makes a default format repository always, which is wrong: 
1105
        # it should be a TestCaseWithRepository in order to get the 
1106
        # default format.
1986.1.1 by Robert Collins
Move test_branch_on_vfat into a repository implementation test, to ensure that all repository formats are safe on vfat.
1107
        wt = self.make_branch_and_tree('repo')
2052.2.1 by Alexander Belchenko
test_on_vfat win32 fix: use binary line-endings
1108
        self.build_tree(["repo/foo"], line_endings='binary')
1986.1.1 by Robert Collins
Move test_branch_on_vfat into a repository implementation test, to ensure that all repository formats are safe on vfat.
1109
        # add file with id containing wierd characters
1110
        wt.add(['foo'], [FOO_ID])
1111
        wt.commit('this is my new commit', rev_id=REV_ID)
1112
        # now access over vfat; should be safe
1113
        branch = bzrdir.BzrDir.open('vfat+' + self.get_url('repo')).open_branch()
1114
        revtree = branch.repository.revision_tree(REV_ID)
3015.2.13 by Robert Collins
More lock correctness for the use of get_file_text in repository_implementations.
1115
        revtree.lock_read()
1116
        self.addCleanup(revtree.unlock)
1986.1.1 by Robert Collins
Move test_branch_on_vfat into a repository implementation test, to ensure that all repository formats are safe on vfat.
1117
        contents = revtree.get_file_text(FOO_ID)
1118
        self.assertEqual(contents, 'contents of repo/foo\n')
2520.4.54 by Aaron Bentley
Hang a create_bundle method off repository
1119
1120
    def test_create_bundle(self):
1121
        wt = self.make_branch_and_tree('repo')
1122
        self.build_tree(['repo/file1'])
1123
        wt.add('file1')
1124
        wt.commit('file1', rev_id='rev1')
1125
        fileobj = StringIO()
1126
        wt.branch.repository.create_bundle('rev1', NULL_REVISION, fileobj)