254
254
def parse_line_delta_iter(self, lines):
255
255
return iter(self.parse_line_delta(lines))
257
def parse_line_delta(self, lines, version_id):
257
def parse_line_delta(self, lines, version_id, plain=False):
258
258
"""Convert a line based delta into internal representation.
260
260
line delta is in the form of:
263
263
revid(utf8) newline\n
264
264
internal representation is
265
265
(start, end, count, [1..count tuples (revid, newline)])
267
:param plain: If True, the lines are returned as a plain
268
list, not as a list of tuples, i.e.
269
(start, end, count, [1..count newline])
268
272
lines = iter(lines)
274
278
return cache.setdefault(origin, origin), text
276
280
# walk through the lines parsing.
278
start, end, count = [int(n) for n in header.split(',')]
279
contents = [tuple(next().split(' ', 1)) for i in xrange(count)]
280
result.append((start, end, count, contents))
281
# Note that the plain test is explicitly pulled out of the
282
# loop to minimise any performance impact
285
start, end, count = [int(n) for n in header.split(',')]
286
contents = [next().split(' ', 1)[1] for i in xrange(count)]
287
result.append((start, end, count, contents))
290
start, end, count = [int(n) for n in header.split(',')]
291
contents = [tuple(next().split(' ', 1)) for i in xrange(count)]
292
result.append((start, end, count, contents))
283
295
def get_fulltext_content(self, lines):
411
423
def __init__(self, relpath, transport, file_mode=None, access_mode=None,
412
factory=None, basis_knit=DEPRECATED_PARAMETER, delta=True,
413
create=False, create_parent_dir=False, delay_create=False,
414
dir_mode=None, index=None, access_method=None):
424
factory=None, delta=True, create=False, create_parent_dir=False,
425
delay_create=False, dir_mode=None, index=None, access_method=None):
415
426
"""Construct a knit at location specified by relpath.
417
428
:param create: If not True, only open an existing knit.
422
433
actually be created until the first data is stored.
423
434
:param index: An index to use for the knit.
425
if deprecated_passed(basis_knit):
426
warnings.warn("KnitVersionedFile.__(): The basis_knit parameter is"
427
" deprecated as of bzr 0.9.",
428
DeprecationWarning, stacklevel=2)
429
436
if access_mode is None:
430
437
access_mode = 'w'
431
438
super(KnitVersionedFile, self).__init__(access_mode)
455
462
self._data = _KnitData(_access)
457
464
def __repr__(self):
458
return '%s(%s)' % (self.__class__.__name__,
465
return '%s(%s)' % (self.__class__.__name__,
459
466
self.transport.abspath(self.filename))
461
468
def _check_should_delta(self, first_parents):
971
978
the requested versions and content_map contains the KnitContents.
972
979
Both dicts take version_ids as their keys.
974
for version_id in version_ids:
975
if not self.has_version(version_id):
976
raise RevisionNotPresent(version_id, self.filename)
977
981
record_map = self._get_record_map(version_ids)
1413
1417
def get_method(self, version_id):
1414
1418
"""Return compression method of specified version."""
1415
options = self._cache[version_id][1]
1420
options = self._cache[version_id][1]
1422
raise RevisionNotPresent(version_id, self._filename)
1416
1423
if 'fulltext' in options:
1417
1424
return 'fulltext'
1651
1658
return 'fulltext'
1653
1660
def _get_node(self, version_id):
1654
return list(self._get_entries(self._version_ids_to_keys([version_id])))[0]
1662
return list(self._get_entries(self._version_ids_to_keys([version_id])))[0]
1664
raise RevisionNotPresent(version_id, self)
1656
1666
def get_options(self, version_id):
1657
1667
"""Return a string represention options.
2154
2164
assert isinstance(self.source, KnitVersionedFile)
2155
2165
assert isinstance(self.target, KnitVersionedFile)
2167
# If the source and target are mismatched w.r.t. annotations vs
2168
# plain, the data needs to be converted accordingly
2169
if self.source.factory.annotated == self.target.factory.annotated:
2171
elif self.source.factory.annotated:
2172
converter = self._anno_to_plain_converter
2174
# We're converting from a plain to an annotated knit. This requires
2175
# building the annotations from scratch. The generic join code
2176
# handles this implicitly so we delegate to it.
2177
return super(InterKnit, self).join(pb, msg, version_ids,
2157
2180
version_ids = self._get_source_version_ids(version_ids, ignore_missing)
2159
2181
if not version_ids:
2213
2235
assert version_id == version_id2, 'logic error, inconsistent results'
2214
2236
count = count + 1
2215
2237
pb.update("Joining knit", count, total)
2216
raw_records.append((version_id, options, parents, len(raw_data)))
2239
size, raw_data = converter(raw_data, version_id, options,
2242
size = len(raw_data)
2243
raw_records.append((version_id, options, parents, size))
2217
2244
raw_datum.append(raw_data)
2218
2245
self.target._add_raw_records(raw_records, ''.join(raw_datum))
2250
def _anno_to_plain_converter(self, raw_data, version_id, options,
2252
"""Convert annotated content to plain content."""
2253
data, digest = self.source._data._parse_record(version_id, raw_data)
2254
if 'fulltext' in options:
2255
content = self.source.factory.parse_fulltext(data, version_id)
2256
lines = self.target.factory.lower_fulltext(content)
2258
delta = self.source.factory.parse_line_delta(data, version_id,
2260
lines = self.target.factory.lower_line_delta(delta)
2261
return self.target._data._record_to_data(version_id, digest, lines)
2224
2264
InterVersionedFile.register_optimiser(InterKnit)