def applyTest(self, old, delta, new): s1 = RCSStream(old) self.assertEqual(s1.get_text(), old) s1.apply_diff(delta) self.assertEqual(s1.get_text(), new) s2 = RCSStream(old) self.assertEqual(s2.get_text(), old) s2.invert_diff(delta) self.assertEqual(s2.get_text(), new)
def applyTest(self, old, delta, new): s1 = RCSStream(old) self.assertEqual(s1.get_text(), old) s1.apply_diff(delta) self.assertEqual(s1.get_text(), new) s2 = RCSStream(old) self.assertEqual(s2.get_text(), old) s2.invert_diff(delta) self.assertEqual(s2.get_text(), new)
def set_revision_info(self, rev, log, text): revrec = self.revrecs.get(rev) if revrec is None: return base_rev = revrec.base if base_rev is None: # This must be the last revision on trunk, for which the # fulltext is stored directly in the RCS file: assert self.last_revrec is None if revrec.mark is not None: revrec.write_blob(self.blobfile, text) if revrec.is_needed(): self.last_revrec = revrec self.last_rcsstream = RCSStream(text) elif self.last_revrec is not None and base_rev == self.last_revrec.rev: # Our base revision is stored in self.last_rcsstream. self.last_revrec.refs.remove(rev) if self.last_revrec.is_needed(): if not self.last_revrec.is_written(): self.last_revrec.write( self.fulltext_file, self.last_rcsstream.get_text() ) self.last_rcsstream.apply_diff(text) if revrec.mark is not None: revrec.write_blob(self.blobfile, self.last_rcsstream.get_text()) if revrec.is_needed(): self.last_revrec = revrec else: self.last_revrec = None self.last_rcsstream = None else: # Our base revision is not stored in self.last_rcsstream; it # will have to be obtained from elsewhere. # Store the old last_rcsstream if necessary: if self.last_revrec is not None: if not self.last_revrec.is_written(): self.last_revrec.write( self.fulltext_file, self.last_rcsstream.get_text() ) self.last_revrec = None self.last_rcsstream = None base_revrec = self[base_rev] rcsstream = RCSStream(base_revrec.read_fulltext()) base_revrec.refs.remove(rev) rcsstream.apply_diff(text) if revrec.mark is not None: revrec.write_blob(self.blobfile, rcsstream.get_text()) if revrec.is_needed(): self.last_revrec = revrec self.last_rcsstream = rcsstream del rcsstream
def set_revision_info(self, rev, log, text): revrec = self.revrecs.get(rev) if revrec is None: return base_rev = revrec.base if base_rev is None: # This must be the last revision on trunk, for which the # fulltext is stored directly in the RCS file: assert self.last_revrec is None if revrec.mark is not None: revrec.write_blob(self.blobfile, text) if revrec.is_needed(): self.last_revrec = revrec self.last_rcsstream = RCSStream(text) elif self.last_revrec is not None and base_rev == self.last_revrec.rev: # Our base revision is stored in self.last_rcsstream. self.last_revrec.refs.remove(rev) if self.last_revrec.is_needed(): if not self.last_revrec.is_written(): self.last_revrec.write( self.fulltext_file, self.last_rcsstream.get_text() ) self.last_rcsstream.apply_diff(text) if revrec.mark is not None: revrec.write_blob(self.blobfile, self.last_rcsstream.get_text()) if revrec.is_needed(): self.last_revrec = revrec else: self.last_revrec = None self.last_rcsstream = None else: # Our base revision is not stored in self.last_rcsstream; it # will have to be obtained from elsewhere. # Store the old last_rcsstream if necessary: if self.last_revrec is not None: if not self.last_revrec.is_written(): self.last_revrec.write( self.fulltext_file, self.last_rcsstream.get_text() ) self.last_revrec = None self.last_rcsstream = None base_revrec = self[base_rev] rcsstream = RCSStream(base_revrec.read_fulltext()) base_revrec.refs.remove(rev) rcsstream.apply_diff(text) if revrec.mark is not None: revrec.write_blob(self.blobfile, rcsstream.get_text()) if revrec.is_needed(): self.last_revrec = revrec self.last_rcsstream = rcsstream del rcsstream
def checkout(self, text_record_db): base_text = text_record_db[self.pred_id].checkout(text_record_db) rcs_stream = RCSStream(base_text) delta_text = text_record_db.delta_db[self.id] rcs_stream.apply_diff(delta_text) text = rcs_stream.get_text() del rcs_stream self.refcount -= 1 if self.refcount == 0: # This text will never be needed again; just delete ourselves # without ever having stored the fulltext to the checkout # database: del text_record_db[self.id] else: # Store a new CheckedOutTextRecord in place of ourselves: text_record_db.checkout_db['%x' % self.id] = text new_text_record = CheckedOutTextRecord(self.id) new_text_record.refcount = self.refcount text_record_db.replace(new_text_record) return text
def checkout(self, text_record_db): base_text = text_record_db[self.pred_id].checkout(text_record_db) co = RCSStream(base_text) delta_text = text_record_db.delta_db[self.id] co.apply_diff(delta_text) text = co.get_text() del co self.refcount -= 1 if self.refcount == 0: # This text will never be needed again; just delete ourselves # without ever having stored the fulltext to the checkout # database: del text_record_db[self.id] else: # Store a new CheckedOutTextRecord in place of ourselves: text_record_db.checkout_db['%x' % self.id] = text new_text_record = CheckedOutTextRecord(self.id) new_text_record.refcount = self.refcount text_record_db.replace(new_text_record) return text
class WriteBlobSink(Sink): def __init__(self, blobfile, marks): self.blobfile = blobfile # A map {rev : RevRecord} for all of the revisions whose fulltext # will still be needed: self.revrecs = {} # The revisions that need marks will definitely be needed, so # create records for them now (the rest will be filled in while # reading the RCS file): for (rev, mark) in marks.items(): self.revrecs[rev] = RevRecord(rev, mark) # The RevRecord of the last fulltext that has been reconstructed, # if it still is_needed(): self.last_revrec = None # An RCSStream holding the fulltext of last_revrec: self.last_rcsstream = None # A file to temporarily hold the fulltexts of revisions for which # no blobs are needed: self.fulltext_file = tempfile.TemporaryFile() def __getitem__(self, rev): try: return self.revrecs[rev] except KeyError: revrec = RevRecord(rev) self.revrecs[rev] = revrec return revrec def define_revision(self, rev, timestamp, author, state, branches, next): revrec = self[rev] if next is not None: revrec.refs.add(next) revrec.refs.update(branches) for dependent_rev in revrec.refs: dependent_revrec = self[dependent_rev] assert dependent_revrec.base is None dependent_revrec.base = rev def tree_completed(self): """Remove unneeded RevRecords. Remove the RevRecords for any revisions whose fulltext will not be needed (neither as blob output nor as the base of another needed revision).""" revrecs_to_remove = [ revrec for revrec in self.revrecs.itervalues() if not revrec.is_needed() ] while revrecs_to_remove: revrec = revrecs_to_remove.pop() del self.revrecs[revrec.rev] if revrec.base is not None: base_revrec = self[revrec.base] base_revrec.refs.remove(revrec.rev) if not base_revrec.is_needed(): revrecs_to_remove.append(base_revrec) def set_revision_info(self, rev, log, text): revrec = self.revrecs.get(rev) if revrec is None: return base_rev = revrec.base if base_rev is None: # This must be the last revision on trunk, for which the # fulltext is stored directly in the RCS file: assert self.last_revrec is None if revrec.mark is not None: revrec.write_blob(self.blobfile, text) if revrec.is_needed(): self.last_revrec = revrec self.last_rcsstream = RCSStream(text) elif self.last_revrec is not None and base_rev == self.last_revrec.rev: # Our base revision is stored in self.last_rcsstream. self.last_revrec.refs.remove(rev) if self.last_revrec.is_needed() and not self.last_revrec.is_written(): self.last_revrec.write( self.fulltext_file, self.last_rcsstream.get_text() ) self.last_rcsstream.apply_diff(text) if revrec.mark is not None: revrec.write_blob(self.blobfile, self.last_rcsstream.get_text()) if revrec.is_needed(): self.last_revrec = revrec else: self.last_revrec = None self.last_rcsstream = None else: # Our base revision is not stored in self.last_rcsstream; it # will have to be obtained from elsewhere. # Store the old last_rcsstream if necessary: if self.last_revrec is not None: if not self.last_revrec.is_written(): self.last_revrec.write( self.fulltext_file, self.last_rcsstream.get_text() ) self.last_revrec = None self.last_rcsstream = None base_revrec = self[base_rev] rcsstream = RCSStream(base_revrec.read_fulltext()) base_revrec.refs.remove(rev) rcsstream.apply_diff(text) if revrec.mark is not None: revrec.write_blob(self.blobfile, rcsstream.get_text()) if revrec.is_needed(): self.last_revrec = revrec self.last_rcsstream = rcsstream del rcsstream def parse_completed(self): self.fulltext_file.close()
class WriteBlobSink(Sink): def __init__(self, blobfile, marks): self.blobfile = blobfile # A map {rev : RevRecord} for all of the revisions whose fulltext # will still be needed: self.revrecs = {} # The revisions that need marks will definitely be needed, so # create records for them now (the rest will be filled in while # reading the RCS file): for (rev, mark) in marks.items(): self.revrecs[rev] = RevRecord(rev, mark) # The RevRecord of the last fulltext that has been reconstructed, # if it still is_needed(): self.last_revrec = None # An RCSStream holding the fulltext of last_revrec: self.last_rcsstream = None # A file to temporarily hold the fulltexts of revisions for which # no blobs are needed: self.fulltext_file = tempfile.TemporaryFile() def __getitem__(self, rev): try: return self.revrecs[rev] except KeyError: revrec = RevRecord(rev) self.revrecs[rev] = revrec return revrec def define_revision(self, rev, timestamp, author, state, branches, next): revrec = self[rev] if next is not None: revrec.refs.add(next) revrec.refs.update(branches) for dependent_rev in revrec.refs: dependent_revrec = self[dependent_rev] assert dependent_revrec.base is None dependent_revrec.base = rev def tree_completed(self): """Remove unneeded RevRecords. Remove the RevRecords for any revisions whose fulltext will not be needed (neither as blob output nor as the base of another needed revision).""" revrecs_to_remove = [ revrec for revrec in self.revrecs.itervalues() if not revrec.is_needed() ] while revrecs_to_remove: revrec = revrecs_to_remove.pop() del self.revrecs[revrec.rev] base_revrec = self[revrec.base] base_revrec.refs.remove(revrec.rev) if not base_revrec.is_needed(): revrecs_to_remove.append(base_revrec) def set_revision_info(self, rev, log, text): revrec = self.revrecs.get(rev) if revrec is None: return base_rev = revrec.base if base_rev is None: # This must be the last revision on trunk, for which the # fulltext is stored directly in the RCS file: assert self.last_revrec is None if revrec.mark is not None: revrec.write_blob(self.blobfile, text) if revrec.is_needed(): self.last_revrec = revrec self.last_rcsstream = RCSStream(text) elif self.last_revrec is not None and base_rev == self.last_revrec.rev: # Our base revision is stored in self.last_rcsstream. self.last_revrec.refs.remove(rev) if self.last_revrec.is_needed(): if not self.last_revrec.is_written(): self.last_revrec.write(self.fulltext_file, self.last_rcsstream.get_text()) self.last_rcsstream.apply_diff(text) if revrec.mark is not None: revrec.write_blob(self.blobfile, self.last_rcsstream.get_text()) if revrec.is_needed(): self.last_revrec = revrec else: self.last_revrec = None self.last_rcsstream = None else: # Our base revision is not stored in self.last_rcsstream; it # will have to be obtained from elsewhere. # Store the old last_rcsstream if necessary: if self.last_revrec is not None: if not self.last_revrec.is_written(): self.last_revrec.write(self.fulltext_file, self.last_rcsstream.get_text()) self.last_revrec = None self.last_rcsstream = None base_revrec = self[base_rev] rcsstream = RCSStream(base_revrec.read_fulltext()) base_revrec.refs.remove(rev) rcsstream.apply_diff(text) if revrec.mark is not None: revrec.write_blob(self.blobfile, rcsstream.get_text()) if revrec.is_needed(): self.last_revrec = revrec self.last_rcsstream = rcsstream del rcsstream def parse_completed(self): self.fulltext_file.close()