Mercurial > public > mercurial-scm > hg-stable
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: |