/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,
26
    remote,
27
    repository,
28
    )
1852.10.3 by Robert Collins
Remove all uses of compare_trees and replace with Tree.changes_from throughout bzrlib.
29
from bzrlib.delta import TreeDelta
1731.1.33 by Aaron Bentley
Revert no-special-root changes
30
from bzrlib.inventory import Inventory, InventoryDirectory
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
31
from bzrlib.revision import NULL_REVISION
2279.7.9 by Andrew Bennetts
Remove some redundant code pointed out by Robert's review, and remove some unused imports while I'm there.
32
from bzrlib.tests import TestCaseWithTransport, TestSkipped
2485.7.1 by Robert Collins
Relocate TestCaseWithRepository to be more central.
33
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.
34
from bzrlib.transport import get_transport
35
from bzrlib.upgrade import upgrade
36
from bzrlib.workingtree import WorkingTree
37
38
2018.5.66 by Wouter van Heyst
Fix repository test parameterization for RemoteRepository.
39
class TestRepositoryMakeBranchAndTree(TestCaseWithRepository):
40
41
    def test_repository_format(self):
2018.5.119 by Robert Collins
Unbreak TestRepositoryMakeBranchAndTree.
42
        # make sure the repository on tree.branch is of the desired format,
43
        # because developers use this api to setup the tree, branch and 
44
        # repository for their tests: having it now give the right repository
45
        # type would invalidate the tests.
2018.5.66 by Wouter van Heyst
Fix repository test parameterization for RemoteRepository.
46
        tree = self.make_branch_and_tree('repo')
47
        self.assertIsInstance(tree.branch.repository._format,
48
            self.repository_format.__class__)
2381.1.1 by Robert Collins
Split out hpss test fixes which dont depend on new or altered API's.
49
50
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
51
class TestRepository(TestCaseWithRepository):
52
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.
53
    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.
54
        #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.
55
        # such as signatures[not tested yet] etc etc.
56
        # when changing to the current default format.
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
57
        tree_a = self.make_branch_and_tree('a')
2381.1.3 by Robert Collins
Review feedback.
58
        self.build_tree(['a/foo'])
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
59
        tree_a.add('foo', 'file1')
60
        tree_a.commit('rev1', rev_id='rev1')
61
        bzrdirb = self.make_bzrdir('b')
62
        repo_b = tree_a.branch.repository.clone(bzrdirb)
63
        tree_b = repo_b.revision_tree('rev1')
64
        tree_b.get_file_text('file1')
65
        rev1 = repo_b.get_revision('rev1')
66
1910.2.63 by Aaron Bentley
Add supports_rich_root member to repository
67
    def test_supports_rich_root(self):
68
        tree = self.make_branch_and_tree('a')
69
        tree.commit('')
70
        second_revision = tree.commit('')
71
        inv = tree.branch.repository.revision_tree(second_revision).inventory
72
        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.
73
        self.assertEqual(rich_root,
1910.2.63 by Aaron Bentley
Add supports_rich_root member to repository
74
                         tree.branch.repository.supports_rich_root())
75
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
76
    def test_clone_specific_format(self):
77
        """todo"""
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
78
79
    def test_format_initialize_find_open(self):
80
        # loopback test to check the current format initializes to itself.
81
        if not self.repository_format.is_supported():
82
            # unsupported formats are not loopback testable
83
            # because the default open will not open them and
84
            # they may not be initializable.
85
            return
86
        # supported formats must be able to init and open
87
        t = get_transport(self.get_url())
88
        readonly_t = get_transport(self.get_readonly_url())
89
        made_control = self.bzrdir_format.initialize(t.base)
90
        made_repo = self.repository_format.initialize(made_control)
91
        self.assertEqual(made_control, made_repo.bzrdir)
92
93
        # find it via bzrdir opening:
94
        opened_control = bzrdir.BzrDir.open(readonly_t.base)
95
        direct_opened_repo = opened_control.open_repository()
96
        self.assertEqual(direct_opened_repo.__class__, made_repo.__class__)
97
        self.assertEqual(opened_control, direct_opened_repo.bzrdir)
98
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
99
        self.assertIsInstance(direct_opened_repo._format,
100
                              self.repository_format.__class__)
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
101
        # find it via Repository.open
102
        opened_repo = repository.Repository.open(readonly_t.base)
103
        self.failUnless(isinstance(opened_repo, made_repo.__class__))
104
        self.assertEqual(made_repo._format.__class__,
105
                         opened_repo._format.__class__)
106
        # if it has a unique id string, can we probe for it ?
107
        try:
108
            self.repository_format.get_format_string()
109
        except NotImplementedError:
110
            return
111
        self.assertEqual(self.repository_format,
112
                         repository.RepositoryFormat.find_format(opened_control))
113
114
    def test_create_repository(self):
1534.6.1 by Robert Collins
allow API creation of shared repositories
115
        # 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.
116
        if not self.bzrdir_format.is_supported():
117
            # unsupported formats are not loopback testable
118
            # because the default open will not open them and
119
            # they may not be initializable.
120
            return
121
        t = get_transport(self.get_url())
122
        made_control = self.bzrdir_format.initialize(t.base)
123
        made_repo = made_control.create_repository()
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
124
        # Check that we have a repository object.
125
        made_repo.has_revision('foo')
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
126
        self.assertEqual(made_control, made_repo.bzrdir)
1534.6.1 by Robert Collins
allow API creation of shared repositories
127
        
128
    def test_create_repository_shared(self):
129
        # bzrdir can construct a shared repository.
130
        if not self.bzrdir_format.is_supported():
131
            # unsupported formats are not loopback testable
132
            # because the default open will not open them and
133
            # they may not be initializable.
134
            return
135
        t = get_transport(self.get_url())
136
        made_control = self.bzrdir_format.initialize(t.base)
137
        try:
138
            made_repo = made_control.create_repository(shared=True)
139
        except errors.IncompatibleFormat:
140
            # not all repository formats understand being shared, or
141
            # may only be shared in some circumstances.
142
            return
1752.2.50 by Andrew Bennetts
Implement RemoteBzrDir.create_{branch,workingtree}
143
        # Check that we have a repository object.
144
        made_repo.has_revision('foo')
1534.6.1 by Robert Collins
allow API creation of shared repositories
145
        self.assertEqual(made_control, made_repo.bzrdir)
1534.6.3 by Robert Collins
find_repository sufficiently robust.
146
        self.assertTrue(made_repo.is_shared())
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
147
148
    def test_revision_tree(self):
149
        wt = self.make_branch_and_tree('.')
1731.1.33 by Aaron Bentley
Revert no-special-root changes
150
        wt.set_root_id('fixed-root')
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
151
        wt.commit('lala!', rev_id='revision-1', allow_pointless=True)
152
        tree = wt.branch.repository.revision_tree('revision-1')
1731.1.45 by Aaron Bentley
Merge bzr.dev
153
        self.assertEqual('revision-1', tree.inventory.root.revision) 
154
        expected = InventoryDirectory('fixed-root', '', None)
155
        expected.revision = 'revision-1'
156
        self.assertEqual([('', 'V', 'directory', 'fixed-root', expected)],
1731.1.54 by Aaron Bentley
Fix revision_tree tests
157
                         list(tree.list_files(include_root=True)))
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
158
        tree = wt.branch.repository.revision_tree(None)
1731.1.54 by Aaron Bentley
Fix revision_tree tests
159
        self.assertEqual([], list(tree.list_files(include_root=True)))
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
160
        tree = wt.branch.repository.revision_tree(NULL_REVISION)
1731.1.54 by Aaron Bentley
Fix revision_tree tests
161
        self.assertEqual([], list(tree.list_files(include_root=True)))
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
162
1770.3.3 by Jelmer Vernooij
Add tests for Branch.get_revision_delta() and Repository.get_revision_delta().
163
    def test_get_revision_delta(self):
164
        tree_a = self.make_branch_and_tree('a')
2381.1.3 by Robert Collins
Review feedback.
165
        self.build_tree(['a/foo'])
1770.3.3 by Jelmer Vernooij
Add tests for Branch.get_revision_delta() and Repository.get_revision_delta().
166
        tree_a.add('foo', 'file1')
167
        tree_a.commit('rev1', rev_id='rev1')
2381.1.3 by Robert Collins
Review feedback.
168
        self.build_tree(['a/vla'])
1770.3.3 by Jelmer Vernooij
Add tests for Branch.get_revision_delta() and Repository.get_revision_delta().
169
        tree_a.add('vla', 'file2')
170
        tree_a.commit('rev2', rev_id='rev2')
171
172
        delta = tree_a.branch.repository.get_revision_delta('rev1')
173
        self.assertIsInstance(delta, TreeDelta)
174
        self.assertEqual([('foo', 'file1', 'file')], delta.added)
175
        delta = tree_a.branch.repository.get_revision_delta('rev2')
176
        self.assertIsInstance(delta, TreeDelta)
177
        self.assertEqual([('vla', 'file2', 'file')], delta.added)
178
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.
179
    def test_clone_bzrdir_repository_revision(self):
180
        # make a repository with some revisions,
181
        # and clone it, this should not have unreferenced revisions.
182
        # also: test cloning with a revision id of NULL_REVISION -> empty repo.
183
        raise TestSkipped('revision limiting is not implemented yet.')
184
185
    def test_clone_repository_basis_revision(self):
186
        raise TestSkipped('the use of a basis should not add noise data to the result.')
187
1534.6.5 by Robert Collins
Cloning of repos preserves shared and make-working-tree attributes.
188
    def test_clone_shared_no_tree(self):
189
        # cloning a shared repository keeps it shared
190
        # and preserves the make_working_tree setting.
191
        made_control = self.make_bzrdir('source')
192
        try:
193
            made_repo = made_control.create_repository(shared=True)
194
        except errors.IncompatibleFormat:
195
            # not all repository formats understand being shared, or
196
            # may only be shared in some circumstances.
197
            return
2018.14.2 by Andrew Bennetts
All but one repository_implementation tests for RemoteRepository passing.
198
        try:
199
            made_repo.set_make_working_trees(False)
200
        except NotImplementedError:
2018.5.120 by Robert Collins
The Repository API ``make_working_trees`` is now permitted to return
201
            # the repository does not support having its tree-making flag
202
            # toggled.
203
            return
1534.6.5 by Robert Collins
Cloning of repos preserves shared and make-working-tree attributes.
204
        result = made_control.clone(self.get_url('target'))
1752.2.55 by Andrew Bennetts
Replace another isinstance(made_repo, Repository) check.
205
        # Check that we have a repository object.
206
        made_repo.has_revision('foo')
207
1534.6.5 by Robert Collins
Cloning of repos preserves shared and make-working-tree attributes.
208
        self.assertEqual(made_control, made_repo.bzrdir)
209
        self.assertTrue(result.open_repository().is_shared())
210
        self.assertFalse(result.open_repository().make_working_trees())
211
2018.5.90 by Andrew Bennetts
Fix test_upgrade_preserves_signatures; it incorrectly assumed that upgrade(wt, ...) would necessarily affect the repository.
212
    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.
213
        wt = self.make_branch_and_tree('source')
214
        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.
215
        repo = wt.branch.repository
2617.6.4 by Robert Collins
Update tests with things that break when a repository requires write groups to be used.
216
        repo.lock_write()
217
        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.
218
        repo.sign_revision('A', bzrlib.gpg.LoopbackGPGStrategy(None))
2617.6.4 by Robert Collins
Update tests with things that break when a repository requires write groups to be used.
219
        repo.commit_write_group()
220
        repo.unlock()
2018.5.90 by Andrew Bennetts
Fix test_upgrade_preserves_signatures; it incorrectly assumed that upgrade(wt, ...) would necessarily affect the repository.
221
        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.
222
        try:
223
            old_format = bzrdir.BzrDirFormat.get_default_format()
224
            # This gives metadir branches something they can convert to.
225
            # it would be nice to have a 'latest' vs 'default' concept.
2255.2.208 by Robert Collins
Remove more references to 'experimental' formats.
226
            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.
227
            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.
228
        except errors.UpToDateFormat:
229
            # this is in the most current format already.
230
            return
1910.2.12 by Aaron Bentley
Implement knit repo format 2
231
        except errors.BadConversionTarget, e:
232
            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.
233
        wt = WorkingTree.open(wt.basedir)
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
234
        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.
235
        self.assertEqual(old_signature, new_signature)
236
1624.3.19 by Olaf Conradi
New call get_format_description to give a user-friendly description of a
237
    def test_format_description(self):
238
        repo = self.make_repository('.')
239
        text = repo._format.get_format_description()
240
        self.failUnless(len(text))
241
1666.1.6 by Robert Collins
Make knit the default format.
242
    def assertMessageRoundtrips(self, message):
243
        """Assert that message roundtrips to a repository and back intact."""
244
        tree = self.make_branch_and_tree('.')
245
        tree.commit(message, rev_id='a', allow_pointless=True)
246
        rev = tree.branch.repository.get_revision('a')
247
        # we have to manually escape this as we dont try to
248
        # roundtrip xml invalid characters at this point.
249
        # when escaping is moved to the serialiser, this test
250
        # can check against the literal message rather than
251
        # this escaped version.
252
        escaped_message, escape_count = re.subn(
253
            u'[^\x09\x0A\x0D\u0020-\uD7FF\uE000-\uFFFD]+',
254
            lambda match: match.group(0).encode('unicode_escape'),
255
            message)
256
        escaped_message= re.sub('\r', '\n', escaped_message)
257
        self.assertEqual(rev.message, escaped_message)
258
        # insist the class is unicode no matter what came in for 
259
        # consistency.
260
        self.assertIsInstance(rev.message, unicode)
261
262
    def test_commit_unicode_message(self):
263
        # a siple unicode message should be preserved
264
        self.assertMessageRoundtrips(u'foo bar gamm\xae plop')
265
266
    def test_commit_unicode_control_characters(self):
267
        # a unicode message with control characters should roundtrip too.
268
        self.assertMessageRoundtrips(
269
            "All 8-bit chars: " +  ''.join([unichr(x) for x in range(256)]))
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
270
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
271
    def test_check_repository(self):
272
        """Check a fairly simple repository's history"""
273
        tree = self.make_branch_and_tree('.')
274
        tree.commit('initial empty commit', rev_id='a-rev',
275
                    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.
276
        result = tree.branch.repository.check()
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
277
        # writes to log; should accept both verbose or non-verbose
278
        result.report_results(verbose=True)
279
        result.report_results(verbose=False)
280
1756.1.5 by Aaron Bentley
Test get_revisions with all repository types (and fix bug...)
281
    def test_get_revisions(self):
282
        tree = self.make_branch_and_tree('.')
283
        tree.commit('initial empty commit', rev_id='a-rev',
284
                    allow_pointless=True)
285
        tree.commit('second empty commit', rev_id='b-rev',
286
                    allow_pointless=True)
287
        tree.commit('third empty commit', rev_id='c-rev',
288
                    allow_pointless=True)
289
        repo = tree.branch.repository
290
        revision_ids = ['a-rev', 'b-rev', 'c-rev']
291
        revisions = repo.get_revisions(revision_ids)
292
        assert len(revisions) == 3, repr(revisions)
293
        zipped = zip(revisions, revision_ids)
294
        self.assertEqual(len(zipped), 3)
295
        for revision, revision_id in zipped:
296
            self.assertEqual(revision.revision_id, revision_id)
297
            self.assertEqual(revision, repo.get_revision(revision_id))
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
298
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
299
    def test_root_entry_has_revision(self):
300
        tree = self.make_branch_and_tree('.')
301
        tree.commit('message', rev_id='rev_id')
2255.7.65 by Robert Collins
Split test_root_revision_entry into tree and repository portions.
302
        rev_tree = tree.branch.repository.revision_tree(tree.last_revision())
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
303
        self.assertEqual('rev_id', rev_tree.inventory.root.revision)
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
304
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.
305
    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
306
        # Needs testing here because differences between repo and working tree
307
        # basis inventory formats can lead to bugs.
308
        t = self.make_branch_and_tree('.')
309
        b = t.branch
310
        open('a', 'wb').write('a\n')
311
        t.add('a')
312
        t.commit('a', rev_id='r1')
313
314
        t._control_files.get_utf8('basis-inventory-cache')
315
316
        basis_inv = t.basis_tree().inventory
317
        self.assertEquals('r1', basis_inv.revision_id)
318
        
319
        store_inv = b.repository.get_inventory('r1')
320
        self.assertEquals(store_inv._byid, basis_inv._byid)
321
322
        open('b', 'wb').write('b\n')
323
        t.add('b')
324
        t.commit('b', rev_id='r2')
325
326
        t._control_files.get_utf8('basis-inventory-cache')
327
328
        basis_inv_txt = t.read_basis_inventory()
2100.3.15 by Aaron Bentley
get test suite passing
329
        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
330
        self.assertEquals('r2', basis_inv.revision_id)
331
        store_inv = b.repository.get_inventory('r2')
332
333
        self.assertEquals(store_inv._byid, basis_inv._byid)
334
1910.2.36 by Aaron Bentley
Get upgrade from format4 under test and fixed for all formats
335
    def test_upgrade_from_format4(self):
336
        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.
337
        if self.repository_format.get_format_description() \
338
            == "Repository format 4":
1910.2.36 by Aaron Bentley
Get upgrade from format4 under test and fixed for all formats
339
            raise TestSkipped('Cannot convert format-4 to itself')
1752.2.89 by Andrew Bennetts
Skip test_upgrade_from_format4 for RemoteRepositoryFormat.
340
        if isinstance(self.repository_format, remote.RemoteRepositoryFormat):
341
            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
342
        self.build_tree_contents(_upgrade_dir_template)
343
        old_repodir = bzrlib.bzrdir.BzrDir.open_unsupported('.')
344
        old_repo_format = old_repodir.open_repository()._format
345
        format = self.repository_format._matchingbzrdir
346
        try:
347
            format.repository_format = self.repository_format
348
        except AttributeError:
349
            pass
350
        upgrade('.', format)
351
1910.2.37 by Aaron Bentley
Handle empty commits, fix test
352
    def test_pointless_commit(self):
353
        tree = self.make_branch_and_tree('.')
354
        self.assertRaises(errors.PointlessCommit, tree.commit, 'pointless',
355
                          allow_pointless=False)
356
        tree.commit('pointless', allow_pointless=True)
357
2323.5.17 by Martin Pool
Add supports_tree_reference to all repo formats (robert)
358
    def test_format_attributes(self):
359
        """All repository formats should have some basic attributes."""
360
        # create a repository to get a real format instance, not the 
361
        # template from the test suite parameterisation.
362
        repo = self.make_repository('.')
363
        repo._format.rich_root_data
364
        repo._format.supports_tree_reference
365
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
366
    def test_get_data_stream(self):
367
        # Make a repo with a revision
368
        tree = self.make_branch_and_tree('t')
369
        self.build_tree(['t/foo'])
370
        tree.add('foo', 'file1')
371
        tree.commit('message', rev_id='rev_id')
372
        repo = tree.branch.repository
373
374
        # Get a data stream (a file-like object) for that revision
375
        try:
376
            stream = repo.get_data_stream(['rev_id'])
377
        except NotImplementedError:
2535.3.14 by Andrew Bennetts
Move serialising repo data stream to bytes into smart protocol.
378
            # Not all repositories support streaming.
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
379
            return
380
2535.3.14 by Andrew Bennetts
Move serialising repo data stream to bytes into smart protocol.
381
        # The data stream is a iterator that yields (name, versioned_file)
382
        # pairs for:
2535.3.62 by Andrew Bennetts
Cosmetic changes.
383
        #   * the file knit (or knits; if this repo has rich roots there will
384
        #     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.
385
        #   * the inventory knit
386
        #   * the revisions knit
387
        # in that order.
2535.3.50 by Andrew Bennetts
Use tuple names in data streams rather than concatenated strings.
388
        expected_record_names = [
389
            ('file', 'file1'),
390
            ('inventory',),
391
            ('signatures',),
392
            ('revisions',)]
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
393
        streamed_names = []
2535.3.15 by Andrew Bennetts
Add KnitVersionedFile.get_stream_as_bytes, start smart implementation of RemoteRepository.get_data_stream.
394
        for name, bytes in stream:
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
395
            streamed_names.append(name)
396
397
        if repo.supports_rich_root():
2535.3.14 by Andrew Bennetts
Move serialising repo data stream to bytes into smart protocol.
398
            # Check for the root versioned file in the stream, then remove it
399
            # from streamed_names so we can compare that with
400
            # expected_record_names.
401
            # Note that the file knits can be in any order, so this test is
402
            # written to allow that.
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
403
            inv = repo.get_inventory('rev_id')
2535.3.50 by Andrew Bennetts
Use tuple names in data streams rather than concatenated strings.
404
            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.
405
            self.assertTrue(expected_record_name in streamed_names)
406
            streamed_names.remove(expected_record_name)
407
408
        self.assertEqual(expected_record_names, streamed_names)
409
2535.3.17 by Andrew Bennetts
[broken] Closer to a working Repository.fetch_revisions smart request.
410
    def test_insert_data_stream(self):
411
        tree = self.make_branch_and_tree('source')
412
        self.build_tree(['source/foo'])
413
        tree.add('foo', 'file1')
414
        tree.commit('message', rev_id='rev_id')
415
        source_repo = tree.branch.repository
416
        dest_repo = self.make_repository('dest')
417
        try:
418
            stream = source_repo.get_data_stream(['rev_id'])
419
        except NotImplementedError, e:
420
            # Not all repositories support streaming.
421
            self.assertContainsRe(str(e), 'get_data_stream')
422
            raise TestSkipped('This format does not support streaming.')
423
424
        dest_repo.insert_data_stream(stream)
425
        self.assertTrue(dest_repo.has_revision('rev_id'))
426
2520.4.113 by Aaron Bentley
Avoid peeking at Repository._serializer
427
    def test_get_serializer_format(self):
428
        repo = self.make_repository('.')
429
        format = repo.get_serializer_format()
430
        self.assertEqual(repo._serializer.format_num, format)
431
2708.1.7 by Aaron Bentley
Rename extract_files_bytes to iter_files_bytes
432
    def test_iter_files_bytes(self):
2708.1.3 by Aaron Bentley
Implement extract_files_bytes on Repository
433
        tree = self.make_branch_and_tree('tree')
434
        self.build_tree_contents([('tree/file1', 'foo'),
435
                                  ('tree/file2', 'bar')])
436
        tree.add(['file1', 'file2'], ['file1-id', 'file2-id'])
437
        tree.commit('rev1', rev_id='rev1')
438
        self.build_tree_contents([('tree/file1', 'baz')])
439
        tree.commit('rev2', rev_id='rev2')
2708.1.11 by Aaron Bentley
Test and tweak error handling
440
        repository = tree.branch.repository
2708.1.6 by Aaron Bentley
Turn extract_files_bytes into an iterator
441
        extracted = dict((i, ''.join(b)) for i, b in
2708.1.11 by Aaron Bentley
Test and tweak error handling
442
                         repository.iter_files_bytes(
2708.1.6 by Aaron Bentley
Turn extract_files_bytes into an iterator
443
                         [('file1-id', 'rev1', 'file1-old'),
444
                          ('file1-id', 'rev2', 'file1-new'),
445
                          ('file2-id', 'rev1', 'file2'),
446
                         ]))
447
        self.assertEqual('foo', extracted['file1-old'])
448
        self.assertEqual('bar', extracted['file2'])
449
        self.assertEqual('baz', extracted['file1-new'])
2708.1.11 by Aaron Bentley
Test and tweak error handling
450
        self.assertRaises(errors.RevisionNotPresent, list,
451
                          repository.iter_files_bytes(
452
                          [('file1-id', 'rev3', 'file1-notpresent')]))
2818.4.1 by Robert Collins
Various test fixes and tweaks for packs.
453
        self.assertRaises((errors.RevisionNotPresent, errors.NoSuchId), list,
2708.1.11 by Aaron Bentley
Test and tweak error handling
454
                          repository.iter_files_bytes(
455
                          [('file3-id', 'rev3', 'file1-notpresent')]))
2708.1.3 by Aaron Bentley
Implement extract_files_bytes on Repository
456
2535.3.63 by Andrew Bennetts
Add repository implementations test for item_keys_introduced_by.
457
    def test_item_keys_introduced_by(self):
458
        # Make a repo with one revision and one versioned file.
459
        tree = self.make_branch_and_tree('t')
460
        self.build_tree(['t/foo'])
461
        tree.add('foo', 'file1')
462
        tree.commit('message', rev_id='rev_id')
463
        repo = tree.branch.repository
464
465
        # Item keys will be in this order, for maximum convenience for
466
        # generating data to insert into knit repository:
467
        #   * files
468
        #   * inventory
469
        #   * signatures
470
        #   * revisions
471
        expected_item_keys = [
472
            ('file', 'file1', ['rev_id']),
473
            ('inventory', None, ['rev_id']),
474
            ('signatures', None, []),
475
            ('revisions', None, ['rev_id'])]
476
        item_keys = list(repo.item_keys_introduced_by(['rev_id']))
477
        item_keys = [
478
            (kind, file_id, list(versions))
479
            for (kind, file_id, versions) in item_keys]
480
481
        if repo.supports_rich_root():
482
            # Check for the root versioned file in the item_keys, then remove
483
            # it from streamed_names so we can compare that with
484
            # expected_record_names.
485
            # Note that the file keys can be in any order, so this test is
486
            # written to allow that.
487
            inv = repo.get_inventory('rev_id')
488
            root_item_key = ('file', inv.root.file_id, ['rev_id'])
489
            self.assertTrue(root_item_key in item_keys)
490
            item_keys.remove(root_item_key)
491
492
        self.assertEqual(expected_item_keys, item_keys)
493
2850.4.1 by Andrew Bennetts
Add smoketest for repo.get_graph, and fix bug in RemoteRepository.get_graph that it reveals.
494
    def test_get_graph(self):
495
        """Bare-bones smoketest that all repositories implement get_graph."""
496
        repo = self.make_repository('repo')
497
        repo.get_graph()
498
2819.2.4 by Andrew Bennetts
Add a 'revision_graph_can_have_wrong_parents' method to repository.
499
    def test_implements_revision_graph_can_have_wrong_parents(self):
500
        """All repositories should implement
501
        revision_graph_can_have_wrong_parents, so that check and reconcile can
502
        work correctly.
503
        """
504
        repo = self.make_repository('.')
505
        # This should work, not raise NotImplementedError:
2819.2.5 by Andrew Bennetts
Make reconcile abort gracefully if the revision index has bad parents.
506
        result = repo.revision_graph_can_have_wrong_parents()
507
        if result:
508
            # If true, then this repo must also implement
509
            # _find_inconsistent_revision_parents and
510
            # _check_for_inconsistent_revision_parents.  So calling these
511
            # should also not raise NotImplementedError.
512
            list(repo._find_inconsistent_revision_parents())
513
            repo._check_for_inconsistent_revision_parents()
2819.2.4 by Andrew Bennetts
Add a 'revision_graph_can_have_wrong_parents' method to repository.
514
1852.9.6 by Robert Collins
Merge the change from Tree.compare to Tree.changes_from.
515
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
516
class TestRepositoryLocking(TestCaseWithRepository):
517
518
    def test_leave_lock_in_place(self):
519
        repo = self.make_repository('r')
520
        # Lock the repository, then use leave_lock_in_place so that when we
521
        # 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.
522
        token = repo.lock_write()
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
523
        try:
2018.5.76 by Andrew Bennetts
Testing that repository.{dont_,}leave_lock_in_place raises NotImplementedError if lock_write returns None.
524
            if token is None:
525
                # This test does not apply, because this repository refuses lock
526
                # tokens.
527
                self.assertRaises(NotImplementedError, repo.leave_lock_in_place)
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
528
                return
2018.5.76 by Andrew Bennetts
Testing that repository.{dont_,}leave_lock_in_place raises NotImplementedError if lock_write returns None.
529
            repo.leave_lock_in_place()
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
530
        finally:
531
            repo.unlock()
532
        # We should be unable to relock the repo.
533
        self.assertRaises(errors.LockContention, repo.lock_write)
534
535
    def test_dont_leave_lock_in_place(self):
536
        repo = self.make_repository('r')
537
        # Create a lock on disk.
538
        token = repo.lock_write()
539
        try:
540
            if token is None:
541
                # This test does not apply, because this repository refuses lock
542
                # tokens.
2018.5.76 by Andrew Bennetts
Testing that repository.{dont_,}leave_lock_in_place raises NotImplementedError if lock_write returns None.
543
                self.assertRaises(NotImplementedError,
544
                                  repo.dont_leave_lock_in_place)
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
545
                return
546
            try:
547
                repo.leave_lock_in_place()
548
            except NotImplementedError:
549
                # This repository doesn't support this API.
550
                return
551
        finally:
552
            repo.unlock()
553
        # Reacquire the lock (with a different repository object) by using the
554
        # token.
555
        new_repo = repo.bzrdir.open_repository()
556
        new_repo.lock_write(token=token)
557
        # Call dont_leave_lock_in_place, so that the lock will be released by
558
        # this instance, even though the lock wasn't originally acquired by it.
559
        new_repo.dont_leave_lock_in_place()
560
        new_repo.unlock()
561
        # Now the repository is unlocked.  Test this by locking it (without a
562
        # token).
563
        repo.lock_write()
564
        repo.unlock()
565
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
566
    def test_lock_read_then_unlock(self):
567
        # Calling lock_read then unlocking should work without errors.
568
        repo = self.make_repository('r')
569
        repo.lock_read()
570
        repo.unlock()
571
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
572
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
573
class TestCaseWithComplexRepository(TestCaseWithRepository):
574
575
    def setUp(self):
576
        super(TestCaseWithComplexRepository, self).setUp()
577
        tree_a = self.make_branch_and_tree('a')
578
        self.bzrdir = tree_a.branch.bzrdir
579
        # 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.
580
        # this may need some generalising for knits.
2818.4.1 by Robert Collins
Various test fixes and tweaks for packs.
581
        tree_a.lock_write()
582
        try:
583
            tree_a.branch.repository.start_write_group()
584
            inv_file = tree_a.branch.repository.get_inventory_weave()
585
            try:
586
                inv_file.add_lines('orphan', [], [])
587
            except:
588
                tree_a.branch.repository.commit_write_group()
589
                raise
590
            else:
591
                tree_a.branch.repository.abort_write_group()
592
        finally:
593
            tree_a.unlock()
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
594
        # add a real revision 'rev1'
595
        tree_a.commit('rev1', rev_id='rev1', allow_pointless=True)
596
        # add a real revision 'rev2' based on rev1
597
        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.
598
        # 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.
599
        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.
600
        tree_a.commit('rev3', rev_id='rev3', allow_pointless=True)
601
        # 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.
602
        tree_a.add_parent_tree_id('ghost1')
603
        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.
604
        tree_a.commit('rev4', rev_id='rev4', allow_pointless=True)
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
605
1756.3.20 by Aaron Bentley
Tests for get_revision_deltas and revisions_trees
606
    def test_revision_trees(self):
607
        revision_ids = ['rev1', 'rev2', 'rev3', 'rev4']
608
        repository = self.bzrdir.open_repository()
609
        trees1 = list(repository.revision_trees(revision_ids))
610
        trees2 = [repository.revision_tree(t) for t in revision_ids]
611
        assert len(trees1) == len(trees2)
612
        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.
613
            assert not tree2.changes_from(tree1).has_changed()
1756.3.20 by Aaron Bentley
Tests for get_revision_deltas and revisions_trees
614
1756.3.22 by Aaron Bentley
Tweaks from review
615
    def test_get_deltas_for_revisions(self):
1756.3.20 by Aaron Bentley
Tests for get_revision_deltas and revisions_trees
616
        repository = self.bzrdir.open_repository()
617
        revisions = [repository.get_revision(r) for r in 
618
                     ['rev1', 'rev2', 'rev3', 'rev4']]
1756.3.22 by Aaron Bentley
Tweaks from review
619
        deltas1 = list(repository.get_deltas_for_revisions(revisions))
1756.3.20 by Aaron Bentley
Tests for get_revision_deltas and revisions_trees
620
        deltas2 = [repository.get_revision_delta(r.revision_id) for r in
621
                   revisions]
622
        assert deltas1 == deltas2
623
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
624
    def test_all_revision_ids(self):
625
        # 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.
626
        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.
627
                         self.bzrdir.open_repository().all_revision_ids())
628
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
629
    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.
630
        # get_ancestry(revision that is in some data but not fully installed
631
        # -> NoSuchRevision
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
632
        self.assertRaises(errors.NoSuchRevision,
633
                          self.bzrdir.open_repository().get_ancestry, 'orphan')
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
634
2530.1.1 by Aaron Bentley
Make topological sorting optional for get_ancestry
635
    def test_get_unsorted_ancestry(self):
636
        repo = self.bzrdir.open_repository()
637
        self.assertEqual(set(repo.get_ancestry('rev3')),
638
                         set(repo.get_ancestry('rev3', topo_sorted=False)))
639
1590.1.1 by Robert Collins
Improve common_ancestor performance.
640
    def test_get_revision_graph(self):
641
        # 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:
642
        self.assertEqual({'rev1':(),
643
                          'rev2':('rev1', ),
644
                          'rev3':('rev2', ),
645
                          '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.
646
                          },
1590.1.1 by Robert Collins
Improve common_ancestor performance.
647
                         self.bzrdir.open_repository().get_revision_graph(None))
2625.8.1 by Robert Collins
LIBRARY API BREAKS:
648
        self.assertEqual({'rev1':()},
1590.1.1 by Robert Collins
Improve common_ancestor performance.
649
                         self.bzrdir.open_repository().get_revision_graph('rev1'))
2625.8.1 by Robert Collins
LIBRARY API BREAKS:
650
        self.assertEqual({'rev1':(),
651
                          'rev2':('rev1', )},
1590.1.1 by Robert Collins
Improve common_ancestor performance.
652
                         self.bzrdir.open_repository().get_revision_graph('rev2'))
2279.7.9 by Andrew Bennetts
Remove some redundant code pointed out by Robert's review, and remove some unused imports while I'm there.
653
        self.assertRaises(errors.NoSuchRevision,
1590.1.1 by Robert Collins
Improve common_ancestor performance.
654
                          self.bzrdir.open_repository().get_revision_graph,
655
                          'orphan')
1594.2.3 by Robert Collins
bugfix revision.MultipleRevisionSources.get_revision_graph to integrate ghosts between sources. [slow on weaves, fast on knits.
656
        # and ghosts are not mentioned
2625.8.1 by Robert Collins
LIBRARY API BREAKS:
657
        self.assertEqual({'rev1':(),
658
                          'rev2':('rev1', ),
659
                          '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.
660
                          },
661
                         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.
662
        # and we can ask for the NULLREVISION graph
663
        self.assertEqual({},
664
            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.
665
666
    def test_get_revision_graph_with_ghosts(self):
667
        # we can get a graph object with roots, ghosts, ancestors and
668
        # descendants.
669
        repo = self.bzrdir.open_repository()
670
        graph = repo.get_revision_graph_with_ghosts([])
671
        self.assertEqual(set(['rev1']), graph.roots)
672
        self.assertEqual(set(['ghost1', 'ghost2']), graph.ghosts)
673
        self.assertEqual({'rev1':[],
674
                          'rev2':['rev1'],
675
                          'rev3':['rev2', 'ghost1'],
676
                          'rev4':['rev3', 'ghost1', 'ghost2'],
677
                          },
678
                          graph.get_ancestors())
679
        self.assertEqual({'ghost1':{'rev3':1, 'rev4':1},
680
                          'ghost2':{'rev4':1},
681
                          'rev1':{'rev2':1},
682
                          'rev2':{'rev3':1},
683
                          'rev3':{'rev4':1},
684
                          'rev4':{},
685
                          },
686
                          graph.get_descendants())
1836.3.1 by Robert Collins
(robertc) Teach repository.get_revision_graph, and revision.common_ancestor, about NULL_REVISION.
687
        # and we can ask for the NULLREVISION graph
688
        graph = repo.get_revision_graph_with_ghosts([NULL_REVISION])
689
        self.assertEqual({}, graph.get_ancestors())
690
        self.assertEqual({}, graph.get_descendants())
1590.1.1 by Robert Collins
Improve common_ancestor performance.
691
2229.2.1 by Aaron Bentley
Reject reserved ids in versiondfile, tree, branch and repository
692
    def test_reserved_id(self):
693
        repo = self.make_repository('repository')
2818.4.1 by Robert Collins
Various test fixes and tweaks for packs.
694
        repo.lock_write()
695
        repo.start_write_group()
696
        try:
697
            self.assertRaises(errors.ReservedId, repo.add_inventory, 'reserved:',
698
                              None, None)
699
            self.assertRaises(errors.ReservedId, repo.add_revision, 'reserved:',
700
                              None)
701
        finally:
702
            repo.abort_write_group()
703
            repo.unlock()
2229.2.3 by Aaron Bentley
change reserved_id to is_reserved_id, add check_not_reserved for DRY
704
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
705
706
class TestCaseWithCorruptRepository(TestCaseWithRepository):
707
708
    def setUp(self):
709
        super(TestCaseWithCorruptRepository, self).setUp()
710
        # a inventory with no parents and the revision has parents..
711
        # i.e. a ghost.
712
        repo = self.make_repository('inventory_with_unnecessary_ghost')
2617.6.4 by Robert Collins
Update tests with things that break when a repository requires write groups to be used.
713
        repo.lock_write()
714
        repo.start_write_group()
1910.2.23 by Aaron Bentley
Fix up test cases that manually construct inventories
715
        inv = Inventory(revision_id = 'ghost')
716
        inv.root.revision = 'ghost'
1907.1.1 by Aaron Bentley
Unshelved all changes except those related to removing RootEntry
717
        sha1 = repo.add_inventory('ghost', inv, [])
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
718
        rev = bzrlib.revision.Revision(timestamp=0,
719
                                       timezone=None,
720
                                       committer="Foo Bar <foo@example.com>",
721
                                       message="Message",
722
                                       inventory_sha1=sha1,
723
                                       revision_id='ghost')
724
        rev.parent_ids = ['the_ghost']
725
        repo.add_revision('ghost', rev)
726
         
1910.2.23 by Aaron Bentley
Fix up test cases that manually construct inventories
727
        inv = Inventory(revision_id = 'the_ghost')
728
        inv.root.revision = 'the_ghost'
1907.1.1 by Aaron Bentley
Unshelved all changes except those related to removing RootEntry
729
        sha1 = repo.add_inventory('the_ghost', inv, [])
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
730
        rev = bzrlib.revision.Revision(timestamp=0,
731
                                       timezone=None,
732
                                       committer="Foo Bar <foo@example.com>",
733
                                       message="Message",
734
                                       inventory_sha1=sha1,
735
                                       revision_id='the_ghost')
736
        rev.parent_ids = []
737
        repo.add_revision('the_ghost', rev)
738
        # check its setup usefully
739
        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.
740
        self.assertEqual(['ghost'], inv_weave.get_ancestry(['ghost']))
2617.6.4 by Robert Collins
Update tests with things that break when a repository requires write groups to be used.
741
        repo.commit_write_group()
742
        repo.unlock()
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
743
1594.2.10 by Robert Collins
Teach knit fetching and branching to only duplicate relevant data avoiding unnecessary reconciles.
744
    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.
745
        repo_url = self.get_url('inventory_with_unnecessary_ghost')
746
        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.
747
        reported_wrong = False
748
        try:
749
            if repo.get_ancestry('ghost') != [None, 'the_ghost', 'ghost']:
750
                reported_wrong = True
751
        except errors.CorruptRepository:
752
            # caught the bad data:
753
            return
754
        if not reported_wrong:
755
            return
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
756
        self.assertRaises(errors.CorruptRepository, repo.get_revision, 'ghost')
757
1594.2.3 by Robert Collins
bugfix revision.MultipleRevisionSources.get_revision_graph to integrate ghosts between sources. [slow on weaves, fast on knits.
758
    def test_corrupt_revision_get_revision_reconcile(self):
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
759
        repo_url = self.get_url('inventory_with_unnecessary_ghost')
760
        repo = repository.Repository.open(repo_url)
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
761
        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.
762
763
2018.5.29 by Robert Collins
Dont run the vfat repository test on RemoteRepositories as there is no point.
764
# FIXME: document why this is a TestCaseWithTransport rather than a
765
#        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.
766
class TestEscaping(TestCaseWithTransport):
767
    """Test that repositories can be stored correctly on VFAT transports.
768
    
769
    Makes sure we have proper escaping of invalid characters, etc.
770
771
    It'd be better to test all operations on the FakeVFATTransportDecorator,
772
    but working trees go straight to the os not through the Transport layer.
773
    Therefore we build some history first in the regular way and then 
774
    check it's safe to access for vfat.
775
    """
776
777
    def test_on_vfat(self):
2018.5.29 by Robert Collins
Dont run the vfat repository test on RemoteRepositories as there is no point.
778
        # dont bother with remote repository testing, because this test is
779
        # about local disk layout/support.
780
        from bzrlib.remote import RemoteRepositoryFormat
781
        if isinstance(self.repository_format, RemoteRepositoryFormat):
782
            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.
783
        FOO_ID = 'foo<:>ID'
2018.5.29 by Robert Collins
Dont run the vfat repository test on RemoteRepositories as there is no point.
784
        REV_ID = 'revid-1' 
785
        # this makes a default format repository always, which is wrong: 
786
        # it should be a TestCaseWithRepository in order to get the 
787
        # 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.
788
        wt = self.make_branch_and_tree('repo')
2052.2.1 by Alexander Belchenko
test_on_vfat win32 fix: use binary line-endings
789
        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.
790
        # add file with id containing wierd characters
791
        wt.add(['foo'], [FOO_ID])
792
        wt.commit('this is my new commit', rev_id=REV_ID)
793
        # now access over vfat; should be safe
794
        branch = bzrdir.BzrDir.open('vfat+' + self.get_url('repo')).open_branch()
795
        revtree = branch.repository.revision_tree(REV_ID)
796
        contents = revtree.get_file_text(FOO_ID)
797
        self.assertEqual(contents, 'contents of repo/foo\n')
2520.4.54 by Aaron Bentley
Hang a create_bundle method off repository
798
799
    def test_create_bundle(self):
800
        wt = self.make_branch_and_tree('repo')
801
        self.build_tree(['repo/file1'])
802
        wt.add('file1')
803
        wt.commit('file1', rev_id='rev1')
804
        fileobj = StringIO()
805
        wt.branch.repository.create_bundle('rev1', NULL_REVISION, fileobj)