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