49
49
transport = self._backing_transport.clone(path)
50
50
bzrdir = BzrDir.open_from_transport(transport)
51
repository = bzrdir.open_repository()
52
return self.do_repository_request(repository, *args)
51
# Save the repository for use with do_body.
52
self._repository = bzrdir.open_repository()
53
return self.do_repository_request(self._repository, *args)
55
def do_repository_request(self, repository, *args):
56
"""Override to provide an implementation for a verb."""
57
# No-op for verbs that take bodies (None as a result indicates a body
55
62
class SmartServerRepositoryGetParentMap(SmartServerRepositoryRequest):
309
316
class SmartServerRepositoryStreamKnitDataForRevisions(SmartServerRepositoryRequest):
317
"""Bzr <= 1.1 streaming pull, buffers all data on server."""
311
319
def do_repository_request(self, repository, *revision_ids):
312
320
repository.lock_read()
316
324
repository.unlock()
318
326
def _do_repository_request(self, repository, revision_ids):
319
stream = repository.get_data_stream(revision_ids)
327
stream = repository.get_data_stream_for_search(
328
repository.revision_ids_to_search_result(set(revision_ids)))
320
329
buffer = StringIO()
321
330
pack = ContainerSerialiser()
322
331
buffer.write(pack.begin())
332
341
class SmartServerRepositoryStreamRevisionsChunked(SmartServerRepositoryRequest):
342
"""Bzr 1.1+ streaming pull."""
334
def do_repository_request(self, repository, *revision_ids):
344
def do_body(self, body_bytes):
345
lines = body_bytes.split('\n')
346
start_keys = set(lines[0].split(' '))
347
exclude_keys = set(lines[1].split(' '))
348
revision_count = int(lines[2])
349
repository = self._repository
335
350
repository.lock_read()
337
stream = repository.get_data_stream(revision_ids)
352
search = repository.get_graph()._make_breadth_first_searcher(
356
next_revs = search.next()
357
except StopIteration:
359
search.stop_searching_any(exclude_keys.intersection(next_revs))
360
search_result = search.get_result()
361
if search_result.get_recipe()[2] != revision_count:
362
# we got back a different amount of data than expected, this
363
# gets reported as NoSuchRevision, because less revisions
364
# indicates missing revisions, and more should never happen as
365
# the excludes list considers ghosts and ensures that ghost
366
# filling races are not a problem.
367
return FailedSmartServerResponse(('NoSuchRevision',))
368
stream = repository.get_data_stream_for_search(search_result)
338
369
except Exception:
339
370
repository.unlock()
348
379
for name_tuple, bytes in stream:
349
380
yield pack.bytes_record(bytes, [name_tuple])
350
381
except errors.RevisionNotPresent, e:
382
# This shouldn't be able to happen, but as we don't buffer
383
# everything it can in theory happen.
351
384
yield FailedSmartServerResponse(('NoSuchRevision', e.revision_id))
352
385
repository.unlock()