/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1
# Copyright (C) 2006-2012, 2016 Canonical Ltd
1685.1.63 by Martin Pool
Small Transport fixups
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.
1685.1.63 by Martin Pool
Small Transport fixups
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.
1685.1.63 by Martin Pool
Small Transport fixups
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
16
17
"""Tests for the Repository facility that are not interface tests.
18
3689.1.4 by John Arbash Meinel
Doc strings that reference repository_implementations
19
For interface tests see tests/per_repository/*.py.
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
20
21
For concrete class tests see this file, and for storage formats tests
22
also see this file.
23
"""
24
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
25
from stat import S_ISDIR
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
26
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
27
import breezy
28
from breezy.errors import (
5651.3.1 by Jelmer Vernooij
Add RepositoryFormatRegistry.
29
    UnknownFormatError,
30
    )
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
31
from breezy import (
4360.4.3 by John Arbash Meinel
Introduce a KnitPackStreamSource which is used when
32
    tests,
5609.9.1 by Martin
Blindly change all users of get_transport to address the function via the transport module
33
    transport,
6670.4.1 by Jelmer Vernooij
Update imports.
34
    )
35
from breezy.bzr import (
36
    bzrdir,
37
    btree_index,
38
    inventory,
39
    repository as bzrrepository,
40
    versionedfile,
41
    vf_repository,
6341.1.4 by Jelmer Vernooij
Move more functionality to vf_search.
42
    vf_search,
4360.4.3 by John Arbash Meinel
Introduce a KnitPackStreamSource which is used when
43
    )
6670.4.1 by Jelmer Vernooij
Update imports.
44
from breezy.bzr.btree_index import BTreeBuilder, BTreeGraphIndex
45
from breezy.bzr.index import GraphIndex
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
46
from breezy.repository import RepositoryFormat
47
from breezy.tests import (
2670.3.5 by Andrew Bennetts
Remove get_stream_as_bytes from KnitVersionedFile's API, make it a function in knitrepo.py instead.
48
    TestCase,
49
    TestCaseWithTransport,
50
    )
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
51
from breezy import (
6472.2.1 by Jelmer Vernooij
Use bzrdir.controldir for generic access to control directories.
52
    controldir,
2535.3.41 by Andrew Bennetts
Add tests for InterRemoteToOther.is_compatible.
53
    errors,
2929.3.5 by Vincent Ladeuil
New files, same warnings, same fixes.
54
    osutils,
2241.1.1 by Martin Pool
Change RepositoryFormat to use a Registry rather than ad-hoc dictionary
55
    repository,
2535.3.57 by Andrew Bennetts
Perform some sanity checking of data streams rather than blindly inserting them into our repository.
56
    revision as _mod_revision,
2241.1.1 by Martin Pool
Change RepositoryFormat to use a Registry rather than ad-hoc dictionary
57
    upgrade,
58
    workingtree,
59
    )
6670.4.5 by Jelmer Vernooij
Move breezy.repofmt contents to breezy.bzr.
60
from breezy.bzr import (
3735.42.5 by John Arbash Meinel
Change the tests so we now just use a direct test that _get_source is
61
    groupcompress_repo,
62
    knitrepo,
5757.2.2 by Jelmer Vernooij
Fix imports.
63
    knitpack_repo,
3735.42.5 by John Arbash Meinel
Change the tests so we now just use a direct test that _get_source is
64
    pack_repo,
65
    )
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
66
67
68
class TestDefaultFormat(TestCase):
69
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
70
    def test_get_set_default_format(self):
6472.2.1 by Jelmer Vernooij
Use bzrdir.controldir for generic access to control directories.
71
        old_default = controldir.format_registry.get('default')
2204.5.3 by Aaron Bentley
zap old repository default handling
72
        private_default = old_default().repository_format.__class__
5651.3.2 by Jelmer Vernooij
Fix deprecation warnings in test suite.
73
        old_format = repository.format_registry.get_default()
1910.2.33 by Aaron Bentley
Fix default format test
74
        self.assertTrue(isinstance(old_format, private_default))
7143.15.2 by Jelmer Vernooij
Run autopep8.
75
2204.5.3 by Aaron Bentley
zap old repository default handling
76
        def make_sample_bzrdir():
77
            my_bzrdir = bzrdir.BzrDirMetaFormat1()
78
            my_bzrdir.repository_format = SampleRepositoryFormat()
79
            return my_bzrdir
6472.2.1 by Jelmer Vernooij
Use bzrdir.controldir for generic access to control directories.
80
        controldir.format_registry.remove('default')
81
        controldir.format_registry.register('sample', make_sample_bzrdir, '')
82
        controldir.format_registry.set_default('sample')
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
83
        # creating a repository should now create an instrumented dir.
84
        try:
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
85
            # the default branch format is used by the meta dir format
86
            # which is not the default bzrdir format at this point
1685.1.63 by Martin Pool
Small Transport fixups
87
            dir = bzrdir.BzrDirMetaFormat1().initialize('memory:///')
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
88
            result = dir.create_repository()
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
89
            self.assertEqual(result, 'A bzr repository dir')
2241.1.1 by Martin Pool
Change RepositoryFormat to use a Registry rather than ad-hoc dictionary
90
        finally:
6472.2.1 by Jelmer Vernooij
Use bzrdir.controldir for generic access to control directories.
91
            controldir.format_registry.remove('default')
92
            controldir.format_registry.remove('sample')
93
            controldir.format_registry.register('default', old_default, '')
5651.3.2 by Jelmer Vernooij
Fix deprecation warnings in test suite.
94
        self.assertIsInstance(repository.format_registry.get_default(),
2204.5.3 by Aaron Bentley
zap old repository default handling
95
                              old_format.__class__)
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
96
97
6653.2.1 by Jelmer Vernooij
Move bzr-specific repository code out of breezy.bzrrepository.
98
class SampleRepositoryFormat(bzrrepository.RepositoryFormatMetaDir):
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
99
    """A sample format
100
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
101
    this format is initializable, unsupported to aid in testing the
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
102
    open and open(unsupported=True) routines.
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
103
    """
104
6349.2.6 by Jelmer Vernooij
Add test for RepositoryFormatMetaDir.from_string.
105
    @classmethod
106
    def get_format_string(cls):
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
107
        """See RepositoryFormat.get_format_string()."""
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
108
        return b"Sample .bzr repository format."
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
109
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
110
    def initialize(self, a_controldir, shared=False):
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
111
        """Initialize a repository in a BzrDir"""
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
112
        t = a_controldir.get_repository_transport(self)
1955.3.13 by John Arbash Meinel
Run the full test suite, and fix up any deprecation warnings.
113
        t.put_bytes('format', self.get_format_string())
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
114
        return 'A bzr repository dir'
115
116
    def is_supported(self):
117
        return False
118
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
119
    def open(self, a_controldir, _found=False):
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
120
        return "opened repository."
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
121
122
5651.3.5 by Jelmer Vernooij
add tests for 'extra' repository formats.
123
class SampleExtraRepositoryFormat(repository.RepositoryFormat):
124
    """A sample format that can not be used in a metadir
125
126
    """
127
128
    def get_format_string(self):
129
        raise NotImplementedError
130
131
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
132
class TestRepositoryFormat(TestCaseWithTransport):
133
    """Tests for the Repository format detection used by the bzr meta dir facility.BzrBranchFormat facility."""
134
135
    def test_find_format(self):
136
        # is the right format object found for a repository?
137
        # create a branch with a few known format objects.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
138
        # this is not quite the same as
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
139
        self.build_tree(["foo/", "bar/"])
7143.15.2 by Jelmer Vernooij
Run autopep8.
140
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
141
        def check_format(format, url):
6746.2.1 by Jelmer Vernooij
Rename matchingbzrdir to matchingcontroldir.
142
            dir = format._matchingcontroldir.initialize(url)
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
143
            format.initialize(dir)
7143.15.2 by Jelmer Vernooij
Run autopep8.
144
            found_format = bzrrepository.RepositoryFormatMetaDir.find_format(
145
                dir)
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
146
            self.assertIsInstance(found_format, format.__class__)
5582.10.54 by Jelmer Vernooij
Use default format rather than RepositoryFormat7.
147
        check_format(repository.format_registry.get_default(), "bar")
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
148
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
149
    def test_find_format_no_repository(self):
150
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
151
        self.assertRaises(errors.NoRepositoryPresent,
6653.2.2 by Jelmer Vernooij
Fix imports.
152
                          bzrrepository.RepositoryFormatMetaDir.find_format,
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
153
                          dir)
154
6349.2.6 by Jelmer Vernooij
Add test for RepositoryFormatMetaDir.from_string.
155
    def test_from_string(self):
156
        self.assertIsInstance(
157
            SampleRepositoryFormat.from_string(
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
158
                b"Sample .bzr repository format."),
6349.2.6 by Jelmer Vernooij
Add test for RepositoryFormatMetaDir.from_string.
159
            SampleRepositoryFormat)
6213.1.54 by Jelmer Vernooij
Fix tests.
160
        self.assertRaises(AssertionError,
7143.15.2 by Jelmer Vernooij
Run autopep8.
161
                          SampleRepositoryFormat.from_string,
162
                          b"Different .bzr repository format.")
6349.2.6 by Jelmer Vernooij
Add test for RepositoryFormatMetaDir.from_string.
163
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
164
    def test_find_format_unknown_format(self):
165
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
166
        SampleRepositoryFormat().initialize(dir)
167
        self.assertRaises(UnknownFormatError,
6653.2.2 by Jelmer Vernooij
Fix imports.
168
                          bzrrepository.RepositoryFormatMetaDir.find_format,
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
169
                          dir)
170
6213.1.16 by Jelmer Vernooij
Feature support in repository.
171
    def test_find_format_with_features(self):
172
        tree = self.make_branch_and_tree('.', format='2a')
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
173
        tree.branch.repository.update_feature_flags({b"name": b"necessity"})
7143.15.2 by Jelmer Vernooij
Run autopep8.
174
        found_format = bzrrepository.RepositoryFormatMetaDir.find_format(
175
            tree.controldir)
176
        self.assertIsInstance(
177
            found_format, bzrrepository.RepositoryFormatMetaDir)
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
178
        self.assertEqual(found_format.features.get(b"name"), b"necessity")
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
179
        self.assertRaises(
180
            bzrdir.MissingFeature, found_format.check_support_status, True)
181
        self.addCleanup(
182
            bzrrepository.RepositoryFormatMetaDir.unregister_feature, b"name")
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
183
        bzrrepository.RepositoryFormatMetaDir.register_feature(b"name")
6213.1.32 by Jelmer Vernooij
Fix check support status.
184
        found_format.check_support_status(True)
6213.1.16 by Jelmer Vernooij
Feature support in repository.
185
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
186
5651.3.1 by Jelmer Vernooij
Add RepositoryFormatRegistry.
187
class TestRepositoryFormatRegistry(TestCase):
188
189
    def setUp(self):
190
        super(TestRepositoryFormatRegistry, self).setUp()
191
        self.registry = repository.RepositoryFormatRegistry()
192
193
    def test_register_unregister_format(self):
194
        format = SampleRepositoryFormat()
195
        self.registry.register(format)
7143.15.2 by Jelmer Vernooij
Run autopep8.
196
        self.assertEqual(format, self.registry.get(
197
            b"Sample .bzr repository format."))
5651.3.1 by Jelmer Vernooij
Add RepositoryFormatRegistry.
198
        self.registry.remove(format)
7143.15.2 by Jelmer Vernooij
Run autopep8.
199
        self.assertRaises(KeyError, self.registry.get,
200
                          b"Sample .bzr repository format.")
5651.3.1 by Jelmer Vernooij
Add RepositoryFormatRegistry.
201
5651.3.2 by Jelmer Vernooij
Fix deprecation warnings in test suite.
202
    def test_get_all(self):
5651.3.1 by Jelmer Vernooij
Add RepositoryFormatRegistry.
203
        format = SampleRepositoryFormat()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
204
        self.assertEqual([], self.registry._get_all())
5651.3.1 by Jelmer Vernooij
Add RepositoryFormatRegistry.
205
        self.registry.register(format)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
206
        self.assertEqual([format], self.registry._get_all())
5651.3.5 by Jelmer Vernooij
add tests for 'extra' repository formats.
207
208
    def test_register_extra(self):
209
        format = SampleExtraRepositoryFormat()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
210
        self.assertEqual([], self.registry._get_all())
5651.3.5 by Jelmer Vernooij
add tests for 'extra' repository formats.
211
        self.registry.register_extra(format)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
212
        self.assertEqual([format], self.registry._get_all())
5651.3.5 by Jelmer Vernooij
add tests for 'extra' repository formats.
213
214
    def test_register_extra_lazy(self):
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
215
        self.assertEqual([], self.registry._get_all())
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
216
        self.registry.register_extra_lazy("breezy.tests.test_repository",
7143.15.2 by Jelmer Vernooij
Run autopep8.
217
                                          "SampleExtraRepositoryFormat")
5651.3.7 by Jelmer Vernooij
Fix tests.
218
        formats = self.registry._get_all()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
219
        self.assertEqual(1, len(formats))
5651.3.5 by Jelmer Vernooij
add tests for 'extra' repository formats.
220
        self.assertIsInstance(formats[0], SampleExtraRepositoryFormat)
5651.3.1 by Jelmer Vernooij
Add RepositoryFormatRegistry.
221
222
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
223
class TestFormatKnit1(TestCaseWithTransport):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
224
3565.3.1 by Robert Collins
* The generic fetch code now uses two attributes on Repository objects
225
    def test_attribute__fetch_order(self):
226
        """Knits need topological data insertion."""
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
227
        repo = self.make_repository(
228
            '.', format=controldir.format_registry.get('knit')())
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
229
        self.assertEqual('topological', repo._format._fetch_order)
3565.3.1 by Robert Collins
* The generic fetch code now uses two attributes on Repository objects
230
231
    def test_attribute__fetch_uses_deltas(self):
232
        """Knits reuse deltas."""
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
233
        repo = self.make_repository(
234
            '.', format=controldir.format_registry.get('knit')())
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
235
        self.assertEqual(True, repo._format._fetch_uses_deltas)
3565.3.1 by Robert Collins
* The generic fetch code now uses two attributes on Repository objects
236
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
237
    def test_disk_layout(self):
238
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
239
        repo = knitrepo.RepositoryFormatKnit1().initialize(control)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
240
        # in case of side effects of locking.
241
        repo.lock_write()
242
        repo.unlock()
243
        # we want:
244
        # format 'Bazaar-NG Knit Repository Format 1'
1553.5.62 by Martin Pool
Add tests that MetaDir repositories use LockDirs
245
        # lock: is a directory
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
246
        # inventory.weave == empty_weave
247
        # empty revision-store directory
248
        # empty weaves directory
249
        t = control.get_repository_transport(None)
6973.6.3 by Jelmer Vernooij
More fixes.
250
        with t.get('format') as f:
251
            self.assertEqualDiff(b'Bazaar-NG Knit Repository Format 1',
252
                                 f.read())
1553.5.57 by Martin Pool
[merge] sync from bzr.dev
253
        # XXX: no locks left when unlocked at the moment
254
        # self.assertEqualDiff('', t.get('lock').read())
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
255
        self.assertTrue(S_ISDIR(t.stat('knits').st_mode))
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
256
        self.check_knits(t)
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.
257
        # Check per-file knits.
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
258
        control.create_branch()
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.
259
        tree = control.create_workingtree()
6973.6.3 by Jelmer Vernooij
More fixes.
260
        tree.add(['foo'], [b'Nasty-IdC:'], ['file'])
261
        tree.put_file_bytes_non_atomic('foo', b'')
6855.4.1 by Jelmer Vernooij
Yet more bees.
262
        tree.commit('1st post', rev_id=b'foo')
7058.4.1 by Jelmer Vernooij
Fix another 40 tests.
263
        self.assertHasKnit(t, 'knits/e8/%254easty-%2549d%2543%253a',
7143.15.2 by Jelmer Vernooij
Run autopep8.
264
                           b'\nfoo fulltext 0 81  :')
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
265
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
266
    def assertHasKnit(self, t, knit_name, extra_content=b''):
1654.1.3 by Robert Collins
Refactor repository knit tests slightly to remove duplication - add a assertHasKnit method.
267
        """Assert that knit_name exists on t."""
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
268
        self.assertEqualDiff(b'# bzr knit index 8\n' + extra_content,
1654.1.3 by Robert Collins
Refactor repository knit tests slightly to remove duplication - add a assertHasKnit method.
269
                             t.get(knit_name + '.kndx').read())
270
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
271
    def check_knits(self, t):
272
        """check knit content for a repository."""
7058.4.1 by Jelmer Vernooij
Fix another 40 tests.
273
        self.assertHasKnit(t, 'inventory')
274
        self.assertHasKnit(t, 'revisions')
275
        self.assertHasKnit(t, 'signatures')
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
276
277
    def test_shared_disk_layout(self):
278
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
279
        knitrepo.RepositoryFormatKnit1().initialize(control, shared=True)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
280
        # we want:
281
        # format 'Bazaar-NG Knit Repository Format 1'
1553.5.62 by Martin Pool
Add tests that MetaDir repositories use LockDirs
282
        # lock: is a directory
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
283
        # inventory.weave == empty_weave
284
        # empty revision-store directory
285
        # empty weaves directory
286
        # a 'shared-storage' marker file.
287
        t = control.get_repository_transport(None)
7045.4.21 by Jelmer Vernooij
Fix some msgeditor tests.
288
        with t.get('format') as f:
289
            self.assertEqualDiff(b'Bazaar-NG Knit Repository Format 1',
290
                                 f.read())
1553.5.57 by Martin Pool
[merge] sync from bzr.dev
291
        # XXX: no locks left when unlocked at the moment
292
        # self.assertEqualDiff('', t.get('lock').read())
7045.4.21 by Jelmer Vernooij
Fix some msgeditor tests.
293
        self.assertEqualDiff(b'', t.get('shared-storage').read())
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
294
        self.assertTrue(S_ISDIR(t.stat('knits').st_mode))
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
295
        self.check_knits(t)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
296
297
    def test_shared_no_tree_disk_layout(self):
298
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
299
        repo = knitrepo.RepositoryFormatKnit1().initialize(
300
            control, shared=True)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
301
        repo.set_make_working_trees(False)
302
        # we want:
303
        # format 'Bazaar-NG Knit Repository Format 1'
304
        # lock ''
305
        # inventory.weave == empty_weave
306
        # empty revision-store directory
307
        # empty weaves directory
308
        # a 'shared-storage' marker file.
309
        t = control.get_repository_transport(None)
7045.4.21 by Jelmer Vernooij
Fix some msgeditor tests.
310
        with t.get('format') as f:
311
            self.assertEqualDiff(b'Bazaar-NG Knit Repository Format 1',
312
                                 f.read())
1553.5.57 by Martin Pool
[merge] sync from bzr.dev
313
        # XXX: no locks left when unlocked at the moment
314
        # self.assertEqualDiff('', t.get('lock').read())
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
315
        self.assertEqualDiff(b'', t.get('shared-storage').read())
316
        self.assertEqualDiff(b'', t.get('no-working-trees').read())
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
317
        repo.set_make_working_trees(True)
318
        self.assertFalse(t.has('no-working-trees'))
319
        self.assertTrue(S_ISDIR(t.stat('knits').st_mode))
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
320
        self.check_knits(t)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
321
2917.2.1 by John Arbash Meinel
Fix bug #152360. The xml5 serializer should be using
322
    def test_deserialise_sets_root_revision(self):
323
        """We must have a inventory.root.revision
324
325
        Old versions of the XML5 serializer did not set the revision_id for
326
        the whole inventory. So we grab the one from the expected text. Which
327
        is valid when the api is not being abused.
328
        """
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
329
        repo = self.make_repository(
330
            '.', format=controldir.format_registry.get('knit')())
6973.13.2 by Jelmer Vernooij
Fix some more tests.
331
        inv_xml = b'<inventory format="5">\n</inventory>\n'
332
        inv = repo._deserialise_inventory(b'test-rev-id', inv_xml)
333
        self.assertEqual(b'test-rev-id', inv.root.revision)
2917.2.1 by John Arbash Meinel
Fix bug #152360. The xml5 serializer should be using
334
335
    def test_deserialise_uses_global_revision_id(self):
336
        """If it is set, then we re-use the global revision id"""
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
337
        repo = self.make_repository(
338
            '.', format=controldir.format_registry.get('knit')())
6973.13.2 by Jelmer Vernooij
Fix some more tests.
339
        inv_xml = (b'<inventory format="5" revision_id="other-rev-id">\n'
340
                   b'</inventory>\n')
2917.2.1 by John Arbash Meinel
Fix bug #152360. The xml5 serializer should be using
341
        # Arguably, the deserialise_inventory should detect a mismatch, and
342
        # raise an error, rather than silently using one revision_id over the
343
        # other.
4988.3.3 by Jelmer Vernooij
rename Repository.deserialise_inventory to Repository._deserialise_inventory.
344
        self.assertRaises(AssertionError, repo._deserialise_inventory,
7143.15.2 by Jelmer Vernooij
Run autopep8.
345
                          b'test-rev-id', inv_xml)
6973.13.2 by Jelmer Vernooij
Fix some more tests.
346
        inv = repo._deserialise_inventory(b'other-rev-id', inv_xml)
347
        self.assertEqual(b'other-rev-id', inv.root.revision)
2917.2.1 by John Arbash Meinel
Fix bug #152360. The xml5 serializer should be using
348
3221.3.1 by Robert Collins
* Repository formats have a new supported-feature attribute
349
    def test_supports_external_lookups(self):
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
350
        repo = self.make_repository(
351
            '.', format=controldir.format_registry.get('knit')())
3221.3.1 by Robert Collins
* Repository formats have a new supported-feature attribute
352
        self.assertFalse(repo._format.supports_external_lookups)
353
2535.3.53 by Andrew Bennetts
Remove get_stream_as_bytes from KnitVersionedFile's API, make it a function in knitrepo.py instead.
354
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
355
class DummyRepository(object):
356
    """A dummy repository for testing."""
357
3452.2.11 by Andrew Bennetts
Merge thread.
358
    _format = None
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
359
    _serializer = None
360
361
    def supports_rich_root(self):
4606.4.1 by Robert Collins
Prepare test_repository's inter_repository tests for 2a.
362
        if self._format is not None:
363
            return self._format.rich_root_data
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
364
        return False
365
3709.5.10 by Andrew Bennetts
Fix test failure caused by missing attributes on DummyRepository.
366
    def get_graph(self):
367
        raise NotImplementedError
368
369
    def get_parent_map(self, revision_ids):
370
        raise NotImplementedError
371
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
372
373
class InterDummy(repository.InterRepository):
374
    """An inter-repository optimised code path for DummyRepository.
375
376
    This is for use during testing where we use DummyRepository as repositories
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
377
    so that none of the default regsitered inter-repository classes will
2818.4.2 by Robert Collins
Review feedback.
378
    MATCH.
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
379
    """
380
381
    @staticmethod
382
    def is_compatible(repo_source, repo_target):
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
383
        """InterDummy is compatible with DummyRepository."""
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
384
        return (isinstance(repo_source, DummyRepository) and
7143.15.2 by Jelmer Vernooij
Run autopep8.
385
                isinstance(repo_target, DummyRepository))
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
386
387
1534.1.27 by Robert Collins
Start InterRepository with InterRepository.get.
388
class TestInterRepository(TestCaseWithTransport):
389
390
    def test_get_default_inter_repository(self):
391
        # test that the InterRepository.get(repo_a, repo_b) probes
392
        # for a inter_repo class where is_compatible(repo_a, repo_b) returns
393
        # true and returns a default inter_repo otherwise.
394
        # This also tests that the default registered optimised interrepository
395
        # classes do not barf inappropriately when a surprising repository type
396
        # is handed to them.
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
397
        dummy_a = DummyRepository()
5815.4.19 by Jelmer Vernooij
Fix test failures.
398
        dummy_a._format = RepositoryFormat()
399
        dummy_a._format.supports_full_versioned_files = True
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
400
        dummy_b = DummyRepository()
5815.4.19 by Jelmer Vernooij
Fix test failures.
401
        dummy_b._format = RepositoryFormat()
402
        dummy_b._format.supports_full_versioned_files = True
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
403
        self.assertGetsDefaultInterRepository(dummy_a, dummy_b)
404
405
    def assertGetsDefaultInterRepository(self, repo_a, repo_b):
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
406
        """Asserts that InterRepository.get(repo_a, repo_b) -> the default.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
407
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
408
        The effective default is now InterSameDataRepository because there is
409
        no actual sane default in the presence of incompatible data models.
410
        """
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
411
        inter_repo = repository.InterRepository.get(repo_a, repo_b)
5815.4.19 by Jelmer Vernooij
Fix test failures.
412
        self.assertEqual(vf_repository.InterSameDataRepository,
1534.1.27 by Robert Collins
Start InterRepository with InterRepository.get.
413
                         inter_repo.__class__)
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
414
        self.assertEqual(repo_a, inter_repo.source)
415
        self.assertEqual(repo_b, inter_repo.target)
416
417
    def test_register_inter_repository_class(self):
418
        # test that a optimised code path provider - a
419
        # InterRepository subclass can be registered and unregistered
420
        # and that it is correctly selected when given a repository
421
        # pair that it returns true on for the is_compatible static method
422
        # check
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
423
        dummy_a = DummyRepository()
4606.4.1 by Robert Collins
Prepare test_repository's inter_repository tests for 2a.
424
        dummy_a._format = RepositoryFormat()
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
425
        dummy_b = DummyRepository()
4606.4.1 by Robert Collins
Prepare test_repository's inter_repository tests for 2a.
426
        dummy_b._format = RepositoryFormat()
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
427
        repo = self.make_repository('.')
428
        # hack dummies to look like repo somewhat.
429
        dummy_a._serializer = repo._serializer
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
430
        dummy_a._format.supports_tree_reference = (
431
            repo._format.supports_tree_reference)
4606.4.1 by Robert Collins
Prepare test_repository's inter_repository tests for 2a.
432
        dummy_a._format.rich_root_data = repo._format.rich_root_data
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
433
        dummy_a._format.supports_full_versioned_files = (
434
            repo._format.supports_full_versioned_files)
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
435
        dummy_b._serializer = repo._serializer
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
436
        dummy_b._format.supports_tree_reference = (
437
            repo._format.supports_tree_reference)
4606.4.1 by Robert Collins
Prepare test_repository's inter_repository tests for 2a.
438
        dummy_b._format.rich_root_data = repo._format.rich_root_data
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
439
        dummy_b._format.supports_full_versioned_files = (
440
            repo._format.supports_full_versioned_files)
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
441
        repository.InterRepository.register_optimiser(InterDummy)
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
442
        try:
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
443
            # we should get the default for something InterDummy returns False
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
444
            # to
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
445
            self.assertFalse(InterDummy.is_compatible(dummy_a, repo))
446
            self.assertGetsDefaultInterRepository(dummy_a, repo)
447
            # and we should get an InterDummy for a pair it 'likes'
448
            self.assertTrue(InterDummy.is_compatible(dummy_a, dummy_b))
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
449
            inter_repo = repository.InterRepository.get(dummy_a, dummy_b)
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
450
            self.assertEqual(InterDummy, inter_repo.__class__)
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
451
            self.assertEqual(dummy_a, inter_repo.source)
452
            self.assertEqual(dummy_b, inter_repo.target)
453
        finally:
2305.2.3 by Andrew Bennetts
Bring across test_repository improvements from the hpss branch to fix the last test failures.
454
            repository.InterRepository.unregister_optimiser(InterDummy)
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
455
        # now we should get the default InterRepository object again.
456
        self.assertGetsDefaultInterRepository(dummy_a, dummy_b)
1534.1.33 by Robert Collins
Move copy_content_into into InterRepository and InterWeaveRepo, and disable the default codepath test as we have optimised paths for all current combinations.
457
2241.1.17 by Martin Pool
Restore old InterWeave tests
458
5671.4.2 by Jelmer Vernooij
Use stub formats to test CopyConverter.
459
class TestRepositoryFormat1(knitrepo.RepositoryFormatKnit1):
460
6213.1.16 by Jelmer Vernooij
Feature support in repository.
461
    @classmethod
462
    def get_format_string(cls):
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
463
        return b"Test Format 1"
5671.4.2 by Jelmer Vernooij
Use stub formats to test CopyConverter.
464
465
466
class TestRepositoryFormat2(knitrepo.RepositoryFormatKnit1):
467
6213.1.16 by Jelmer Vernooij
Feature support in repository.
468
    @classmethod
469
    def get_format_string(cls):
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
470
        return b"Test Format 2"
5671.4.2 by Jelmer Vernooij
Use stub formats to test CopyConverter.
471
472
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.
473
class TestRepositoryConverter(TestCaseWithTransport):
474
475
    def test_convert_empty(self):
5671.4.2 by Jelmer Vernooij
Use stub formats to test CopyConverter.
476
        source_format = TestRepositoryFormat1()
477
        target_format = TestRepositoryFormat2()
478
        repository.format_registry.register(source_format)
479
        self.addCleanup(repository.format_registry.remove,
7143.15.2 by Jelmer Vernooij
Run autopep8.
480
                        source_format)
5671.4.2 by Jelmer Vernooij
Use stub formats to test CopyConverter.
481
        repository.format_registry.register(target_format)
482
        self.addCleanup(repository.format_registry.remove,
7143.15.2 by Jelmer Vernooij
Run autopep8.
483
                        target_format)
5609.9.4 by Vincent Ladeuil
Use self.get_transport instead of transport.get_transport where possible.
484
        t = self.get_transport()
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.
485
        t.mkdir('repository')
486
        repo_dir = bzrdir.BzrDirMetaFormat1().initialize('repository')
5671.4.2 by Jelmer Vernooij
Use stub formats to test CopyConverter.
487
        repo = TestRepositoryFormat1().initialize(repo_dir)
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.
488
        converter = repository.CopyConverter(target_format)
6861.4.1 by Jelmer Vernooij
Make progress bars context managers.
489
        with breezy.ui.ui_factory.nested_progress_bar() as pb:
1594.1.3 by Robert Collins
Fixup pb usage to use nested_progress_bar.
490
            converter.convert(repo, pb)
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.
491
        repo = repo_dir.open_repository()
492
        self.assertTrue(isinstance(target_format, repo._format.__class__))
1843.2.5 by Aaron Bentley
Add test of _unescape_xml
493
494
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
495
class TestRepositoryFormatKnit3(TestCaseWithTransport):
1910.2.13 by Aaron Bentley
Start work on converter
496
3565.3.1 by Robert Collins
* The generic fetch code now uses two attributes on Repository objects
497
    def test_attribute__fetch_order(self):
498
        """Knits need topological data insertion."""
499
        format = bzrdir.BzrDirMetaFormat1()
500
        format.repository_format = knitrepo.RepositoryFormatKnit3()
501
        repo = self.make_repository('.', format=format)
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
502
        self.assertEqual('topological', repo._format._fetch_order)
3565.3.1 by Robert Collins
* The generic fetch code now uses two attributes on Repository objects
503
504
    def test_attribute__fetch_uses_deltas(self):
505
        """Knits reuse deltas."""
506
        format = bzrdir.BzrDirMetaFormat1()
507
        format.repository_format = knitrepo.RepositoryFormatKnit3()
508
        repo = self.make_repository('.', format=format)
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
509
        self.assertEqual(True, repo._format._fetch_uses_deltas)
3565.3.1 by Robert Collins
* The generic fetch code now uses two attributes on Repository objects
510
1910.2.13 by Aaron Bentley
Start work on converter
511
    def test_convert(self):
512
        """Ensure the upgrade adds weaves for roots"""
1910.2.35 by Aaron Bentley
Better fix for convesion test
513
        format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
514
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1910.2.35 by Aaron Bentley
Better fix for convesion test
515
        tree = self.make_branch_and_tree('.', format)
6973.13.2 by Jelmer Vernooij
Fix some more tests.
516
        tree.commit("Dull commit", rev_id=b"dull")
6973.5.2 by Jelmer Vernooij
Add more bees.
517
        revision_tree = tree.branch.repository.revision_tree(b'dull')
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
518
        with revision_tree.lock_read():
7143.16.21 by Jelmer Vernooij
Fix regressions.
519
            self.assertRaises(
520
                errors.NoSuchFile, revision_tree.get_file_lines, u'')
1910.2.13 by Aaron Bentley
Start work on converter
521
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
522
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.13 by Aaron Bentley
Start work on converter
523
        upgrade.Convert('.', format)
1910.2.27 by Aaron Bentley
Fixed conversion test
524
        tree = workingtree.WorkingTree.open('.')
6973.5.2 by Jelmer Vernooij
Add more bees.
525
        revision_tree = tree.branch.repository.revision_tree(b'dull')
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
526
        with revision_tree.lock_read():
527
            revision_tree.get_file_lines(u'')
6855.4.1 by Jelmer Vernooij
Yet more bees.
528
        tree.commit("Another dull commit", rev_id=b'dull2')
6973.5.2 by Jelmer Vernooij
Add more bees.
529
        revision_tree = tree.branch.repository.revision_tree(b'dull2')
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.
530
        revision_tree.lock_read()
531
        self.addCleanup(revision_tree.unlock)
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
532
        self.assertEqual(b'dull', revision_tree.get_file_revision(u''))
2220.2.2 by Martin Pool
Add tag command and basic implementation
533
3221.3.1 by Robert Collins
* Repository formats have a new supported-feature attribute
534
    def test_supports_external_lookups(self):
535
        format = bzrdir.BzrDirMetaFormat1()
536
        format.repository_format = knitrepo.RepositoryFormatKnit3()
537
        repo = self.make_repository('.', format=format)
538
        self.assertFalse(repo._format.supports_external_lookups)
539
2535.3.57 by Andrew Bennetts
Perform some sanity checking of data streams rather than blindly inserting them into our repository.
540
4667.1.1 by John Arbash Meinel
Drop the Test2a test times from 5+s down to 1.4s
541
class Test2a(tests.TestCaseWithMemoryTransport):
4431.3.7 by Jonathan Lange
Cherrypick bzr.dev 4470, resolving conflicts.
542
5365.5.20 by John Arbash Meinel
Add some tests that check the leaf factory is correct.
543
    def test_chk_bytes_uses_custom_btree_parser(self):
544
        mt = self.make_branch_and_memory_tree('test', format='2a')
545
        mt.lock_write()
546
        self.addCleanup(mt.unlock)
6855.4.1 by Jelmer Vernooij
Yet more bees.
547
        mt.add([''], [b'root-id'])
5365.5.20 by John Arbash Meinel
Add some tests that check the leaf factory is correct.
548
        mt.commit('first')
549
        index = mt.branch.repository.chk_bytes._index._graph_index._indices[0]
550
        self.assertEqual(btree_index._gcchk_factory, index._leaf_factory)
551
        # It should also work if we re-open the repo
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
552
        repo = mt.branch.repository.controldir.open_repository()
5365.5.20 by John Arbash Meinel
Add some tests that check the leaf factory is correct.
553
        repo.lock_read()
554
        self.addCleanup(repo.unlock)
555
        index = repo.chk_bytes._index._graph_index._indices[0]
556
        self.assertEqual(btree_index._gcchk_factory, index._leaf_factory)
557
4634.20.1 by Robert Collins
Fix bug 402652 by recompressing all texts that are streamed - slightly slower at fetch, substantially faster and more compact at read.
558
    def test_fetch_combines_groups(self):
559
        builder = self.make_branch_builder('source', format='2a')
560
        builder.start_series()
6816.2.3 by Jelmer Vernooij
Port over last uses of build_snapshot.
561
        builder.build_snapshot(None, [
6855.4.1 by Jelmer Vernooij
Yet more bees.
562
            ('add', ('', b'root-id', 'directory', '')),
6883.22.11 by Jelmer Vernooij
merge trunk
563
            ('add', ('file', b'file-id', 'file', b'content\n'))],
6973.5.2 by Jelmer Vernooij
Add more bees.
564
            revision_id=b'1')
6883.22.11 by Jelmer Vernooij
merge trunk
565
        builder.build_snapshot([b'1'], [
566
            ('modify', ('file', b'content-2\n'))],
567
            revision_id=b'2')
568
        builder.finish_series()
569
        source = builder.get_branch()
570
        target = self.make_repository('target', format='2a')
571
        target.fetch(source.repository)
572
        target.lock_read()
573
        self.addCleanup(target.unlock)
574
        details = target.texts._index.get_build_details(
575
            [(b'file-id', b'1',), (b'file-id', b'2',)])
576
        file_1_details = details[(b'file-id', b'1')]
577
        file_2_details = details[(b'file-id', b'2')]
578
        # The index, and what to read off disk, should be the same for both
579
        # versions of the file.
580
        self.assertEqual(file_1_details[0][:3], file_2_details[0][:3])
581
582
    def test_fetch_combines_groups(self):
583
        builder = self.make_branch_builder('source', format='2a')
584
        builder.start_series()
585
        builder.build_snapshot(None, [
586
            ('add', ('', b'root-id', 'directory', '')),
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
587
            ('add', ('file', b'file-id', 'file', b'content\n'))],
6883.22.11 by Jelmer Vernooij
merge trunk
588
            revision_id=b'1')
589
        builder.build_snapshot([b'1'], [
590
            ('modify', ('file', b'content-2\n'))],
591
            revision_id=b'2')
592
        builder.finish_series()
593
        source = builder.get_branch()
594
        target = self.make_repository('target', format='2a')
595
        target.fetch(source.repository)
596
        target.lock_read()
597
        self.addCleanup(target.unlock)
598
        details = target.texts._index.get_build_details(
599
            [(b'file-id', b'1',), (b'file-id', b'2',)])
600
        file_1_details = details[(b'file-id', b'1')]
601
        file_2_details = details[(b'file-id', b'2')]
602
        # The index, and what to read off disk, should be the same for both
603
        # versions of the file.
604
        self.assertEqual(file_1_details[0][:3], file_2_details[0][:3])
605
606
    def test_fetch_combines_groups(self):
607
        builder = self.make_branch_builder('source', format='2a')
608
        builder.start_series()
609
        builder.build_snapshot(None, [
610
            ('add', ('', b'root-id', 'directory', '')),
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
611
            ('add', ('file', b'file-id', 'file', b'content\n'))],
6883.22.11 by Jelmer Vernooij
merge trunk
612
            revision_id=b'1')
613
        builder.build_snapshot([b'1'], [
614
            ('modify', ('file', b'content-2\n'))],
615
            revision_id=b'2')
616
        builder.finish_series()
617
        source = builder.get_branch()
618
        target = self.make_repository('target', format='2a')
619
        target.fetch(source.repository)
620
        target.lock_read()
621
        self.addCleanup(target.unlock)
622
        details = target.texts._index.get_build_details(
623
            [(b'file-id', b'1',), (b'file-id', b'2',)])
624
        file_1_details = details[(b'file-id', b'1')]
625
        file_2_details = details[(b'file-id', b'2')]
4634.23.1 by Robert Collins
Cherrypick from bzr.dev: Fix bug 402652: recompress badly packed groups during fetch. (John Arbash Meinel, Robert Collins)
626
        # The index, and what to read off disk, should be the same for both
627
        # versions of the file.
628
        self.assertEqual(file_1_details[0][:3], file_2_details[0][:3])
629
4431.3.7 by Jonathan Lange
Cherrypick bzr.dev 4470, resolving conflicts.
630
    def test_format_pack_compresses_True(self):
631
        repo = self.make_repository('repo', format='2a')
632
        self.assertTrue(repo._format.pack_compresses)
3735.2.40 by Robert Collins
Add development4 which has a parent_id to basename index on CHKInventory objects.
633
634
    def test_inventories_use_chk_map_with_parent_base_dict(self):
4667.1.1 by John Arbash Meinel
Drop the Test2a test times from 5+s down to 1.4s
635
        tree = self.make_branch_and_memory_tree('repo', format="2a")
636
        tree.lock_write()
6855.4.1 by Jelmer Vernooij
Yet more bees.
637
        tree.add([''], [b'TREE_ROOT'])
3735.2.40 by Robert Collins
Add development4 which has a parent_id to basename index on CHKInventory objects.
638
        revid = tree.commit("foo")
4667.1.1 by John Arbash Meinel
Drop the Test2a test times from 5+s down to 1.4s
639
        tree.unlock()
3735.2.40 by Robert Collins
Add development4 which has a parent_id to basename index on CHKInventory objects.
640
        tree.lock_read()
641
        self.addCleanup(tree.unlock)
642
        inv = tree.branch.repository.get_inventory(revid)
3735.2.41 by Robert Collins
Make the parent_id_basename index be updated during CHKInventory.apply_delta.
643
        self.assertNotEqual(None, inv.parent_id_basename_to_file_id)
644
        inv.parent_id_basename_to_file_id._ensure_root()
3735.2.40 by Robert Collins
Add development4 which has a parent_id to basename index on CHKInventory objects.
645
        inv.id_to_entry._ensure_root()
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
646
        self.assertEqual(65536, inv.id_to_entry._root_node.maximum_size)
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
647
        self.assertEqual(
648
            65536, inv.parent_id_basename_to_file_id._root_node.maximum_size)
3735.2.40 by Robert Collins
Add development4 which has a parent_id to basename index on CHKInventory objects.
649
4431.3.7 by Jonathan Lange
Cherrypick bzr.dev 4470, resolving conflicts.
650
    def test_autopack_unchanged_chk_nodes(self):
651
        # at 20 unchanged commits, chk pages are packed that are split into
652
        # two groups such that the new pack being made doesn't have all its
653
        # pages in the source packs (though they are in the repository).
4667.1.1 by John Arbash Meinel
Drop the Test2a test times from 5+s down to 1.4s
654
        # Use a memory backed repository, we don't need to hit disk for this
655
        tree = self.make_branch_and_memory_tree('tree', format='2a')
656
        tree.lock_write()
657
        self.addCleanup(tree.unlock)
6855.4.1 by Jelmer Vernooij
Yet more bees.
658
        tree.add([''], [b'TREE_ROOT'])
4431.3.7 by Jonathan Lange
Cherrypick bzr.dev 4470, resolving conflicts.
659
        for pos in range(20):
660
            tree.commit(str(pos))
661
662
    def test_pack_with_hint(self):
4667.1.1 by John Arbash Meinel
Drop the Test2a test times from 5+s down to 1.4s
663
        tree = self.make_branch_and_memory_tree('tree', format='2a')
664
        tree.lock_write()
665
        self.addCleanup(tree.unlock)
6855.4.1 by Jelmer Vernooij
Yet more bees.
666
        tree.add([''], [b'TREE_ROOT'])
4431.3.7 by Jonathan Lange
Cherrypick bzr.dev 4470, resolving conflicts.
667
        # 1 commit to leave untouched
668
        tree.commit('1')
669
        to_keep = tree.branch.repository._pack_collection.names()
670
        # 2 to combine
671
        tree.commit('2')
672
        tree.commit('3')
673
        all = tree.branch.repository._pack_collection.names()
674
        combine = list(set(all) - set(to_keep))
675
        self.assertLength(3, all)
676
        self.assertLength(2, combine)
677
        tree.branch.repository.pack(hint=combine)
678
        final = tree.branch.repository._pack_collection.names()
679
        self.assertLength(2, final)
680
        self.assertFalse(combine[0] in final)
681
        self.assertFalse(combine[1] in final)
682
        self.assertSubset(to_keep, final)
683
4360.4.3 by John Arbash Meinel
Introduce a KnitPackStreamSource which is used when
684
    def test_stream_source_to_gc(self):
4462.2.1 by Robert Collins
Add new attribute to RepositoryFormat pack_compresses, hinting when pack can be useful.
685
        source = self.make_repository('source', format='2a')
686
        target = self.make_repository('target', format='2a')
4360.4.3 by John Arbash Meinel
Introduce a KnitPackStreamSource which is used when
687
        stream = source._get_source(target._format)
688
        self.assertIsInstance(stream, groupcompress_repo.GroupCHKStreamSource)
689
690
    def test_stream_source_to_non_gc(self):
4462.2.1 by Robert Collins
Add new attribute to RepositoryFormat pack_compresses, hinting when pack can be useful.
691
        source = self.make_repository('source', format='2a')
4360.4.3 by John Arbash Meinel
Introduce a KnitPackStreamSource which is used when
692
        target = self.make_repository('target', format='rich-root-pack')
693
        stream = source._get_source(target._format)
694
        # We don't want the child GroupCHKStreamSource
5815.4.15 by Jelmer Vernooij
Fix some imports.
695
        self.assertIs(type(stream), vf_repository.StreamSource)
4360.4.3 by John Arbash Meinel
Introduce a KnitPackStreamSource which is used when
696
4360.4.9 by John Arbash Meinel
Merge bzr.dev, bringing in the gc stacking fixes.
697
    def test_get_stream_for_missing_keys_includes_all_chk_refs(self):
698
        source_builder = self.make_branch_builder('source',
7143.15.2 by Jelmer Vernooij
Run autopep8.
699
                                                  format='2a')
4360.4.9 by John Arbash Meinel
Merge bzr.dev, bringing in the gc stacking fixes.
700
        # We have to build a fairly large tree, so that we are sure the chk
701
        # pages will have split into multiple pages.
6855.4.1 by Jelmer Vernooij
Yet more bees.
702
        entries = [('add', ('', b'a-root-id', 'directory', None))]
4360.4.9 by John Arbash Meinel
Merge bzr.dev, bringing in the gc stacking fixes.
703
        for i in 'abcdefghijklmnopqrstuvwxyz123456789':
704
            for j in 'abcdefghijklmnopqrstuvwxyz123456789':
705
                fname = i + j
6855.4.1 by Jelmer Vernooij
Yet more bees.
706
                fid = fname.encode('utf-8') + b'-id'
7032.1.1 by Jelmer Vernooij
Fix some chk_map tests.
707
                content = b'content for %s\n' % (fname.encode('utf-8'),)
4360.4.9 by John Arbash Meinel
Merge bzr.dev, bringing in the gc stacking fixes.
708
                entries.append(('add', (fname, fid, 'file', content)))
709
        source_builder.start_series()
6855.4.1 by Jelmer Vernooij
Yet more bees.
710
        source_builder.build_snapshot(None, entries, revision_id=b'rev-1')
4360.4.9 by John Arbash Meinel
Merge bzr.dev, bringing in the gc stacking fixes.
711
        # Now change a few of them, so we get a few new pages for the second
712
        # revision
6855.4.1 by Jelmer Vernooij
Yet more bees.
713
        source_builder.build_snapshot([b'rev-1'], [
6883.22.11 by Jelmer Vernooij
merge trunk
714
            ('modify', ('aa', b'new content for aa-id\n')),
715
            ('modify', ('cc', b'new content for cc-id\n')),
716
            ('modify', ('zz', b'new content for zz-id\n')),
6855.4.1 by Jelmer Vernooij
Yet more bees.
717
            ], revision_id=b'rev-2')
4360.4.9 by John Arbash Meinel
Merge bzr.dev, bringing in the gc stacking fixes.
718
        source_builder.finish_series()
719
        source_branch = source_builder.get_branch()
720
        source_branch.lock_read()
721
        self.addCleanup(source_branch.unlock)
4462.2.1 by Robert Collins
Add new attribute to RepositoryFormat pack_compresses, hinting when pack can be useful.
722
        target = self.make_repository('target', format='2a')
4360.4.9 by John Arbash Meinel
Merge bzr.dev, bringing in the gc stacking fixes.
723
        source = source_branch.repository._get_source(target._format)
724
        self.assertIsInstance(source, groupcompress_repo.GroupCHKStreamSource)
725
726
        # On a regular pass, getting the inventories and chk pages for rev-2
727
        # would only get the newly created chk pages
6855.4.1 by Jelmer Vernooij
Yet more bees.
728
        search = vf_search.SearchResult({b'rev-2'}, {b'rev-1'}, 1,
7143.15.2 by Jelmer Vernooij
Run autopep8.
729
                                        {b'rev-2'})
7058.4.1 by Jelmer Vernooij
Fix another 40 tests.
730
        simple_chk_records = set()
4360.4.9 by John Arbash Meinel
Merge bzr.dev, bringing in the gc stacking fixes.
731
        for vf_name, substream in source.get_stream(search):
732
            if vf_name == 'chk_bytes':
733
                for record in substream:
7058.4.1 by Jelmer Vernooij
Fix another 40 tests.
734
                    simple_chk_records.add(record.key)
4360.4.9 by John Arbash Meinel
Merge bzr.dev, bringing in the gc stacking fixes.
735
            else:
736
                for _ in substream:
737
                    continue
738
        # 3 pages, the root (InternalNode), + 2 pages which actually changed
7058.4.1 by Jelmer Vernooij
Fix another 40 tests.
739
        self.assertEqual({(b'sha1:91481f539e802c76542ea5e4c83ad416bf219f73',),
7032.1.1 by Jelmer Vernooij
Fix some chk_map tests.
740
                          (b'sha1:4ff91971043668583985aec83f4f0ab10a907d3f',),
741
                          (b'sha1:81e7324507c5ca132eedaf2d8414ee4bb2226187',),
7058.4.1 by Jelmer Vernooij
Fix another 40 tests.
742
                          (b'sha1:b101b7da280596c71a4540e9a1eeba8045985ee0',)},
743
                         set(simple_chk_records))
4360.4.9 by John Arbash Meinel
Merge bzr.dev, bringing in the gc stacking fixes.
744
        # Now, when we do a similar call using 'get_stream_for_missing_keys'
745
        # we should get a much larger set of pages.
7032.1.1 by Jelmer Vernooij
Fix some chk_map tests.
746
        missing = [('inventories', b'rev-2')]
7058.3.1 by Jelmer Vernooij
Some more sortin'.
747
        full_chk_records = set()
4360.4.9 by John Arbash Meinel
Merge bzr.dev, bringing in the gc stacking fixes.
748
        for vf_name, substream in source.get_stream_for_missing_keys(missing):
749
            if vf_name == 'inventories':
750
                for record in substream:
7032.1.1 by Jelmer Vernooij
Fix some chk_map tests.
751
                    self.assertEqual((b'rev-2',), record.key)
4360.4.9 by John Arbash Meinel
Merge bzr.dev, bringing in the gc stacking fixes.
752
            elif vf_name == 'chk_bytes':
753
                for record in substream:
7058.3.1 by Jelmer Vernooij
Some more sortin'.
754
                    full_chk_records.add(record.key)
4360.4.9 by John Arbash Meinel
Merge bzr.dev, bringing in the gc stacking fixes.
755
            else:
756
                self.fail('Should not be getting a stream of %s' % (vf_name,))
757
        # We have 257 records now. This is because we have 1 root page, and 256
758
        # leaf pages in a complete listing.
759
        self.assertEqual(257, len(full_chk_records))
760
        self.assertSubset(simple_chk_records, full_chk_records)
761
4465.2.7 by Aaron Bentley
Move test_inconsistency_fatal to test_repository
762
    def test_inconsistency_fatal(self):
763
        repo = self.make_repository('repo', format='2a')
764
        self.assertTrue(repo.revisions._index._inconsistency_fatal)
765
        self.assertFalse(repo.texts._index._inconsistency_fatal)
766
        self.assertFalse(repo.inventories._index._inconsistency_fatal)
767
        self.assertFalse(repo.signatures._index._inconsistency_fatal)
768
        self.assertFalse(repo.chk_bytes._index._inconsistency_fatal)
769
4360.4.3 by John Arbash Meinel
Introduce a KnitPackStreamSource which is used when
770
771
class TestKnitPackStreamSource(tests.TestCaseWithMemoryTransport):
772
773
    def test_source_to_exact_pack_092(self):
774
        source = self.make_repository('source', format='pack-0.92')
775
        target = self.make_repository('target', format='pack-0.92')
776
        stream_source = source._get_source(target._format)
7143.15.2 by Jelmer Vernooij
Run autopep8.
777
        self.assertIsInstance(
778
            stream_source, knitpack_repo.KnitPackStreamSource)
4360.4.3 by John Arbash Meinel
Introduce a KnitPackStreamSource which is used when
779
780
    def test_source_to_exact_pack_rich_root_pack(self):
781
        source = self.make_repository('source', format='rich-root-pack')
782
        target = self.make_repository('target', format='rich-root-pack')
783
        stream_source = source._get_source(target._format)
7143.15.2 by Jelmer Vernooij
Run autopep8.
784
        self.assertIsInstance(
785
            stream_source, knitpack_repo.KnitPackStreamSource)
4360.4.3 by John Arbash Meinel
Introduce a KnitPackStreamSource which is used when
786
787
    def test_source_to_exact_pack_19(self):
788
        source = self.make_repository('source', format='1.9')
789
        target = self.make_repository('target', format='1.9')
790
        stream_source = source._get_source(target._format)
7143.15.2 by Jelmer Vernooij
Run autopep8.
791
        self.assertIsInstance(
792
            stream_source, knitpack_repo.KnitPackStreamSource)
4360.4.3 by John Arbash Meinel
Introduce a KnitPackStreamSource which is used when
793
794
    def test_source_to_exact_pack_19_rich_root(self):
795
        source = self.make_repository('source', format='1.9-rich-root')
796
        target = self.make_repository('target', format='1.9-rich-root')
797
        stream_source = source._get_source(target._format)
7143.15.2 by Jelmer Vernooij
Run autopep8.
798
        self.assertIsInstance(
799
            stream_source, knitpack_repo.KnitPackStreamSource)
4360.4.3 by John Arbash Meinel
Introduce a KnitPackStreamSource which is used when
800
801
    def test_source_to_remote_exact_pack_19(self):
802
        trans = self.make_smart_server('target')
803
        trans.ensure_base()
804
        source = self.make_repository('source', format='1.9')
805
        target = self.make_repository('target', format='1.9')
806
        target = repository.Repository.open(trans.base)
807
        stream_source = source._get_source(target._format)
7143.15.2 by Jelmer Vernooij
Run autopep8.
808
        self.assertIsInstance(
809
            stream_source, knitpack_repo.KnitPackStreamSource)
4360.4.3 by John Arbash Meinel
Introduce a KnitPackStreamSource which is used when
810
811
    def test_stream_source_to_non_exact(self):
812
        source = self.make_repository('source', format='pack-0.92')
813
        target = self.make_repository('target', format='1.9')
814
        stream = source._get_source(target._format)
5815.4.15 by Jelmer Vernooij
Fix some imports.
815
        self.assertIs(type(stream), vf_repository.StreamSource)
4360.4.3 by John Arbash Meinel
Introduce a KnitPackStreamSource which is used when
816
817
    def test_stream_source_to_non_exact_rich_root(self):
818
        source = self.make_repository('source', format='1.9')
819
        target = self.make_repository('target', format='1.9-rich-root')
820
        stream = source._get_source(target._format)
5815.4.15 by Jelmer Vernooij
Fix some imports.
821
        self.assertIs(type(stream), vf_repository.StreamSource)
4360.4.3 by John Arbash Meinel
Introduce a KnitPackStreamSource which is used when
822
823
    def test_source_to_remote_non_exact_pack_19(self):
824
        trans = self.make_smart_server('target')
825
        trans.ensure_base()
826
        source = self.make_repository('source', format='1.9')
827
        target = self.make_repository('target', format='1.6')
828
        target = repository.Repository.open(trans.base)
829
        stream_source = source._get_source(target._format)
5815.4.15 by Jelmer Vernooij
Fix some imports.
830
        self.assertIs(type(stream_source), vf_repository.StreamSource)
4360.4.3 by John Arbash Meinel
Introduce a KnitPackStreamSource which is used when
831
832
    def test_stream_source_to_knit(self):
833
        source = self.make_repository('source', format='pack-0.92')
834
        target = self.make_repository('target', format='dirstate')
835
        stream = source._get_source(target._format)
5815.4.15 by Jelmer Vernooij
Fix some imports.
836
        self.assertIs(type(stream), vf_repository.StreamSource)
4360.4.3 by John Arbash Meinel
Introduce a KnitPackStreamSource which is used when
837
3735.2.40 by Robert Collins
Add development4 which has a parent_id to basename index on CHKInventory objects.
838
4343.3.32 by John Arbash Meinel
Change the tests for _find_revision_outside_set to the new _find_parent_ids function.
839
class TestDevelopment6FindParentIdsOfRevisions(TestCaseWithTransport):
840
    """Tests for _find_parent_ids_of_revisions."""
3735.4.1 by Andrew Bennetts
Add _find_revision_outside_set.
841
842
    def setUp(self):
4343.3.32 by John Arbash Meinel
Change the tests for _find_revision_outside_set to the new _find_parent_ids function.
843
        super(TestDevelopment6FindParentIdsOfRevisions, self).setUp()
5546.1.1 by Andrew Bennetts
Remove RepositoryFormatCHK1 and RepositoryFormatCHK2.
844
        self.builder = self.make_branch_builder('source')
3735.4.1 by Andrew Bennetts
Add _find_revision_outside_set.
845
        self.builder.start_series()
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
846
        self.builder.build_snapshot(
847
            None,
848
            [('add', ('', b'tree-root', 'directory', None))],
849
            revision_id=b'initial')
3735.4.1 by Andrew Bennetts
Add _find_revision_outside_set.
850
        self.repo = self.builder.get_branch().repository
851
        self.addCleanup(self.builder.finish_series)
3735.2.99 by John Arbash Meinel
Merge bzr.dev 4034. Whitespace cleanup
852
4343.3.32 by John Arbash Meinel
Change the tests for _find_revision_outside_set to the new _find_parent_ids function.
853
    def assertParentIds(self, expected_result, rev_set):
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
854
        self.assertEqual(
855
            sorted(expected_result),
856
            sorted(self.repo._find_parent_ids_of_revisions(rev_set)))
3735.4.1 by Andrew Bennetts
Add _find_revision_outside_set.
857
858
    def test_simple(self):
6973.5.2 by Jelmer Vernooij
Add more bees.
859
        self.builder.build_snapshot(None, [], revision_id=b'revid1')
6973.13.2 by Jelmer Vernooij
Fix some more tests.
860
        self.builder.build_snapshot([b'revid1'], [], revision_id=b'revid2')
861
        rev_set = [b'revid2']
862
        self.assertParentIds([b'revid1'], rev_set)
3735.4.1 by Andrew Bennetts
Add _find_revision_outside_set.
863
864
    def test_not_first_parent(self):
6973.5.2 by Jelmer Vernooij
Add more bees.
865
        self.builder.build_snapshot(None, [], revision_id=b'revid1')
6973.13.2 by Jelmer Vernooij
Fix some more tests.
866
        self.builder.build_snapshot([b'revid1'], [], revision_id=b'revid2')
867
        self.builder.build_snapshot([b'revid2'], [], revision_id=b'revid3')
868
        rev_set = [b'revid3', b'revid2']
869
        self.assertParentIds([b'revid1'], rev_set)
3735.4.1 by Andrew Bennetts
Add _find_revision_outside_set.
870
871
    def test_not_null(self):
6973.13.2 by Jelmer Vernooij
Fix some more tests.
872
        rev_set = [b'initial']
4343.3.32 by John Arbash Meinel
Change the tests for _find_revision_outside_set to the new _find_parent_ids function.
873
        self.assertParentIds([], rev_set)
3735.4.1 by Andrew Bennetts
Add _find_revision_outside_set.
874
875
    def test_not_null_set(self):
6973.5.2 by Jelmer Vernooij
Add more bees.
876
        self.builder.build_snapshot(None, [], revision_id=b'revid1')
3735.4.1 by Andrew Bennetts
Add _find_revision_outside_set.
877
        rev_set = [_mod_revision.NULL_REVISION]
4343.3.32 by John Arbash Meinel
Change the tests for _find_revision_outside_set to the new _find_parent_ids function.
878
        self.assertParentIds([], rev_set)
3735.4.1 by Andrew Bennetts
Add _find_revision_outside_set.
879
880
    def test_ghost(self):
6973.5.2 by Jelmer Vernooij
Add more bees.
881
        self.builder.build_snapshot(None, [], revision_id=b'revid1')
6973.13.2 by Jelmer Vernooij
Fix some more tests.
882
        rev_set = [b'ghost', b'revid1']
883
        self.assertParentIds([b'initial'], rev_set)
3735.4.1 by Andrew Bennetts
Add _find_revision_outside_set.
884
885
    def test_ghost_parent(self):
6973.5.2 by Jelmer Vernooij
Add more bees.
886
        self.builder.build_snapshot(None, [], revision_id=b'revid1')
7143.15.2 by Jelmer Vernooij
Run autopep8.
887
        self.builder.build_snapshot(
888
            [b'revid1', b'ghost'], [], revision_id=b'revid2')
6973.13.2 by Jelmer Vernooij
Fix some more tests.
889
        rev_set = [b'revid2', b'revid1']
890
        self.assertParentIds([b'ghost', b'initial'], rev_set)
3735.4.1 by Andrew Bennetts
Add _find_revision_outside_set.
891
892
    def test_righthand_parent(self):
6973.5.2 by Jelmer Vernooij
Add more bees.
893
        self.builder.build_snapshot(None, [], revision_id=b'revid1')
6973.13.2 by Jelmer Vernooij
Fix some more tests.
894
        self.builder.build_snapshot([b'revid1'], [], revision_id=b'revid2a')
895
        self.builder.build_snapshot([b'revid1'], [], revision_id=b'revid2b')
896
        self.builder.build_snapshot([b'revid2a', b'revid2b'], [],
6973.5.2 by Jelmer Vernooij
Add more bees.
897
                                    revision_id=b'revid3')
6973.13.2 by Jelmer Vernooij
Fix some more tests.
898
        rev_set = [b'revid3', b'revid2a']
899
        self.assertParentIds([b'revid1', b'revid2b'], rev_set)
3735.4.1 by Andrew Bennetts
Add _find_revision_outside_set.
900
901
2535.3.57 by Andrew Bennetts
Perform some sanity checking of data streams rather than blindly inserting them into our repository.
902
class TestWithBrokenRepo(TestCaseWithTransport):
2592.3.214 by Robert Collins
Merge bzr.dev.
903
    """These tests seem to be more appropriate as interface tests?"""
2535.3.57 by Andrew Bennetts
Perform some sanity checking of data streams rather than blindly inserting them into our repository.
904
905
    def make_broken_repository(self):
906
        # XXX: This function is borrowed from Aaron's "Reconcile can fix bad
907
        # parent references" branch which is due to land in bzr.dev soon.  Once
908
        # it does, this duplication should be removed.
909
        repo = self.make_repository('broken-repo')
910
        cleanups = []
911
        try:
912
            repo.lock_write()
913
            cleanups.append(repo.unlock)
914
            repo.start_write_group()
915
            cleanups.append(repo.commit_write_group)
916
            # make rev1a: A well-formed revision, containing 'file1'
6973.5.2 by Jelmer Vernooij
Add more bees.
917
            inv = inventory.Inventory(revision_id=b'rev1a')
6973.13.2 by Jelmer Vernooij
Fix some more tests.
918
            inv.root.revision = b'rev1a'
919
            self.add_file(repo, inv, 'file1', b'rev1a', [])
920
            repo.texts.add_lines((inv.root.file_id, b'rev1a'), [], [])
921
            repo.add_inventory(b'rev1a', inv, [])
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
922
            revision = _mod_revision.Revision(
923
                b'rev1a',
924
                committer='jrandom@example.com', timestamp=0,
925
                inventory_sha1='', timezone=0, message='foo', parent_ids=[])
6973.13.2 by Jelmer Vernooij
Fix some more tests.
926
            repo.add_revision(b'rev1a', revision, inv)
2535.3.57 by Andrew Bennetts
Perform some sanity checking of data streams rather than blindly inserting them into our repository.
927
928
            # make rev1b, which has no Revision, but has an Inventory, and
929
            # file1
6973.5.2 by Jelmer Vernooij
Add more bees.
930
            inv = inventory.Inventory(revision_id=b'rev1b')
6973.13.2 by Jelmer Vernooij
Fix some more tests.
931
            inv.root.revision = b'rev1b'
932
            self.add_file(repo, inv, 'file1', b'rev1b', [])
933
            repo.add_inventory(b'rev1b', inv, [])
2535.3.57 by Andrew Bennetts
Perform some sanity checking of data streams rather than blindly inserting them into our repository.
934
935
            # make rev2, with file1 and file2
936
            # file2 is sane
937
            # file1 has 'rev1b' as an ancestor, even though this is not
938
            # mentioned by 'rev1a', making it an unreferenced ancestor
939
            inv = inventory.Inventory()
6973.13.2 by Jelmer Vernooij
Fix some more tests.
940
            self.add_file(repo, inv, 'file1', b'rev2', [b'rev1a', b'rev1b'])
941
            self.add_file(repo, inv, 'file2', b'rev2', [])
942
            self.add_revision(repo, b'rev2', inv, [b'rev1a'])
2535.3.57 by Andrew Bennetts
Perform some sanity checking of data streams rather than blindly inserting them into our repository.
943
944
            # make ghost revision rev1c
945
            inv = inventory.Inventory()
6973.13.2 by Jelmer Vernooij
Fix some more tests.
946
            self.add_file(repo, inv, 'file2', b'rev1c', [])
2535.3.57 by Andrew Bennetts
Perform some sanity checking of data streams rather than blindly inserting them into our repository.
947
948
            # make rev3 with file2
949
            # file2 refers to 'rev1c', which is a ghost in this repository, so
950
            # file2 cannot have rev1c as its ancestor.
951
            inv = inventory.Inventory()
6973.13.2 by Jelmer Vernooij
Fix some more tests.
952
            self.add_file(repo, inv, 'file2', b'rev3', [b'rev1c'])
953
            self.add_revision(repo, b'rev3', inv, [b'rev1c'])
2535.3.57 by Andrew Bennetts
Perform some sanity checking of data streams rather than blindly inserting them into our repository.
954
            return repo
955
        finally:
956
            for cleanup in reversed(cleanups):
957
                cleanup()
958
959
    def add_revision(self, repo, revision_id, inv, parent_ids):
960
        inv.revision_id = revision_id
961
        inv.root.revision = revision_id
4634.35.21 by Andrew Bennetts
Fix test_insert_from_broken_repo in test_repository.
962
        repo.texts.add_lines((inv.root.file_id, revision_id), [], [])
2535.3.57 by Andrew Bennetts
Perform some sanity checking of data streams rather than blindly inserting them into our repository.
963
        repo.add_inventory(revision_id, inv, parent_ids)
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
964
        revision = _mod_revision.Revision(
965
            revision_id,
966
            committer='jrandom@example.com', timestamp=0, inventory_sha1='',
967
            timezone=0, message='foo', parent_ids=parent_ids)
6351.3.2 by Jelmer Vernooij
Convert some gpg options to config stacks.
968
        repo.add_revision(revision_id, revision, inv)
2535.3.57 by Andrew Bennetts
Perform some sanity checking of data streams rather than blindly inserting them into our repository.
969
970
    def add_file(self, repo, inv, filename, revision, parents):
7045.4.30 by Jelmer Vernooij
Fix some more tests.
971
        file_id = filename.encode('utf-8') + b'-id'
7058.4.24 by Jelmer Vernooij
Fix insert_from_broken_repo test.
972
        content = [b'line\n']
6973.13.2 by Jelmer Vernooij
Fix some more tests.
973
        entry = inventory.InventoryFile(file_id, filename, b'TREE_ROOT')
2535.3.57 by Andrew Bennetts
Perform some sanity checking of data streams rather than blindly inserting them into our repository.
974
        entry.revision = revision
7058.4.24 by Jelmer Vernooij
Fix insert_from_broken_repo test.
975
        entry.text_sha1 = osutils.sha_strings(content)
2535.4.10 by Andrew Bennetts
Fix one failing test, disable another.
976
        entry.text_size = 0
2535.3.57 by Andrew Bennetts
Perform some sanity checking of data streams rather than blindly inserting them into our repository.
977
        inv.add(entry)
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.
978
        text_key = (file_id, revision)
979
        parent_keys = [(file_id, parent) for parent in parents]
7058.4.24 by Jelmer Vernooij
Fix insert_from_broken_repo test.
980
        repo.texts.add_lines(text_key, parent_keys, content)
2535.3.57 by Andrew Bennetts
Perform some sanity checking of data streams rather than blindly inserting them into our repository.
981
982
    def test_insert_from_broken_repo(self):
983
        """Inserting a data stream from a broken repository won't silently
984
        corrupt the target repository.
985
        """
986
        broken_repo = self.make_broken_repository()
987
        empty_repo = self.make_repository('empty-repo')
4606.1.1 by Robert Collins
Change test_insert_from_broken_repo from a known failure to a working test.
988
        try:
989
            empty_repo.fetch(broken_repo)
990
        except (errors.RevisionNotPresent, errors.BzrCheckError):
991
            # Test successful: compression parent not being copied leads to
992
            # error.
993
            return
994
        empty_repo.lock_read()
995
        self.addCleanup(empty_repo.unlock)
6634.2.1 by Martin
Apply 2to3 next fixer and make compatible
996
        text = next(empty_repo.texts.get_record_stream(
6973.13.2 by Jelmer Vernooij
Fix some more tests.
997
            [(b'file2-id', b'rev3')], 'topological', True))
998
        self.assertEqual(b'line\n', text.get_bytes_as('fulltext'))
2592.3.214 by Robert Collins
Merge bzr.dev.
999
1000
2592.3.84 by Robert Collins
Start of autopacking logic.
1001
class TestRepositoryPackCollection(TestCaseWithTransport):
1002
1003
    def get_format(self):
6653.6.5 by Jelmer Vernooij
Rename make_bzrdir to make_controldir.
1004
        return controldir.format_registry.make_controldir('pack-0.92')
2592.3.84 by Robert Collins
Start of autopacking logic.
1005
3711.4.1 by John Arbash Meinel
Fix bug #242510, when determining the autopack sequence,
1006
    def get_packs(self):
1007
        format = self.get_format()
1008
        repo = self.make_repository('.', format=format)
1009
        return repo._pack_collection
1010
3789.2.20 by John Arbash Meinel
The autopack code can now trigger itself to retry when _copy_revision_texts fails.
1011
    def make_packs_and_alt_repo(self, write_lock=False):
3789.2.19 by John Arbash Meinel
Refactor to make the tests a bit simpler
1012
        """Create a pack repo with 3 packs, and access it via a second repo."""
4617.4.1 by Robert Collins
Fix a pack specific test which didn't lock its format down.
1013
        tree = self.make_branch_and_tree('.', format=self.get_format())
3789.2.19 by John Arbash Meinel
Refactor to make the tests a bit simpler
1014
        tree.lock_write()
1015
        self.addCleanup(tree.unlock)
1016
        rev1 = tree.commit('one')
1017
        rev2 = tree.commit('two')
1018
        rev3 = tree.commit('three')
1019
        r = repository.Repository.open('.')
3789.2.20 by John Arbash Meinel
The autopack code can now trigger itself to retry when _copy_revision_texts fails.
1020
        if write_lock:
1021
            r.lock_write()
1022
        else:
1023
            r.lock_read()
3789.2.19 by John Arbash Meinel
Refactor to make the tests a bit simpler
1024
        self.addCleanup(r.unlock)
1025
        packs = r._pack_collection
1026
        packs.ensure_loaded()
1027
        return tree, r, packs, [rev1, rev2, rev3]
1028
4634.127.1 by John Arbash Meinel
Partial fix for bug #507557.
1029
    def test__clear_obsolete_packs(self):
1030
        packs = self.get_packs()
1031
        obsolete_pack_trans = packs.transport.clone('obsolete_packs')
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
1032
        obsolete_pack_trans.put_bytes('a-pack.pack', b'content\n')
1033
        obsolete_pack_trans.put_bytes('a-pack.rix', b'content\n')
1034
        obsolete_pack_trans.put_bytes('a-pack.iix', b'content\n')
1035
        obsolete_pack_trans.put_bytes('another-pack.pack', b'foo\n')
1036
        obsolete_pack_trans.put_bytes('not-a-pack.rix', b'foo\n')
4634.127.1 by John Arbash Meinel
Partial fix for bug #507557.
1037
        res = packs._clear_obsolete_packs()
1038
        self.assertEqual(['a-pack', 'another-pack'], sorted(res))
1039
        self.assertEqual([], obsolete_pack_trans.list_dir('.'))
1040
1041
    def test__clear_obsolete_packs_preserve(self):
1042
        packs = self.get_packs()
1043
        obsolete_pack_trans = packs.transport.clone('obsolete_packs')
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
1044
        obsolete_pack_trans.put_bytes('a-pack.pack', b'content\n')
1045
        obsolete_pack_trans.put_bytes('a-pack.rix', b'content\n')
1046
        obsolete_pack_trans.put_bytes('a-pack.iix', b'content\n')
1047
        obsolete_pack_trans.put_bytes('another-pack.pack', b'foo\n')
1048
        obsolete_pack_trans.put_bytes('not-a-pack.rix', b'foo\n')
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
1049
        res = packs._clear_obsolete_packs(preserve={'a-pack'})
4634.127.1 by John Arbash Meinel
Partial fix for bug #507557.
1050
        self.assertEqual(['a-pack', 'another-pack'], sorted(res))
1051
        self.assertEqual(['a-pack.iix', 'a-pack.pack', 'a-pack.rix'],
1052
                         sorted(obsolete_pack_trans.list_dir('.')))
1053
2592.3.84 by Robert Collins
Start of autopacking logic.
1054
    def test__max_pack_count(self):
2592.3.219 by Robert Collins
Review feedback.
1055
        """The maximum pack count is a function of the number of revisions."""
2592.3.84 by Robert Collins
Start of autopacking logic.
1056
        # no revisions - one pack, so that we can have a revision free repo
1057
        # without it blowing up
3711.4.1 by John Arbash Meinel
Fix bug #242510, when determining the autopack sequence,
1058
        packs = self.get_packs()
2592.3.84 by Robert Collins
Start of autopacking logic.
1059
        self.assertEqual(1, packs._max_pack_count(0))
1060
        # after that the sum of the digits, - check the first 1-9
1061
        self.assertEqual(1, packs._max_pack_count(1))
1062
        self.assertEqual(2, packs._max_pack_count(2))
1063
        self.assertEqual(3, packs._max_pack_count(3))
1064
        self.assertEqual(4, packs._max_pack_count(4))
1065
        self.assertEqual(5, packs._max_pack_count(5))
1066
        self.assertEqual(6, packs._max_pack_count(6))
1067
        self.assertEqual(7, packs._max_pack_count(7))
1068
        self.assertEqual(8, packs._max_pack_count(8))
1069
        self.assertEqual(9, packs._max_pack_count(9))
1070
        # check the boundary cases with two digits for the next decade
1071
        self.assertEqual(1, packs._max_pack_count(10))
1072
        self.assertEqual(2, packs._max_pack_count(11))
1073
        self.assertEqual(10, packs._max_pack_count(19))
1074
        self.assertEqual(2, packs._max_pack_count(20))
1075
        self.assertEqual(3, packs._max_pack_count(21))
1076
        # check some arbitrary big numbers
1077
        self.assertEqual(25, packs._max_pack_count(112894))
1078
4928.1.1 by Martin Pool
Give RepositoryPackCollection a repr
1079
    def test_repr(self):
1080
        packs = self.get_packs()
1081
        self.assertContainsRe(repr(packs),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1082
                              'RepositoryPackCollection(.*Repository(.*))')
4928.1.1 by Martin Pool
Give RepositoryPackCollection a repr
1083
4634.127.2 by John Arbash Meinel
Change the _obsolete_packs code to handle files that are already gone.
1084
    def test__obsolete_packs(self):
1085
        tree, r, packs, revs = self.make_packs_and_alt_repo(write_lock=True)
1086
        names = packs.names()
1087
        pack = packs.get_pack_by_name(names[0])
1088
        # Schedule this one for removal
1089
        packs._remove_pack_from_memory(pack)
1090
        # Simulate a concurrent update by renaming the .pack file and one of
1091
        # the indices
1092
        packs.transport.rename('packs/%s.pack' % (names[0],),
1093
                               'obsolete_packs/%s.pack' % (names[0],))
1094
        packs.transport.rename('indices/%s.iix' % (names[0],),
1095
                               'obsolete_packs/%s.iix' % (names[0],))
1096
        # Now trigger the obsoletion, and ensure that all the remaining files
1097
        # are still renamed
1098
        packs._obsolete_packs([pack])
1099
        self.assertEqual([n + '.pack' for n in names[1:]],
1100
                         sorted(packs._pack_transport.list_dir('.')))
1101
        # names[0] should not be present in the index anymore
1102
        self.assertEqual(names[1:],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1103
                         sorted({osutils.splitext(n)[0] for n in
1104
                                 packs._index_transport.list_dir('.')}))
4634.127.2 by John Arbash Meinel
Change the _obsolete_packs code to handle files that are already gone.
1105
6225.2.8 by Jelmer Vernooij
Fix creation of obsolete_packs if it is missing.
1106
    def test__obsolete_packs_missing_directory(self):
1107
        tree, r, packs, revs = self.make_packs_and_alt_repo(write_lock=True)
1108
        r.control_transport.rmdir('obsolete_packs')
1109
        names = packs.names()
1110
        pack = packs.get_pack_by_name(names[0])
1111
        # Schedule this one for removal
1112
        packs._remove_pack_from_memory(pack)
1113
        # Now trigger the obsoletion, and ensure that all the remaining files
1114
        # are still renamed
1115
        packs._obsolete_packs([pack])
1116
        self.assertEqual([n + '.pack' for n in names[1:]],
1117
                         sorted(packs._pack_transport.list_dir('.')))
1118
        # names[0] should not be present in the index anymore
1119
        self.assertEqual(names[1:],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1120
                         sorted({osutils.splitext(n)[0] for n in
1121
                                 packs._index_transport.list_dir('.')}))
6225.2.8 by Jelmer Vernooij
Fix creation of obsolete_packs if it is missing.
1122
2592.3.84 by Robert Collins
Start of autopacking logic.
1123
    def test_pack_distribution_zero(self):
3711.4.1 by John Arbash Meinel
Fix bug #242510, when determining the autopack sequence,
1124
        packs = self.get_packs()
2592.3.84 by Robert Collins
Start of autopacking logic.
1125
        self.assertEqual([0], packs.pack_distribution(0))
3052.1.6 by John Arbash Meinel
Change the lock check to raise ObjectNotLocked.
1126
1127
    def test_ensure_loaded_unlocked(self):
3711.4.1 by John Arbash Meinel
Fix bug #242510, when determining the autopack sequence,
1128
        packs = self.get_packs()
3052.1.6 by John Arbash Meinel
Change the lock check to raise ObjectNotLocked.
1129
        self.assertRaises(errors.ObjectNotLocked,
3711.4.1 by John Arbash Meinel
Fix bug #242510, when determining the autopack sequence,
1130
                          packs.ensure_loaded)
3052.1.6 by John Arbash Meinel
Change the lock check to raise ObjectNotLocked.
1131
2592.3.84 by Robert Collins
Start of autopacking logic.
1132
    def test_pack_distribution_one_to_nine(self):
3711.4.1 by John Arbash Meinel
Fix bug #242510, when determining the autopack sequence,
1133
        packs = self.get_packs()
2592.3.84 by Robert Collins
Start of autopacking logic.
1134
        self.assertEqual([1],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1135
                         packs.pack_distribution(1))
2592.3.84 by Robert Collins
Start of autopacking logic.
1136
        self.assertEqual([1, 1],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1137
                         packs.pack_distribution(2))
2592.3.84 by Robert Collins
Start of autopacking logic.
1138
        self.assertEqual([1, 1, 1],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1139
                         packs.pack_distribution(3))
2592.3.84 by Robert Collins
Start of autopacking logic.
1140
        self.assertEqual([1, 1, 1, 1],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1141
                         packs.pack_distribution(4))
2592.3.84 by Robert Collins
Start of autopacking logic.
1142
        self.assertEqual([1, 1, 1, 1, 1],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1143
                         packs.pack_distribution(5))
2592.3.84 by Robert Collins
Start of autopacking logic.
1144
        self.assertEqual([1, 1, 1, 1, 1, 1],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1145
                         packs.pack_distribution(6))
2592.3.84 by Robert Collins
Start of autopacking logic.
1146
        self.assertEqual([1, 1, 1, 1, 1, 1, 1],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1147
                         packs.pack_distribution(7))
2592.3.84 by Robert Collins
Start of autopacking logic.
1148
        self.assertEqual([1, 1, 1, 1, 1, 1, 1, 1],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1149
                         packs.pack_distribution(8))
2592.3.84 by Robert Collins
Start of autopacking logic.
1150
        self.assertEqual([1, 1, 1, 1, 1, 1, 1, 1, 1],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1151
                         packs.pack_distribution(9))
2592.3.84 by Robert Collins
Start of autopacking logic.
1152
1153
    def test_pack_distribution_stable_at_boundaries(self):
1154
        """When there are multi-rev packs the counts are stable."""
3711.4.1 by John Arbash Meinel
Fix bug #242510, when determining the autopack sequence,
1155
        packs = self.get_packs()
2592.3.84 by Robert Collins
Start of autopacking logic.
1156
        # in 10s:
1157
        self.assertEqual([10], packs.pack_distribution(10))
1158
        self.assertEqual([10, 1], packs.pack_distribution(11))
1159
        self.assertEqual([10, 10], packs.pack_distribution(20))
1160
        self.assertEqual([10, 10, 1], packs.pack_distribution(21))
1161
        # 100s
1162
        self.assertEqual([100], packs.pack_distribution(100))
1163
        self.assertEqual([100, 1], packs.pack_distribution(101))
1164
        self.assertEqual([100, 10, 1], packs.pack_distribution(111))
1165
        self.assertEqual([100, 100], packs.pack_distribution(200))
1166
        self.assertEqual([100, 100, 1], packs.pack_distribution(201))
1167
        self.assertEqual([100, 100, 10, 1], packs.pack_distribution(211))
1168
2592.3.85 by Robert Collins
Finish autopack corner cases.
1169
    def test_plan_pack_operations_2009_revisions_skip_all_packs(self):
3711.4.1 by John Arbash Meinel
Fix bug #242510, when determining the autopack sequence,
1170
        packs = self.get_packs()
2592.3.85 by Robert Collins
Finish autopack corner cases.
1171
        existing_packs = [(2000, "big"), (9, "medium")]
1172
        # rev count - 2009 -> 2x1000 + 9x1
1173
        pack_operations = packs.plan_autopack_combinations(
1174
            existing_packs, [1000, 1000, 1, 1, 1, 1, 1, 1, 1, 1, 1])
1175
        self.assertEqual([], pack_operations)
1176
1177
    def test_plan_pack_operations_2010_revisions_skip_all_packs(self):
3711.4.1 by John Arbash Meinel
Fix bug #242510, when determining the autopack sequence,
1178
        packs = self.get_packs()
2592.3.85 by Robert Collins
Finish autopack corner cases.
1179
        existing_packs = [(2000, "big"), (9, "medium"), (1, "single")]
1180
        # rev count - 2010 -> 2x1000 + 1x10
1181
        pack_operations = packs.plan_autopack_combinations(
1182
            existing_packs, [1000, 1000, 10])
1183
        self.assertEqual([], pack_operations)
1184
1185
    def test_plan_pack_operations_2010_combines_smallest_two(self):
3711.4.1 by John Arbash Meinel
Fix bug #242510, when determining the autopack sequence,
1186
        packs = self.get_packs()
2592.3.85 by Robert Collins
Finish autopack corner cases.
1187
        existing_packs = [(1999, "big"), (9, "medium"), (1, "single2"),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1188
                          (1, "single1")]
2592.3.85 by Robert Collins
Finish autopack corner cases.
1189
        # rev count - 2010 -> 2x1000 + 1x10 (3)
1190
        pack_operations = packs.plan_autopack_combinations(
1191
            existing_packs, [1000, 1000, 10])
3711.4.2 by John Arbash Meinel
Change the logic to solve it in a different way.
1192
        self.assertEqual([[2, ["single2", "single1"]]], pack_operations)
2592.3.85 by Robert Collins
Finish autopack corner cases.
1193
3711.4.2 by John Arbash Meinel
Change the logic to solve it in a different way.
1194
    def test_plan_pack_operations_creates_a_single_op(self):
3711.4.1 by John Arbash Meinel
Fix bug #242510, when determining the autopack sequence,
1195
        packs = self.get_packs()
3711.4.2 by John Arbash Meinel
Change the logic to solve it in a different way.
1196
        existing_packs = [(50, 'a'), (40, 'b'), (30, 'c'), (10, 'd'),
1197
                          (10, 'e'), (6, 'f'), (4, 'g')]
1198
        # rev count 150 -> 1x100 and 5x10
1199
        # The two size 10 packs do not need to be touched. The 50, 40, 30 would
1200
        # be combined into a single 120 size pack, and the 6 & 4 would
1201
        # becombined into a size 10 pack. However, if we have to rewrite them,
1202
        # we save a pack file with no increased I/O by putting them into the
1203
        # same file.
1204
        distribution = packs.pack_distribution(150)
3711.4.1 by John Arbash Meinel
Fix bug #242510, when determining the autopack sequence,
1205
        pack_operations = packs.plan_autopack_combinations(existing_packs,
3711.4.2 by John Arbash Meinel
Change the logic to solve it in a different way.
1206
                                                           distribution)
1207
        self.assertEqual([[130, ['a', 'b', 'c', 'f', 'g']]], pack_operations)
3711.4.1 by John Arbash Meinel
Fix bug #242510, when determining the autopack sequence,
1208
2592.3.173 by Robert Collins
Basic implementation of all_packs.
1209
    def test_all_packs_none(self):
1210
        format = self.get_format()
1211
        tree = self.make_branch_and_tree('.', format=format)
1212
        tree.lock_read()
1213
        self.addCleanup(tree.unlock)
2592.3.232 by Martin Pool
Disambiguate two member variables called _packs into _packs_by_name and _pack_collection
1214
        packs = tree.branch.repository._pack_collection
2592.3.173 by Robert Collins
Basic implementation of all_packs.
1215
        packs.ensure_loaded()
1216
        self.assertEqual([], packs.all_packs())
1217
1218
    def test_all_packs_one(self):
1219
        format = self.get_format()
1220
        tree = self.make_branch_and_tree('.', format=format)
1221
        tree.commit('start')
1222
        tree.lock_read()
1223
        self.addCleanup(tree.unlock)
2592.3.232 by Martin Pool
Disambiguate two member variables called _packs into _packs_by_name and _pack_collection
1224
        packs = tree.branch.repository._pack_collection
2592.3.173 by Robert Collins
Basic implementation of all_packs.
1225
        packs.ensure_loaded()
2592.3.176 by Robert Collins
Various pack refactorings.
1226
        self.assertEqual([
1227
            packs.get_pack_by_name(packs.names()[0])],
1228
            packs.all_packs())
2592.3.173 by Robert Collins
Basic implementation of all_packs.
1229
1230
    def test_all_packs_two(self):
1231
        format = self.get_format()
1232
        tree = self.make_branch_and_tree('.', format=format)
1233
        tree.commit('start')
1234
        tree.commit('continue')
1235
        tree.lock_read()
1236
        self.addCleanup(tree.unlock)
2592.3.232 by Martin Pool
Disambiguate two member variables called _packs into _packs_by_name and _pack_collection
1237
        packs = tree.branch.repository._pack_collection
2592.3.173 by Robert Collins
Basic implementation of all_packs.
1238
        packs.ensure_loaded()
1239
        self.assertEqual([
2592.3.176 by Robert Collins
Various pack refactorings.
1240
            packs.get_pack_by_name(packs.names()[0]),
1241
            packs.get_pack_by_name(packs.names()[1]),
2592.3.173 by Robert Collins
Basic implementation of all_packs.
1242
            ], packs.all_packs())
1243
2592.3.176 by Robert Collins
Various pack refactorings.
1244
    def test_get_pack_by_name(self):
1245
        format = self.get_format()
1246
        tree = self.make_branch_and_tree('.', format=format)
1247
        tree.commit('start')
1248
        tree.lock_read()
1249
        self.addCleanup(tree.unlock)
2592.3.232 by Martin Pool
Disambiguate two member variables called _packs into _packs_by_name and _pack_collection
1250
        packs = tree.branch.repository._pack_collection
4145.1.6 by Robert Collins
More test fallout, but all caught now.
1251
        packs.reset()
2592.3.176 by Robert Collins
Various pack refactorings.
1252
        packs.ensure_loaded()
1253
        name = packs.names()[0]
1254
        pack_1 = packs.get_pack_by_name(name)
1255
        # the pack should be correctly initialised
3517.4.5 by Martin Pool
Correct use of packs._names in test_get_pack_by_name
1256
        sizes = packs._names[name]
3221.12.4 by Robert Collins
Implement basic repository supporting external references.
1257
        rev_index = GraphIndex(packs._index_transport, name + '.rix', sizes[0])
1258
        inv_index = GraphIndex(packs._index_transport, name + '.iix', sizes[1])
1259
        txt_index = GraphIndex(packs._index_transport, name + '.tix', sizes[2])
1260
        sig_index = GraphIndex(packs._index_transport, name + '.six', sizes[3])
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
1261
        self.assertEqual(
1262
            pack_repo.ExistingPack(
1263
                packs._pack_transport, name, rev_index, inv_index, txt_index,
1264
                sig_index), pack_1)
2592.3.176 by Robert Collins
Various pack refactorings.
1265
        # and the same instance should be returned on successive calls.
1266
        self.assertTrue(pack_1 is packs.get_pack_by_name(name))
1267
3789.1.2 by John Arbash Meinel
Add RepositoryPackCollection.reload_pack_names()
1268
    def test_reload_pack_names_new_entry(self):
3789.2.19 by John Arbash Meinel
Refactor to make the tests a bit simpler
1269
        tree, r, packs, revs = self.make_packs_and_alt_repo()
3789.1.2 by John Arbash Meinel
Add RepositoryPackCollection.reload_pack_names()
1270
        names = packs.names()
1271
        # Add a new pack file into the repository
3789.2.19 by John Arbash Meinel
Refactor to make the tests a bit simpler
1272
        rev4 = tree.commit('four')
3789.1.2 by John Arbash Meinel
Add RepositoryPackCollection.reload_pack_names()
1273
        new_names = tree.branch.repository._pack_collection.names()
1274
        new_name = set(new_names).difference(names)
1275
        self.assertEqual(1, len(new_name))
1276
        new_name = new_name.pop()
1277
        # The old collection hasn't noticed yet
1278
        self.assertEqual(names, packs.names())
3789.1.8 by John Arbash Meinel
Change the api of reload_pack_names().
1279
        self.assertTrue(packs.reload_pack_names())
3789.1.2 by John Arbash Meinel
Add RepositoryPackCollection.reload_pack_names()
1280
        self.assertEqual(new_names, packs.names())
1281
        # And the repository can access the new revision
7143.15.2 by Jelmer Vernooij
Run autopep8.
1282
        self.assertEqual({rev4: (revs[-1],)}, r.get_parent_map([rev4]))
3789.1.8 by John Arbash Meinel
Change the api of reload_pack_names().
1283
        self.assertFalse(packs.reload_pack_names())
3789.1.2 by John Arbash Meinel
Add RepositoryPackCollection.reload_pack_names()
1284
1285
    def test_reload_pack_names_added_and_removed(self):
3789.2.19 by John Arbash Meinel
Refactor to make the tests a bit simpler
1286
        tree, r, packs, revs = self.make_packs_and_alt_repo()
3789.1.2 by John Arbash Meinel
Add RepositoryPackCollection.reload_pack_names()
1287
        names = packs.names()
1288
        # Now repack the whole thing
1289
        tree.branch.repository.pack()
1290
        new_names = tree.branch.repository._pack_collection.names()
1291
        # The other collection hasn't noticed yet
1292
        self.assertEqual(names, packs.names())
3789.1.8 by John Arbash Meinel
Change the api of reload_pack_names().
1293
        self.assertTrue(packs.reload_pack_names())
3789.1.2 by John Arbash Meinel
Add RepositoryPackCollection.reload_pack_names()
1294
        self.assertEqual(new_names, packs.names())
7143.15.2 by Jelmer Vernooij
Run autopep8.
1295
        self.assertEqual({revs[-1]: (revs[-2],)}, r.get_parent_map([revs[-1]]))
3789.1.8 by John Arbash Meinel
Change the api of reload_pack_names().
1296
        self.assertFalse(packs.reload_pack_names())
3789.1.2 by John Arbash Meinel
Add RepositoryPackCollection.reload_pack_names()
1297
4634.126.1 by John Arbash Meinel
(jam) Fix bug #507566, concurrent autopacking correctness.
1298
    def test_reload_pack_names_preserves_pending(self):
1299
        # TODO: Update this to also test for pending-deleted names
1300
        tree, r, packs, revs = self.make_packs_and_alt_repo(write_lock=True)
1301
        # We will add one pack (via start_write_group + insert_record_stream),
1302
        # and remove another pack (via _remove_pack_from_memory)
1303
        orig_names = packs.names()
1304
        orig_at_load = packs._packs_at_load
6634.2.1 by Martin
Apply 2to3 next fixer and make compatible
1305
        to_remove_name = next(iter(orig_names))
4634.126.1 by John Arbash Meinel
(jam) Fix bug #507566, concurrent autopacking correctness.
1306
        r.start_write_group()
1307
        self.addCleanup(r.abort_write_group)
1308
        r.texts.insert_record_stream([versionedfile.FulltextContentFactory(
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
1309
            (b'text', b'rev'), (), None, b'content\n')])
4634.126.1 by John Arbash Meinel
(jam) Fix bug #507566, concurrent autopacking correctness.
1310
        new_pack = packs._new_pack
1311
        self.assertTrue(new_pack.data_inserted())
1312
        new_pack.finish()
1313
        packs.allocate(new_pack)
1314
        packs._new_pack = None
1315
        removed_pack = packs.get_pack_by_name(to_remove_name)
1316
        packs._remove_pack_from_memory(removed_pack)
1317
        names = packs.names()
4634.127.3 by John Arbash Meinel
Add code so we don't try to obsolete files someone else has 'claimed'.
1318
        all_nodes, deleted_nodes, new_nodes, _ = packs._diff_pack_names()
7078.7.1 by Jelmer Vernooij
Fix some stream tests.
1319
        new_names = {x[0] for x in new_nodes}
1320
        self.assertEqual(names, sorted([x[0] for x in all_nodes]))
4634.126.1 by John Arbash Meinel
(jam) Fix bug #507566, concurrent autopacking correctness.
1321
        self.assertEqual(set(names) - set(orig_names), new_names)
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
1322
        self.assertEqual({new_pack.name}, new_names)
4634.126.1 by John Arbash Meinel
(jam) Fix bug #507566, concurrent autopacking correctness.
1323
        self.assertEqual([to_remove_name],
7078.7.1 by Jelmer Vernooij
Fix some stream tests.
1324
                         sorted([x[0] for x in deleted_nodes]))
4634.126.1 by John Arbash Meinel
(jam) Fix bug #507566, concurrent autopacking correctness.
1325
        packs.reload_pack_names()
1326
        reloaded_names = packs.names()
1327
        self.assertEqual(orig_at_load, packs._packs_at_load)
1328
        self.assertEqual(names, reloaded_names)
4634.127.3 by John Arbash Meinel
Add code so we don't try to obsolete files someone else has 'claimed'.
1329
        all_nodes, deleted_nodes, new_nodes, _ = packs._diff_pack_names()
7078.7.1 by Jelmer Vernooij
Fix some stream tests.
1330
        new_names = {x[0] for x in new_nodes}
1331
        self.assertEqual(names, sorted([x[0] for x in all_nodes]))
4634.126.1 by John Arbash Meinel
(jam) Fix bug #507566, concurrent autopacking correctness.
1332
        self.assertEqual(set(names) - set(orig_names), new_names)
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
1333
        self.assertEqual({new_pack.name}, new_names)
4634.126.1 by John Arbash Meinel
(jam) Fix bug #507566, concurrent autopacking correctness.
1334
        self.assertEqual([to_remove_name],
7078.7.1 by Jelmer Vernooij
Fix some stream tests.
1335
                         sorted([x[0] for x in deleted_nodes]))
4634.126.1 by John Arbash Meinel
(jam) Fix bug #507566, concurrent autopacking correctness.
1336
4634.127.5 by John Arbash Meinel
Possible fix for making sure packs triggering autopacking get cleaned up.
1337
    def test_autopack_obsoletes_new_pack(self):
1338
        tree, r, packs, revs = self.make_packs_and_alt_repo(write_lock=True)
1339
        packs._max_pack_count = lambda x: 1
1340
        packs.pack_distribution = lambda x: [10]
1341
        r.start_write_group()
1342
        r.revisions.insert_record_stream([versionedfile.FulltextContentFactory(
7045.4.21 by Jelmer Vernooij
Fix some msgeditor tests.
1343
            (b'bogus-rev',), (), None, b'bogus-content\n')])
4634.127.5 by John Arbash Meinel
Possible fix for making sure packs triggering autopacking get cleaned up.
1344
        # This should trigger an autopack, which will combine everything into a
1345
        # single pack file.
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
1346
        r.commit_write_group()
4634.127.5 by John Arbash Meinel
Possible fix for making sure packs triggering autopacking get cleaned up.
1347
        names = packs.names()
1348
        self.assertEqual(1, len(names))
1349
        self.assertEqual([names[0] + '.pack'],
1350
                         packs._pack_transport.list_dir('.'))
1351
3789.2.20 by John Arbash Meinel
The autopack code can now trigger itself to retry when _copy_revision_texts fails.
1352
    def test_autopack_reloads_and_stops(self):
1353
        tree, r, packs, revs = self.make_packs_and_alt_repo(write_lock=True)
1354
        # After we have determined what needs to be autopacked, trigger a
1355
        # full-pack via the other repo which will cause us to re-evaluate and
1356
        # decide we don't need to do anything
1357
        orig_execute = packs._execute_pack_operations
7143.15.2 by Jelmer Vernooij
Run autopep8.
1358
3789.2.20 by John Arbash Meinel
The autopack code can now trigger itself to retry when _copy_revision_texts fails.
1359
        def _munged_execute_pack_ops(*args, **kwargs):
1360
            tree.branch.repository.pack()
1361
            return orig_execute(*args, **kwargs)
1362
        packs._execute_pack_operations = _munged_execute_pack_ops
1363
        packs._max_pack_count = lambda x: 1
1364
        packs.pack_distribution = lambda x: [10]
1365
        self.assertFalse(packs.autopack())
1366
        self.assertEqual(1, len(packs.names()))
1367
        self.assertEqual(tree.branch.repository._pack_collection.names(),
1368
                         packs.names())
1369
4634.127.1 by John Arbash Meinel
Partial fix for bug #507557.
1370
    def test__save_pack_names(self):
1371
        tree, r, packs, revs = self.make_packs_and_alt_repo(write_lock=True)
1372
        names = packs.names()
1373
        pack = packs.get_pack_by_name(names[0])
1374
        packs._remove_pack_from_memory(pack)
1375
        packs._save_pack_names(obsolete_packs=[pack])
1376
        cur_packs = packs._pack_transport.list_dir('.')
1377
        self.assertEqual([n + '.pack' for n in names[1:]], sorted(cur_packs))
1378
        # obsolete_packs will also have stuff like .rix and .iix present.
1379
        obsolete_packs = packs.transport.list_dir('obsolete_packs')
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
1380
        obsolete_names = {osutils.splitext(n)[0] for n in obsolete_packs}
4634.127.1 by John Arbash Meinel
Partial fix for bug #507557.
1381
        self.assertEqual([pack.name], sorted(obsolete_names))
1382
1383
    def test__save_pack_names_already_obsoleted(self):
1384
        tree, r, packs, revs = self.make_packs_and_alt_repo(write_lock=True)
1385
        names = packs.names()
1386
        pack = packs.get_pack_by_name(names[0])
1387
        packs._remove_pack_from_memory(pack)
1388
        # We are going to simulate a concurrent autopack by manually obsoleting
1389
        # the pack directly.
1390
        packs._obsolete_packs([pack])
1391
        packs._save_pack_names(clear_obsolete_packs=True,
1392
                               obsolete_packs=[pack])
1393
        cur_packs = packs._pack_transport.list_dir('.')
1394
        self.assertEqual([n + '.pack' for n in names[1:]], sorted(cur_packs))
1395
        # Note that while we set clear_obsolete_packs=True, it should not
1396
        # delete a pack file that we have also scheduled for obsoletion.
1397
        obsolete_packs = packs.transport.list_dir('obsolete_packs')
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
1398
        obsolete_names = {osutils.splitext(n)[0] for n in obsolete_packs}
4634.127.1 by John Arbash Meinel
Partial fix for bug #507557.
1399
        self.assertEqual([pack.name], sorted(obsolete_names))
1400
6225.2.6 by Jelmer Vernooij
Move pack clear test to test_repository.
1401
    def test_pack_no_obsolete_packs_directory(self):
1402
        """Bug #314314, don't fail if obsolete_packs directory does
1403
        not exist."""
1404
        tree, r, packs, revs = self.make_packs_and_alt_repo(write_lock=True)
1405
        r.control_transport.rmdir('obsolete_packs')
1406
        packs._clear_obsolete_packs()
4634.127.3 by John Arbash Meinel
Add code so we don't try to obsolete files someone else has 'claimed'.
1407
2592.3.173 by Robert Collins
Basic implementation of all_packs.
1408
1409
class TestPack(TestCaseWithTransport):
1410
    """Tests for the Pack object."""
1411
1412
    def assertCurrentlyEqual(self, left, right):
1413
        self.assertTrue(left == right)
1414
        self.assertTrue(right == left)
1415
        self.assertFalse(left != right)
1416
        self.assertFalse(right != left)
1417
1418
    def assertCurrentlyNotEqual(self, left, right):
1419
        self.assertFalse(left == right)
1420
        self.assertFalse(right == left)
1421
        self.assertTrue(left != right)
1422
        self.assertTrue(right != left)
1423
1424
    def test___eq____ne__(self):
2592.3.191 by Robert Collins
Give Pack responsibility for index naming, and two concrete classes - NewPack for new packs and ExistingPack for packs we read from disk.
1425
        left = pack_repo.ExistingPack('', '', '', '', '', '')
1426
        right = pack_repo.ExistingPack('', '', '', '', '', '')
2592.3.173 by Robert Collins
Basic implementation of all_packs.
1427
        self.assertCurrentlyEqual(left, right)
1428
        # change all attributes and ensure equality changes as we do.
1429
        left.revision_index = 'a'
1430
        self.assertCurrentlyNotEqual(left, right)
1431
        right.revision_index = 'a'
1432
        self.assertCurrentlyEqual(left, right)
1433
        left.inventory_index = 'a'
1434
        self.assertCurrentlyNotEqual(left, right)
1435
        right.inventory_index = 'a'
1436
        self.assertCurrentlyEqual(left, right)
1437
        left.text_index = 'a'
1438
        self.assertCurrentlyNotEqual(left, right)
1439
        right.text_index = 'a'
1440
        self.assertCurrentlyEqual(left, right)
1441
        left.signature_index = 'a'
1442
        self.assertCurrentlyNotEqual(left, right)
1443
        right.signature_index = 'a'
1444
        self.assertCurrentlyEqual(left, right)
1445
        left.name = 'a'
1446
        self.assertCurrentlyNotEqual(left, right)
1447
        right.name = 'a'
1448
        self.assertCurrentlyEqual(left, right)
1449
        left.transport = 'a'
1450
        self.assertCurrentlyNotEqual(left, right)
1451
        right.transport = 'a'
1452
        self.assertCurrentlyEqual(left, right)
2592.3.179 by Robert Collins
Generate the revision_index_map for packing during the core operation, from the pack objects.
1453
1454
    def test_file_name(self):
2592.3.191 by Robert Collins
Give Pack responsibility for index naming, and two concrete classes - NewPack for new packs and ExistingPack for packs we read from disk.
1455
        pack = pack_repo.ExistingPack('', 'a_name', '', '', '', '')
2592.3.179 by Robert Collins
Generate the revision_index_map for packing during the core operation, from the pack objects.
1456
        self.assertEqual('a_name.pack', pack.file_name())
2592.3.192 by Robert Collins
Move new revision index management to NewPack.
1457
1458
1459
class TestNewPack(TestCaseWithTransport):
1460
    """Tests for pack_repo.NewPack."""
1461
2592.3.193 by Robert Collins
Move hash tracking of new packs into NewPack.
1462
    def test_new_instance_attributes(self):
2592.3.194 by Robert Collins
Output the revision index from NewPack.finish
1463
        upload_transport = self.get_transport('upload')
1464
        pack_transport = self.get_transport('pack')
1465
        index_transport = self.get_transport('index')
1466
        upload_transport.mkdir('.')
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
1467
        collection = pack_repo.RepositoryPackCollection(
1468
            repo=None,
3830.3.1 by Martin Pool
NewPack should be constructed from the PackCollection, rather than attributes of it
1469
            transport=self.get_transport('.'),
1470
            index_transport=index_transport,
1471
            upload_transport=upload_transport,
1472
            pack_transport=pack_transport,
1473
            index_builder_class=BTreeBuilder,
4241.6.8 by Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil
Add --development6-rich-root, disabling the legacy and unneeded development2 format, and activating the tests for CHK features disabled pending this format. (Robert Collins, John Arbash Meinel, Ian Clatworthy, Vincent Ladeuil)
1474
            index_class=BTreeGraphIndex,
1475
            use_chk_index=False)
3830.3.1 by Martin Pool
NewPack should be constructed from the PackCollection, rather than attributes of it
1476
        pack = pack_repo.NewPack(collection)
7143.15.2 by Jelmer Vernooij
Run autopep8.
1477
        self.addCleanup(pack.abort)  # Make sure the write stream gets closed
3735.1.1 by Robert Collins
Add development2 formats using BTree indices.
1478
        self.assertIsInstance(pack.revision_index, BTreeBuilder)
1479
        self.assertIsInstance(pack.inventory_index, BTreeBuilder)
2929.3.5 by Vincent Ladeuil
New files, same warnings, same fixes.
1480
        self.assertIsInstance(pack._hash, type(osutils.md5()))
2592.3.194 by Robert Collins
Output the revision index from NewPack.finish
1481
        self.assertTrue(pack.upload_transport is upload_transport)
1482
        self.assertTrue(pack.index_transport is index_transport)
1483
        self.assertTrue(pack.pack_transport is pack_transport)
1484
        self.assertEqual(None, pack.index_sizes)
1485
        self.assertEqual(20, len(pack.random_name))
1486
        self.assertIsInstance(pack.random_name, str)
1487
        self.assertIsInstance(pack.start_time, float)
2951.1.2 by Robert Collins
Partial refactoring of pack_repo to create a Packer object for packing.
1488
1489
1490
class TestPacker(TestCaseWithTransport):
1491
    """Tests for the packs repository Packer class."""
2951.1.10 by Robert Collins
Peer review feedback with Ian.
1492
3824.2.4 by John Arbash Meinel
Add a test that ensures the pack ordering changes as part of calling .pack()
1493
    def test_pack_optimizes_pack_order(self):
4617.8.1 by Robert Collins
Lock down another test assuming the default was a PackRepository.
1494
        builder = self.make_branch_builder('.', format="1.9")
3824.2.4 by John Arbash Meinel
Add a test that ensures the pack ordering changes as part of calling .pack()
1495
        builder.start_series()
6816.2.3 by Jelmer Vernooij
Port over last uses of build_snapshot.
1496
        builder.build_snapshot(None, [
6973.13.2 by Jelmer Vernooij
Fix some more tests.
1497
            ('add', ('', b'root-id', 'directory', None)),
1498
            ('add', ('f', b'f-id', 'file', b'content\n'))],
6973.5.2 by Jelmer Vernooij
Add more bees.
1499
            revision_id=b'A')
6973.13.2 by Jelmer Vernooij
Fix some more tests.
1500
        builder.build_snapshot([b'A'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1501
                               [('modify', ('f', b'new-content\n'))],
1502
                               revision_id=b'B')
6973.13.2 by Jelmer Vernooij
Fix some more tests.
1503
        builder.build_snapshot([b'B'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1504
                               [('modify', ('f', b'third-content\n'))],
1505
                               revision_id=b'C')
6973.13.2 by Jelmer Vernooij
Fix some more tests.
1506
        builder.build_snapshot([b'C'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1507
                               [('modify', ('f', b'fourth-content\n'))],
1508
                               revision_id=b'D')
3824.2.4 by John Arbash Meinel
Add a test that ensures the pack ordering changes as part of calling .pack()
1509
        b = builder.get_branch()
1510
        b.lock_read()
1511
        builder.finish_series()
1512
        self.addCleanup(b.unlock)
1513
        # At this point, we should have 4 pack files available
1514
        # Because of how they were built, they correspond to
1515
        # ['D', 'C', 'B', 'A']
1516
        packs = b.repository._pack_collection.packs
5757.7.5 by Jelmer Vernooij
Fix imports in tests.
1517
        packer = knitpack_repo.KnitPacker(b.repository._pack_collection,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1518
                                          packs, 'testing',
1519
                                          revision_ids=[b'B', b'C'])
3824.2.4 by John Arbash Meinel
Add a test that ensures the pack ordering changes as part of calling .pack()
1520
        # Now, when we are copying the B & C revisions, their pack files should
1521
        # be moved to the front of the stack
3824.2.5 by Andrew Bennetts
Minor tweaks to comments etc.
1522
        # The new ordering moves B & C to the front of the .packs attribute,
1523
        # and leaves the others in the original order.
3824.2.4 by John Arbash Meinel
Add a test that ensures the pack ordering changes as part of calling .pack()
1524
        new_packs = [packs[1], packs[2], packs[0], packs[3]]
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
1525
        packer.pack()
3824.2.4 by John Arbash Meinel
Add a test that ensures the pack ordering changes as part of calling .pack()
1526
        self.assertEqual(new_packs, packer.packs)
3146.6.1 by Aaron Bentley
InterDifferingSerializer shows a progress bar
1527
1528
3777.5.4 by John Arbash Meinel
OptimisingPacker now sets the optimize flags for the indexes being built.
1529
class TestOptimisingPacker(TestCaseWithTransport):
1530
    """Tests for the OptimisingPacker class."""
1531
1532
    def get_pack_collection(self):
1533
        repo = self.make_repository('.')
1534
        return repo._pack_collection
1535
1536
    def test_open_pack_will_optimise(self):
5757.7.3 by Jelmer Vernooij
Move more knitpack-specific functionality out of Packer.
1537
        packer = knitpack_repo.OptimisingKnitPacker(self.get_pack_collection(),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1538
                                                    [], '.test')
3777.5.4 by John Arbash Meinel
OptimisingPacker now sets the optimize flags for the indexes being built.
1539
        new_pack = packer.open_pack()
7143.15.2 by Jelmer Vernooij
Run autopep8.
1540
        self.addCleanup(new_pack.abort)  # ensure cleanup
3777.5.4 by John Arbash Meinel
OptimisingPacker now sets the optimize flags for the indexes being built.
1541
        self.assertIsInstance(new_pack, pack_repo.NewPack)
1542
        self.assertTrue(new_pack.revision_index._optimize_for_size)
1543
        self.assertTrue(new_pack.inventory_index._optimize_for_size)
1544
        self.assertTrue(new_pack.text_index._optimize_for_size)
1545
        self.assertTrue(new_pack.signature_index._optimize_for_size)
4462.2.6 by Robert Collins
Cause StreamSink to partially pack repositories after cross format fetches when beneficial.
1546
1547
4634.170.1 by John Arbash Meinel
Fix bug #437003. Autopacking should not fail for an
1548
class TestGCCHKPacker(TestCaseWithTransport):
1549
1550
    def make_abc_branch(self):
1551
        builder = self.make_branch_builder('source')
1552
        builder.start_series()
6816.2.3 by Jelmer Vernooij
Port over last uses of build_snapshot.
1553
        builder.build_snapshot(None, [
6973.13.2 by Jelmer Vernooij
Fix some more tests.
1554
            ('add', ('', b'root-id', 'directory', None)),
1555
            ('add', ('file', b'file-id', 'file', b'content\n')),
6973.5.2 by Jelmer Vernooij
Add more bees.
1556
            ], revision_id=b'A')
6973.13.2 by Jelmer Vernooij
Fix some more tests.
1557
        builder.build_snapshot([b'A'], [
1558
            ('add', ('dir', b'dir-id', 'directory', None))],
6973.5.2 by Jelmer Vernooij
Add more bees.
1559
            revision_id=b'B')
6973.13.2 by Jelmer Vernooij
Fix some more tests.
1560
        builder.build_snapshot([b'B'], [
1561
            ('modify', ('file', b'new content\n'))],
6973.5.2 by Jelmer Vernooij
Add more bees.
1562
            revision_id=b'C')
4634.170.1 by John Arbash Meinel
Fix bug #437003. Autopacking should not fail for an
1563
        builder.finish_series()
1564
        return builder.get_branch()
1565
1566
    def make_branch_with_disjoint_inventory_and_revision(self):
1567
        """a repo with separate packs for a revisions Revision and Inventory.
1568
1569
        There will be one pack file that holds the Revision content, and one
1570
        for the Inventory content.
1571
1572
        :return: (repository,
1573
                  pack_name_with_rev_A_Revision,
1574
                  pack_name_with_rev_A_Inventory,
1575
                  pack_name_with_rev_C_content)
1576
        """
1577
        b_source = self.make_abc_branch()
7143.15.2 by Jelmer Vernooij
Run autopep8.
1578
        b_base = b_source.controldir.sprout(
1579
            'base', revision_id=b'A').open_branch()
1580
        b_stacked = b_base.controldir.sprout(
1581
            'stacked', stacked=True).open_branch()
4634.170.1 by John Arbash Meinel
Fix bug #437003. Autopacking should not fail for an
1582
        b_stacked.lock_write()
1583
        self.addCleanup(b_stacked.unlock)
7045.4.13 by Jelmer Vernooij
Some more test fixes.
1584
        b_stacked.fetch(b_source, b'B')
4634.170.1 by John Arbash Meinel
Fix bug #437003. Autopacking should not fail for an
1585
        # Now re-open the stacked repo directly (no fallbacks) so that we can
1586
        # fill in the A rev.
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
1587
        repo_not_stacked = b_stacked.controldir.open_repository()
4634.170.1 by John Arbash Meinel
Fix bug #437003. Autopacking should not fail for an
1588
        repo_not_stacked.lock_write()
1589
        self.addCleanup(repo_not_stacked.unlock)
1590
        # Now we should have a pack file with A's inventory, but not its
1591
        # Revision
7045.4.13 by Jelmer Vernooij
Some more test fixes.
1592
        self.assertEqual([(b'A',), (b'B',)],
4634.170.1 by John Arbash Meinel
Fix bug #437003. Autopacking should not fail for an
1593
                         sorted(repo_not_stacked.inventories.keys()))
7045.4.13 by Jelmer Vernooij
Some more test fixes.
1594
        self.assertEqual([(b'B',)],
4634.170.1 by John Arbash Meinel
Fix bug #437003. Autopacking should not fail for an
1595
                         sorted(repo_not_stacked.revisions.keys()))
1596
        stacked_pack_names = repo_not_stacked._pack_collection.names()
1597
        # We have a couple names here, figure out which has A's inventory
1598
        for name in stacked_pack_names:
1599
            pack = repo_not_stacked._pack_collection.get_pack_by_name(name)
1600
            keys = [n[1] for n in pack.inventory_index.iter_all_entries()]
7045.4.13 by Jelmer Vernooij
Some more test fixes.
1601
            if (b'A',) in keys:
4634.170.1 by John Arbash Meinel
Fix bug #437003. Autopacking should not fail for an
1602
                inv_a_pack_name = name
1603
                break
1604
        else:
1605
            self.fail('Could not find pack containing A\'s inventory')
7045.4.13 by Jelmer Vernooij
Some more test fixes.
1606
        repo_not_stacked.fetch(b_source.repository, b'A')
1607
        self.assertEqual([(b'A',), (b'B',)],
4634.170.1 by John Arbash Meinel
Fix bug #437003. Autopacking should not fail for an
1608
                         sorted(repo_not_stacked.revisions.keys()))
1609
        new_pack_names = set(repo_not_stacked._pack_collection.names())
1610
        rev_a_pack_names = new_pack_names.difference(stacked_pack_names)
1611
        self.assertEqual(1, len(rev_a_pack_names))
1612
        rev_a_pack_name = list(rev_a_pack_names)[0]
1613
        # Now fetch 'C', so we have a couple pack files to join
7045.4.13 by Jelmer Vernooij
Some more test fixes.
1614
        repo_not_stacked.fetch(b_source.repository, b'C')
4634.170.1 by John Arbash Meinel
Fix bug #437003. Autopacking should not fail for an
1615
        rev_c_pack_names = set(repo_not_stacked._pack_collection.names())
1616
        rev_c_pack_names = rev_c_pack_names.difference(new_pack_names)
1617
        self.assertEqual(1, len(rev_c_pack_names))
1618
        rev_c_pack_name = list(rev_c_pack_names)[0]
1619
        return (repo_not_stacked, rev_a_pack_name, inv_a_pack_name,
1620
                rev_c_pack_name)
1621
1622
    def test_pack_with_distant_inventories(self):
1623
        # See https://bugs.launchpad.net/bzr/+bug/437003
1624
        # When repacking, it is possible to have an inventory in a different
1625
        # pack file than the associated revision. An autopack can then come
1626
        # along, and miss that inventory, and complain.
1627
        (repo, rev_a_pack_name, inv_a_pack_name, rev_c_pack_name
1628
         ) = self.make_branch_with_disjoint_inventory_and_revision()
1629
        a_pack = repo._pack_collection.get_pack_by_name(rev_a_pack_name)
1630
        c_pack = repo._pack_collection.get_pack_by_name(rev_c_pack_name)
1631
        packer = groupcompress_repo.GCCHKPacker(repo._pack_collection,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1632
                                                [a_pack, c_pack], '.test-pack')
4634.170.1 by John Arbash Meinel
Fix bug #437003. Autopacking should not fail for an
1633
        # This would raise ValueError in bug #437003, but should not raise an
1634
        # error once fixed.
1635
        packer.pack()
1636
1637
    def test_pack_with_missing_inventory(self):
1638
        # Similar to test_pack_with_missing_inventory, but this time, we force
1639
        # the A inventory to actually be gone from the repository.
1640
        (repo, rev_a_pack_name, inv_a_pack_name, rev_c_pack_name
1641
         ) = self.make_branch_with_disjoint_inventory_and_revision()
1642
        inv_a_pack = repo._pack_collection.get_pack_by_name(inv_a_pack_name)
1643
        repo._pack_collection._remove_pack_from_memory(inv_a_pack)
1644
        packer = groupcompress_repo.GCCHKPacker(repo._pack_collection,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1645
                                                repo._pack_collection.all_packs(), '.test-pack')
4634.170.1 by John Arbash Meinel
Fix bug #437003. Autopacking should not fail for an
1646
        e = self.assertRaises(ValueError, packer.pack)
1647
        packer.new_pack.abort()
4634.170.2 by John Arbash Meinel
Loosen the match a bit. Newer versions have StaticTuple.
1648
        self.assertContainsRe(str(e),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1649
                              r"We are missing inventories for revisions: .*'A'")
4634.170.1 by John Arbash Meinel
Fix bug #437003. Autopacking should not fail for an
1650
1651
4431.3.7 by Jonathan Lange
Cherrypick bzr.dev 4470, resolving conflicts.
1652
class TestCrossFormatPacks(TestCaseWithTransport):
1653
1654
    def log_pack(self, hint=None):
1655
        self.calls.append(('pack', hint))
1656
        self.orig_pack(hint=hint)
1657
        if self.expect_hint:
1658
            self.assertTrue(hint)
1659
1660
    def run_stream(self, src_fmt, target_fmt, expect_pack_called):
1661
        self.expect_hint = expect_pack_called
1662
        self.calls = []
1663
        source_tree = self.make_branch_and_tree('src', format=src_fmt)
1664
        source_tree.lock_write()
1665
        self.addCleanup(source_tree.unlock)
1666
        tip = source_tree.commit('foo')
1667
        target = self.make_repository('target', format=target_fmt)
1668
        target.lock_write()
1669
        self.addCleanup(target.unlock)
1670
        source = source_tree.branch.repository._get_source(target._format)
1671
        self.orig_pack = target.pack
5340.15.1 by John Arbash Meinel
supersede exc-info branch
1672
        self.overrideAttr(target, "pack", self.log_pack)
4431.3.7 by Jonathan Lange
Cherrypick bzr.dev 4470, resolving conflicts.
1673
        search = target.search_missing_revision_ids(
5539.2.11 by Andrew Bennetts
Fix deprecation warning from test suite.
1674
            source_tree.branch.repository, revision_ids=[tip])
4431.3.7 by Jonathan Lange
Cherrypick bzr.dev 4470, resolving conflicts.
1675
        stream = source.get_stream(search)
1676
        from_format = source_tree.branch.repository._format
1677
        sink = target._get_sink()
1678
        sink.insert_stream(stream, from_format, [])
1679
        if expect_pack_called:
1680
            self.assertLength(1, self.calls)
1681
        else:
1682
            self.assertLength(0, self.calls)
1683
1684
    def run_fetch(self, src_fmt, target_fmt, expect_pack_called):
1685
        self.expect_hint = expect_pack_called
1686
        self.calls = []
1687
        source_tree = self.make_branch_and_tree('src', format=src_fmt)
1688
        source_tree.lock_write()
1689
        self.addCleanup(source_tree.unlock)
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
1690
        source_tree.commit('foo')
4431.3.7 by Jonathan Lange
Cherrypick bzr.dev 4470, resolving conflicts.
1691
        target = self.make_repository('target', format=target_fmt)
1692
        target.lock_write()
1693
        self.addCleanup(target.unlock)
1694
        source = source_tree.branch.repository
1695
        self.orig_pack = target.pack
5340.15.1 by John Arbash Meinel
supersede exc-info branch
1696
        self.overrideAttr(target, "pack", self.log_pack)
4431.3.7 by Jonathan Lange
Cherrypick bzr.dev 4470, resolving conflicts.
1697
        target.fetch(source)
1698
        if expect_pack_called:
1699
            self.assertLength(1, self.calls)
1700
        else:
1701
            self.assertLength(0, self.calls)
1702
1703
    def test_sink_format_hint_no(self):
1704
        # When the target format says packing makes no difference, pack is not
1705
        # called.
1706
        self.run_stream('1.9', 'rich-root-pack', False)
1707
1708
    def test_sink_format_hint_yes(self):
1709
        # When the target format says packing makes a difference, pack is
1710
        # called.
1711
        self.run_stream('1.9', '2a', True)
1712
1713
    def test_sink_format_same_no(self):
1714
        # When the formats are the same, pack is not called.
1715
        self.run_stream('2a', '2a', False)
1716
1717
    def test_IDS_format_hint_no(self):
1718
        # When the target format says packing makes no difference, pack is not
1719
        # called.
1720
        self.run_fetch('1.9', 'rich-root-pack', False)
1721
1722
    def test_IDS_format_hint_yes(self):
1723
        # When the target format says packing makes a difference, pack is
1724
        # called.
1725
        self.run_fetch('1.9', '2a', True)
1726
1727
    def test_IDS_format_same_no(self):
1728
        # When the formats are the same, pack is not called.
1729
        self.run_fetch('2a', '2a', False)
6015.20.1 by John Arbash Meinel
Add a __repr__ to _LazyListJoin to make it easier to debug.
1730
1731
1732
class Test_LazyListJoin(tests.TestCase):
1733
1734
    def test__repr__(self):
1735
        lazy = repository._LazyListJoin(['a'], ['b'])
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
1736
        self.assertEqual("breezy.repository._LazyListJoin((['a'], ['b']))",
6015.20.1 by John Arbash Meinel
Add a __repr__ to _LazyListJoin to make it easier to debug.
1737
                         repr(lazy))
6213.1.21 by Jelmer Vernooij
Add feature support for repository.
1738
1739
1740
class TestFeatures(tests.TestCaseWithTransport):
1741
1742
    def test_open_with_present_feature(self):
1743
        self.addCleanup(
6653.2.2 by Jelmer Vernooij
Fix imports.
1744
            bzrrepository.RepositoryFormatMetaDir.unregister_feature,
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
1745
            b"makes-cheese-sandwich")
6653.2.2 by Jelmer Vernooij
Fix imports.
1746
        bzrrepository.RepositoryFormatMetaDir.register_feature(
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
1747
            b"makes-cheese-sandwich")
6213.1.21 by Jelmer Vernooij
Add feature support for repository.
1748
        repo = self.make_repository('.')
1749
        repo.lock_write()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
1750
        repo._format.features[b"makes-cheese-sandwich"] = b"required"
6213.1.21 by Jelmer Vernooij
Add feature support for repository.
1751
        repo._format.check_support_status(False)
1752
        repo.unlock()
1753
1754
    def test_open_with_missing_required_feature(self):
1755
        repo = self.make_repository('.')
1756
        repo.lock_write()
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
1757
        repo._format.features[b"makes-cheese-sandwich"] = b"required"
6731.1.3 by Jelmer Vernooij
Move MissingFeature error to breezy.bzr.bzrdir.
1758
        self.assertRaises(bzrdir.MissingFeature,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1759
                          repo._format.check_support_status, False)