~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

  • Committer: John Arbash Meinel
  • Date: 2010-02-17 17:11:16 UTC
  • mfrom: (4797.2.17 2.1)
  • mto: (4797.2.18 2.1)
  • mto: This revision was merged to the branch mainline in revision 5055.
  • Revision ID: john@arbash-meinel.com-20100217171116-h7t9223ystbnx5h8
merge bzr.2.1 in preparation for NEWS entry.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd
 
1
# Copyright (C) 2005-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
24
24
    bzrdir,
25
25
    check,
26
26
    chk_map,
 
27
    config,
27
28
    debug,
28
29
    errors,
 
30
    fetch as _mod_fetch,
29
31
    fifo_cache,
30
32
    generate_ids,
31
33
    gpg,
39
41
    osutils,
40
42
    revision as _mod_revision,
41
43
    symbol_versioning,
 
44
    trace,
42
45
    tsort,
43
46
    ui,
44
47
    versionedfile,
50
53
""")
51
54
 
52
55
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
53
 
from bzrlib.lock import _RelockDebugMixin
54
56
from bzrlib.inter import InterObject
55
57
from bzrlib.inventory import (
56
58
    Inventory,
58
60
    ROOT_ID,
59
61
    entry_factory,
60
62
    )
 
63
from bzrlib.lock import _RelockDebugMixin
61
64
from bzrlib import registry
62
65
from bzrlib.trace import (
63
66
    log_exception_quietly, note, mutter, mutter_callsite, warning)
206
209
            # an inventory delta was accumulated without creating a new
207
210
            # inventory.
208
211
            basis_id = self.basis_delta_revision
209
 
            self.inv_sha1 = self.repository.add_inventory_by_delta(
 
212
            # We ignore the 'inventory' returned by add_inventory_by_delta
 
213
            # because self.new_inventory is used to hint to the rest of the
 
214
            # system what code path was taken
 
215
            self.inv_sha1, _ = self.repository.add_inventory_by_delta(
210
216
                basis_id, self._basis_delta, self._new_revision_id,
211
217
                self.parents)
212
218
        else:
1300
1306
        self._reconcile_does_inventory_gc = True
1301
1307
        self._reconcile_fixes_text_parents = False
1302
1308
        self._reconcile_backsup_inventory = True
1303
 
        # not right yet - should be more semantically clear ?
1304
 
        #
1305
 
        # TODO: make sure to construct the right store classes, etc, depending
1306
 
        # on whether escaping is required.
1307
 
        self._warn_if_deprecated()
1308
1309
        self._write_group = None
1309
1310
        # Additional places to query for data.
1310
1311
        self._fallback_repositories = []
1311
1312
        # An InventoryEntry cache, used during deserialization
1312
1313
        self._inventory_entry_cache = fifo_cache.FIFOCache(10*1024)
 
1314
        # Is it safe to return inventory entries directly from the entry cache,
 
1315
        # rather copying them?
 
1316
        self._safe_to_return_from_cache = False
1313
1317
 
1314
1318
    def __repr__(self):
1315
1319
        if self._fallback_repositories:
1382
1386
        locked = self.is_locked()
1383
1387
        result = self.control_files.lock_write(token=token)
1384
1388
        if not locked:
 
1389
            self._warn_if_deprecated()
1385
1390
            self._note_lock('w')
1386
1391
            for repo in self._fallback_repositories:
1387
1392
                # Writes don't affect fallback repos
1393
1398
        locked = self.is_locked()
1394
1399
        self.control_files.lock_read()
1395
1400
        if not locked:
 
1401
            self._warn_if_deprecated()
1396
1402
            self._note_lock('r')
1397
1403
            for repo in self._fallback_repositories:
1398
1404
                repo.lock_read()
2427
2433
        :param xml: A serialised inventory.
2428
2434
        """
2429
2435
        result = self._serializer.read_inventory_from_string(xml, revision_id,
2430
 
                    entry_cache=self._inventory_entry_cache)
 
2436
                    entry_cache=self._inventory_entry_cache,
 
2437
                    return_from_cache=self._safe_to_return_from_cache)
2431
2438
        if result.revision_id != revision_id:
2432
2439
            raise AssertionError('revision id mismatch %s != %s' % (
2433
2440
                result.revision_id, revision_id))
2665
2672
        for ((revision_id,), parent_keys) in \
2666
2673
                self.revisions.get_parent_map(query_keys).iteritems():
2667
2674
            if parent_keys:
2668
 
                result[revision_id] = tuple(parent_revid
2669
 
                    for (parent_revid,) in parent_keys)
 
2675
                result[revision_id] = tuple([parent_revid
 
2676
                    for (parent_revid,) in parent_keys])
2670
2677
            else:
2671
2678
                result[revision_id] = (_mod_revision.NULL_REVISION,)
2672
2679
        return result
2774
2781
        result.check(callback_refs)
2775
2782
        return result
2776
2783
 
2777
 
    def _warn_if_deprecated(self):
 
2784
    def _warn_if_deprecated(self, branch=None):
2778
2785
        global _deprecation_warning_done
2779
2786
        if _deprecation_warning_done:
2780
2787
            return
2781
 
        _deprecation_warning_done = True
2782
 
        warning("Format %s for %s is deprecated - please use 'bzr upgrade' to get better performance"
2783
 
                % (self._format, self.bzrdir.transport.base))
 
2788
        try:
 
2789
            if branch is None:
 
2790
                conf = config.GlobalConfig()
 
2791
            else:
 
2792
                conf = branch.get_config()
 
2793
            if conf.suppress_warning('format_deprecation'):
 
2794
                return
 
2795
            warning("Format %s for %s is deprecated -"
 
2796
                    " please use 'bzr upgrade' to get better performance"
 
2797
                    % (self._format, self.bzrdir.transport.base))
 
2798
        finally:
 
2799
            _deprecation_warning_done = True
2784
2800
 
2785
2801
    def supports_rich_root(self):
2786
2802
        return self._format.rich_root_data
3090
3106
        """
3091
3107
        try:
3092
3108
            transport = a_bzrdir.get_repository_transport(None)
3093
 
            format_string = transport.get("format").read()
 
3109
            format_string = transport.get_bytes("format")
3094
3110
            return format_registry.get(format_string)
3095
3111
        except errors.NoSuchFile:
3096
3112
            raise errors.NoRepositoryPresent(a_bzrdir)
3409
3425
                   provided a default one will be created.
3410
3426
        :return: None.
3411
3427
        """
3412
 
        from bzrlib.fetch import RepoFetcher
3413
 
        f = RepoFetcher(to_repository=self.target,
 
3428
        f = _mod_fetch.RepoFetcher(to_repository=self.target,
3414
3429
                               from_repository=self.source,
3415
3430
                               last_revision=revision_id,
3416
3431
                               fetch_spec=fetch_spec,
3816
3831
                basis_id, delta, current_revision_id, parents_parents)
3817
3832
            cache[current_revision_id] = parent_tree
3818
3833
 
3819
 
    def _fetch_batch(self, revision_ids, basis_id, cache):
 
3834
    def _fetch_batch(self, revision_ids, basis_id, cache, a_graph=None):
3820
3835
        """Fetch across a few revisions.
3821
3836
 
3822
3837
        :param revision_ids: The revisions to copy
3823
3838
        :param basis_id: The revision_id of a tree that must be in cache, used
3824
3839
            as a basis for delta when no other base is available
3825
3840
        :param cache: A cache of RevisionTrees that we can use.
 
3841
        :param a_graph: A Graph object to determine the heads() of the
 
3842
            rich-root data stream.
3826
3843
        :return: The revision_id of the last converted tree. The RevisionTree
3827
3844
            for it will be in cache
3828
3845
        """
3835
3852
        pending_revisions = []
3836
3853
        parent_map = self.source.get_parent_map(revision_ids)
3837
3854
        self._fetch_parent_invs_for_stacking(parent_map, cache)
 
3855
        self.source._safe_to_return_from_cache = True
3838
3856
        for tree in self.source.revision_trees(revision_ids):
3839
3857
            # Find a inventory delta for this revision.
3840
3858
            # Find text entries that need to be copied, too.
3888
3906
            pending_revisions.append(revision)
3889
3907
            cache[current_revision_id] = tree
3890
3908
            basis_id = current_revision_id
 
3909
        self.source._safe_to_return_from_cache = False
3891
3910
        # Copy file texts
3892
3911
        from_texts = self.source.texts
3893
3912
        to_texts = self.target.texts
3894
3913
        if root_keys_to_create:
3895
 
            from bzrlib.fetch import _new_root_data_stream
3896
 
            root_stream = _new_root_data_stream(
 
3914
            root_stream = _mod_fetch._new_root_data_stream(
3897
3915
                root_keys_to_create, self._revision_id_to_root_id, parent_map,
3898
 
                self.source)
 
3916
                self.source, graph=a_graph)
3899
3917
            to_texts.insert_record_stream(root_stream)
3900
3918
        to_texts.insert_record_stream(from_texts.get_record_stream(
3901
3919
            text_keys, self.target._format._fetch_order,
3958
3976
        cache[basis_id] = basis_tree
3959
3977
        del basis_tree # We don't want to hang on to it here
3960
3978
        hints = []
 
3979
        if self._converting_to_rich_root and len(revision_ids) > 100:
 
3980
            a_graph = _mod_fetch._get_rich_root_heads_graph(self.source,
 
3981
                                                            revision_ids)
 
3982
        else:
 
3983
            a_graph = None
 
3984
 
3961
3985
        for offset in range(0, len(revision_ids), batch_size):
3962
3986
            self.target.start_write_group()
3963
3987
            try:
3964
3988
                pb.update('Transferring revisions', offset,
3965
3989
                          len(revision_ids))
3966
3990
                batch = revision_ids[offset:offset+batch_size]
3967
 
                basis_id = self._fetch_batch(batch, basis_id, cache)
 
3991
                basis_id = self._fetch_batch(batch, basis_id, cache,
 
3992
                                             a_graph=a_graph)
3968
3993
            except:
 
3994
                self.source._safe_to_return_from_cache = False
3969
3995
                self.target.abort_write_group()
3970
3996
                raise
3971
3997
            else:
3983
4009
        """See InterRepository.fetch()."""
3984
4010
        if fetch_spec is not None:
3985
4011
            raise AssertionError("Not implemented yet...")
 
4012
        # See <https://launchpad.net/bugs/456077> asking for a warning here
 
4013
        #
 
4014
        # nb this is only active for local-local fetches; other things using
 
4015
        # streaming.
 
4016
        ui.ui_factory.warn_cross_format_fetch(self.source._format,
 
4017
            self.target._format)
3986
4018
        if (not self.source.supports_rich_root()
3987
4019
            and self.target.supports_rich_root()):
3988
4020
            self._converting_to_rich_root = True
4281
4313
                    self._extract_and_insert_inventories(
4282
4314
                        substream, src_serializer)
4283
4315
            elif substream_type == 'inventory-deltas':
 
4316
                ui.ui_factory.warn_cross_format_fetch(src_format,
 
4317
                    self.target_repo._format)
4284
4318
                self._extract_and_insert_inventory_deltas(
4285
4319
                    substream, src_serializer)
4286
4320
            elif substream_type == 'chk_bytes':
4443
4477
        fetching the inventory weave.
4444
4478
        """
4445
4479
        if self._rich_root_upgrade():
4446
 
            import bzrlib.fetch
4447
 
            return bzrlib.fetch.Inter1and2Helper(
 
4480
            return _mod_fetch.Inter1and2Helper(
4448
4481
                self.from_repository).generate_root_texts(revs)
4449
4482
        else:
4450
4483
            return []
4592
4625
 
4593
4626
    def _get_convertable_inventory_stream(self, revision_ids,
4594
4627
                                          delta_versus_null=False):
4595
 
        # The source is using CHKs, but the target either doesn't or it has a
4596
 
        # different serializer.  The StreamSink code expects to be able to
 
4628
        # The two formats are sufficiently different that there is no fast
 
4629
        # path, so we need to send just inventorydeltas, which any
 
4630
        # sufficiently modern client can insert into any repository.
 
4631
        # The StreamSink code expects to be able to
4597
4632
        # convert on the target, so we need to put bytes-on-the-wire that can
4598
4633
        # be converted.  That means inventory deltas (if the remote is <1.19,
4599
4634
        # RemoteStreamSink will fallback to VFS to insert the deltas).