/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)
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
326
        self.assertEqual(len(revisions), 3)
1756.1.5 by Aaron Bentley
Test get_revisions with all repository types (and fix bug...)
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
1910.2.36 by Aaron Bentley
Get upgrade from format4 under test and fixed for all formats
339
    def test_upgrade_from_format4(self):
340
        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.
341
        if self.repository_format.get_format_description() \
342
            == "Repository format 4":
1910.2.36 by Aaron Bentley
Get upgrade from format4 under test and fixed for all formats
343
            raise TestSkipped('Cannot convert format-4 to itself')
1752.2.89 by Andrew Bennetts
Skip test_upgrade_from_format4 for RemoteRepositoryFormat.
344
        if isinstance(self.repository_format, remote.RemoteRepositoryFormat):
345
            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
346
        self.build_tree_contents(_upgrade_dir_template)
347
        old_repodir = bzrlib.bzrdir.BzrDir.open_unsupported('.')
348
        old_repo_format = old_repodir.open_repository()._format
349
        format = self.repository_format._matchingbzrdir
350
        try:
351
            format.repository_format = self.repository_format
352
        except AttributeError:
353
            pass
354
        upgrade('.', format)
355
1910.2.37 by Aaron Bentley
Handle empty commits, fix test
356
    def test_pointless_commit(self):
357
        tree = self.make_branch_and_tree('.')
358
        self.assertRaises(errors.PointlessCommit, tree.commit, 'pointless',
359
                          allow_pointless=False)
360
        tree.commit('pointless', allow_pointless=True)
361
2323.5.17 by Martin Pool
Add supports_tree_reference to all repo formats (robert)
362
    def test_format_attributes(self):
363
        """All repository formats should have some basic attributes."""
364
        # create a repository to get a real format instance, not the 
3128.1.3 by Vincent Ladeuil
Since we are there s/parameteris.*/parameteriz&/.
365
        # template from the test suite parameterization.
2323.5.17 by Martin Pool
Add supports_tree_reference to all repo formats (robert)
366
        repo = self.make_repository('.')
367
        repo._format.rich_root_data
368
        repo._format.supports_tree_reference
369
3184.1.9 by Robert Collins
* ``Repository.get_data_stream`` is now deprecated in favour of
370
    def test_get_data_stream_deprecated(self):
371
        # If get_data_stream is present it must be deprecated
372
        tree = self.make_branch_and_tree('t')
373
        self.build_tree(['t/foo'])
374
        tree.add('foo', 'file1')
375
        tree.commit('message', rev_id='rev_id')
376
        repo = tree.branch.repository
3381.1.1 by Aaron Bentley
Fix lock-taking iterators
377
        repo.lock_read()
378
        self.addCleanup(repo.unlock)
3184.1.9 by Robert Collins
* ``Repository.get_data_stream`` is now deprecated in favour of
379
        try:
380
            stream = self.applyDeprecated(one_two, repo.get_data_stream,
381
                ['rev_id'])
382
        except NotImplementedError:
383
            raise TestNotApplicable("%s doesn't support get_data_stream"
384
                % repo._format)
385
        except AttributeError:
386
            pass
387
388
    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.
389
        # Make a repo with a revision
390
        tree = self.make_branch_and_tree('t')
391
        self.build_tree(['t/foo'])
392
        tree.add('foo', 'file1')
393
        tree.commit('message', rev_id='rev_id')
394
        repo = tree.branch.repository
395
396
        # 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
397
        search = graph.SearchResult(set(['rev_id']), set([NULL_REVISION]), 1,
398
            set(['rev_id']))
3381.1.3 by Aaron Bentley
Stop locking in get_data_stream_for_search
399
        repo.lock_read()
400
        self.addCleanup(repo.unlock)
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
401
        try:
3184.1.9 by Robert Collins
* ``Repository.get_data_stream`` is now deprecated in favour of
402
            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.
403
        except NotImplementedError:
3023.2.1 by Martin Pool
test_get_data_stream should indicate NotApplicable rather than silently passing
404
            raise TestNotApplicable("%s doesn't support get_data_stream"
405
                % repo._format)
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
406
2535.3.14 by Andrew Bennetts
Move serialising repo data stream to bytes into smart protocol.
407
        # The data stream is a iterator that yields (name, versioned_file)
408
        # pairs for:
2535.3.62 by Andrew Bennetts
Cosmetic changes.
409
        #   * the file knit (or knits; if this repo has rich roots there will
410
        #     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.
411
        #   * the inventory knit
412
        #   * the revisions knit
413
        # in that order.
2535.3.50 by Andrew Bennetts
Use tuple names in data streams rather than concatenated strings.
414
        expected_record_names = [
415
            ('file', 'file1'),
416
            ('inventory',),
417
            ('signatures',),
418
            ('revisions',)]
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
419
        streamed_names = []
2535.3.15 by Andrew Bennetts
Add KnitVersionedFile.get_stream_as_bytes, start smart implementation of RemoteRepository.get_data_stream.
420
        for name, bytes in stream:
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
421
            streamed_names.append(name)
422
423
        if repo.supports_rich_root():
2535.3.14 by Andrew Bennetts
Move serialising repo data stream to bytes into smart protocol.
424
            # Check for the root versioned file in the stream, then remove it
425
            # from streamed_names so we can compare that with
426
            # expected_record_names.
427
            # Note that the file knits can be in any order, so this test is
428
            # written to allow that.
2535.3.12 by Andrew Bennetts
Add a first cut of a get_data_stream method to Repository.
429
            inv = repo.get_inventory('rev_id')
2535.3.50 by Andrew Bennetts
Use tuple names in data streams rather than concatenated strings.
430
            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.
431
            self.assertTrue(expected_record_name in streamed_names)
432
            streamed_names.remove(expected_record_name)
433
434
        self.assertEqual(expected_record_names, streamed_names)
435
2535.3.17 by Andrew Bennetts
[broken] Closer to a working Repository.fetch_revisions smart request.
436
    def test_insert_data_stream(self):
437
        tree = self.make_branch_and_tree('source')
438
        self.build_tree(['source/foo'])
439
        tree.add('foo', 'file1')
440
        tree.commit('message', rev_id='rev_id')
441
        source_repo = tree.branch.repository
442
        dest_repo = self.make_repository('dest')
3204.1.2 by Ian Clatworthy
Fix error handling in insert_data_stream (Lukas Lalinsky)
443
        search = dest_repo.search_missing_revision_ids(source_repo,
444
            revision_id='rev_id')
3381.1.3 by Aaron Bentley
Stop locking in get_data_stream_for_search
445
        source_repo.lock_read()
446
        self.addCleanup(source_repo.unlock)
2535.3.17 by Andrew Bennetts
[broken] Closer to a working Repository.fetch_revisions smart request.
447
        try:
3204.1.2 by Ian Clatworthy
Fix error handling in insert_data_stream (Lukas Lalinsky)
448
            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.
449
        except NotImplementedError, e:
450
            # Not all repositories support streaming.
3184.1.9 by Robert Collins
* ``Repository.get_data_stream`` is now deprecated in favour of
451
            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.
452
            raise TestSkipped('This format does not support streaming.')
453
2592.3.214 by Robert Collins
Merge bzr.dev.
454
        dest_repo.lock_write()
455
        try:
456
            dest_repo.start_write_group()
457
            try:
458
                dest_repo.insert_data_stream(stream)
459
            except:
460
                dest_repo.abort_write_group()
461
                raise
462
            else:
463
                dest_repo.commit_write_group()
464
        finally:
465
            dest_repo.unlock()
466
        # reopen to be sure it was added.
467
        dest_repo = dest_repo.bzrdir.open_repository()
2535.3.17 by Andrew Bennetts
[broken] Closer to a working Repository.fetch_revisions smart request.
468
        self.assertTrue(dest_repo.has_revision('rev_id'))
469
3184.5.1 by Lukáš Lalinský
Fix handling of some error cases in insert_data_stream
470
        # 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)
471
        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
472
        dest_repo.lock_write()
473
        try:
474
            dest_repo.start_write_group()
475
            try:
476
                dest_repo.insert_data_stream(stream)
477
            except:
478
                dest_repo.abort_write_group()
479
                raise
480
            else:
481
                dest_repo.commit_write_group()
482
        finally:
483
            dest_repo.unlock()
484
485
        # try to insert data stream with invalid key
486
        stream = [[('bogus-key',), '']]
487
        self.assertRaises(errors.RepositoryDataStreamError,
488
                          dest_repo.insert_data_stream, stream)
489
2520.4.113 by Aaron Bentley
Avoid peeking at Repository._serializer
490
    def test_get_serializer_format(self):
491
        repo = self.make_repository('.')
492
        format = repo.get_serializer_format()
493
        self.assertEqual(repo._serializer.format_num, format)
494
2708.1.7 by Aaron Bentley
Rename extract_files_bytes to iter_files_bytes
495
    def test_iter_files_bytes(self):
2708.1.3 by Aaron Bentley
Implement extract_files_bytes on Repository
496
        tree = self.make_branch_and_tree('tree')
497
        self.build_tree_contents([('tree/file1', 'foo'),
498
                                  ('tree/file2', 'bar')])
499
        tree.add(['file1', 'file2'], ['file1-id', 'file2-id'])
500
        tree.commit('rev1', rev_id='rev1')
501
        self.build_tree_contents([('tree/file1', 'baz')])
502
        tree.commit('rev2', rev_id='rev2')
2708.1.11 by Aaron Bentley
Test and tweak error handling
503
        repository = tree.branch.repository
2592.3.214 by Robert Collins
Merge bzr.dev.
504
        repository.lock_read()
505
        self.addCleanup(repository.unlock)
2708.1.6 by Aaron Bentley
Turn extract_files_bytes into an iterator
506
        extracted = dict((i, ''.join(b)) for i, b in
2708.1.11 by Aaron Bentley
Test and tweak error handling
507
                         repository.iter_files_bytes(
2708.1.6 by Aaron Bentley
Turn extract_files_bytes into an iterator
508
                         [('file1-id', 'rev1', 'file1-old'),
509
                          ('file1-id', 'rev2', 'file1-new'),
510
                          ('file2-id', 'rev1', 'file2'),
511
                         ]))
512
        self.assertEqual('foo', extracted['file1-old'])
513
        self.assertEqual('bar', extracted['file2'])
514
        self.assertEqual('baz', extracted['file1-new'])
2708.1.11 by Aaron Bentley
Test and tweak error handling
515
        self.assertRaises(errors.RevisionNotPresent, list,
516
                          repository.iter_files_bytes(
517
                          [('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.
518
        self.assertRaises((errors.RevisionNotPresent, errors.NoSuchId), list,
2708.1.11 by Aaron Bentley
Test and tweak error handling
519
                          repository.iter_files_bytes(
520
                          [('file3-id', 'rev3', 'file1-notpresent')]))
2708.1.3 by Aaron Bentley
Implement extract_files_bytes on Repository
521
2535.3.63 by Andrew Bennetts
Add repository implementations test for item_keys_introduced_by.
522
    def test_item_keys_introduced_by(self):
523
        # Make a repo with one revision and one versioned file.
524
        tree = self.make_branch_and_tree('t')
525
        self.build_tree(['t/foo'])
526
        tree.add('foo', 'file1')
527
        tree.commit('message', rev_id='rev_id')
528
        repo = tree.branch.repository
3381.1.3 by Aaron Bentley
Stop locking in get_data_stream_for_search
529
        repo.lock_read()
530
        self.addCleanup(repo.unlock)
2535.3.63 by Andrew Bennetts
Add repository implementations test for item_keys_introduced_by.
531
532
        # Item keys will be in this order, for maximum convenience for
533
        # generating data to insert into knit repository:
534
        #   * files
535
        #   * inventory
536
        #   * signatures
537
        #   * revisions
538
        expected_item_keys = [
539
            ('file', 'file1', ['rev_id']),
540
            ('inventory', None, ['rev_id']),
541
            ('signatures', None, []),
542
            ('revisions', None, ['rev_id'])]
543
        item_keys = list(repo.item_keys_introduced_by(['rev_id']))
544
        item_keys = [
545
            (kind, file_id, list(versions))
546
            for (kind, file_id, versions) in item_keys]
547
548
        if repo.supports_rich_root():
549
            # Check for the root versioned file in the item_keys, then remove
550
            # it from streamed_names so we can compare that with
551
            # expected_record_names.
552
            # Note that the file keys can be in any order, so this test is
553
            # written to allow that.
554
            inv = repo.get_inventory('rev_id')
555
            root_item_key = ('file', inv.root.file_id, ['rev_id'])
556
            self.assertTrue(root_item_key in item_keys)
557
            item_keys.remove(root_item_key)
558
559
        self.assertEqual(expected_item_keys, item_keys)
560
2850.4.1 by Andrew Bennetts
Add smoketest for repo.get_graph, and fix bug in RemoteRepository.get_graph that it reveals.
561
    def test_get_graph(self):
562
        """Bare-bones smoketest that all repositories implement get_graph."""
563
        repo = self.make_repository('repo')
2592.3.214 by Robert Collins
Merge bzr.dev.
564
        repo.lock_read()
565
        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.
566
        repo.get_graph()
567
3146.1.1 by Aaron Bentley
Fix bad ghost handling in KnitParentsProvider
568
    def test_graph_ghost_handling(self):
569
        tree = self.make_branch_and_tree('here')
570
        tree.lock_write()
571
        self.addCleanup(tree.unlock)
572
        tree.commit('initial commit', rev_id='rev1')
573
        tree.add_parent_tree_id('ghost')
574
        tree.commit('commit-with-ghost', rev_id='rev2')
575
        graph = tree.branch.repository.get_graph()
576
        parents = graph.get_parent_map(['ghost', 'rev2'])
577
        self.assertTrue('ghost' not in parents)
3146.1.2 by Aaron Bentley
ParentsProviders now provide tuples of parents, never lists
578
        self.assertEqual(parents['rev2'], ('rev1', 'ghost'))
579
580
    def test_parent_map_type(self):
581
        tree = self.make_branch_and_tree('here')
582
        tree.lock_write()
583
        self.addCleanup(tree.unlock)
584
        tree.commit('initial commit', rev_id='rev1')
585
        tree.commit('next commit', rev_id='rev2')
586
        graph = tree.branch.repository.get_graph()
587
        parents = graph.get_parent_map([NULL_REVISION, 'rev1', 'rev2'])
588
        for value in parents.values():
589
            self.assertIsInstance(value, tuple)
3146.1.1 by Aaron Bentley
Fix bad ghost handling in KnitParentsProvider
590
2819.2.4 by Andrew Bennetts
Add a 'revision_graph_can_have_wrong_parents' method to repository.
591
    def test_implements_revision_graph_can_have_wrong_parents(self):
592
        """All repositories should implement
593
        revision_graph_can_have_wrong_parents, so that check and reconcile can
594
        work correctly.
595
        """
596
        repo = self.make_repository('.')
597
        # This should work, not raise NotImplementedError:
2592.3.214 by Robert Collins
Merge bzr.dev.
598
        if not repo.revision_graph_can_have_wrong_parents():
599
            return
600
        repo.lock_read()
601
        self.addCleanup(repo.unlock)
602
        # This repo must also implement
603
        # _find_inconsistent_revision_parents and
604
        # _check_for_inconsistent_revision_parents.  So calling these
605
        # should not raise NotImplementedError.
606
        list(repo._find_inconsistent_revision_parents())
607
        repo._check_for_inconsistent_revision_parents()
2819.2.4 by Andrew Bennetts
Add a 'revision_graph_can_have_wrong_parents' method to repository.
608
2996.2.4 by Aaron Bentley
Rename function to add_signature_text
609
    def test_add_signature_text(self):
2996.2.3 by Aaron Bentley
Add tests for install_revisions and add_signature
610
        repo = self.make_repository('repo')
611
        repo.lock_write()
612
        self.addCleanup(repo.unlock)
613
        self.addCleanup(repo.commit_write_group)
614
        repo.start_write_group()
615
        inv = Inventory(revision_id='A')
616
        inv.root.revision = 'A'
617
        repo.add_inventory('A', inv, [])
618
        repo.add_revision('A', Revision('A', committer='A', timestamp=0,
619
                          inventory_sha1='', timezone=0, message='A'))
2996.2.4 by Aaron Bentley
Rename function to add_signature_text
620
        repo.add_signature_text('A', 'This might be a signature')
2996.2.3 by Aaron Bentley
Add tests for install_revisions and add_signature
621
        self.assertEqual('This might be a signature',
622
                         repo.get_signature_text('A'))
623
3305.1.1 by Jelmer Vernooij
Make sure that specifying the inv= argument to add_revision() sets the
624
    def test_add_revision_inventory_sha1(self):
625
        repo = self.make_repository('repo')
626
        inv = Inventory(revision_id='A')
627
        inv.root.revision = 'A'
628
        inv.root.file_id = 'fixed-root'
629
        repo.lock_write()
630
        repo.start_write_group()
631
        repo.add_revision('A', Revision('A', committer='B', timestamp=0,
632
                          timezone=0, message='C'), inv=inv)
633
        repo.commit_write_group()
634
        repo.unlock()
635
        repo.lock_read()
636
        self.assertEquals(osutils.sha_string(
637
            repo._serializer.write_inventory_to_string(inv)),
638
            repo.get_revision('A').inventory_sha1)
639
        repo.unlock()
640
2996.2.3 by Aaron Bentley
Add tests for install_revisions and add_signature
641
    def test_install_revisions(self):
642
        wt = self.make_branch_and_tree('source')
643
        wt.commit('A', allow_pointless=True, rev_id='A')
644
        repo = wt.branch.repository
645
        repo.lock_write()
646
        repo.start_write_group()
647
        repo.sign_revision('A', bzrlib.gpg.LoopbackGPGStrategy(None))
648
        repo.commit_write_group()
649
        repo.unlock()
650
        repo.lock_read()
651
        self.addCleanup(repo.unlock)
652
        repo2 = self.make_repository('repo2')
653
        revision = repo.get_revision('A')
654
        tree = repo.revision_tree('A')
655
        signature = repo.get_signature_text('A')
656
        repo2.lock_write()
657
        self.addCleanup(repo2.unlock)
658
        repository.install_revisions(repo2, [(revision, tree, signature)])
659
        self.assertEqual(revision, repo2.get_revision('A'))
660
        self.assertEqual(signature, repo2.get_signature_text('A'))
1852.9.6 by Robert Collins
Merge the change from Tree.compare to Tree.changes_from.
661
3047.1.1 by Andrew Bennetts
Fix for bug 164626, add test that Repository.sprout preserves format.
662
    # XXX: this helper duplicated from tests.test_repository
663
    def make_remote_repository(self, path):
664
        """Make a RemoteRepository object backed by a real repository that will
665
        be created at the given path."""
666
        repo = self.make_repository(path)
667
        smart_server = server.SmartTCPServer_for_testing()
668
        smart_server.setUp(self.get_server())
669
        remote_transport = get_transport(smart_server.get_url()).clone(path)
670
        self.addCleanup(smart_server.tearDown)
671
        remote_bzrdir = bzrdir.BzrDir.open_from_transport(remote_transport)
672
        remote_repo = remote_bzrdir.open_repository()
673
        return remote_repo
674
3047.1.2 by Andrew Bennetts
Directly test that sprouting branches from a HPSS preserves the repository format.
675
    def test_sprout_from_hpss_preserves_format(self):
676
        """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.
677
        if self.repository_format == RepositoryFormat7():
678
            raise KnownFailure(
679
                "Cannot fetch weaves over smart protocol.")
680
        remote_repo = self.make_remote_repository('remote')
681
        local_bzrdir = self.make_bzrdir('local')
682
        try:
683
            local_repo = remote_repo.sprout(local_bzrdir)
684
        except errors.TransportNotPossible:
685
            raise TestNotApplicable(
686
                "Cannot lock_read old formats like AllInOne over HPSS.")
687
        remote_backing_repo = bzrdir.BzrDir.open(
688
            self.get_vfs_only_url('remote')).open_repository()
689
        self.assertEqual(remote_backing_repo._format, local_repo._format)
690
3047.1.2 by Andrew Bennetts
Directly test that sprouting branches from a HPSS preserves the repository format.
691
    def test_sprout_branch_from_hpss_preserves_repo_format(self):
692
        """branch.sprout from a smart server preserves the repository format.
693
        """
694
        weave_formats = [RepositoryFormat5(), RepositoryFormat6(),
695
                         RepositoryFormat7()]
696
        if self.repository_format in weave_formats:
697
            raise KnownFailure(
698
                "Cannot fetch weaves over smart protocol.")
699
        remote_repo = self.make_remote_repository('remote')
700
        remote_branch = remote_repo.bzrdir.create_branch()
701
        try:
702
            local_bzrdir = remote_branch.bzrdir.sprout('local')
703
        except errors.TransportNotPossible:
704
            raise TestNotApplicable(
705
                "Cannot lock_read old formats like AllInOne over HPSS.")
706
        local_repo = local_bzrdir.open_repository()
707
        remote_backing_repo = bzrdir.BzrDir.open(
708
            self.get_vfs_only_url('remote')).open_repository()
709
        self.assertEqual(remote_backing_repo._format, local_repo._format)
710
3089.2.1 by Andrew Bennetts
Implement RemoteRepository._make_parents_provider.
711
    def test__make_parents_provider(self):
712
        """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.
713
        an object with a get_parent_map method.
3089.2.1 by Andrew Bennetts
Implement RemoteRepository._make_parents_provider.
714
        """
715
        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.
716
        repo._make_parents_provider().get_parent_map
3089.2.1 by Andrew Bennetts
Implement RemoteRepository._make_parents_provider.
717
3140.1.2 by Aaron Bentley
Add ability to find branches inside repositories
718
    def make_repository_and_foo_bar(self, shared):
719
        made_control = self.make_bzrdir('repository')
720
        repo = made_control.create_repository(shared=shared)
721
        bzrdir.BzrDir.create_branch_convenience(self.get_url('repository/foo'),
722
                                                force_new_repo=False)
723
        bzrdir.BzrDir.create_branch_convenience(self.get_url('repository/bar'),
724
                                                force_new_repo=True)
3140.1.3 by Aaron Bentley
Add support for finding branches to BzrDir
725
        baz = self.make_bzrdir('repository/baz')
726
        qux = self.make_branch('repository/baz/qux')
3140.1.6 by Aaron Bentley
Add test that nested branches are returned
727
        quxx = self.make_branch('repository/baz/qux/quxx')
3140.1.2 by Aaron Bentley
Add ability to find branches inside repositories
728
        return repo
729
730
    def test_find_branches(self):
731
        repo = self.make_repository_and_foo_bar(shared=False)
732
        branches = repo.find_branches()
733
        self.assertContainsRe(branches[-1].base, 'repository/foo/$')
3140.1.6 by Aaron Bentley
Add test that nested branches are returned
734
        self.assertContainsRe(branches[-3].base, 'repository/baz/qux/$')
735
        self.assertContainsRe(branches[-2].base, 'repository/baz/qux/quxx/$')
3140.1.2 by Aaron Bentley
Add ability to find branches inside repositories
736
        # in some formats, creating a repo creates a branch
3140.1.6 by Aaron Bentley
Add test that nested branches are returned
737
        if len(branches) == 6:
738
            self.assertContainsRe(branches[-4].base, 'repository/baz/$')
739
            self.assertContainsRe(branches[-5].base, 'repository/bar/$')
740
            self.assertContainsRe(branches[-6].base, 'repository/$')
741
        else:
742
            self.assertEqual(4, len(branches))
3140.1.3 by Aaron Bentley
Add support for finding branches to BzrDir
743
            self.assertContainsRe(branches[-4].base, 'repository/bar/$')
3140.1.2 by Aaron Bentley
Add ability to find branches inside repositories
744
745
    def test_find_branches_using(self):
746
        try:
747
            repo = self.make_repository_and_foo_bar(shared=True)
748
        except errors.IncompatibleFormat:
749
            raise TestNotApplicable
750
        branches = repo.find_branches(using=True)
751
        self.assertContainsRe(branches[-1].base, 'repository/foo/$')
752
        # in some formats, creating a repo creates a branch
753
        if len(branches) == 2:
754
            self.assertContainsRe(branches[-2].base, 'repository/$')
755
        else:
756
            self.assertEqual(1, len(branches))
757
3140.1.9 by Aaron Bentley
Optimize find_branches for standalone repositories
758
    def test_find_branches_using_standalone(self):
759
        branch = self.make_branch('branch')
760
        contained = self.make_branch('branch/contained')
761
        branches = branch.repository.find_branches(using=True)
762
        self.assertEqual([branch.base], [b.base for b in branches])
763
        branches = branch.repository.find_branches(using=False)
764
        self.assertEqual([branch.base, contained.base],
765
                         [b.base for b in branches])
766
767
    def test_find_branches_using_empty_standalone_repo(self):
768
        repo = self.make_repository('repo')
769
        self.assertFalse(repo.is_shared())
770
        try:
771
            repo.bzrdir.open_branch()
772
        except errors.NotBranchError:
773
            self.assertEqual([], repo.find_branches(using=True))
774
        else:
775
            self.assertEqual([repo.bzrdir.root_transport.base],
776
                             [b.base for b in repo.find_branches(using=True)])
777
3349.1.1 by Aaron Bentley
Enable setting and getting make_working_trees for all repositories
778
    def test_set_get_make_working_trees_true(self):
779
        repo = self.make_repository('repo')
3349.1.2 by Aaron Bentley
Change ValueError to RepositoryUpgradeRequired
780
        try:
781
            repo.set_make_working_trees(True)
782
        except errors.RepositoryUpgradeRequired, e:
783
            raise TestNotApplicable('Format does not support this flag.')
3349.1.1 by Aaron Bentley
Enable setting and getting make_working_trees for all repositories
784
        self.assertTrue(repo.make_working_trees())
785
786
    def test_set_get_make_working_trees_false(self):
787
        repo = self.make_repository('repo')
788
        try:
789
            repo.set_make_working_trees(False)
3349.1.2 by Aaron Bentley
Change ValueError to RepositoryUpgradeRequired
790
        except errors.RepositoryUpgradeRequired, e:
791
            raise TestNotApplicable('Format does not support this flag.')
792
        self.assertFalse(repo.make_working_trees())
3349.1.1 by Aaron Bentley
Enable setting and getting make_working_trees for all repositories
793
3047.1.1 by Andrew Bennetts
Fix for bug 164626, add test that Repository.sprout preserves format.
794
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
795
class TestRepositoryLocking(TestCaseWithRepository):
796
797
    def test_leave_lock_in_place(self):
798
        repo = self.make_repository('r')
799
        # Lock the repository, then use leave_lock_in_place so that when we
800
        # 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.
801
        token = repo.lock_write()
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
802
        try:
2018.5.76 by Andrew Bennetts
Testing that repository.{dont_,}leave_lock_in_place raises NotImplementedError if lock_write returns None.
803
            if token is None:
804
                # This test does not apply, because this repository refuses lock
805
                # tokens.
806
                self.assertRaises(NotImplementedError, repo.leave_lock_in_place)
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
807
                return
2018.5.76 by Andrew Bennetts
Testing that repository.{dont_,}leave_lock_in_place raises NotImplementedError if lock_write returns None.
808
            repo.leave_lock_in_place()
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
809
        finally:
810
            repo.unlock()
811
        # We should be unable to relock the repo.
812
        self.assertRaises(errors.LockContention, repo.lock_write)
813
814
    def test_dont_leave_lock_in_place(self):
815
        repo = self.make_repository('r')
816
        # Create a lock on disk.
817
        token = repo.lock_write()
818
        try:
819
            if token is None:
820
                # This test does not apply, because this repository refuses lock
821
                # tokens.
2018.5.76 by Andrew Bennetts
Testing that repository.{dont_,}leave_lock_in_place raises NotImplementedError if lock_write returns None.
822
                self.assertRaises(NotImplementedError,
823
                                  repo.dont_leave_lock_in_place)
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
824
                return
825
            try:
826
                repo.leave_lock_in_place()
827
            except NotImplementedError:
828
                # This repository doesn't support this API.
829
                return
830
        finally:
831
            repo.unlock()
832
        # Reacquire the lock (with a different repository object) by using the
833
        # token.
834
        new_repo = repo.bzrdir.open_repository()
835
        new_repo.lock_write(token=token)
836
        # Call dont_leave_lock_in_place, so that the lock will be released by
837
        # this instance, even though the lock wasn't originally acquired by it.
838
        new_repo.dont_leave_lock_in_place()
839
        new_repo.unlock()
840
        # Now the repository is unlocked.  Test this by locking it (without a
841
        # token).
842
        repo.lock_write()
843
        repo.unlock()
844
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
845
    def test_lock_read_then_unlock(self):
846
        # Calling lock_read then unlocking should work without errors.
847
        repo = self.make_repository('r')
848
        repo.lock_read()
849
        repo.unlock()
850
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
851
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
852
class TestCaseWithComplexRepository(TestCaseWithRepository):
853
854
    def setUp(self):
855
        super(TestCaseWithComplexRepository, self).setUp()
856
        tree_a = self.make_branch_and_tree('a')
857
        self.bzrdir = tree_a.branch.bzrdir
858
        # 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.
859
        # 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.
860
        tree_a.lock_write()
861
        try:
862
            tree_a.branch.repository.start_write_group()
863
            inv_file = tree_a.branch.repository.get_inventory_weave()
864
            try:
865
                inv_file.add_lines('orphan', [], [])
866
            except:
867
                tree_a.branch.repository.commit_write_group()
868
                raise
869
            else:
870
                tree_a.branch.repository.abort_write_group()
871
        finally:
872
            tree_a.unlock()
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
873
        # add a real revision 'rev1'
874
        tree_a.commit('rev1', rev_id='rev1', allow_pointless=True)
875
        # add a real revision 'rev2' based on rev1
876
        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.
877
        # 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.
878
        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.
879
        tree_a.commit('rev3', rev_id='rev3', allow_pointless=True)
880
        # 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.
881
        tree_a.add_parent_tree_id('ghost1')
882
        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.
883
        tree_a.commit('rev4', rev_id='rev4', allow_pointless=True)
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
884
1756.3.20 by Aaron Bentley
Tests for get_revision_deltas and revisions_trees
885
    def test_revision_trees(self):
886
        revision_ids = ['rev1', 'rev2', 'rev3', 'rev4']
887
        repository = self.bzrdir.open_repository()
2592.3.214 by Robert Collins
Merge bzr.dev.
888
        repository.lock_read()
889
        self.addCleanup(repository.unlock)
1756.3.20 by Aaron Bentley
Tests for get_revision_deltas and revisions_trees
890
        trees1 = list(repository.revision_trees(revision_ids))
891
        trees2 = [repository.revision_tree(t) for t in revision_ids]
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
892
        self.assertEqual(len(trees1), len(trees2))
1756.3.20 by Aaron Bentley
Tests for get_revision_deltas and revisions_trees
893
        for tree1, tree2 in zip(trees1, trees2):
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
894
            self.assertFalse(tree2.changes_from(tree1).has_changed())
1756.3.20 by Aaron Bentley
Tests for get_revision_deltas and revisions_trees
895
1756.3.22 by Aaron Bentley
Tweaks from review
896
    def test_get_deltas_for_revisions(self):
1756.3.20 by Aaron Bentley
Tests for get_revision_deltas and revisions_trees
897
        repository = self.bzrdir.open_repository()
2592.3.214 by Robert Collins
Merge bzr.dev.
898
        repository.lock_read()
899
        self.addCleanup(repository.unlock)
1756.3.20 by Aaron Bentley
Tests for get_revision_deltas and revisions_trees
900
        revisions = [repository.get_revision(r) for r in 
901
                     ['rev1', 'rev2', 'rev3', 'rev4']]
1756.3.22 by Aaron Bentley
Tweaks from review
902
        deltas1 = list(repository.get_deltas_for_revisions(revisions))
1756.3.20 by Aaron Bentley
Tests for get_revision_deltas and revisions_trees
903
        deltas2 = [repository.get_revision_delta(r.revision_id) for r in
904
                   revisions]
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
905
        self.assertEqual(deltas1, deltas2)
1756.3.20 by Aaron Bentley
Tests for get_revision_deltas and revisions_trees
906
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
907
    def test_all_revision_ids(self):
908
        # 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.
909
        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.
910
                         self.bzrdir.open_repository().all_revision_ids())
911
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
912
    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.
913
        # get_ancestry(revision that is in some data but not fully installed
914
        # -> NoSuchRevision
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
915
        self.assertRaises(errors.NoSuchRevision,
916
                          self.bzrdir.open_repository().get_ancestry, 'orphan')
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
917
2530.1.1 by Aaron Bentley
Make topological sorting optional for get_ancestry
918
    def test_get_unsorted_ancestry(self):
919
        repo = self.bzrdir.open_repository()
920
        self.assertEqual(set(repo.get_ancestry('rev3')),
921
                         set(repo.get_ancestry('rev3', topo_sorted=False)))
922
2229.2.1 by Aaron Bentley
Reject reserved ids in versiondfile, tree, branch and repository
923
    def test_reserved_id(self):
924
        repo = self.make_repository('repository')
2592.3.61 by Robert Collins
Remove inventory.kndx.
925
        repo.lock_write()
926
        repo.start_write_group()
927
        try:
928
            self.assertRaises(errors.ReservedId, repo.add_inventory, 'reserved:',
929
                              None, None)
930
            self.assertRaises(errors.ReservedId, repo.add_revision, 'reserved:',
931
                              None)
932
        finally:
933
            repo.abort_write_group()
934
            repo.unlock()
2229.2.3 by Aaron Bentley
change reserved_id to is_reserved_id, add check_not_reserved for DRY
935
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
936
937
class TestCaseWithCorruptRepository(TestCaseWithRepository):
938
939
    def setUp(self):
940
        super(TestCaseWithCorruptRepository, self).setUp()
941
        # a inventory with no parents and the revision has parents..
942
        # i.e. a ghost.
943
        repo = self.make_repository('inventory_with_unnecessary_ghost')
2592.3.38 by Robert Collins
All experimental format tests passing again.
944
        repo.lock_write()
945
        repo.start_write_group()
1910.2.23 by Aaron Bentley
Fix up test cases that manually construct inventories
946
        inv = Inventory(revision_id = 'ghost')
947
        inv.root.revision = 'ghost'
1907.1.1 by Aaron Bentley
Unshelved all changes except those related to removing RootEntry
948
        sha1 = repo.add_inventory('ghost', inv, [])
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
949
        rev = bzrlib.revision.Revision(timestamp=0,
950
                                       timezone=None,
951
                                       committer="Foo Bar <foo@example.com>",
952
                                       message="Message",
953
                                       inventory_sha1=sha1,
954
                                       revision_id='ghost')
955
        rev.parent_ids = ['the_ghost']
956
        repo.add_revision('ghost', rev)
957
         
1910.2.23 by Aaron Bentley
Fix up test cases that manually construct inventories
958
        inv = Inventory(revision_id = 'the_ghost')
959
        inv.root.revision = 'the_ghost'
1907.1.1 by Aaron Bentley
Unshelved all changes except those related to removing RootEntry
960
        sha1 = repo.add_inventory('the_ghost', inv, [])
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
961
        rev = bzrlib.revision.Revision(timestamp=0,
962
                                       timezone=None,
963
                                       committer="Foo Bar <foo@example.com>",
964
                                       message="Message",
965
                                       inventory_sha1=sha1,
966
                                       revision_id='the_ghost')
967
        rev.parent_ids = []
968
        repo.add_revision('the_ghost', rev)
969
        # check its setup usefully
970
        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.
971
        self.assertEqual(['ghost'], inv_weave.get_ancestry(['ghost']))
2592.3.38 by Robert Collins
All experimental format tests passing again.
972
        repo.commit_write_group()
973
        repo.unlock()
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
974
1594.2.10 by Robert Collins
Teach knit fetching and branching to only duplicate relevant data avoiding unnecessary reconciles.
975
    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.
976
        repo_url = self.get_url('inventory_with_unnecessary_ghost')
977
        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.
978
        reported_wrong = False
979
        try:
980
            if repo.get_ancestry('ghost') != [None, 'the_ghost', 'ghost']:
981
                reported_wrong = True
982
        except errors.CorruptRepository:
983
            # caught the bad data:
984
            return
985
        if not reported_wrong:
986
            return
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
987
        self.assertRaises(errors.CorruptRepository, repo.get_revision, 'ghost')
988
1594.2.3 by Robert Collins
bugfix revision.MultipleRevisionSources.get_revision_graph to integrate ghosts between sources. [slow on weaves, fast on knits.
989
    def test_corrupt_revision_get_revision_reconcile(self):
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
990
        repo_url = self.get_url('inventory_with_unnecessary_ghost')
991
        repo = repository.Repository.open(repo_url)
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
992
        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.
993
994
2018.5.29 by Robert Collins
Dont run the vfat repository test on RemoteRepositories as there is no point.
995
# FIXME: document why this is a TestCaseWithTransport rather than a
996
#        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.
997
class TestEscaping(TestCaseWithTransport):
998
    """Test that repositories can be stored correctly on VFAT transports.
999
    
1000
    Makes sure we have proper escaping of invalid characters, etc.
1001
1002
    It'd be better to test all operations on the FakeVFATTransportDecorator,
1003
    but working trees go straight to the os not through the Transport layer.
1004
    Therefore we build some history first in the regular way and then 
1005
    check it's safe to access for vfat.
1006
    """
1007
1008
    def test_on_vfat(self):
2018.5.29 by Robert Collins
Dont run the vfat repository test on RemoteRepositories as there is no point.
1009
        # dont bother with remote repository testing, because this test is
1010
        # about local disk layout/support.
1011
        from bzrlib.remote import RemoteRepositoryFormat
1012
        if isinstance(self.repository_format, RemoteRepositoryFormat):
1013
            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.
1014
        FOO_ID = 'foo<:>ID'
2018.5.29 by Robert Collins
Dont run the vfat repository test on RemoteRepositories as there is no point.
1015
        REV_ID = 'revid-1' 
1016
        # this makes a default format repository always, which is wrong: 
1017
        # it should be a TestCaseWithRepository in order to get the 
1018
        # 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.
1019
        wt = self.make_branch_and_tree('repo')
2052.2.1 by Alexander Belchenko
test_on_vfat win32 fix: use binary line-endings
1020
        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.
1021
        # add file with id containing wierd characters
1022
        wt.add(['foo'], [FOO_ID])
1023
        wt.commit('this is my new commit', rev_id=REV_ID)
1024
        # now access over vfat; should be safe
1025
        branch = bzrdir.BzrDir.open('vfat+' + self.get_url('repo')).open_branch()
1026
        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.
1027
        revtree.lock_read()
1028
        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.
1029
        contents = revtree.get_file_text(FOO_ID)
1030
        self.assertEqual(contents, 'contents of repo/foo\n')
2520.4.54 by Aaron Bentley
Hang a create_bundle method off repository
1031
1032
    def test_create_bundle(self):
1033
        wt = self.make_branch_and_tree('repo')
1034
        self.build_tree(['repo/file1'])
1035
        wt.add('file1')
1036
        wt.commit('file1', rev_id='rev1')
1037
        fileobj = StringIO()
1038
        wt.branch.repository.create_bundle('rev1', NULL_REVISION, fileobj)