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