comparison 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
comparison
equal deleted inserted replaced
4260:bdbfc2193524 4261:cd7b36b7869c
24 return text.replace('\0', '\\0') 24 return text.replace('\0', '\\0')
25 25
26 def _string_unescape(text): 26 def _string_unescape(text):
27 return text.decode('string_escape') 27 return text.decode('string_escape')
28 28
29 class appender:
30 '''the changelog index must be update last on disk, so we use this class
31 to delay writes to it'''
32 def __init__(self, fp, buf):
33 self.data = buf
34 self.fp = fp
35 self.offset = fp.tell()
36 self.size = util.fstat(fp).st_size
37
38 def end(self):
39 return self.size + len("".join(self.data))
40 def tell(self):
41 return self.offset
42 def flush(self):
43 pass
44 def close(self):
45 close(self.fp)
46
47 def seek(self, offset, whence=0):
48 '''virtual file offset spans real file and data'''
49 if whence == 0:
50 self.offset = offset
51 elif whence == 1:
52 self.offset += offset
53 elif whence == 2:
54 self.offset = self.end() + offset
55 if self.offset < self.size:
56 self.fp.seek(self.offset)
57
58 def read(self, count=-1):
59 '''only trick here is reads that span real file and data'''
60 ret = ""
61 old_offset = self.offset
62 if self.offset < self.size:
63 s = self.fp.read(count)
64 ret = s
65 self.offset += len(s)
66 if count > 0:
67 count -= len(s)
68 if count != 0:
69 doff = self.offset - self.size
70 self.data.insert(0, "".join(self.data))
71 del self.data[1:]
72 s = self.data[0][doff:doff+count]
73 self.offset += len(s)
74 ret += s
75 return ret
76
77 def write(self, s):
78 self.data.append(s)
79 self.offset += len(s)
80
29 class changelog(revlog): 81 class changelog(revlog):
30 def __init__(self, opener): 82 def __init__(self, opener):
31 revlog.__init__(self, opener, "00changelog.i") 83 revlog.__init__(self, opener, "00changelog.i")
84
85 def delayupdate(self):
86 "delay visibility of index updates to other readers"
87 self._realopener = self.opener
88 self.opener = self._appendopener
89 self._delaybuf = []
90
91 def finalize(self, tr):
92 "finalize index updates"
93 self.opener = self._realopener
94 if self._delaybuf:
95 fp = self.opener(self.indexfile, 'a')
96 fp.write("".join(self._delaybuf))
97 fp.close()
98 del self._delaybuf
99 self.checkinlinesize(tr)
100
101 def _appendopener(self, name, mode='r'):
102 fp = self._realopener(name, mode)
103 if not name == self.indexfile:
104 return fp
105 return appender(fp, self._delaybuf)
106
107 def checkinlinesize(self, tr, fp=None):
108 if self.opener == self._appendopener:
109 return
110 return revlog.checkinlinesize(self, tr, fp)
32 111
33 def decode_extra(self, text): 112 def decode_extra(self, text):
34 extra = {} 113 extra = {}
35 for l in text.split('\0'): 114 for l in text.split('\0'):
36 if not l: 115 if not l: