~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

  • Committer: John Arbash Meinel
  • Date: 2009-07-29 21:35:05 UTC
  • mfrom: (4576 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4577.
  • Revision ID: john@arbash-meinel.com-20090729213505-tkqsvy1zfpocu75w
Merge bzr.dev 4576 in prep for NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2007, 2008 Canonical Ltd
 
1
# Copyright (C) 2006, 2007, 2008, 2009 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
 
 
20
17
import bz2
21
18
 
22
19
from bzrlib import (
27
24
    debug,
28
25
    errors,
29
26
    graph,
 
27
    lock,
30
28
    lockdir,
31
 
    pack,
32
29
    repository,
33
30
    revision,
34
31
    revision as _mod_revision,
35
32
    symbol_versioning,
36
 
    urlutils,
37
33
)
38
34
from bzrlib.branch import BranchReferenceFormat
39
35
from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
63
59
        except errors.ErrorFromSmartServer, err:
64
60
            self._translate_error(err, **err_context)
65
61
 
 
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
 
66
68
    def _call_with_body_bytes_expecting_body(self, method, args, body_bytes,
67
69
                                             **err_context):
68
70
        try:
568
570
        return self._creating_repo._real_repository._format.network_name()
569
571
 
570
572
    @property
 
573
    def pack_compresses(self):
 
574
        self._ensure_real()
 
575
        return self._custom_format.pack_compresses
 
576
 
 
577
    @property
571
578
    def _serializer(self):
572
579
        self._ensure_real()
573
580
        return self._custom_format._serializer
675
682
        return self._real_repository.get_missing_parent_inventories(
676
683
            check_for_missing_texts=check_for_missing_texts)
677
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)
 
715
 
678
716
    def _ensure_real(self):
679
717
        """Ensure that there is a _real_repository set.
680
718
 
689
727
        invocation. If in doubt chat to the bzr network team.
690
728
        """
691
729
        if self._real_repository is None:
692
 
            if 'hpss' in debug.debug_flags:
 
730
            if 'hpssvfs' in debug.debug_flags:
693
731
                import traceback
694
732
                warning('VFS Repository access triggered\n%s',
695
733
                    ''.join(traceback.format_stack()))
779
817
            result.add(_mod_revision.NULL_REVISION)
780
818
        return result
781
819
 
 
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
 
782
833
    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
783
837
        return (self.__class__ is other.__class__ and
784
838
                self.bzrdir.transport.base == other.bzrdir.transport.base)
785
839
 
991
1045
 
992
1046
    def unlock(self):
993
1047
        if not self._lock_count:
994
 
            raise errors.LockNotHeld(self)
 
1048
            return lock.cant_unlock_not_held(self)
995
1049
        self._lock_count -= 1
996
1050
        if self._lock_count > 0:
997
1051
            return
1196
1250
            raise errors.InternalBzrError(
1197
1251
                "May not fetch while in a write group.")
1198
1252
        # fast path same-url fetch operations
1199
 
        if self.has_same_location(source) and fetch_spec is None:
 
1253
        if (self.has_same_location(source)
 
1254
            and fetch_spec is None
 
1255
            and self._has_same_fallbacks(source)):
1200
1256
            # check that last_revision is in 'from' and then return a
1201
1257
            # no-operation.
1202
1258
            if (revision_id is not None and
1462
1518
        return self._real_repository.inventories
1463
1519
 
1464
1520
    @needs_write_lock
1465
 
    def pack(self):
 
1521
    def pack(self, hint=None):
1466
1522
        """Compress the data within the repository.
1467
1523
 
1468
1524
        This is not currently implemented within the smart server.
1469
1525
        """
1470
1526
        self._ensure_real()
1471
 
        return self._real_repository.pack()
 
1527
        return self._real_repository.pack(hint=hint)
1472
1528
 
1473
1529
    @property
1474
1530
    def revisions(self):
1895
1951
        self._ensure_real()
1896
1952
        return self._custom_format.supports_stacking()
1897
1953
 
 
1954
    def supports_set_append_revisions_only(self):
 
1955
        self._ensure_real()
 
1956
        return self._custom_format.supports_set_append_revisions_only()
 
1957
 
1898
1958
 
1899
1959
class RemoteBranch(branch.Branch, _RpcHelper):
1900
1960
    """Branch stored on a server accessed by HPSS RPC.
1919
1979
        # We intentionally don't call the parent class's __init__, because it
1920
1980
        # will try to assign to self.tags, which is a property in this subclass.
1921
1981
        # And the parent's __init__ doesn't do much anyway.
1922
 
        self._revision_id_to_revno_cache = None
1923
 
        self._partial_revision_id_to_revno_cache = {}
1924
 
        self._revision_history_cache = None
1925
 
        self._last_revision_info_cache = None
1926
 
        self._merge_sorted_revisions_cache = None
1927
1982
        self.bzrdir = remote_bzrdir
1928
1983
        if _client is not None:
1929
1984
            self._client = _client
1943
1998
        else:
1944
1999
            self._real_branch = None
1945
2000
        # Fill out expected attributes of branch for bzrlib API users.
 
2001
        self._clear_cached_state()
1946
2002
        self.base = self.bzrdir.root_transport.base
1947
2003
        self._control_files = None
1948
2004
        self._lock_mode = None
1970
2026
        hooks = branch.Branch.hooks['open']
1971
2027
        for hook in hooks:
1972
2028
            hook(self)
 
2029
        self._is_stacked = False
1973
2030
        if setup_stacking:
1974
2031
            self._setup_stacking()
1975
2032
 
1981
2038
        except (errors.NotStacked, errors.UnstackableBranchFormat,
1982
2039
            errors.UnstackableRepositoryFormat), e:
1983
2040
            return
 
2041
        self._is_stacked = True
1984
2042
        self._activate_fallback_location(fallback_url)
1985
2043
 
1986
2044
    def _get_config(self):
2088
2146
            raise errors.UnexpectedSmartServerResponse(response)
2089
2147
        return response[1]
2090
2148
 
 
2149
    def set_stacked_on_url(self, url):
 
2150
        branch.Branch.set_stacked_on_url(self, url)
 
2151
        if not url:
 
2152
            self._is_stacked = False
 
2153
        else:
 
2154
            self._is_stacked = True
 
2155
        
2091
2156
    def _vfs_get_tags_bytes(self):
2092
2157
        self._ensure_real()
2093
2158
        return self._real_branch._get_tags_bytes()
2103
2168
            return self._vfs_get_tags_bytes()
2104
2169
        return response[0]
2105
2170
 
 
2171
    def _vfs_set_tags_bytes(self, bytes):
 
2172
        self._ensure_real()
 
2173
        return self._real_branch._set_tags_bytes(bytes)
 
2174
 
 
2175
    def _set_tags_bytes(self, bytes):
 
2176
        medium = self._client._medium
 
2177
        if medium._is_remote_before((1, 18)):
 
2178
            self._vfs_set_tags_bytes(bytes)
 
2179
        try:
 
2180
            args = (
 
2181
                self._remote_path(), self._lock_token, self._repo_lock_token)
 
2182
            response = self._call_with_body_bytes(
 
2183
                'Branch.set_tags_bytes', args, bytes)
 
2184
        except errors.UnknownSmartMethod:
 
2185
            medium._remember_remote_is_before((1, 18))
 
2186
            self._vfs_set_tags_bytes(bytes)
 
2187
 
2106
2188
    def lock_read(self):
2107
2189
        self.repository.lock_read()
2108
2190
        if not self._lock_mode:
2162
2244
            self.repository.lock_write(self._repo_lock_token)
2163
2245
        return self._lock_token or None
2164
2246
 
2165
 
    def _set_tags_bytes(self, bytes):
2166
 
        self._ensure_real()
2167
 
        return self._real_branch._set_tags_bytes(bytes)
2168
 
 
2169
2247
    def _unlock(self, branch_token, repo_token):
2170
2248
        err_context = {'token': str((branch_token, repo_token))}
2171
2249
        response = self._call(
2220
2298
            raise NotImplementedError(self.dont_leave_lock_in_place)
2221
2299
        self._leave_lock = False
2222
2300
 
 
2301
    def get_rev_id(self, revno, history=None):
 
2302
        if revno == 0:
 
2303
            return _mod_revision.NULL_REVISION
 
2304
        last_revision_info = self.last_revision_info()
 
2305
        ok, result = self.repository.get_rev_id_for_revno(
 
2306
            revno, last_revision_info)
 
2307
        if ok:
 
2308
            return result
 
2309
        missing_parent = result[1]
 
2310
        # Either the revision named by the server is missing, or its parent
 
2311
        # is.  Call get_parent_map to determine which, so that we report a
 
2312
        # useful error.
 
2313
        parent_map = self.repository.get_parent_map([missing_parent])
 
2314
        if missing_parent in parent_map:
 
2315
            missing_parent = parent_map[missing_parent]
 
2316
        raise errors.RevisionNotPresent(missing_parent, self.repository)
 
2317
 
2223
2318
    def _last_revision_info(self):
2224
2319
        response = self._call('Branch.last_revision_info', self._remote_path())
2225
2320
        if response[0] != 'ok':
2230
2325
 
2231
2326
    def _gen_revision_history(self):
2232
2327
        """See Branch._gen_revision_history()."""
 
2328
        if self._is_stacked:
 
2329
            self._ensure_real()
 
2330
            return self._real_branch._gen_revision_history()
2233
2331
        response_tuple, response_handler = self._call_expecting_body(
2234
2332
            'Branch.revision_history', self._remote_path())
2235
2333
        if response_tuple[0] != 'ok':