/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 bzrlib/repository.py

  • Committer: Martin Pool
  • Date: 2010-10-14 21:23:08 UTC
  • mto: This revision was merged to the branch mainline in revision 5495.
  • Revision ID: mbp@sourcefrog.net-20101014212308-avfax5qlqwo1rrb1
Also mention news about hooks

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
    check,
26
26
    chk_map,
27
27
    config,
 
28
    controldir,
28
29
    debug,
29
 
    errors,
30
30
    fetch as _mod_fetch,
31
31
    fifo_cache,
32
32
    generate_ids,
44
44
    symbol_versioning,
45
45
    trace,
46
46
    tsort,
47
 
    ui,
48
47
    versionedfile,
49
48
    )
50
49
from bzrlib.bundle import serializer
53
52
from bzrlib.testament import Testament
54
53
""")
55
54
 
 
55
from bzrlib import (
 
56
    errors,
 
57
    registry,
 
58
    ui,
 
59
    )
56
60
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
57
61
from bzrlib.inter import InterObject
58
62
from bzrlib.inventory import (
61
65
    ROOT_ID,
62
66
    entry_factory,
63
67
    )
64
 
from bzrlib.lock import _RelockDebugMixin
65
 
from bzrlib import registry
 
68
from bzrlib.recordcounter import RecordCounter
 
69
from bzrlib.lock import _RelockDebugMixin, LogicalLockResult
66
70
from bzrlib.trace import (
67
71
    log_exception_quietly, note, mutter, mutter_callsite, warning)
68
72
 
71
75
_deprecation_warning_done = False
72
76
 
73
77
 
 
78
class IsInWriteGroupError(errors.InternalBzrError):
 
79
 
 
80
    _fmt = "May not refresh_data of repo %(repo)s while in a write group."
 
81
 
 
82
    def __init__(self, repo):
 
83
        errors.InternalBzrError.__init__(self, repo=repo)
 
84
 
 
85
 
74
86
class CommitBuilder(object):
75
87
    """Provides an interface to build up a commit.
76
88
 
231
243
 
232
244
    def _gen_revision_id(self):
233
245
        """Return new revision-id."""
234
 
        return generate_ids.gen_revision_id(self._config.username(),
235
 
                                            self._timestamp)
 
246
        return generate_ids.gen_revision_id(self._committer, self._timestamp)
236
247
 
237
248
    def _generate_revision_if_needed(self):
238
249
        """Create a revision id if None was supplied.
278
289
 
279
290
        :param tree: The tree which is being committed.
280
291
        """
281
 
        # NB: if there are no parents then this method is not called, so no
282
 
        # need to guard on parents having length.
 
292
        if len(self.parents) == 0:
 
293
            raise errors.RootMissing()
283
294
        entry = entry_factory['directory'](tree.path2id(''), '',
284
295
            None)
285
296
        entry.revision = self._new_revision_id
423
434
            else:
424
435
                # we don't need to commit this, because the caller already
425
436
                # determined that an existing revision of this file is
426
 
                # appropriate. If its not being considered for committing then
 
437
                # appropriate. If it's not being considered for committing then
427
438
                # it and all its parents to the root must be unaltered so
428
439
                # no-change against the basis.
429
440
                if ie.revision == self._new_revision_id:
745
756
                    # after iter_changes examines and decides it has changed,
746
757
                    # we will unconditionally record a new version even if some
747
758
                    # other process reverts it while commit is running (with
748
 
                    # the revert happening after iter_changes did it's
 
759
                    # the revert happening after iter_changes did its
749
760
                    # examination).
750
761
                    if change[7][1]:
751
762
                        entry.executable = True
860
871
        # versioned roots do not change unless the tree found a change.
861
872
 
862
873
 
863
 
class RepositoryWriteLockResult(object):
 
874
class RepositoryWriteLockResult(LogicalLockResult):
864
875
    """The result of write locking a repository.
865
876
 
866
877
    :ivar repository_token: The token obtained from the underlying lock, or
869
880
    """
870
881
 
871
882
    def __init__(self, unlock, repository_token):
 
883
        LogicalLockResult.__init__(self, unlock)
872
884
        self.repository_token = repository_token
873
 
        self.unlock = unlock
 
885
 
 
886
    def __repr__(self):
 
887
        return "RepositoryWriteLockResult(%s, %s)" % (self.repository_token,
 
888
            self.unlock)
874
889
 
875
890
 
876
891
######################################################################
877
892
# Repositories
878
893
 
879
894
 
880
 
class Repository(_RelockDebugMixin, bzrdir.ControlComponent):
 
895
class Repository(_RelockDebugMixin, controldir.ControlComponent):
881
896
    """Repository holding history for one or more branches.
882
897
 
883
898
    The repository holds and retrieves historical information including
930
945
        pointing to .bzr/repository.
931
946
    """
932
947
 
933
 
    # What class to use for a CommitBuilder. Often its simpler to change this
 
948
    # What class to use for a CommitBuilder. Often it's simpler to change this
934
949
    # in a Repository class subclass rather than to override
935
950
    # get_commit_builder.
936
951
    _commit_builder_class = CommitBuilder
1031
1046
                " id and insertion revid (%r, %r)"
1032
1047
                % (inv.revision_id, revision_id))
1033
1048
        if inv.root is None:
1034
 
            raise AssertionError()
 
1049
            raise errors.RootMissing()
1035
1050
        return self._add_inventory_checked(revision_id, inv, parents)
1036
1051
 
1037
1052
    def _add_inventory_checked(self, revision_id, inv, parents):
1430
1445
            for repo in self._fallback_repositories:
1431
1446
                repo.lock_read()
1432
1447
            self._refresh_data()
1433
 
        return self
 
1448
        return LogicalLockResult(self.unlock)
1434
1449
 
1435
1450
    def get_physical_lock_status(self):
1436
1451
        return self.control_files.get_physical_lock_status()
1654
1669
        return missing_keys
1655
1670
 
1656
1671
    def refresh_data(self):
1657
 
        """Re-read any data needed to to synchronise with disk.
 
1672
        """Re-read any data needed to synchronise with disk.
1658
1673
 
1659
1674
        This method is intended to be called after another repository instance
1660
1675
        (such as one used by a smart server) has inserted data into the
1661
 
        repository. It may not be called during a write group, but may be
1662
 
        called at any other time.
 
1676
        repository. On all repositories this will work outside of write groups.
 
1677
        Some repository formats (pack and newer for bzrlib native formats)
 
1678
        support refresh_data inside write groups. If called inside a write
 
1679
        group on a repository that does not support refreshing in a write group
 
1680
        IsInWriteGroupError will be raised.
1663
1681
        """
1664
 
        if self.is_in_write_group():
1665
 
            raise errors.InternalBzrError(
1666
 
                "May not refresh_data while in a write group.")
1667
1682
        self._refresh_data()
1668
1683
 
1669
1684
    def resume_write_group(self, tokens):
1708
1723
                "May not fetch while in a write group.")
1709
1724
        # fast path same-url fetch operations
1710
1725
        # TODO: lift out to somewhere common with RemoteRepository
1711
 
        # <https://bugs.edge.launchpad.net/bzr/+bug/401646>
 
1726
        # <https://bugs.launchpad.net/bzr/+bug/401646>
1712
1727
        if (self.has_same_location(source)
1713
1728
            and fetch_spec is None
1714
1729
            and self._has_same_fallbacks(source)):
2496
2511
            ancestors will be traversed.
2497
2512
        """
2498
2513
        graph = self.get_graph()
2499
 
        next_id = revision_id
2500
 
        while True:
2501
 
            if next_id in (None, _mod_revision.NULL_REVISION):
2502
 
                return
2503
 
            try:
2504
 
                parents = graph.get_parent_map([next_id])[next_id]
2505
 
            except KeyError:
2506
 
                raise errors.RevisionNotPresent(next_id, self)
2507
 
            yield next_id
2508
 
            if len(parents) == 0:
2509
 
                return
2510
 
            else:
2511
 
                next_id = parents[0]
 
2514
        stop_revisions = (None, _mod_revision.NULL_REVISION)
 
2515
        return graph.iter_lefthand_ancestry(revision_id, stop_revisions)
2512
2516
 
2513
2517
    def is_shared(self):
2514
2518
        """Return True if this repository is flagged as a shared repository."""
2615
2619
        types it should be a no-op that just returns.
2616
2620
 
2617
2621
        This stub method does not require a lock, but subclasses should use
2618
 
        @needs_write_lock as this is a long running call its reasonable to
 
2622
        @needs_write_lock as this is a long running call it's reasonable to
2619
2623
        implicitly lock for the user.
2620
2624
 
2621
2625
        :param hint: If not supplied, the whole repository is packed.
3374
3378
    'bzrlib.repofmt.groupcompress_repo',
3375
3379
    'RepositoryFormat2a',
3376
3380
    )
 
3381
format_registry.register_lazy(
 
3382
    'Bazaar development format 8\n',
 
3383
    'bzrlib.repofmt.groupcompress_repo',
 
3384
    'RepositoryFormat2aSubtree',
 
3385
    )
3377
3386
 
3378
3387
 
3379
3388
class InterRepository(InterObject):
3833
3842
                basis_id, delta, current_revision_id, parents_parents)
3834
3843
            cache[current_revision_id] = parent_tree
3835
3844
 
3836
 
    def _fetch_batch(self, revision_ids, basis_id, cache, a_graph=None):
 
3845
    def _fetch_batch(self, revision_ids, basis_id, cache):
3837
3846
        """Fetch across a few revisions.
3838
3847
 
3839
3848
        :param revision_ids: The revisions to copy
3840
3849
        :param basis_id: The revision_id of a tree that must be in cache, used
3841
3850
            as a basis for delta when no other base is available
3842
3851
        :param cache: A cache of RevisionTrees that we can use.
3843
 
        :param a_graph: A Graph object to determine the heads() of the
3844
 
            rich-root data stream.
3845
3852
        :return: The revision_id of the last converted tree. The RevisionTree
3846
3853
            for it will be in cache
3847
3854
        """
3915
3922
        if root_keys_to_create:
3916
3923
            root_stream = _mod_fetch._new_root_data_stream(
3917
3924
                root_keys_to_create, self._revision_id_to_root_id, parent_map,
3918
 
                self.source, graph=a_graph)
 
3925
                self.source)
3919
3926
            to_texts.insert_record_stream(root_stream)
3920
3927
        to_texts.insert_record_stream(from_texts.get_record_stream(
3921
3928
            text_keys, self.target._format._fetch_order,
3978
3985
        cache[basis_id] = basis_tree
3979
3986
        del basis_tree # We don't want to hang on to it here
3980
3987
        hints = []
3981
 
        if self._converting_to_rich_root and len(revision_ids) > 100:
3982
 
            a_graph = _mod_fetch._get_rich_root_heads_graph(self.source,
3983
 
                                                            revision_ids)
3984
 
        else:
3985
 
            a_graph = None
 
3988
        a_graph = None
3986
3989
 
3987
3990
        for offset in range(0, len(revision_ids), batch_size):
3988
3991
            self.target.start_write_group()
3990
3993
                pb.update('Transferring revisions', offset,
3991
3994
                          len(revision_ids))
3992
3995
                batch = revision_ids[offset:offset+batch_size]
3993
 
                basis_id = self._fetch_batch(batch, basis_id, cache,
3994
 
                                             a_graph=a_graph)
 
3996
                basis_id = self._fetch_batch(batch, basis_id, cache)
3995
3997
            except:
3996
3998
                self.source._safe_to_return_from_cache = False
3997
3999
                self.target.abort_write_group()
4063
4065
            basis_id = first_rev.parent_ids[0]
4064
4066
            # only valid as a basis if the target has it
4065
4067
            self.target.get_revision(basis_id)
4066
 
            # Try to get a basis tree - if its a ghost it will hit the
 
4068
            # Try to get a basis tree - if it's a ghost it will hit the
4067
4069
            # NoSuchRevision case.
4068
4070
            basis_tree = self.source.revision_tree(basis_id)
4069
4071
        except (IndexError, errors.NoSuchRevision):
4269
4271
                is_resume = False
4270
4272
            try:
4271
4273
                # locked_insert_stream performs a commit|suspend.
4272
 
                return self._locked_insert_stream(stream, src_format, is_resume)
 
4274
                return self._locked_insert_stream(stream, src_format,
 
4275
                    is_resume)
4273
4276
            except:
4274
4277
                self.target_repo.abort_write_group(suppress_errors=True)
4275
4278
                raise
4322
4325
                # required if the serializers are different only in terms of
4323
4326
                # the inventory.
4324
4327
                if src_serializer == to_serializer:
4325
 
                    self.target_repo.revisions.insert_record_stream(
4326
 
                        substream)
 
4328
                    self.target_repo.revisions.insert_record_stream(substream)
4327
4329
                else:
4328
4330
                    self._extract_and_insert_revisions(substream,
4329
4331
                        src_serializer)
4437
4439
        """Create a StreamSource streaming from from_repository."""
4438
4440
        self.from_repository = from_repository
4439
4441
        self.to_format = to_format
 
4442
        self._record_counter = RecordCounter()
4440
4443
 
4441
4444
    def delta_on_metadata(self):
4442
4445
        """Return True if delta's are permitted on metadata streams.