~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

  • Committer: Vincent Ladeuil
  • Date: 2009-05-05 15:31:34 UTC
  • mto: (4343.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 4344.
  • Revision ID: v.ladeuil+lp@free.fr-20090505153134-q4bp4is9gywsmzrv
Clean up test for log formats.

* bzrlib/tests/blackbox/test_logformats.py:
Update tests to actual style.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2007, 2008, 2009 Canonical Ltd
 
1
# Copyright (C) 2006, 2007, 2008 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
# TODO: At some point, handle upgrades by just passing the whole request
 
18
# across to run on the server.
 
19
 
17
20
import bz2
18
21
 
19
22
from bzrlib import (
20
 
    bencode,
21
23
    branch,
22
24
    bzrdir,
23
25
    config,
24
26
    debug,
25
27
    errors,
26
28
    graph,
27
 
    lock,
28
29
    lockdir,
 
30
    pack,
29
31
    repository,
30
32
    revision,
31
33
    revision as _mod_revision,
32
34
    symbol_versioning,
 
35
    urlutils,
33
36
)
34
37
from bzrlib.branch import BranchReferenceFormat
35
38
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
42
45
from bzrlib.smart import client, vfs, repository as smart_repo
43
46
from bzrlib.revision import ensure_null, NULL_REVISION
44
47
from bzrlib.trace import mutter, note, warning
 
48
from bzrlib.util import bencode
45
49
 
46
50
 
47
51
class _RpcHelper(object):
59
63
        except errors.ErrorFromSmartServer, err:
60
64
            self._translate_error(err, **err_context)
61
65
 
62
 
    def _call_with_body_bytes(self, method, args, body_bytes, **err_context):
63
 
        try:
64
 
            return self._client.call_with_body_bytes(method, args, body_bytes)
65
 
        except errors.ErrorFromSmartServer, err:
66
 
            self._translate_error(err, **err_context)
67
 
 
68
66
    def _call_with_body_bytes_expecting_body(self, method, args, body_bytes,
69
67
                                             **err_context):
70
68
        try:
570
568
        return self._creating_repo._real_repository._format.network_name()
571
569
 
572
570
    @property
573
 
    def pack_compresses(self):
574
 
        self._ensure_real()
575
 
        return self._custom_format.pack_compresses
576
 
 
577
 
    @property
578
571
    def _serializer(self):
579
572
        self._ensure_real()
580
573
        return self._custom_format._serializer
677
670
        self._ensure_real()
678
671
        return self._real_repository.suspend_write_group()
679
672
 
680
 
    def get_missing_parent_inventories(self, check_for_missing_texts=True):
681
 
        self._ensure_real()
682
 
        return self._real_repository.get_missing_parent_inventories(
683
 
            check_for_missing_texts=check_for_missing_texts)
684
 
 
685
 
    def _get_rev_id_for_revno_vfs(self, revno, known_pair):
686
 
        self._ensure_real()
687
 
        return self._real_repository.get_rev_id_for_revno(
688
 
            revno, known_pair)
689
 
 
690
 
    def get_rev_id_for_revno(self, revno, known_pair):
691
 
        """See Repository.get_rev_id_for_revno."""
692
 
        path = self.bzrdir._path_for_remote_call(self._client)
693
 
        try:
694
 
            if self._client._medium._is_remote_before((1, 17)):
695
 
                return self._get_rev_id_for_revno_vfs(revno, known_pair)
696
 
            response = self._call(
697
 
                'Repository.get_rev_id_for_revno', path, revno, known_pair)
698
 
        except errors.UnknownSmartMethod:
699
 
            self._client._medium._remember_remote_is_before((1, 17))
700
 
            return self._get_rev_id_for_revno_vfs(revno, known_pair)
701
 
        if response[0] == 'ok':
702
 
            return True, response[1]
703
 
        elif response[0] == 'history-incomplete':
704
 
            known_pair = response[1:3]
705
 
            for fallback in self._fallback_repositories:
706
 
                found, result = fallback.get_rev_id_for_revno(revno, known_pair)
707
 
                if found:
708
 
                    return True, result
709
 
                else:
710
 
                    known_pair = result
711
 
            # Not found in any fallbacks
712
 
            return False, known_pair
713
 
        else:
714
 
            raise errors.UnexpectedSmartServerResponse(response)
 
673
    def get_missing_parent_inventories(self):
 
674
        self._ensure_real()
 
675
        return self._real_repository.get_missing_parent_inventories()
715
676
 
716
677
    def _ensure_real(self):
717
678
        """Ensure that there is a _real_repository set.
727
688
        invocation. If in doubt chat to the bzr network team.
728
689
        """
729
690
        if self._real_repository is None:
730
 
            if 'hpssvfs' in debug.debug_flags:
731
 
                import traceback
732
 
                warning('VFS Repository access triggered\n%s',
733
 
                    ''.join(traceback.format_stack()))
734
691
            self._unstacked_provider.missing_keys.clear()
735
692
            self.bzrdir._ensure_real()
736
693
            self._set_real_repository(
817
774
            result.add(_mod_revision.NULL_REVISION)
818
775
        return result
819
776
 
820
 
    def _has_same_fallbacks(self, other_repo):
821
 
        """Returns true if the repositories have the same fallbacks."""
822
 
        # XXX: copied from Repository; it should be unified into a base class
823
 
        # <https://bugs.edge.launchpad.net/bzr/+bug/401622>
824
 
        my_fb = self._fallback_repositories
825
 
        other_fb = other_repo._fallback_repositories
826
 
        if len(my_fb) != len(other_fb):
827
 
            return False
828
 
        for f, g in zip(my_fb, other_fb):
829
 
            if not f.has_same_location(g):
830
 
                return False
831
 
        return True
832
 
 
833
777
    def has_same_location(self, other):
834
 
        # TODO: Move to RepositoryBase and unify with the regular Repository
835
 
        # one; unfortunately the tests rely on slightly different behaviour at
836
 
        # present -- mbp 20090710
837
778
        return (self.__class__ is other.__class__ and
838
779
                self.bzrdir.transport.base == other.bzrdir.transport.base)
839
780
 
915
856
            self._unstacked_provider.enable_cache(cache_misses=True)
916
857
            if self._real_repository is not None:
917
858
                self._real_repository.lock_read()
918
 
            for repo in self._fallback_repositories:
919
 
                repo.lock_read()
920
859
        else:
921
860
            self._lock_count += 1
 
861
        for repo in self._fallback_repositories:
 
862
            repo.lock_read()
922
863
 
923
864
    def _remote_lock_write(self, token):
924
865
        path = self.bzrdir._path_for_remote_call(self._client)
956
897
            self._lock_count = 1
957
898
            cache_misses = self._real_repository is None
958
899
            self._unstacked_provider.enable_cache(cache_misses=cache_misses)
959
 
            for repo in self._fallback_repositories:
960
 
                # Writes don't affect fallback repos
961
 
                repo.lock_read()
962
900
        elif self._lock_mode == 'r':
963
901
            raise errors.ReadOnlyError(self)
964
902
        else:
965
903
            self._lock_count += 1
 
904
        for repo in self._fallback_repositories:
 
905
            # Writes don't affect fallback repos
 
906
            repo.lock_read()
966
907
        return self._lock_token or None
967
908
 
968
909
    def leave_lock_in_place(self):
1045
986
 
1046
987
    def unlock(self):
1047
988
        if not self._lock_count:
1048
 
            return lock.cant_unlock_not_held(self)
 
989
            raise errors.LockNotHeld(self)
1049
990
        self._lock_count -= 1
1050
991
        if self._lock_count > 0:
1051
992
            return
1070
1011
                self._lock_token = None
1071
1012
                if not self._leave_lock:
1072
1013
                    self._unlock(old_token)
1073
 
        # Fallbacks are always 'lock_read()' so we don't pay attention to
1074
 
        # self._leave_lock
1075
 
        for repo in self._fallback_repositories:
1076
 
            repo.unlock()
1077
1014
 
1078
1015
    def break_lock(self):
1079
1016
        # should hand off to the network
1143
1080
        # We need to accumulate additional repositories here, to pass them in
1144
1081
        # on various RPC's.
1145
1082
        #
1146
 
        if self.is_locked():
1147
 
            # We will call fallback.unlock() when we transition to the unlocked
1148
 
            # state, so always add a lock here. If a caller passes us a locked
1149
 
            # repository, they are responsible for unlocking it later.
1150
 
            repository.lock_read()
1151
1083
        self._fallback_repositories.append(repository)
1152
1084
        # If self._real_repository was parameterised already (e.g. because a
1153
1085
        # _real_branch had its get_stacked_on_url method called), then the
1250
1182
            raise errors.InternalBzrError(
1251
1183
                "May not fetch while in a write group.")
1252
1184
        # fast path same-url fetch operations
1253
 
        if (self.has_same_location(source)
1254
 
            and fetch_spec is None
1255
 
            and self._has_same_fallbacks(source)):
 
1185
        if self.has_same_location(source) and fetch_spec is None:
1256
1186
            # check that last_revision is in 'from' and then return a
1257
1187
            # no-operation.
1258
1188
            if (revision_id is not None and
1470
1400
        return self._real_repository.get_revision_reconcile(revision_id)
1471
1401
 
1472
1402
    @needs_read_lock
1473
 
    def check(self, revision_ids=None, callback_refs=None, check_repo=True):
 
1403
    def check(self, revision_ids=None):
1474
1404
        self._ensure_real()
1475
 
        return self._real_repository.check(revision_ids=revision_ids,
1476
 
            callback_refs=callback_refs, check_repo=check_repo)
 
1405
        return self._real_repository.check(revision_ids=revision_ids)
1477
1406
 
1478
1407
    def copy_content_into(self, destination, revision_id=None):
1479
1408
        self._ensure_real()
1519
1448
        return self._real_repository.inventories
1520
1449
 
1521
1450
    @needs_write_lock
1522
 
    def pack(self, hint=None):
 
1451
    def pack(self):
1523
1452
        """Compress the data within the repository.
1524
1453
 
1525
1454
        This is not currently implemented within the smart server.
1526
1455
        """
1527
1456
        self._ensure_real()
1528
 
        return self._real_repository.pack(hint=hint)
 
1457
        return self._real_repository.pack()
1529
1458
 
1530
1459
    @property
1531
1460
    def revisions(self):
1619
1548
        self._ensure_real()
1620
1549
        return self._real_repository.revision_graph_can_have_wrong_parents()
1621
1550
 
1622
 
    def _find_inconsistent_revision_parents(self, revisions_iterator=None):
 
1551
    def _find_inconsistent_revision_parents(self):
1623
1552
        self._ensure_real()
1624
 
        return self._real_repository._find_inconsistent_revision_parents(
1625
 
            revisions_iterator)
 
1553
        return self._real_repository._find_inconsistent_revision_parents()
1626
1554
 
1627
1555
    def _check_for_inconsistent_revision_parents(self):
1628
1556
        self._ensure_real()
1634
1562
            providers.insert(0, other)
1635
1563
        providers.extend(r._make_parents_provider() for r in
1636
1564
                         self._fallback_repositories)
1637
 
        return graph.StackedParentsProvider(providers)
 
1565
        return graph._StackedParentsProvider(providers)
1638
1566
 
1639
1567
    def _serialise_search_recipe(self, recipe):
1640
1568
        """Serialise a graph search recipe.
1735
1663
        if (self.from_repository._fallback_repositories and
1736
1664
            self.to_format._fetch_order == 'topological'):
1737
1665
            return self._real_stream(self.from_repository, search)
1738
 
        sources = []
1739
 
        seen = set()
1740
 
        repos = [self.from_repository]
1741
 
        while repos:
1742
 
            repo = repos.pop(0)
1743
 
            if repo in seen:
1744
 
                continue
1745
 
            seen.add(repo)
1746
 
            repos.extend(repo._fallback_repositories)
1747
 
            sources.append(repo)
1748
 
        return self.missing_parents_chain(search, sources)
 
1666
        return self.missing_parents_chain(search, [self.from_repository] +
 
1667
            self.from_repository._fallback_repositories)
1749
1668
 
1750
1669
    def _real_stream(self, repo, search):
1751
1670
        """Get a stream for search from repo.
1962
1881
        self._ensure_real()
1963
1882
        return self._custom_format.supports_stacking()
1964
1883
 
1965
 
    def supports_set_append_revisions_only(self):
1966
 
        self._ensure_real()
1967
 
        return self._custom_format.supports_set_append_revisions_only()
1968
 
 
1969
1884
 
1970
1885
class RemoteBranch(branch.Branch, _RpcHelper):
1971
1886
    """Branch stored on a server accessed by HPSS RPC.
1990
1905
        # We intentionally don't call the parent class's __init__, because it
1991
1906
        # will try to assign to self.tags, which is a property in this subclass.
1992
1907
        # And the parent's __init__ doesn't do much anyway.
 
1908
        self._revision_id_to_revno_cache = None
 
1909
        self._partial_revision_id_to_revno_cache = {}
 
1910
        self._revision_history_cache = None
 
1911
        self._last_revision_info_cache = None
 
1912
        self._merge_sorted_revisions_cache = None
1993
1913
        self.bzrdir = remote_bzrdir
1994
1914
        if _client is not None:
1995
1915
            self._client = _client
2009
1929
        else:
2010
1930
            self._real_branch = None
2011
1931
        # Fill out expected attributes of branch for bzrlib API users.
2012
 
        self._clear_cached_state()
2013
1932
        self.base = self.bzrdir.root_transport.base
2014
1933
        self._control_files = None
2015
1934
        self._lock_mode = None
2037
1956
        hooks = branch.Branch.hooks['open']
2038
1957
        for hook in hooks:
2039
1958
            hook(self)
2040
 
        self._is_stacked = False
2041
1959
        if setup_stacking:
2042
1960
            self._setup_stacking()
2043
1961
 
2049
1967
        except (errors.NotStacked, errors.UnstackableBranchFormat,
2050
1968
            errors.UnstackableRepositoryFormat), e:
2051
1969
            return
2052
 
        self._is_stacked = True
2053
 
        self._activate_fallback_location(fallback_url)
 
1970
        self._activate_fallback_location(fallback_url, None)
2054
1971
 
2055
1972
    def _get_config(self):
2056
1973
        return RemoteBranchConfig(self)
2157
2074
            raise errors.UnexpectedSmartServerResponse(response)
2158
2075
        return response[1]
2159
2076
 
2160
 
    def set_stacked_on_url(self, url):
2161
 
        branch.Branch.set_stacked_on_url(self, url)
2162
 
        if not url:
2163
 
            self._is_stacked = False
2164
 
        else:
2165
 
            self._is_stacked = True
2166
 
        
2167
2077
    def _vfs_get_tags_bytes(self):
2168
2078
        self._ensure_real()
2169
2079
        return self._real_branch._get_tags_bytes()
2179
2089
            return self._vfs_get_tags_bytes()
2180
2090
        return response[0]
2181
2091
 
2182
 
    def _vfs_set_tags_bytes(self, bytes):
2183
 
        self._ensure_real()
2184
 
        return self._real_branch._set_tags_bytes(bytes)
2185
 
 
2186
 
    def _set_tags_bytes(self, bytes):
2187
 
        medium = self._client._medium
2188
 
        if medium._is_remote_before((1, 18)):
2189
 
            self._vfs_set_tags_bytes(bytes)
2190
 
        try:
2191
 
            args = (
2192
 
                self._remote_path(), self._lock_token, self._repo_lock_token)
2193
 
            response = self._call_with_body_bytes(
2194
 
                'Branch.set_tags_bytes', args, bytes)
2195
 
        except errors.UnknownSmartMethod:
2196
 
            medium._remember_remote_is_before((1, 18))
2197
 
            self._vfs_set_tags_bytes(bytes)
2198
 
 
2199
2092
    def lock_read(self):
2200
2093
        self.repository.lock_read()
2201
2094
        if not self._lock_mode:
2255
2148
            self.repository.lock_write(self._repo_lock_token)
2256
2149
        return self._lock_token or None
2257
2150
 
 
2151
    def _set_tags_bytes(self, bytes):
 
2152
        self._ensure_real()
 
2153
        return self._real_branch._set_tags_bytes(bytes)
 
2154
 
2258
2155
    def _unlock(self, branch_token, repo_token):
2259
2156
        err_context = {'token': str((branch_token, repo_token))}
2260
2157
        response = self._call(
2309
2206
            raise NotImplementedError(self.dont_leave_lock_in_place)
2310
2207
        self._leave_lock = False
2311
2208
 
2312
 
    def get_rev_id(self, revno, history=None):
2313
 
        if revno == 0:
2314
 
            return _mod_revision.NULL_REVISION
2315
 
        last_revision_info = self.last_revision_info()
2316
 
        ok, result = self.repository.get_rev_id_for_revno(
2317
 
            revno, last_revision_info)
2318
 
        if ok:
2319
 
            return result
2320
 
        missing_parent = result[1]
2321
 
        # Either the revision named by the server is missing, or its parent
2322
 
        # is.  Call get_parent_map to determine which, so that we report a
2323
 
        # useful error.
2324
 
        parent_map = self.repository.get_parent_map([missing_parent])
2325
 
        if missing_parent in parent_map:
2326
 
            missing_parent = parent_map[missing_parent]
2327
 
        raise errors.RevisionNotPresent(missing_parent, self.repository)
2328
 
 
2329
2209
    def _last_revision_info(self):
2330
2210
        response = self._call('Branch.last_revision_info', self._remote_path())
2331
2211
        if response[0] != 'ok':
2336
2216
 
2337
2217
    def _gen_revision_history(self):
2338
2218
        """See Branch._gen_revision_history()."""
2339
 
        if self._is_stacked:
2340
 
            self._ensure_real()
2341
 
            return self._real_branch._gen_revision_history()
2342
2219
        response_tuple, response_handler = self._call_expecting_body(
2343
2220
            'Branch.revision_history', self._remote_path())
2344
2221
        if response_tuple[0] != 'ok':