Mercurial > public > mercurial-scm > hg-stable
diff mercurial/changelog.py @ 4261:cd7b36b7869c
restructure changelog file appending
- make appending code proper part of changelog with delayupdate/finalize
- use simplified appender that tracks pending data in memory
- eliminate old appendfile and helper classes
- update addchangegroup to use new interface and reuse the existing changelog
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Thu, 22 Mar 2007 23:37:44 -0500 |
parents | b11a2fb59cf5 |
children | 73c918c71300 |
line wrap: on
line diff
--- a/mercurial/changelog.py Thu Mar 22 20:10:46 2007 -0500 +++ b/mercurial/changelog.py Thu Mar 22 23:37:44 2007 -0500 @@ -26,10 +26,89 @@ def _string_unescape(text): return text.decode('string_escape') +class appender: + '''the changelog index must be update last on disk, so we use this class + to delay writes to it''' + def __init__(self, fp, buf): + self.data = buf + self.fp = fp + self.offset = fp.tell() + self.size = util.fstat(fp).st_size + + def end(self): + return self.size + len("".join(self.data)) + def tell(self): + return self.offset + def flush(self): + pass + def close(self): + close(self.fp) + + def seek(self, offset, whence=0): + '''virtual file offset spans real file and data''' + if whence == 0: + self.offset = offset + elif whence == 1: + self.offset += offset + elif whence == 2: + self.offset = self.end() + offset + if self.offset < self.size: + self.fp.seek(self.offset) + + def read(self, count=-1): + '''only trick here is reads that span real file and data''' + ret = "" + old_offset = self.offset + if self.offset < self.size: + s = self.fp.read(count) + ret = s + self.offset += len(s) + if count > 0: + count -= len(s) + if count != 0: + doff = self.offset - self.size + self.data.insert(0, "".join(self.data)) + del self.data[1:] + s = self.data[0][doff:doff+count] + self.offset += len(s) + ret += s + return ret + + def write(self, s): + self.data.append(s) + self.offset += len(s) + class changelog(revlog): def __init__(self, opener): revlog.__init__(self, opener, "00changelog.i") + def delayupdate(self): + "delay visibility of index updates to other readers" + self._realopener = self.opener + self.opener = self._appendopener + self._delaybuf = [] + + def finalize(self, tr): + "finalize index updates" + self.opener = self._realopener + if self._delaybuf: + fp = self.opener(self.indexfile, 'a') + fp.write("".join(self._delaybuf)) + fp.close() + del self._delaybuf + self.checkinlinesize(tr) + + def _appendopener(self, name, mode='r'): + fp = self._realopener(name, mode) + if not name == self.indexfile: + return fp + return appender(fp, self._delaybuf) + + def checkinlinesize(self, tr, fp=None): + if self.opener == self._appendopener: + return + return revlog.checkinlinesize(self, tr, fp) + def decode_extra(self, text): extra = {} for l in text.split('\0'):