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