115
115
"""Return a list of (origin, text) tuples."""
116
116
return list(self.annotate_iter())
118
def apply_delta(self, delta):
119
"""Apply delta to this content."""
121
for start, end, count, lines in delta:
122
self._lines[offset+start:offset+end] = lines
123
offset = offset + (start - end) + count
125
118
def line_delta_iter(self, new_lines):
126
119
"""Generate line-based delta from this content to new_lines."""
127
120
new_texts = [text for origin, text in new_lines._lines]
289
282
self._data = _KnitData(transport, relpath + DATA_SUFFIX,
290
283
access_mode, create=not len(self.versions()))
285
def _add_delta(self, version_id, parents, delta_parent, sha1, noeol, delta):
286
"""See VersionedFile._add_delta()."""
287
self._check_add(version_id, []) # should we check the lines ?
288
self._check_versions_present(parents)
292
for parent in parents:
293
if not self.has_version(parent):
294
ghosts.append(parent)
296
present_parents.append(parent)
298
if delta_parent is None:
299
# reconstitute as full text.
300
assert len(delta) == 1 or len(delta) == 0
302
assert delta[0][0] == 0
303
assert delta[0][1] == 0
304
return super(KnitVersionedFile, self)._add_delta(version_id,
315
options.append('no-eol')
317
if delta_parent is not None:
318
# determine the current delta chain length.
319
# To speed the extract of texts the delta chain is limited
320
# to a fixed number of deltas. This should minimize both
321
# I/O and the time spend applying deltas.
323
delta_parents = [delta_parent]
325
parent = delta_parents[0]
326
method = self._index.get_method(parent)
327
if method == 'fulltext':
329
delta_parents = self._index.get_parents(parent)
331
if method == 'line-delta':
332
# did not find a fulltext in the delta limit.
333
# just do a normal insertion.
334
return super(KnitVersionedFile, self)._add_delta(version_id,
341
options.append('line-delta')
342
store_lines = self.factory.lower_line_delta(delta)
344
where, size = self._data.add_record(version_id, digest, store_lines)
345
self._index.add_version(version_id, options, where, size, parents)
292
347
def clear_cache(self):
293
348
"""Clear the data cache only."""
294
349
self._data.clear_cache()
335
390
data_pos, data_size = self._index.get_position(version_id)
336
391
data, sha1 = self._data.read_records(((version_id, data_pos, data_size),))[version_id]
337
392
version_idx = self._index.lookup(version_id)
393
noeol = 'no-eol' in self._index.get_options(version_id)
338
394
if 'fulltext' == self._index.get_method(version_id):
339
395
new_content = self.factory.parse_fulltext(data, version_idx)
340
396
if parent is not None:
345
401
new_texts = new_content.text()
346
402
delta_seq = SequenceMatcher(None, old_texts, new_texts)
347
return parent, sha1, self._make_line_delta(delta_seq, new_content)
403
return parent, sha1, noeol, self._make_line_delta(delta_seq, new_content)
349
405
delta = self.factory.parse_line_delta(data, version_idx)
350
return parent, sha1, delta
406
return parent, sha1, noeol, delta
352
408
def get_graph_with_ghosts(self):
353
409
"""See VersionedFile.get_graph_with_ghosts()."""
500
556
content = self.factory.parse_fulltext(data, version_idx)
501
557
elif method == 'line-delta':
502
558
delta = self.factory.parse_line_delta(data, version_idx)
503
content.apply_delta(delta)
559
content._lines = self._apply_delta(content._lines, delta)
505
561
if 'no-eol' in self._index.get_options(version_id):
506
562
line = content._lines[-1][1].rstrip('\n')