1
# Copyright (C) 2006, 2007, 2010 Canonical Ltd
1
# Copyright (C) 2006-2010 Canonical Ltd
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
82
81
recreate_search trusts that clients will look for missing things
83
82
they expected and get it from elsewhere.
84
if search_bytes == 'everything':
85
return graph.EverythingResult(repository), None
85
86
lines = search_bytes.split('\n')
86
87
if lines[0] == 'ancestry-of':
395
token = repository.lock_write(token=token)
396
token = repository.lock_write(token=token).repository_token
396
397
except errors.LockContention, e:
397
398
return FailedSmartServerResponse(('LockContention',))
398
399
except errors.UnlockableTransport:
413
414
def do_repository_request(self, repository, to_network_name):
414
415
"""Get a stream for inserting into a to_format repository.
417
The request body is 'search_bytes', a description of the revisions
420
In 2.3 this verb added support for search_bytes == 'everything'. Older
421
implementations will respond with a BadSearch error, and clients should
422
catch this and fallback appropriately.
416
424
:param repository: The repository to stream from.
417
425
:param to_network_name: The network name of the format of the target
492
500
class SmartServerRepositoryGetStream_1_19(SmartServerRepositoryGetStream):
501
"""The same as Repository.get_stream, but will return stream CHK formats to
504
See SmartServerRepositoryGetStream._should_fake_unknown.
494
509
def _should_fake_unknown(self):
495
510
"""Returns False; we don't need to workaround bugs in 1.19+ clients."""
502
517
yield pack_writer.begin()
503
518
yield pack_writer.bytes_record(src_format.network_name(), '')
504
519
for substream_type, substream in stream:
505
if substream_type == 'inventory-deltas':
506
# This doesn't feel like the ideal place to issue this warning;
507
# however we don't want to do it in the Repository that's
508
# generating the stream, because that might be on the server.
509
# Instead we try to observe it as the stream goes by.
510
ui.ui_factory.warn_cross_format_fetch(src_format,
512
520
for record in substream:
513
521
if record.storage_kind in ('chunked', 'fulltext'):
514
522
serialised = record_to_fulltext_bytes(record)
515
elif record.storage_kind == 'inventory-delta':
516
serialised = record_to_inventory_delta_bytes(record)
517
523
elif record.storage_kind == 'absent':
518
524
raise ValueError("Absent factory for %s" % (record.key,))
551
557
:ivar first_bytes: The first bytes to give the next NetworkRecordStream.
554
def __init__(self, byte_stream):
560
def __init__(self, byte_stream, record_counter):
555
561
"""Create a _ByteStreamDecoder."""
556
562
self.stream_decoder = pack.ContainerPushParser()
557
563
self.current_type = None
558
564
self.first_bytes = None
559
565
self.byte_stream = byte_stream
566
self._record_counter = record_counter
561
569
def iter_stream_decoder(self):
562
570
"""Iterate the contents of the pack from stream_decoder."""
588
596
def record_stream(self):
589
597
"""Yield substream_type, substream from the byte stream."""
598
def wrap_and_count(pb, rc, substream):
599
"""Yield records from stream while showing progress."""
602
if self.current_type != 'revisions' and self.key_count != 0:
603
# As we know the number of revisions now (in self.key_count)
604
# we can setup and use record_counter (rc).
605
if not rc.is_initialized():
606
rc.setup(self.key_count, self.key_count)
607
for record in substream.read():
609
if rc.is_initialized() and counter == rc.STEP:
610
rc.increment(counter)
611
pb.update('Estimate', rc.current, rc.max)
613
if self.current_type == 'revisions':
614
# Total records is proportional to number of revs
615
# to fetch. With remote, we used self.key_count to
616
# track the number of revs. Once we have the revs
617
# counts in self.key_count, the progress bar changes
618
# from 'Estimating..' to 'Estimate' above.
620
if counter == rc.STEP:
621
pb.update('Estimating..', self.key_count)
590
626
self.seed_state()
627
pb = ui.ui_factory.nested_progress_bar()
628
rc = self._record_counter
591
629
# Make and consume sub generators, one per substream type:
592
630
while self.first_bytes is not None:
593
631
substream = NetworkRecordStream(self.iter_substream_bytes())
594
632
# after substream is fully consumed, self.current_type is set to
595
633
# the next type, and self.first_bytes is set to the matching bytes.
596
yield self.current_type, substream.read()
634
yield self.current_type, wrap_and_count(pb, rc, substream)
636
pb.update('Done', rc.max, rc.max)
598
639
def seed_state(self):
599
640
"""Prepare the _ByteStreamDecoder to decode from the pack stream."""
604
645
list(self.iter_substream_bytes())
607
def _byte_stream_to_stream(byte_stream):
648
def _byte_stream_to_stream(byte_stream, record_counter=None):
608
649
"""Convert a byte stream into a format and a stream.
610
651
:param byte_stream: A bytes iterator, as output by _stream_to_byte_stream.
611
652
:return: (RepositoryFormat, stream_generator)
613
decoder = _ByteStreamDecoder(byte_stream)
654
decoder = _ByteStreamDecoder(byte_stream, record_counter)
614
655
for bytes in byte_stream:
615
656
decoder.stream_decoder.accept_bytes(bytes)
616
657
for record in decoder.stream_decoder.read_pending_records(max=1):