66
67
:param write_func: a callable that will be called when this
67
68
ContainerWriter needs to write some bytes.
69
self.write_func = write_func
70
self._write_func = write_func
71
self.current_offset = 0
72
74
"""Begin writing a container."""
73
75
self.write_func(FORMAT_ONE + "\n")
77
def write_func(self, bytes):
78
self._write_func(bytes)
79
self.current_offset += len(bytes)
76
82
"""Finish writing a container."""
77
83
self.write_func("E")
79
85
def add_bytes_record(self, bytes, names):
80
"""Add a Bytes record with the given names."""
86
"""Add a Bytes record with the given names.
88
:param bytes: The bytes to insert.
89
:param names: The names to give the inserted bytes.
90
:return: An offset, length tuple. The offset is the offset
91
of the record within the container, and the length is the
92
length of data that will need to be read to reconstitute the
93
record. These offset and length can only be used with the pack
94
interface - they might be offset by headers or other such details
95
and thus are only suitable for use by a ContainerReader.
97
current_offset = self.current_offset
82
99
self.write_func("B")
92
109
self.write_func("\n")
93
110
# Finally, the contents.
94
111
self.write_func(bytes)
112
# return a memo of where we wrote data to allow random access.
113
return current_offset, self.current_offset - current_offset
116
class ReadVFile(object):
117
"""Adapt a readv result iterator to a file like protocol."""
119
def __init__(self, readv_result):
120
self.readv_result = readv_result
121
# the most recent readv result block
125
if (self._string is None or
126
self._string.tell() == self._string_length):
127
length, data = self.readv_result.next()
128
self._string_length = len(data)
129
self._string = StringIO(data)
131
def read(self, length):
133
result = self._string.read(length)
134
if len(result) < length:
135
raise errors.BzrError('request for too much data from a readv hunk.')
139
"""Note that readline will not cross readv segments."""
141
result = self._string.readline()
142
if self._string.tell() == self._string_length and result[-1] != '\n':
143
raise errors.BzrError('short readline in the readvfile hunk.')
147
def make_readv_reader(transport, filename, requested_records):
148
"""Create a ContainerReader that will read selected records only.
150
:param transport: The transport the pack file is located on.
151
:param filename: The filename of the pack file.
152
:param requested_records: The record offset, length tuples as returned
153
by add_bytes_record for the desired records.
155
readv_blocks = [(0, len(FORMAT_ONE)+1)]
156
readv_blocks.extend(requested_records)
157
result = ContainerReader(ReadVFile(
158
transport.readv(filename, readv_blocks)))
97
162
class BaseReader(object):