/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/remote.py

  • Committer: Andrew Bennetts
  • Date: 2009-01-27 07:48:55 UTC
  • mto: This revision was merged to the branch mainline in revision 3981.
  • Revision ID: andrew.bennetts@canonical.com-20090127074855-4z3yi34s583vrd1v
Re-revert changes from another thread that accidentally got reinstated here.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
# across to run on the server.
19
19
 
20
20
import bz2
21
 
import itertools
22
21
 
23
22
from bzrlib import (
24
23
    branch,
42
41
from bzrlib.smart import client, vfs
43
42
from bzrlib.revision import ensure_null, NULL_REVISION
44
43
from bzrlib.trace import mutter, note, warning
45
 
from bzrlib.util import bencode
46
 
from bzrlib.versionedfile import VersionedFiles
47
44
 
48
45
 
49
46
class _RpcHelper(object):
339
336
        self.base = self.bzrdir.transport.base
340
337
        # Additional places to query for data.
341
338
        self._fallback_repositories = []
342
 
        self.texts = RemoteVersionedFiles(self, 'texts')
343
 
        self.inventories = RemoteVersionedFiles(self, 'inventories')
344
 
        self.signatures = RemoteVersionedFiles(self, 'signatures')
345
 
        self.revisions = RemoteVersionedFiles(self, 'revisions')
346
 
        self._vf_objs = [
347
 
            self.texts, self.inventories, self.signatures, self.revisions]
348
339
 
349
340
    def __str__(self):
350
341
        return "%s(%s)" % (self.__class__.__name__, self.base)
865
856
        In the long term getting this back from the remote repository as part
866
857
        of open would be more efficient.
867
858
        """
868
 
        return 'topological'
869
 
#        self._ensure_real()
870
 
#        return self._real_repository._fetch_order
 
859
        self._ensure_real()
 
860
        return self._real_repository._fetch_order
871
861
 
872
862
    @property
873
863
    def _fetch_uses_deltas(self):
953
943
        included_keys = start_set.intersection(result_parents)
954
944
        start_set.difference_update(included_keys)
955
945
        recipe = (start_set, stop_keys, len(parents_map))
 
946
        body = self._serialise_search_recipe(recipe)
956
947
        path = self.bzrdir._path_for_remote_call(self._client)
957
948
        for key in keys:
958
949
            if type(key) is not str:
962
953
        args = (path,) + tuple(keys)
963
954
        try:
964
955
            response = self._call_with_body_bytes_expecting_body(
965
 
                verb, args, _serialise_search_recipe(recipe))
 
956
                verb, args, body)
966
957
        except errors.UnknownSmartMethod:
967
958
            # Server does not support this method, so get the whole graph.
968
959
            # Worse, we have to force a disconnection, because the server now
1083
1074
        # TODO: Suggestion from john: using external tar is much faster than
1084
1075
        # python's tarfile library, but it may not work on windows.
1085
1076
 
 
1077
    @property
 
1078
    def inventories(self):
 
1079
        """Decorate the real repository for now.
 
1080
 
 
1081
        In the long term a full blown network facility is needed to
 
1082
        avoid creating a real repository object locally.
 
1083
        """
 
1084
        self._ensure_real()
 
1085
        return self._real_repository.inventories
 
1086
 
1086
1087
    @needs_write_lock
1087
1088
    def pack(self):
1088
1089
        """Compress the data within the repository.
1092
1093
        self._ensure_real()
1093
1094
        return self._real_repository.pack()
1094
1095
 
 
1096
    @property
 
1097
    def revisions(self):
 
1098
        """Decorate the real repository for now.
 
1099
 
 
1100
        In the short term this should become a real object to intercept graph
 
1101
        lookups.
 
1102
 
 
1103
        In the long term a full blown network facility is needed.
 
1104
        """
 
1105
        self._ensure_real()
 
1106
        return self._real_repository.revisions
 
1107
 
1095
1108
    def set_make_working_trees(self, new_value):
1096
1109
        self._ensure_real()
1097
1110
        self._real_repository.set_make_working_trees(new_value)
1098
1111
 
 
1112
    @property
 
1113
    def signatures(self):
 
1114
        """Decorate the real repository for now.
 
1115
 
 
1116
        In the long term a full blown network facility is needed to avoid
 
1117
        creating a real repository object locally.
 
1118
        """
 
1119
        self._ensure_real()
 
1120
        return self._real_repository.signatures
 
1121
 
1099
1122
    @needs_write_lock
1100
1123
    def sign_revision(self, revision_id, gpg_strategy):
1101
1124
        self._ensure_real()
1102
1125
        return self._real_repository.sign_revision(revision_id, gpg_strategy)
1103
1126
 
 
1127
    @property
 
1128
    def texts(self):
 
1129
        """Decorate the real repository for now.
 
1130
 
 
1131
        In the long term a full blown network facility is needed to avoid
 
1132
        creating a real repository object locally.
 
1133
        """
 
1134
        self._ensure_real()
 
1135
        return self._real_repository.texts
 
1136
 
1104
1137
    @needs_read_lock
1105
1138
    def get_revisions(self, revision_ids):
1106
1139
        self._ensure_real()
1158
1191
                         self._fallback_repositories)
1159
1192
        return graph._StackedParentsProvider(providers)
1160
1193
 
 
1194
    def _serialise_search_recipe(self, recipe):
 
1195
        """Serialise a graph search recipe.
 
1196
 
 
1197
        :param recipe: A search recipe (start, stop, count).
 
1198
        :return: Serialised bytes.
 
1199
        """
 
1200
        start_keys = ' '.join(recipe[0])
 
1201
        stop_keys = ' '.join(recipe[1])
 
1202
        count = str(recipe[2])
 
1203
        return '\n'.join((start_keys, stop_keys, count))
 
1204
 
1161
1205
    def autopack(self):
1162
1206
        path = self.bzrdir._path_for_remote_call(self._client)
1163
1207
        try:
1176
1220
            raise errors.UnexpectedSmartServerResponse(response)
1177
1221
 
1178
1222
 
1179
 
def _serialise_search_recipe(recipe):
1180
 
    """Serialise a graph search recipe.
1181
 
 
1182
 
    :param recipe: A search recipe (start, stop, count).
1183
 
    :return: Serialised bytes.
1184
 
    """
1185
 
    start_keys = ' '.join(recipe[0])
1186
 
    stop_keys = ' '.join(recipe[1])
1187
 
    count = str(recipe[2])
1188
 
    return '\n'.join((start_keys, stop_keys, count))
1189
 
 
1190
 
 
1191
 
def _serialise_record_stream(stream):
1192
 
    """Takes a record stream as returned by get_record_stream and yields bytes.
1193
 
    """
1194
 
    # Yields bencode of (sha1, storage_kind, key, parents, build_details,
1195
 
    #                    record_bytes)
1196
 
    # Note that:
1197
 
    #  - if sha1 is None, sha1 is ''
1198
 
    #  - if parents is None, parents is 'nil' (to distinguish it from empty
1199
 
    # tuple).
1200
 
    #  - if record has no _build_details, build_details is ()
1201
 
    for record in stream:
1202
 
        sha1 = record.sha1
1203
 
        if sha1 is None:
1204
 
            sha1 = ''
1205
 
        parents = record.parents
1206
 
        if record.parents is None:
1207
 
            parents = 'nil'
1208
 
        if record.storage_kind.startswith('knit-'):
1209
 
            build_details = record._build_details
1210
 
        else:
1211
 
            build_details = ()
1212
 
        struct = (sha1, record.storage_kind, record.key, parents,
1213
 
                  build_details, record.get_bytes_as(record.storage_kind))
1214
 
        yield bencode.bencode(struct)
1215
 
 
1216
 
 
1217
 
class RemoteVersionedFiles(VersionedFiles):
1218
 
 
1219
 
    def __init__(self, remote_repo, vf_name):
1220
 
        self.remote_repo = remote_repo
1221
 
        self.vf_name = vf_name
1222
 
 
1223
 
    def _get_real_vf(self):
1224
 
        self.remote_repo._ensure_real()
1225
 
        return getattr(self.remote_repo._real_repository, self.vf_name)
1226
 
 
1227
 
    def add_lines(self, version_id, parents, lines, parent_texts=None,
1228
 
            left_matching_blocks=None, nostore_sha=None, random_id=False,
1229
 
            check_content=True):
1230
 
        real_vf = self._get_real_vf()
1231
 
        return real_vf.add_lines(version_id, parents, lines,
1232
 
            parent_texts=parent_texts,
1233
 
            left_matching_blocks=left_matching_blocks,
1234
 
            nostore_sha=nostore_sha, random_id=random_id,
1235
 
            check_content=check_content)
1236
 
 
1237
 
    def add_mpdiffs(self, records):
1238
 
        real_vf = self._get_real_vf()
1239
 
        return real_vf.add_mpdiffs(records)
1240
 
 
1241
 
    def annotate(self, key):
1242
 
        real_vf = self._get_real_vf()
1243
 
        return real_vf.annotate(key)
1244
 
 
1245
 
    def check(self, progress_bar=None):
1246
 
        real_vf = self._get_real_vf()
1247
 
        return real_vf.check(progress_bar=progress_bar)
1248
 
 
1249
 
    def get_parent_map(self, keys):
1250
 
        real_vf = self._get_real_vf()
1251
 
        return real_vf.get_parent_map(keys)
1252
 
    
1253
 
    def get_record_stream(self, keys, ordering, include_delta_closure):
1254
 
        real_vf = self._get_real_vf()
1255
 
        return real_vf.get_record_stream(keys, ordering, include_delta_closure)
1256
 
 
1257
 
    def get_sha1s(self, keys):
1258
 
        real_vf = self._get_real_vf()
1259
 
        return real_vf.get_sha1s(keys)
1260
 
 
1261
 
    def insert_record_stream(self, stream, _record_serialiser=None):
1262
 
        lock_token = self.remote_repo._lock_token
1263
 
        if lock_token is None:
1264
 
            lock_token = ''
1265
 
        if _record_serialiser is None:
1266
 
            _record_serialiser = _serialise_record_stream
1267
 
        # Tee the stream, because we may need to replay it if we have to
1268
 
        # fallback to the VFS implementation.  This unfortunately means
1269
 
        # the entire record stream will temporarily be buffered in memory, even
1270
 
        # if we don't need to fallback.
1271
 
        # TODO: remember if this server accepts the insert_record_stream RPC,
1272
 
        # and if so skip the buffering.  (And if not, fallback immediately,
1273
 
        # again no buffering.)
1274
 
        stream, fallback_stream = itertools.tee(stream)
1275
 
        byte_stream = _record_serialiser(stream)
1276
 
        client = self.remote_repo._client
1277
 
        path = self.remote_repo.bzrdir._path_for_remote_call(client)
1278
 
        try:
1279
 
            response = client.call_with_body_stream(
1280
 
                ('VersionedFile.insert_record_stream', path, self.vf_name,
1281
 
                 lock_token), byte_stream)
1282
 
        except errors.UnknownSmartMethod:
1283
 
            real_vf = self._get_real_vf()
1284
 
            return real_vf.insert_record_stream(fallback_stream)
1285
 
 
1286
 
        response_tuple, response_handler = response
1287
 
        if response_tuple != ('ok',):
1288
 
            raise errors.UnexpectedSmartServerResponse(response_tuple)
1289
 
 
1290
 
    def iter_lines_added_or_present_in_keys(self, keys, pb=None):
1291
 
        real_vf = self._get_real_vf()
1292
 
        return real_vf.iter_lines_added_or_present_in_keys(keys, pb=pb)
1293
 
 
1294
 
    def keys(self):
1295
 
        real_vf = self._get_real_vf()
1296
 
        return real_vf.keys()
1297
 
 
1298
 
    def make_mpdiffs(self, keys):
1299
 
        real_vf = self._get_real_vf()
1300
 
        return real_vf.make_mpdiffs(keys)
1301
 
 
1302
 
 
1303
1223
class RemoteBranchLockableFiles(LockableFiles):
1304
1224
    """A 'LockableFiles' implementation that talks to a smart server.
1305
1225