142
142
INDEX_SUFFIX = '.kndx'
145
class KnitAdapter(object):
146
"""Base class for knit record adaption."""
149
self._data = _KnitData(None)
150
self._annotate_factory = KnitAnnotateFactory()
151
self._plain_factory = KnitPlainFactory()
154
class FTAnnotatedToUnannotated(KnitAdapter):
155
"""An adapter from FT annotated knits to unannotated ones."""
157
def get_bytes(self, factory, annotated_compressed_bytes):
159
self._data._parse_record_unchecked(annotated_compressed_bytes)
160
content = self._annotate_factory.parse_fulltext(contents, rec[1])
161
size, bytes = self._data._record_to_data(rec[1], rec[3], content.text())
165
class DeltaAnnotatedToUnannotated(KnitAdapter):
166
"""An adapter for deltas from annotated to unannotated."""
168
def get_bytes(self, factory, annotated_compressed_bytes):
170
self._data._parse_record_unchecked(annotated_compressed_bytes)
171
delta = self._annotate_factory.parse_line_delta(contents, rec[1],
173
contents = self._plain_factory.lower_line_delta(delta)
174
size, bytes = self._data._record_to_data(rec[1], rec[3], contents)
178
class FTAnnotatedToFullText(KnitAdapter):
179
"""An adapter from FT annotated knits to unannotated ones."""
181
def get_bytes(self, factory, annotated_compressed_bytes):
183
self._data._parse_record_unchecked(annotated_compressed_bytes)
184
content, delta = self._annotate_factory.parse_record(factory.key[0],
185
contents, factory._build_details, None)
186
return ''.join(content.text())
189
class DeltaAnnotatedToFullText(KnitAdapter):
190
"""An adapter for deltas from annotated to unannotated."""
192
def __init__(self, basis_vf):
193
"""Create an adapter which accesses full texts from basis_vf.
195
:param basis_vf: A versioned file to access basis texts of deltas from.
197
KnitAdapter.__init__(self)
198
self._basis_vf = basis_vf
200
def get_bytes(self, factory, annotated_compressed_bytes):
202
self._data._parse_record_unchecked(annotated_compressed_bytes)
203
delta = self._annotate_factory.parse_line_delta(contents, rec[1],
205
compression_parent = factory.parents[0][0]
206
basis_lines = self._basis_vf.get_lines(compression_parent)
207
# Manually apply the delta because we have one annotated content and
209
basis_content = PlainKnitContent(basis_lines, compression_parent)
210
basis_content.apply_delta(delta, rec[1])
211
basis_content._should_strip_eol = factory._build_details[1]
212
return ''.join(basis_content.text())
145
215
class KnitContentFactory(ContentFactory):
146
216
"""Content factory for streaming from knits.
2518
2587
% (version_id, e.__class__.__name__, str(e)))
2521
def _check_header(self, version_id, line):
2590
def _split_header(self, line):
2522
2591
rec = line.split()
2523
2592
if len(rec) != 4:
2524
2593
raise KnitCorrupt(self._access,
2525
2594
'unexpected number of elements in record header')
2597
def _check_header_version(self, rec, version_id):
2526
2598
if rec[1] != version_id:
2527
2599
raise KnitCorrupt(self._access,
2528
2600
'unexpected version, wanted %r, got %r'
2529
2601
% (version_id, rec[1]))
2603
def _check_header(self, version_id, line):
2604
rec = self._split_header(line)
2605
self._check_header_version(rec, version_id)
2532
def _parse_record(self, version_id, data):
2608
def _parse_record_unchecked(self, data):
2533
2609
# profiling notes:
2534
2610
# 4168 calls in 2880 217 internal
2535
2611
# 4168 calls to _parse_record_header in 2121
2536
2612
# 4168 calls to readlines in 330
2537
2613
df = GzipFile(mode='rb', fileobj=StringIO(data))
2540
2615
record_contents = df.readlines()
2541
2616
except Exception, e:
2542
raise KnitCorrupt(self._access,
2543
"While reading {%s} got %s(%s)"
2544
% (version_id, e.__class__.__name__, str(e)))
2617
raise KnitCorrupt(self._access, "Corrupt compressed record %r, got %s(%s)" %
2618
(data, e.__class__.__name__, str(e)))
2545
2619
header = record_contents.pop(0)
2546
rec = self._check_header(version_id, header)
2620
rec = self._split_header(header)
2548
2621
last_line = record_contents.pop()
2549
2622
if len(record_contents) != int(rec[2]):
2550
2623
raise KnitCorrupt(self._access,
2551
2624
'incorrect number of lines %s != %s'
2552
2625
' for version {%s}'
2553
2626
% (len(record_contents), int(rec[2]),
2555
2628
if last_line != 'end %s\n' % rec[1]:
2556
2629
raise KnitCorrupt(self._access,
2557
2630
'unexpected version end line %r, wanted %r'
2558
% (last_line, version_id))
2631
% (last_line, rec[1]))
2633
return rec, record_contents
2635
def _parse_record(self, version_id, data):
2636
rec, record_contents = self._parse_record_unchecked(data)
2637
self._check_header_version(rec, version_id)
2560
2638
return record_contents, rec[3]
2562
2640
def read_records_iter_raw(self, records):