77
77
"""Returns whether version is present."""
78
78
raise NotImplementedError(self.has_version)
80
def add_delta(self, version_id, parents, delta_parent, sha1, noeol, delta):
81
"""Add a text to the versioned file via a pregenerated delta.
83
:param version_id: The version id being added.
84
:param parents: The parents of the version_id.
85
:param delta_parent: The parent this delta was created against.
86
:param sha1: The sha1 of the full text.
87
:param delta: The delta instructions. See get_delta for details.
89
version_id = osutils.safe_revision_id(version_id)
90
parents = [osutils.safe_revision_id(v) for v in parents]
91
self._check_write_ok()
92
if self.has_version(version_id):
93
raise errors.RevisionAlreadyPresent(version_id, self)
94
return self._add_delta(version_id, parents, delta_parent, sha1, noeol, delta)
96
def _add_delta(self, version_id, parents, delta_parent, sha1, noeol, delta):
97
"""Class specific routine to add a delta.
99
This generic version simply applies the delta to the delta_parent and
102
# strip annotation from delta
104
for start, stop, delta_len, delta_lines in delta:
105
new_delta.append((start, stop, delta_len, [text for origin, text in delta_lines]))
106
if delta_parent is not None:
107
parent_full = self.get_lines(delta_parent)
110
new_full = self._apply_delta(parent_full, new_delta)
111
# its impossible to have noeol on an empty file
112
if noeol and new_full[-1][-1] == '\n':
113
new_full[-1] = new_full[-1][:-1]
114
self.add_lines(version_id, parents, new_full)
116
80
def add_lines(self, version_id, parents, lines, parent_texts=None,
117
left_matching_blocks=None):
81
left_matching_blocks=None, nostore_sha=None, random_id=False,
118
83
"""Add a single text on top of the versioned file.
120
85
Must raise RevisionAlreadyPresent if the new version is
123
88
Must raise RevisionNotPresent if any of the given parents are
124
89
not present in file history.
91
:param lines: A list of lines. Each line must be a bytestring. And all
92
of them except the last must be terminated with \n and contain no
93
other \n's. The last line may either contain no \n's or a single
94
terminated \n. If the lines list does meet this constraint the add
95
routine may error or may succeed - but you will be unable to read
96
the data back accurately. (Checking the lines have been split
97
correctly is expensive and extremely unlikely to catch bugs so it
98
is not done at runtime unless check_content is True.)
125
99
:param parent_texts: An optional dictionary containing the opaque
126
representations of some or all of the parents of
127
version_id to allow delta optimisations.
128
VERY IMPORTANT: the texts must be those returned
129
by add_lines or data corruption can be caused.
100
representations of some or all of the parents of version_id to
101
allow delta optimisations. VERY IMPORTANT: the texts must be those
102
returned by add_lines or data corruption can be caused.
130
103
:param left_matching_blocks: a hint about which areas are common
131
104
between the text and its left-hand-parent. The format is
132
105
the SequenceMatcher.get_matching_blocks format.
133
:return: An opaque representation of the inserted version which can be
134
provided back to future add_lines calls in the parent_texts
106
:param nostore_sha: Raise ExistingContent and do not add the lines to
107
the versioned file if the digest of the lines matches this.
108
:param random_id: If True a random id has been selected rather than
109
an id determined by some deterministic process such as a converter
110
from a foreign VCS. When True the backend may choose not to check
111
for uniqueness of the resulting key within the versioned file, so
112
this should only be done when the result is expected to be unique
114
:param check_content: If True, the lines supplied are verified to be
115
bytestrings that are correctly formed lines.
116
:return: The text sha1, the number of bytes in the text, and an opaque
117
representation of the inserted version which can be provided
118
back to future add_lines calls in the parent_texts dictionary.
137
version_id = osutils.safe_revision_id(version_id)
138
parents = [osutils.safe_revision_id(v) for v in parents]
139
120
self._check_write_ok()
140
121
return self._add_lines(version_id, parents, lines, parent_texts,
141
left_matching_blocks)
122
left_matching_blocks, nostore_sha, random_id, check_content)
143
124
def _add_lines(self, version_id, parents, lines, parent_texts,
144
left_matching_blocks):
125
left_matching_blocks, nostore_sha, random_id, check_content):
145
126
"""Helper to do the class specific add_lines."""
146
127
raise NotImplementedError(self.add_lines)
148
129
def add_lines_with_ghosts(self, version_id, parents, lines,
130
parent_texts=None, nostore_sha=None, random_id=False,
150
132
"""Add lines to the versioned file, allowing ghosts to be present.
152
This takes the same parameters as add_lines.
134
This takes the same parameters as add_lines and returns the same.
154
version_id = osutils.safe_revision_id(version_id)
155
parents = [osutils.safe_revision_id(v) for v in parents]
156
136
self._check_write_ok()
157
137
return self._add_lines_with_ghosts(version_id, parents, lines,
138
parent_texts, nostore_sha, random_id, check_content)
160
def _add_lines_with_ghosts(self, version_id, parents, lines, parent_texts):
140
def _add_lines_with_ghosts(self, version_id, parents, lines, parent_texts,
141
nostore_sha, random_id, check_content):
161
142
"""Helper to do class specific add_lines_with_ghosts."""
162
143
raise NotImplementedError(self.add_lines_with_ghosts)
225
204
raise NotImplementedError(self.create_empty)
227
def fix_parents(self, version_id, new_parents):
228
"""Fix the parents list for version.
230
This is done by appending a new version to the index
231
with identical data except for the parents list.
232
the parents list must be a superset of the current
235
version_id = osutils.safe_revision_id(version_id)
236
new_parents = [osutils.safe_revision_id(p) for p in new_parents]
237
self._check_write_ok()
238
return self._fix_parents(version_id, new_parents)
240
def _fix_parents(self, version_id, new_parents):
241
"""Helper for fix_parents."""
242
raise NotImplementedError(self.fix_parents)
244
def get_delta(self, version):
245
"""Get a delta for constructing version from some other version.
247
:return: (delta_parent, sha1, noeol, delta)
248
Where delta_parent is a version id or None to indicate no parent.
250
raise NotImplementedError(self.get_delta)
252
def get_deltas(self, version_ids):
253
"""Get multiple deltas at once for constructing versions.
255
:return: dict(version_id:(delta_parent, sha1, noeol, delta))
256
Where delta_parent is a version id or None to indicate no parent, and
257
version_id is the version_id created by that delta.
260
for version_id in version_ids:
261
result[version_id] = self.get_delta(version_id)
264
206
def get_format_signature(self):
265
207
"""Get a text description of the data encoding in this file.
269
211
raise NotImplementedError(self.get_format_signature)
271
213
def make_mpdiffs(self, version_ids):
272
"""Create multiparent diffs for specified versions"""
214
"""Create multiparent diffs for specified versions."""
273
215
knit_versions = set()
274
216
for version_id in version_ids:
275
217
knit_versions.add(version_id)
318
261
mpvf.get_diff(parent_ids[0]).num_lines()))
320
263
left_matching_blocks = None
321
version_text = self.add_lines(version, parent_ids, lines,
264
_, _, version_text = self.add_lines(version, parent_ids, lines,
322
265
vf_parents, left_matching_blocks=left_matching_blocks)
323
266
vf_parents[version] = version_text
324
267
for (version, parent_ids, expected_sha1, mpdiff), sha1 in\
459
402
def annotate(self, version_id):
460
403
return list(self.annotate_iter(version_id))
462
def _apply_delta(self, lines, delta):
463
"""Apply delta to lines."""
466
for start, end, count, delta_lines in delta:
467
lines[offset+start:offset+end] = delta_lines
468
offset = offset + (start - end) + count
471
405
def join(self, other, pb=None, msg=None, version_ids=None,
472
406
ignore_missing=False):
473
407
"""Integrate versions from other into this versioned file.
684
618
# TODO: remove parent texts when they are not relevant any more for
685
619
# memory pressure reduction. RBC 20060313
686
620
# pb.update('Converting versioned data', 0, len(order))
687
# deltas = self.source.get_deltas(order)
688
622
for index, version in enumerate(order):
689
pb.update('Converting versioned data', index, len(order))
690
parent_text = target.add_lines(version,
623
pb.update('Converting versioned data', index, total)
624
_, _, parent_text = target.add_lines(version,
691
625
self.source.get_parents(version),
692
626
self.source.get_lines(version),
693
627
parent_texts=parent_texts)
694
628
parent_texts[version] = parent_text
695
#delta_parent, sha1, noeol, delta = deltas[version]
696
#target.add_delta(version,
697
# self.source.get_parents(version),
702
#target.get_lines(version)
704
630
# this should hit the native code path for target
705
631
if target is not self.target: