~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repofmt/knitrepo.py

(jelmer) Use the absolute_import feature everywhere in bzrlib,
 and add a source test to make sure it's used everywhere. (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2007-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
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 __future__ import absolute_import
 
18
 
17
19
from bzrlib.lazy_import import lazy_import
18
20
lazy_import(globals(), """
 
21
import itertools
 
22
 
19
23
from bzrlib import (
20
24
    bzrdir,
21
25
    errors,
24
28
    lockdir,
25
29
    osutils,
26
30
    revision as _mod_revision,
 
31
    trace,
27
32
    transactions,
28
33
    versionedfile,
29
34
    xml5,
31
36
    xml7,
32
37
    )
33
38
""")
34
 
from bzrlib import (
35
 
    symbol_versioning,
36
 
    )
37
39
from bzrlib.decorators import needs_read_lock, needs_write_lock
38
40
from bzrlib.repository import (
39
 
    CommitBuilder,
40
 
    MetaDirRepository,
41
 
    MetaDirRepositoryFormat,
42
 
    RepositoryFormat,
43
 
    RootCommitBuilder,
44
 
    )
45
 
from bzrlib.trace import mutter, mutter_callsite
 
41
    InterRepository,
 
42
    IsInWriteGroupError,
 
43
    RepositoryFormatMetaDir,
 
44
    )
 
45
from bzrlib.vf_repository import (
 
46
    InterSameDataRepository,
 
47
    MetaDirVersionedFileRepository,
 
48
    MetaDirVersionedFileRepositoryFormat,
 
49
    VersionedFileCommitBuilder,
 
50
    VersionedFileRootCommitBuilder,
 
51
    )
 
52
from bzrlib import symbol_versioning
46
53
 
47
54
 
48
55
class _KnitParentsProvider(object):
102
109
        return result
103
110
 
104
111
 
105
 
class KnitRepository(MetaDirRepository):
 
112
class KnitRepository(MetaDirVersionedFileRepository):
106
113
    """Knit format repository."""
107
114
 
108
115
    # These attributes are inherited from the Repository base class. Setting
114
121
 
115
122
    def __init__(self, _format, a_bzrdir, control_files, _commit_builder_class,
116
123
        _serializer):
117
 
        MetaDirRepository.__init__(self, _format, a_bzrdir, control_files)
 
124
        super(KnitRepository, self).__init__(_format, a_bzrdir, control_files)
118
125
        self._commit_builder_class = _commit_builder_class
119
126
        self._serializer = _serializer
120
127
        self._reconcile_fixes_text_parents = True
176
183
        result.get_parent_map([('A',)])
177
184
        return result
178
185
 
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
186
    @needs_read_lock
205
187
    def get_revision(self, revision_id):
206
188
        """Return the Revision object for a named revision"""
210
192
    def _refresh_data(self):
211
193
        if not self.is_locked():
212
194
            return
 
195
        if self.is_in_write_group():
 
196
            raise IsInWriteGroupError(self)
213
197
        # Create a new transaction to force all knits to see the scope change.
214
198
        # This is safe because we're outside a write group.
215
199
        self.control_files._finish_transaction()
229
213
    def _make_parents_provider(self):
230
214
        return _KnitsParentsProvider(self.revisions)
231
215
 
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):
 
216
 
 
217
class RepositoryFormatKnit(MetaDirVersionedFileRepositoryFormat):
270
218
    """Bzr repository knit format (generalized).
271
219
 
272
220
    This repository format has:
301
249
    _fetch_order = 'topological'
302
250
    _fetch_uses_deltas = True
303
251
    fast_deltas = False
 
252
    supports_funky_characters = True
 
253
    # The revision.kndx could potentially claim a revision has a different
 
254
    # parent to the revision text.
 
255
    revision_graph_can_have_wrong_parents = True
304
256
 
305
257
    def _get_inventories(self, repo_transport, repo, name='inventory'):
306
258
        mapper = versionedfile.ConstantMapper(name)
342
294
        :param shared: If true the repository will be initialized as a shared
343
295
                       repository.
344
296
        """
345
 
        mutter('creating repository in %s.', a_bzrdir.transport.base)
 
297
        trace.mutter('creating repository in %s.', a_bzrdir.transport.base)
346
298
        dirs = ['knits']
347
299
        files = []
348
300
        utf8_files = [('format', self.get_format_string())]
360
312
        result.revisions.get_parent_map([('A',)])
361
313
        result.signatures.get_parent_map([('A',)])
362
314
        result.unlock()
 
315
        self._run_post_repo_init_hooks(result, a_bzrdir, shared)
363
316
        return result
364
317
 
365
318
    def open(self, a_bzrdir, _found=False, _override_transport=None):
370
323
                                    than normal. I.e. during 'upgrade'.
371
324
        """
372
325
        if not _found:
373
 
            format = RepositoryFormat.find_format(a_bzrdir)
 
326
            format = RepositoryFormatMetaDir.find_format(a_bzrdir)
374
327
        if _override_transport is not None:
375
328
            repo_transport = _override_transport
376
329
        else:
408
361
    """
409
362
 
410
363
    repository_class = KnitRepository
411
 
    _commit_builder_class = CommitBuilder
 
364
    _commit_builder_class = VersionedFileCommitBuilder
412
365
    @property
413
366
    def _serializer(self):
414
367
        return xml5.serializer_v5
416
369
    def __ne__(self, other):
417
370
        return self.__class__ is not other.__class__
418
371
 
419
 
    def get_format_string(self):
 
372
    @classmethod
 
373
    def get_format_string(cls):
420
374
        """See RepositoryFormat.get_format_string()."""
421
375
        return "Bazaar-NG Knit Repository Format 1"
422
376
 
442
396
    """
443
397
 
444
398
    repository_class = KnitRepository
445
 
    _commit_builder_class = RootCommitBuilder
 
399
    _commit_builder_class = VersionedFileRootCommitBuilder
446
400
    rich_root_data = True
 
401
    experimental = True
447
402
    supports_tree_reference = True
448
403
    @property
449
404
    def _serializer(self):
457
412
 
458
413
    _matchingbzrdir = property(_get_matching_bzrdir, _ignore_setting_bzrdir)
459
414
 
460
 
    def get_format_string(self):
 
415
    @classmethod
 
416
    def get_format_string(cls):
461
417
        """See RepositoryFormat.get_format_string()."""
462
418
        return "Bazaar Knit Repository Format 3 (bzr 0.15)\n"
463
419
 
483
439
    """
484
440
 
485
441
    repository_class = KnitRepository
486
 
    _commit_builder_class = RootCommitBuilder
 
442
    _commit_builder_class = VersionedFileRootCommitBuilder
487
443
    rich_root_data = True
488
444
    supports_tree_reference = False
489
445
    @property
498
454
 
499
455
    _matchingbzrdir = property(_get_matching_bzrdir, _ignore_setting_bzrdir)
500
456
 
501
 
    def get_format_string(self):
 
457
    @classmethod
 
458
    def get_format_string(cls):
502
459
        """See RepositoryFormat.get_format_string()."""
503
460
        return 'Bazaar Knit Repository Format 4 (bzr 1.0)\n'
504
461
 
505
462
    def get_format_description(self):
506
463
        """See RepositoryFormat.get_format_description()."""
507
464
        return "Knit repository format 4"
 
465
 
 
466
 
 
467
class InterKnitRepo(InterSameDataRepository):
 
468
    """Optimised code paths between Knit based repositories."""
 
469
 
 
470
    @classmethod
 
471
    def _get_repo_format_to_test(self):
 
472
        return RepositoryFormatKnit1()
 
473
 
 
474
    @staticmethod
 
475
    def is_compatible(source, target):
 
476
        """Be compatible with known Knit formats.
 
477
 
 
478
        We don't test for the stores being of specific types because that
 
479
        could lead to confusing results, and there is no need to be
 
480
        overly general.
 
481
        """
 
482
        try:
 
483
            are_knits = (isinstance(source._format, RepositoryFormatKnit) and
 
484
                isinstance(target._format, RepositoryFormatKnit))
 
485
        except AttributeError:
 
486
            return False
 
487
        return are_knits and InterRepository._same_model(source, target)
 
488
 
 
489
    @needs_read_lock
 
490
    def search_missing_revision_ids(self,
 
491
            revision_id=symbol_versioning.DEPRECATED_PARAMETER,
 
492
            find_ghosts=True, revision_ids=None, if_present_ids=None,
 
493
            limit=None):
 
494
        """See InterRepository.search_missing_revision_ids()."""
 
495
        if symbol_versioning.deprecated_passed(revision_id):
 
496
            symbol_versioning.warn(
 
497
                'search_missing_revision_ids(revision_id=...) was '
 
498
                'deprecated in 2.4.  Use revision_ids=[...] instead.',
 
499
                DeprecationWarning, stacklevel=2)
 
500
            if revision_ids is not None:
 
501
                raise AssertionError(
 
502
                    'revision_ids is mutually exclusive with revision_id')
 
503
            if revision_id is not None:
 
504
                revision_ids = [revision_id]
 
505
        del revision_id
 
506
        source_ids_set = self._present_source_revisions_for(
 
507
            revision_ids, if_present_ids)
 
508
        # source_ids is the worst possible case we may need to pull.
 
509
        # now we want to filter source_ids against what we actually
 
510
        # have in target, but don't try to check for existence where we know
 
511
        # we do not have a revision as that would be pointless.
 
512
        target_ids = set(self.target.all_revision_ids())
 
513
        possibly_present_revisions = target_ids.intersection(source_ids_set)
 
514
        actually_present_revisions = set(
 
515
            self.target._eliminate_revisions_not_present(possibly_present_revisions))
 
516
        required_revisions = source_ids_set.difference(actually_present_revisions)
 
517
        if revision_ids is not None:
 
518
            # we used get_ancestry to determine source_ids then we are assured all
 
519
            # revisions referenced are present as they are installed in topological order.
 
520
            # and the tip revision was validated by get_ancestry.
 
521
            result_set = required_revisions
 
522
        else:
 
523
            # if we just grabbed the possibly available ids, then
 
524
            # we only have an estimate of whats available and need to validate
 
525
            # that against the revision records.
 
526
            result_set = set(
 
527
                self.source._eliminate_revisions_not_present(required_revisions))
 
528
        if limit is not None:
 
529
            topo_ordered = self.source.get_graph().iter_topo_order(result_set)
 
530
            result_set = set(itertools.islice(topo_ordered, limit))
 
531
        return self.source.revision_ids_to_search_result(result_set)
 
532
 
 
533
 
 
534
InterRepository.register_optimiser(InterKnitRepo)