40
40
from bzrlib.repository import _strip_NULL_ghosts, network_format_registry
41
41
from bzrlib import revision as _mod_revision
42
from bzrlib.util import bencode
42
43
from bzrlib.versionedfile import NetworkRecordStream, record_to_fulltext_bytes
73
def recreate_search(self, repository, search_bytes, discard_excess=False):
74
"""Recreate a search from its serialised form.
76
:param discard_excess: If True, and the search refers to data we don't
77
have, just silently accept that fact - the verb calling
78
recreate_search trusts that clients will look for missing things
79
they expected and get it from elsewhere.
74
def recreate_search(self, repository, search_bytes):
81
75
lines = search_bytes.split('\n')
82
76
if lines[0] == 'ancestry-of':
84
78
search_result = graph.PendingAncestryResult(heads, repository)
85
79
return search_result, None
86
80
elif lines[0] == 'search':
87
return self.recreate_search_from_recipe(repository, lines[1:],
88
discard_excess=discard_excess)
81
return self.recreate_search_from_recipe(repository, lines[1:])
90
83
return (None, FailedSmartServerResponse(('BadSearch',)))
92
def recreate_search_from_recipe(self, repository, lines,
93
discard_excess=False):
94
"""Recreate a specific revision search (vs a from-tip search).
96
:param discard_excess: If True, and the search refers to data we don't
97
have, just silently accept that fact - the verb calling
98
recreate_search trusts that clients will look for missing things
99
they expected and get it from elsewhere.
85
def recreate_search_from_recipe(self, repository, lines):
101
86
start_keys = set(lines[0].split(' '))
102
87
exclude_keys = set(lines[1].split(' '))
103
88
revision_count = int(lines[2])
113
98
search.stop_searching_any(exclude_keys.intersection(next_revs))
114
99
search_result = search.get_result()
115
if (not discard_excess and
116
search_result.get_recipe()[3] != revision_count):
100
if search_result.get_recipe()[3] != revision_count:
117
101
# we got back a different amount of data than expected, this
118
102
# gets reported as NoSuchRevision, because less revisions
119
103
# indicates missing revisions, and more should never happen as
283
267
return SuccessfulSmartServerResponse(('ok', ), '\n'.join(lines))
286
class SmartServerRepositoryGetRevIdForRevno(SmartServerRepositoryReadLocked):
288
def do_readlocked_repository_request(self, repository, revno,
290
"""Find the revid for a given revno, given a known revno/revid pair.
295
found_flag, result = repository.get_rev_id_for_revno(revno, known_pair)
296
except errors.RevisionNotPresent, err:
297
if err.revision_id != known_pair[1]:
298
raise AssertionError(
299
'get_rev_id_for_revno raised RevisionNotPresent for '
300
'non-initial revision: ' + err.revision_id)
301
return FailedSmartServerResponse(
302
('nosuchrevision', err.revision_id))
304
return SuccessfulSmartServerResponse(('ok', result))
306
earliest_revno, earliest_revid = result
307
return SuccessfulSmartServerResponse(
308
('history-incomplete', earliest_revno, earliest_revid))
311
270
class SmartServerRequestHasRevision(SmartServerRepositoryRequest):
313
272
def do_repository_request(self, repository, revision_id):
420
379
repository = self._repository
421
380
repository.lock_read()
423
search_result, error = self.recreate_search(repository, body_bytes,
382
search_result, error = self.recreate_search(repository, body_bytes)
425
383
if error is not None:
426
384
repository.unlock()
460
418
for record in substream:
461
419
if record.storage_kind in ('chunked', 'fulltext'):
462
420
serialised = record_to_fulltext_bytes(record)
463
elif record.storage_kind == 'absent':
464
raise ValueError("Absent factory for %s" % (record.key,))
466
422
serialised = record.get_bytes_as(record.storage_kind)