/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/bzr/knitrepo.py

  • Committer: Jelmer Vernooij
  • Date: 2018-11-29 19:43:19 UTC
  • mto: This revision was merged to the branch mainline in revision 7227.
  • Revision ID: jelmer@jelmer.uk-20181129194319-o009qn8wed0q0134
Don't warn if the filter has already been removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
from bzrlib.lazy_import import lazy_import
 
17
from __future__ import absolute_import
 
18
 
 
19
from ..lazy_import import lazy_import
18
20
lazy_import(globals(), """
19
 
from bzrlib import (
20
 
    bzrdir,
 
21
import itertools
 
22
 
 
23
from breezy import (
 
24
    controldir,
21
25
    errors,
22
 
    knit as _mod_knit,
23
26
    lockable_files,
24
27
    lockdir,
25
28
    osutils,
26
29
    revision as _mod_revision,
27
30
    trace,
28
31
    transactions,
 
32
    )
 
33
from breezy.bzr import (
 
34
    knit as _mod_knit,
29
35
    versionedfile,
30
36
    xml5,
31
37
    xml6,
32
38
    xml7,
33
39
    )
34
40
""")
35
 
from bzrlib import (
36
 
    symbol_versioning,
37
 
    )
38
 
from bzrlib.decorators import needs_read_lock, needs_write_lock
39
 
from bzrlib.repository import (
40
 
    CommitBuilder,
41
 
    MetaDirRepository,
42
 
    MetaDirRepositoryFormat,
43
 
    RepositoryFormat,
44
 
    RootCommitBuilder,
 
41
from ..repository import (
 
42
    InterRepository,
 
43
    IsInWriteGroupError,
 
44
    )
 
45
from ..bzr.repository import (
 
46
    RepositoryFormatMetaDir,
 
47
    )
 
48
from ..bzr.vf_repository import (
 
49
    InterSameDataRepository,
 
50
    MetaDirVersionedFileRepository,
 
51
    MetaDirVersionedFileRepositoryFormat,
 
52
    VersionedFileCommitBuilder,
45
53
    )
46
54
 
47
55
 
102
110
        return result
103
111
 
104
112
 
105
 
class KnitRepository(MetaDirRepository):
 
113
class KnitRepository(MetaDirVersionedFileRepository):
106
114
    """Knit format repository."""
107
115
 
108
116
    # These attributes are inherited from the Repository base class. Setting
112
120
    _commit_builder_class = None
113
121
    _serializer = None
114
122
 
115
 
    def __init__(self, _format, a_bzrdir, control_files, _commit_builder_class,
116
 
        _serializer):
117
 
        MetaDirRepository.__init__(self, _format, a_bzrdir, control_files)
 
123
    def __init__(self, _format, a_controldir, control_files, _commit_builder_class,
 
124
                 _serializer):
 
125
        super(KnitRepository, self).__init__(
 
126
            _format, a_controldir, control_files)
118
127
        self._commit_builder_class = _commit_builder_class
119
128
        self._serializer = _serializer
120
129
        self._reconcile_fixes_text_parents = True
121
130
 
122
 
    @needs_read_lock
123
131
    def _all_revision_ids(self):
124
132
        """See Repository.all_revision_ids()."""
125
 
        return [key[0] for key in self.revisions.keys()]
 
133
        with self.lock_read():
 
134
            return [key[0] for key in self.revisions.keys()]
126
135
 
127
136
    def _activate_new_inventory(self):
128
137
        """Put a replacement inventory.new into use as inventories."""
169
178
 
170
179
    def _temp_inventories(self):
171
180
        result = self._format._get_inventories(self._transport, self,
172
 
            'inventory.new')
 
181
                                               'inventory.new')
173
182
        # Reconciling when the output has no revisions would result in no
174
183
        # writes - but we want to ensure there is an inventory for
175
184
        # compatibility with older clients that don't lazy-load.
176
 
        result.get_parent_map([('A',)])
 
185
        result.get_parent_map([(b'A',)])
177
186
        return result
178
187
 
179
 
    def fileid_involved_between_revs(self, from_revid, to_revid):
180
 
        """Find file_id(s) which are involved in the changes between revisions.
181
 
 
182
 
        This determines the set of revisions which are involved, and then
183
 
        finds all file ids affected by those revisions.
184
 
        """
185
 
        vf = self._get_revision_vf()
186
 
        from_set = set(vf.get_ancestry(from_revid))
187
 
        to_set = set(vf.get_ancestry(to_revid))
188
 
        changed = to_set.difference(from_set)
189
 
        return self._fileid_involved_by_set(changed)
190
 
 
191
 
    def fileid_involved(self, last_revid=None):
192
 
        """Find all file_ids modified in the ancestry of last_revid.
193
 
 
194
 
        :param last_revid: If None, last_revision() will be used.
195
 
        """
196
 
        if not last_revid:
197
 
            changed = set(self.all_revision_ids())
198
 
        else:
199
 
            changed = set(self.get_ancestry(last_revid))
200
 
        if None in changed:
201
 
            changed.remove(None)
202
 
        return self._fileid_involved_by_set(changed)
203
 
 
204
 
    @needs_read_lock
205
188
    def get_revision(self, revision_id):
206
189
        """Return the Revision object for a named revision"""
207
190
        revision_id = osutils.safe_revision_id(revision_id)
208
 
        return self.get_revision_reconcile(revision_id)
 
191
        with self.lock_read():
 
192
            return self.get_revision_reconcile(revision_id)
209
193
 
210
194
    def _refresh_data(self):
211
195
        if not self.is_locked():
212
196
            return
 
197
        if self.is_in_write_group():
 
198
            raise IsInWriteGroupError(self)
213
199
        # Create a new transaction to force all knits to see the scope change.
214
200
        # This is safe because we're outside a write group.
215
201
        self.control_files._finish_transaction()
218
204
        else:
219
205
            self.control_files._set_read_transaction()
220
206
 
221
 
    @needs_write_lock
222
207
    def reconcile(self, other=None, thorough=False):
223
208
        """Reconcile this repository."""
224
 
        from bzrlib.reconcile import KnitReconciler
225
 
        reconciler = KnitReconciler(self, thorough=thorough)
226
 
        reconciler.reconcile()
227
 
        return reconciler
 
209
        from breezy.reconcile import KnitReconciler
 
210
        with self.lock_write():
 
211
            reconciler = KnitReconciler(self, thorough=thorough)
 
212
            reconciler.reconcile()
 
213
            return reconciler
228
214
 
229
215
    def _make_parents_provider(self):
230
216
        return _KnitsParentsProvider(self.revisions)
231
217
 
232
 
    def _find_inconsistent_revision_parents(self, revisions_iterator=None):
233
 
        """Find revisions with different parent lists in the revision object
234
 
        and in the index graph.
235
 
 
236
 
        :param revisions_iterator: None, or an iterator of (revid,
237
 
            Revision-or-None). This iterator controls the revisions checked.
238
 
        :returns: an iterator yielding tuples of (revison-id, parents-in-index,
239
 
            parents-in-revision).
240
 
        """
241
 
        if not self.is_locked():
242
 
            raise AssertionError()
243
 
        vf = self.revisions
244
 
        if revisions_iterator is None:
245
 
            revisions_iterator = self._iter_revisions(None)
246
 
        for revid, revision in revisions_iterator:
247
 
            if revision is None:
248
 
                pass
249
 
            parent_map = vf.get_parent_map([(revid,)])
250
 
            parents_according_to_index = tuple(parent[-1] for parent in
251
 
                parent_map[(revid,)])
252
 
            parents_according_to_revision = tuple(revision.parent_ids)
253
 
            if parents_according_to_index != parents_according_to_revision:
254
 
                yield (revid, parents_according_to_index,
255
 
                    parents_according_to_revision)
256
 
 
257
 
    def _check_for_inconsistent_revision_parents(self):
258
 
        inconsistencies = list(self._find_inconsistent_revision_parents())
259
 
        if inconsistencies:
260
 
            raise errors.BzrCheckError(
261
 
                "Revision knit has inconsistent parents.")
262
 
 
263
 
    def revision_graph_can_have_wrong_parents(self):
264
 
        # The revision.kndx could potentially claim a revision has a different
265
 
        # parent to the revision text.
266
 
        return True
267
 
 
268
 
 
269
 
class RepositoryFormatKnit(MetaDirRepositoryFormat):
 
218
 
 
219
class RepositoryFormatKnit(MetaDirVersionedFileRepositoryFormat):
270
220
    """Bzr repository knit format (generalized).
271
221
 
272
222
    This repository format has:
289
239
    _commit_builder_class = None
290
240
    # Set this attribute in derived clases to control the _serializer that the
291
241
    # repository objects will have passed to their constructor.
 
242
 
292
243
    @property
293
244
    def _serializer(self):
294
245
        return xml5.serializer_v5
301
252
    _fetch_order = 'topological'
302
253
    _fetch_uses_deltas = True
303
254
    fast_deltas = False
 
255
    supports_funky_characters = True
 
256
    # The revision.kndx could potentially claim a revision has a different
 
257
    # parent to the revision text.
 
258
    revision_graph_can_have_wrong_parents = True
304
259
 
305
260
    def _get_inventories(self, repo_transport, repo, name='inventory'):
306
261
        mapper = versionedfile.ConstantMapper(name)
307
262
        index = _mod_knit._KndxIndex(repo_transport, mapper,
308
 
            repo.get_transaction, repo.is_write_locked, repo.is_locked)
 
263
                                     repo.get_transaction, repo.is_write_locked, repo.is_locked)
309
264
        access = _mod_knit._KnitKeyAccess(repo_transport, mapper)
310
265
        return _mod_knit.KnitVersionedFiles(index, access, annotated=False)
311
266
 
312
267
    def _get_revisions(self, repo_transport, repo):
313
268
        mapper = versionedfile.ConstantMapper('revisions')
314
269
        index = _mod_knit._KndxIndex(repo_transport, mapper,
315
 
            repo.get_transaction, repo.is_write_locked, repo.is_locked)
 
270
                                     repo.get_transaction, repo.is_write_locked, repo.is_locked)
316
271
        access = _mod_knit._KnitKeyAccess(repo_transport, mapper)
317
272
        return _mod_knit.KnitVersionedFiles(index, access, max_delta_chain=0,
318
 
            annotated=False)
 
273
                                            annotated=False)
319
274
 
320
275
    def _get_signatures(self, repo_transport, repo):
321
276
        mapper = versionedfile.ConstantMapper('signatures')
322
277
        index = _mod_knit._KndxIndex(repo_transport, mapper,
323
 
            repo.get_transaction, repo.is_write_locked, repo.is_locked)
 
278
                                     repo.get_transaction, repo.is_write_locked, repo.is_locked)
324
279
        access = _mod_knit._KnitKeyAccess(repo_transport, mapper)
325
280
        return _mod_knit.KnitVersionedFiles(index, access, max_delta_chain=0,
326
 
            annotated=False)
 
281
                                            annotated=False)
327
282
 
328
283
    def _get_texts(self, repo_transport, repo):
329
284
        mapper = versionedfile.HashEscapedPrefixMapper()
330
285
        base_transport = repo_transport.clone('knits')
331
286
        index = _mod_knit._KndxIndex(base_transport, mapper,
332
 
            repo.get_transaction, repo.is_write_locked, repo.is_locked)
 
287
                                     repo.get_transaction, repo.is_write_locked, repo.is_locked)
333
288
        access = _mod_knit._KnitKeyAccess(base_transport, mapper)
334
289
        return _mod_knit.KnitVersionedFiles(index, access, max_delta_chain=200,
335
 
            annotated=True)
 
290
                                            annotated=True)
336
291
 
337
 
    def initialize(self, a_bzrdir, shared=False):
 
292
    def initialize(self, a_controldir, shared=False):
338
293
        """Create a knit format 1 repository.
339
294
 
340
 
        :param a_bzrdir: bzrdir to contain the new repository; must already
 
295
        :param a_controldir: bzrdir to contain the new repository; must already
341
296
            be initialized.
342
297
        :param shared: If true the repository will be initialized as a shared
343
298
                       repository.
344
299
        """
345
 
        trace.mutter('creating repository in %s.', a_bzrdir.transport.base)
 
300
        trace.mutter('creating repository in %s.', a_controldir.transport.base)
346
301
        dirs = ['knits']
347
302
        files = []
348
303
        utf8_files = [('format', self.get_format_string())]
349
304
 
350
 
        self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
351
 
        repo_transport = a_bzrdir.get_repository_transport(None)
 
305
        self._upload_blank_content(
 
306
            a_controldir, dirs, files, utf8_files, shared)
 
307
        repo_transport = a_controldir.get_repository_transport(None)
352
308
        control_files = lockable_files.LockableFiles(repo_transport,
353
 
                                'lock', lockdir.LockDir)
 
309
                                                     'lock', lockdir.LockDir)
354
310
        transaction = transactions.WriteTransaction()
355
 
        result = self.open(a_bzrdir=a_bzrdir, _found=True)
 
311
        result = self.open(a_controldir=a_controldir, _found=True)
356
312
        result.lock_write()
357
313
        # the revision id here is irrelevant: it will not be stored, and cannot
358
314
        # already exist, we do this to create files on disk for older clients.
359
 
        result.inventories.get_parent_map([('A',)])
360
 
        result.revisions.get_parent_map([('A',)])
361
 
        result.signatures.get_parent_map([('A',)])
 
315
        result.inventories.get_parent_map([(b'A',)])
 
316
        result.revisions.get_parent_map([(b'A',)])
 
317
        result.signatures.get_parent_map([(b'A',)])
362
318
        result.unlock()
363
 
        self._run_post_repo_init_hooks(result, a_bzrdir, shared)
 
319
        self._run_post_repo_init_hooks(result, a_controldir, shared)
364
320
        return result
365
321
 
366
 
    def open(self, a_bzrdir, _found=False, _override_transport=None):
 
322
    def open(self, a_controldir, _found=False, _override_transport=None):
367
323
        """See RepositoryFormat.open().
368
324
 
369
325
        :param _override_transport: INTERNAL USE ONLY. Allows opening the
371
327
                                    than normal. I.e. during 'upgrade'.
372
328
        """
373
329
        if not _found:
374
 
            format = RepositoryFormat.find_format(a_bzrdir)
 
330
            format = RepositoryFormatMetaDir.find_format(a_controldir)
375
331
        if _override_transport is not None:
376
332
            repo_transport = _override_transport
377
333
        else:
378
 
            repo_transport = a_bzrdir.get_repository_transport(None)
 
334
            repo_transport = a_controldir.get_repository_transport(None)
379
335
        control_files = lockable_files.LockableFiles(repo_transport,
380
 
                                'lock', lockdir.LockDir)
 
336
                                                     'lock', lockdir.LockDir)
381
337
        repo = self.repository_class(_format=self,
382
 
                              a_bzrdir=a_bzrdir,
383
 
                              control_files=control_files,
384
 
                              _commit_builder_class=self._commit_builder_class,
385
 
                              _serializer=self._serializer)
 
338
                                     a_controldir=a_controldir,
 
339
                                     control_files=control_files,
 
340
                                     _commit_builder_class=self._commit_builder_class,
 
341
                                     _serializer=self._serializer)
386
342
        repo.revisions = self._get_revisions(repo_transport, repo)
387
343
        repo.signatures = self._get_signatures(repo_transport, repo)
388
344
        repo.inventories = self._get_inventories(repo_transport, repo)
409
365
    """
410
366
 
411
367
    repository_class = KnitRepository
412
 
    _commit_builder_class = CommitBuilder
 
368
    _commit_builder_class = VersionedFileCommitBuilder
 
369
 
413
370
    @property
414
371
    def _serializer(self):
415
372
        return xml5.serializer_v5
417
374
    def __ne__(self, other):
418
375
        return self.__class__ is not other.__class__
419
376
 
420
 
    def get_format_string(self):
 
377
    @classmethod
 
378
    def get_format_string(cls):
421
379
        """See RepositoryFormat.get_format_string()."""
422
 
        return "Bazaar-NG Knit Repository Format 1"
 
380
        return b"Bazaar-NG Knit Repository Format 1"
423
381
 
424
382
    def get_format_description(self):
425
383
        """See RepositoryFormat.get_format_description()."""
443
401
    """
444
402
 
445
403
    repository_class = KnitRepository
446
 
    _commit_builder_class = RootCommitBuilder
 
404
    _commit_builder_class = VersionedFileCommitBuilder
447
405
    rich_root_data = True
448
406
    experimental = True
449
407
    supports_tree_reference = True
 
408
 
450
409
    @property
451
410
    def _serializer(self):
452
411
        return xml7.serializer_v7
453
412
 
454
413
    def _get_matching_bzrdir(self):
455
 
        return bzrdir.format_registry.make_bzrdir('dirstate-with-subtree')
 
414
        return controldir.format_registry.make_controldir('dirstate-with-subtree')
456
415
 
457
416
    def _ignore_setting_bzrdir(self, format):
458
417
        pass
459
418
 
460
 
    _matchingbzrdir = property(_get_matching_bzrdir, _ignore_setting_bzrdir)
 
419
    _matchingcontroldir = property(
 
420
        _get_matching_bzrdir, _ignore_setting_bzrdir)
461
421
 
462
 
    def get_format_string(self):
 
422
    @classmethod
 
423
    def get_format_string(cls):
463
424
        """See RepositoryFormat.get_format_string()."""
464
 
        return "Bazaar Knit Repository Format 3 (bzr 0.15)\n"
 
425
        return b"Bazaar Knit Repository Format 3 (bzr 0.15)\n"
465
426
 
466
427
    def get_format_description(self):
467
428
        """See RepositoryFormat.get_format_description()."""
485
446
    """
486
447
 
487
448
    repository_class = KnitRepository
488
 
    _commit_builder_class = RootCommitBuilder
 
449
    _commit_builder_class = VersionedFileCommitBuilder
489
450
    rich_root_data = True
490
451
    supports_tree_reference = False
 
452
 
491
453
    @property
492
454
    def _serializer(self):
493
455
        return xml6.serializer_v6
494
456
 
495
457
    def _get_matching_bzrdir(self):
496
 
        return bzrdir.format_registry.make_bzrdir('rich-root')
 
458
        return controldir.format_registry.make_controldir('rich-root')
497
459
 
498
460
    def _ignore_setting_bzrdir(self, format):
499
461
        pass
500
462
 
501
 
    _matchingbzrdir = property(_get_matching_bzrdir, _ignore_setting_bzrdir)
 
463
    _matchingcontroldir = property(
 
464
        _get_matching_bzrdir, _ignore_setting_bzrdir)
502
465
 
503
 
    def get_format_string(self):
 
466
    @classmethod
 
467
    def get_format_string(cls):
504
468
        """See RepositoryFormat.get_format_string()."""
505
 
        return 'Bazaar Knit Repository Format 4 (bzr 1.0)\n'
 
469
        return b'Bazaar Knit Repository Format 4 (bzr 1.0)\n'
506
470
 
507
471
    def get_format_description(self):
508
472
        """See RepositoryFormat.get_format_description()."""
509
473
        return "Knit repository format 4"
 
474
 
 
475
 
 
476
class InterKnitRepo(InterSameDataRepository):
 
477
    """Optimised code paths between Knit based repositories."""
 
478
 
 
479
    @classmethod
 
480
    def _get_repo_format_to_test(self):
 
481
        return RepositoryFormatKnit1()
 
482
 
 
483
    @staticmethod
 
484
    def is_compatible(source, target):
 
485
        """Be compatible with known Knit formats.
 
486
 
 
487
        We don't test for the stores being of specific types because that
 
488
        could lead to confusing results, and there is no need to be
 
489
        overly general.
 
490
        """
 
491
        try:
 
492
            are_knits = (isinstance(source._format, RepositoryFormatKnit)
 
493
                         and isinstance(target._format, RepositoryFormatKnit))
 
494
        except AttributeError:
 
495
            return False
 
496
        return are_knits and InterRepository._same_model(source, target)
 
497
 
 
498
    def search_missing_revision_ids(self,
 
499
                                    find_ghosts=True, revision_ids=None, if_present_ids=None,
 
500
                                    limit=None):
 
501
        """See InterRepository.search_missing_revision_ids()."""
 
502
        with self.lock_read():
 
503
            source_ids_set = self._present_source_revisions_for(
 
504
                revision_ids, if_present_ids)
 
505
            # source_ids is the worst possible case we may need to pull.
 
506
            # now we want to filter source_ids against what we actually
 
507
            # have in target, but don't try to check for existence where we know
 
508
            # we do not have a revision as that would be pointless.
 
509
            target_ids = set(self.target.all_revision_ids())
 
510
            possibly_present_revisions = target_ids.intersection(
 
511
                source_ids_set)
 
512
            actually_present_revisions = set(
 
513
                self.target._eliminate_revisions_not_present(possibly_present_revisions))
 
514
            required_revisions = source_ids_set.difference(
 
515
                actually_present_revisions)
 
516
            if revision_ids is not None:
 
517
                # we used get_ancestry to determine source_ids then we are assured all
 
518
                # revisions referenced are present as they are installed in topological order.
 
519
                # and the tip revision was validated by get_ancestry.
 
520
                result_set = required_revisions
 
521
            else:
 
522
                # if we just grabbed the possibly available ids, then
 
523
                # we only have an estimate of whats available and need to validate
 
524
                # that against the revision records.
 
525
                result_set = set(
 
526
                    self.source._eliminate_revisions_not_present(required_revisions))
 
527
            if limit is not None:
 
528
                topo_ordered = self.source.get_graph().iter_topo_order(result_set)
 
529
                result_set = set(itertools.islice(topo_ordered, limit))
 
530
            return self.source.revision_ids_to_search_result(result_set)
 
531
 
 
532
 
 
533
InterRepository.register_optimiser(InterKnitRepo)