153
def _add_full_text(self, t):
154
"""Add a full text to the file.
156
This is not compressed against any reference version.
158
Returns the index for that text."""
154
def _check_index(self, idx):
155
if idx < 0 or idx > len(self):
156
raise RevfileError("invalid index %r" % idx)
159
def find_sha(self, s):
160
assert isinstance(s, str)
163
for idx, idxrec in enumerate(self):
164
if idxrec[I_SHA] == s:
170
def _add_common(self, text_sha, data, flags, base):
171
"""Add pre-processed data, can be either full text or delta."""
160
173
self.datafile.seek(0, 2) # to end
161
174
self.idxfile.seek(0, 2)
162
175
assert self.idxfile.tell() == _RECORDSIZE * (idx + 1)
163
176
data_offset = self.datafile.tell()
165
assert isinstance(t, str) # not unicode or anything wierd
178
assert isinstance(data, str) # not unicode or anything wierd
167
self.datafile.write(t)
180
self.datafile.write(data)
168
181
self.datafile.flush()
170
entry = sha.new(t).digest()
171
entry += struct.pack(">IIII12x", 0xFFFFFFFFL, 0, data_offset, len(t))
183
assert isinstance(text_sha, str)
185
entry += struct.pack(">IIII12x", base, flags, data_offset, len(data))
172
186
assert len(entry) == _RECORDSIZE
174
188
self.idxfile.write(entry)
175
189
self.idxfile.flush()
180
def _check_index(self, idx):
181
if idx < 0 or idx > len(self):
182
raise RevfileError("invalid index %r" % idx)
185
def find_sha(self, s):
186
assert isinstance(s, str)
189
for idx, idxrec in enumerate(self):
190
if idxrec[I_SHA] == s:
196
def _add_diff(self, text, base):
195
def _add_full_text(self, text):
196
"""Add a full text to the file.
198
This is not compressed against any reference version.
200
Returns the index for that text."""
201
return self._add_common(sha.new(text).digest(), text, 0, _NO_RECORD)
204
def _add_delta(self, text, base):
197
205
"""Add a text stored relative to a previous text."""
198
206
self._check_index(base)
199
207
text_sha = sha.new(text).digest()
208
base_text = self.get(base)
209
data = mdiff.bdiff(base_text, text)
210
return self._add_common(text_sha, data, 0, base)
213
def add(self, text, base=None):
214
# TODO: check it's not already present?
202
218
def addrevision(self, text, changeset):
221
237
open(self.indexfile(), "a").write(entry)
222
238
open(self.datafile(), "a").write(data)
224
def _get_full_text(self, idx):
225
242
idxrec = self[idx]
226
assert idxrec[I_FLAGS] == 0
227
assert idxrec[I_BASE] == _NO_RECORD
243
base = idxrec[I_BASE]
244
if base == _NO_RECORD:
245
text = self._get_full_text(idx, idxrec)
247
text = self._get_patched(idx, idxrec)
249
if sha.new(text).digest() != idxrec[I_SHA]:
250
raise RevfileError("corrupt SHA-1 digest on record %d"
257
def _get_raw(self, idx, idxrec):
229
258
l = idxrec[I_LEN]
233
262
self.datafile.seek(idxrec[I_OFFSET])
235
text = self.datafile.read(l)
264
data = self.datafile.read(l)
237
266
raise RevfileError("short read %d of %d "
238
267
"getting text for record %d in %r"
239
% (len(text), l, idx, self.basename))
268
% (len(data), l, idx, self.basename))
241
if sha.new(text).digest() != idxrec[I_SHA]:
242
raise RevfileError("corrupt SHA-1 digest on record %d"
273
def _get_full_text(self, idx, idxrec):
274
assert idxrec[I_FLAGS] == 0
275
assert idxrec[I_BASE] == _NO_RECORD
277
text = self._get_raw(idx, idxrec)
282
def _get_patched(self, idx, idxrec):
283
assert idxrec[I_FLAGS] == 0
284
base = idxrec[I_BASE]
286
assert base < idx # no loops!
288
base_text = self.get(base)
289
patch = self._get_raw(idx, idxrec)
291
text = mdiff.bpatch(base_text, patch)
248
297
def __len__(self):