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: |