Show More
@@ -11,8 +11,9 from demandload import demandload | |||||
11 | demandload(globals(), "os time util") |
|
11 | demandload(globals(), "os time util") | |
12 |
|
12 | |||
13 | class changelog(revlog): |
|
13 | class changelog(revlog): | |
14 | def __init__(self, opener): |
|
14 | def __init__(self, opener, defversion=0): | |
15 |
revlog.__init__(self, opener, "00changelog.i", "00changelog.d" |
|
15 | revlog.__init__(self, opener, "00changelog.i", "00changelog.d", | |
|
16 | defversion) | |||
16 |
|
17 | |||
17 | def extract(self, text): |
|
18 | def extract(self, text): | |
18 | if not text: |
|
19 | if not text: |
@@ -1268,7 +1268,7 def copy(ui, repo, *pats, **opts): | |||||
1268 |
|
1268 | |||
1269 | def debugancestor(ui, index, rev1, rev2): |
|
1269 | def debugancestor(ui, index, rev1, rev2): | |
1270 | """find the ancestor revision of two revisions in a given index""" |
|
1270 | """find the ancestor revision of two revisions in a given index""" | |
1271 | r = revlog.revlog(util.opener(os.getcwd(), audit=False), index, "") |
|
1271 | r = revlog.revlog(util.opener(os.getcwd(), audit=False), index, "", 0) | |
1272 | a = r.ancestor(r.lookup(rev1), r.lookup(rev2)) |
|
1272 | a = r.ancestor(r.lookup(rev1), r.lookup(rev2)) | |
1273 | ui.write("%d:%s\n" % (r.rev(a), hex(a))) |
|
1273 | ui.write("%d:%s\n" % (r.rev(a), hex(a))) | |
1274 |
|
1274 | |||
@@ -1372,7 +1372,7 def debugstate(ui, repo): | |||||
1372 | def debugdata(ui, file_, rev): |
|
1372 | def debugdata(ui, file_, rev): | |
1373 | """dump the contents of an data file revision""" |
|
1373 | """dump the contents of an data file revision""" | |
1374 | r = revlog.revlog(util.opener(os.getcwd(), audit=False), |
|
1374 | r = revlog.revlog(util.opener(os.getcwd(), audit=False), | |
1375 | file_[:-2] + ".i", file_) |
|
1375 | file_[:-2] + ".i", file_, 0) | |
1376 | try: |
|
1376 | try: | |
1377 | ui.write(r.revision(r.lookup(rev))) |
|
1377 | ui.write(r.revision(r.lookup(rev))) | |
1378 | except KeyError: |
|
1378 | except KeyError: | |
@@ -1380,18 +1380,19 def debugdata(ui, file_, rev): | |||||
1380 |
|
1380 | |||
1381 | def debugindex(ui, file_): |
|
1381 | def debugindex(ui, file_): | |
1382 | """dump the contents of an index file""" |
|
1382 | """dump the contents of an index file""" | |
1383 | r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_, "") |
|
1383 | r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_, "", 0) | |
1384 | ui.write(" rev offset length base linkrev" + |
|
1384 | ui.write(" rev offset length base linkrev" + | |
1385 | " nodeid p1 p2\n") |
|
1385 | " nodeid p1 p2\n") | |
1386 | for i in range(r.count()): |
|
1386 | for i in range(r.count()): | |
1387 |
e = r. |
|
1387 | node = r.node(i) | |
|
1388 | pp = r.parents(node) | |||
1388 | ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % ( |
|
1389 | ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % ( | |
1389 | i, e[0], e[1], e[2], e[3], |
|
1390 | i, r.start(i), r.length(i), r.base(i), r.linkrev(node), | |
1390 |
short(e[ |
|
1391 | short(node), short(pp[0]), short(pp[1]))) | |
1391 |
|
1392 | |||
1392 | def debugindexdot(ui, file_): |
|
1393 | def debugindexdot(ui, file_): | |
1393 | """dump an index DAG as a .dot file""" |
|
1394 | """dump an index DAG as a .dot file""" | |
1394 | r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_, "") |
|
1395 | r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_, "", 0) | |
1395 | ui.write("digraph G {\n") |
|
1396 | ui.write("digraph G {\n") | |
1396 | for i in range(r.count()): |
|
1397 | for i in range(r.count()): | |
1397 | e = r.index[i] |
|
1398 | e = r.index[i] |
@@ -11,10 +11,11 from demandload import * | |||||
11 | demandload(globals(), "bdiff") |
|
11 | demandload(globals(), "bdiff") | |
12 |
|
12 | |||
13 | class filelog(revlog): |
|
13 | class filelog(revlog): | |
14 | def __init__(self, opener, path): |
|
14 | def __init__(self, opener, path, defversion=0): | |
15 | revlog.__init__(self, opener, |
|
15 | revlog.__init__(self, opener, | |
16 | os.path.join("data", self.encodedir(path + ".i")), |
|
16 | os.path.join("data", self.encodedir(path + ".i")), | |
17 |
os.path.join("data", self.encodedir(path + ".d")) |
|
17 | os.path.join("data", self.encodedir(path + ".d")), | |
|
18 | defversion) | |||
18 |
|
19 | |||
19 | # This avoids a collision between a file named foo and a dir named |
|
20 | # This avoids a collision between a file named foo and a dir named | |
20 | # foo.i or foo.d |
|
21 | # foo.i or foo.d |
@@ -10,8 +10,8 import filelog, manifest, changelog, dir | |||||
10 | from node import * |
|
10 | from node import * | |
11 | from i18n import gettext as _ |
|
11 | from i18n import gettext as _ | |
12 | from demandload import * |
|
12 | from demandload import * | |
13 | demandload(globals(), "re lock transaction tempfile stat mdiff errno ui") |
|
|||
14 | demandload(globals(), "appendfile changegroup") |
|
13 | demandload(globals(), "appendfile changegroup") | |
|
14 | demandload(globals(), "re lock transaction tempfile stat mdiff errno ui revlog") | |||
15 |
|
15 | |||
16 | class localrepository(object): |
|
16 | class localrepository(object): | |
17 | def __del__(self): |
|
17 | def __del__(self): | |
@@ -35,8 +35,20 class localrepository(object): | |||||
35 | self.ui = ui.ui(parentui=parentui) |
|
35 | self.ui = ui.ui(parentui=parentui) | |
36 | self.opener = util.opener(self.path) |
|
36 | self.opener = util.opener(self.path) | |
37 | self.wopener = util.opener(self.root) |
|
37 | self.wopener = util.opener(self.root) | |
38 | self.manifest = manifest.manifest(self.opener) |
|
38 | ||
39 | self.changelog = changelog.changelog(self.opener) |
|
39 | try: | |
|
40 | self.ui.readconfig(self.join("hgrc"), self.root) | |||
|
41 | except IOError: | |||
|
42 | pass | |||
|
43 | ||||
|
44 | v = self.ui.revlogopts | |||
|
45 | self.revlogversion = int(v.get('format', 0)) | |||
|
46 | for x in v.get('flags', "").split(): | |||
|
47 | self.revlogversion |= revlog.flagstr(x) | |||
|
48 | ||||
|
49 | self.manifest = manifest.manifest(self.opener, self.revlogversion) | |||
|
50 | self.changelog = changelog.changelog(self.opener, self.revlogversion) | |||
|
51 | self.revlogversion = self.changelog.version | |||
40 | self.tagscache = None |
|
52 | self.tagscache = None | |
41 | self.nodetagscache = None |
|
53 | self.nodetagscache = None | |
42 | self.encodepats = None |
|
54 | self.encodepats = None | |
@@ -48,11 +60,6 class localrepository(object): | |||||
48 | os.mkdir(self.join("data")) |
|
60 | os.mkdir(self.join("data")) | |
49 |
|
61 | |||
50 | self.dirstate = dirstate.dirstate(self.opener, self.ui, self.root) |
|
62 | self.dirstate = dirstate.dirstate(self.opener, self.ui, self.root) | |
51 | try: |
|
|||
52 | self.ui.readconfig(self.join("hgrc"), self.root) |
|
|||
53 | except IOError: |
|
|||
54 | pass |
|
|||
55 |
|
||||
56 | def hook(self, name, throw=False, **args): |
|
63 | def hook(self, name, throw=False, **args): | |
57 | def runhook(name, cmd): |
|
64 | def runhook(name, cmd): | |
58 | self.ui.note(_("running hook %s: %s\n") % (name, cmd)) |
|
65 | self.ui.note(_("running hook %s: %s\n") % (name, cmd)) | |
@@ -167,7 +174,7 class localrepository(object): | |||||
167 | def file(self, f): |
|
174 | def file(self, f): | |
168 | if f[0] == '/': |
|
175 | if f[0] == '/': | |
169 | f = f[1:] |
|
176 | f = f[1:] | |
170 | return filelog.filelog(self.opener, f) |
|
177 | return filelog.filelog(self.opener, f, self.revlogversion) | |
171 |
|
178 | |||
172 | def getcwd(self): |
|
179 | def getcwd(self): | |
173 | return self.dirstate.getcwd() |
|
180 | return self.dirstate.getcwd() |
@@ -12,10 +12,11 from demandload import * | |||||
12 | demandload(globals(), "bisect array") |
|
12 | demandload(globals(), "bisect array") | |
13 |
|
13 | |||
14 | class manifest(revlog): |
|
14 | class manifest(revlog): | |
15 | def __init__(self, opener): |
|
15 | def __init__(self, opener, defversion=0): | |
16 | self.mapcache = None |
|
16 | self.mapcache = None | |
17 | self.listcache = None |
|
17 | self.listcache = None | |
18 |
revlog.__init__(self, opener, "00manifest.i", "00manifest.d" |
|
18 | revlog.__init__(self, opener, "00manifest.i", "00manifest.d", | |
|
19 | defversion) | |||
19 |
|
20 | |||
20 | def read(self, node): |
|
21 | def read(self, node): | |
21 | if node == nullid: return {} # don't upset local cache |
|
22 | if node == nullid: return {} # don't upset local cache |
@@ -16,6 +16,10 from demandload import demandload | |||||
16 | demandload(globals(), "binascii changegroup errno heapq mdiff os") |
|
16 | demandload(globals(), "binascii changegroup errno heapq mdiff os") | |
17 | demandload(globals(), "sha struct zlib") |
|
17 | demandload(globals(), "sha struct zlib") | |
18 |
|
18 | |||
|
19 | # revlog version strings | |||
|
20 | REVLOGV0 = 0 | |||
|
21 | REVLOGNG = 1 | |||
|
22 | ||||
19 | def hash(text, p1, p2): |
|
23 | def hash(text, p1, p2): | |
20 | """generate a hash from the given text and its parent hashes |
|
24 | """generate a hash from the given text and its parent hashes | |
21 |
|
25 | |||
@@ -51,7 +55,19 def decompress(bin): | |||||
51 | if t == 'u': return bin[1:] |
|
55 | if t == 'u': return bin[1:] | |
52 | raise RevlogError(_("unknown compression type %r") % t) |
|
56 | raise RevlogError(_("unknown compression type %r") % t) | |
53 |
|
57 | |||
54 | indexformat = ">4l20s20s20s" |
|
58 | indexformatv0 = ">4l20s20s20s" | |
|
59 | # index ng: | |||
|
60 | # 6 bytes offset | |||
|
61 | # 2 bytes flags | |||
|
62 | # 4 bytes compressed length | |||
|
63 | # 4 bytes uncompressed length | |||
|
64 | # 4 bytes: base rev | |||
|
65 | # 4 bytes link rev | |||
|
66 | # 4 bytes parent 1 rev | |||
|
67 | # 4 bytes parent 2 rev | |||
|
68 | # 32 bytes: nodeid | |||
|
69 | indexformatng = ">Qiiiiii20s12x" | |||
|
70 | versionformat = ">i" | |||
55 |
|
71 | |||
56 | class lazyparser(object): |
|
72 | class lazyparser(object): | |
57 | """ |
|
73 | """ | |
@@ -63,18 +79,16 class lazyparser(object): | |||||
63 | the lazy objects in revlog with the underlying objects for |
|
79 | the lazy objects in revlog with the underlying objects for | |
64 | efficiency in cases where we look at most of the nodes. |
|
80 | efficiency in cases where we look at most of the nodes. | |
65 | """ |
|
81 | """ | |
66 | def __init__(self, data, revlog): |
|
82 | def __init__(self, data, revlog, indexformat): | |
67 | self.data = data |
|
83 | self.data = data | |
68 | self.s = struct.calcsize(indexformat) |
|
84 | self.s = struct.calcsize(indexformat) | |
|
85 | self.indexformat = indexformat | |||
69 | self.l = len(data)/self.s |
|
86 | self.l = len(data)/self.s | |
70 | self.index = [None] * self.l |
|
87 | self.index = [None] * self.l | |
71 | self.map = {nullid: -1} |
|
88 | self.map = {nullid: -1} | |
72 | self.all = 0 |
|
89 | self.all = 0 | |
73 | self.revlog = revlog |
|
90 | self.revlog = revlog | |
74 |
|
91 | |||
75 | def trunc(self, pos): |
|
|||
76 | self.l = pos/self.s |
|
|||
77 |
|
||||
78 | def load(self, pos=None): |
|
92 | def load(self, pos=None): | |
79 | if self.all: return |
|
93 | if self.all: return | |
80 | if pos is not None: |
|
94 | if pos is not None: | |
@@ -89,10 +103,11 class lazyparser(object): | |||||
89 | self.revlog.nodemap = self.map |
|
103 | self.revlog.nodemap = self.map | |
90 |
|
104 | |||
91 | while i < end: |
|
105 | while i < end: | |
|
106 | if not self.index[i]: | |||
92 | d = self.data[i * self.s: (i + 1) * self.s] |
|
107 | d = self.data[i * self.s: (i + 1) * self.s] | |
93 | e = struct.unpack(indexformat, d) |
|
108 | e = struct.unpack(self.indexformat, d) | |
94 | self.index[i] = e |
|
109 | self.index[i] = e | |
95 |
self.map[e[ |
|
110 | self.map[e[-1]] = i | |
96 | i += 1 |
|
111 | i += 1 | |
97 |
|
112 | |||
98 | class lazyindex(object): |
|
113 | class lazyindex(object): | |
@@ -108,12 +123,12 class lazyindex(object): | |||||
108 | return self.p.index[pos] |
|
123 | return self.p.index[pos] | |
109 | def __getitem__(self, pos): |
|
124 | def __getitem__(self, pos): | |
110 | return self.p.index[pos] or self.load(pos) |
|
125 | return self.p.index[pos] or self.load(pos) | |
|
126 | def __setitem__(self, pos, item): | |||
|
127 | self.p.index[pos] = item | |||
111 | def __delitem__(self, pos): |
|
128 | def __delitem__(self, pos): | |
112 | del self.p.index[pos] |
|
129 | del self.p.index[pos] | |
113 | def append(self, e): |
|
130 | def append(self, e): | |
114 | self.p.index.append(e) |
|
131 | self.p.index.append(e) | |
115 | def trunc(self, pos): |
|
|||
116 | self.p.trunc(pos) |
|
|||
117 |
|
132 | |||
118 | class lazymap(object): |
|
133 | class lazymap(object): | |
119 | """a lazy version of the node map""" |
|
134 | """a lazy version of the node map""" | |
@@ -133,10 +148,10 class lazymap(object): | |||||
133 | yield nullid |
|
148 | yield nullid | |
134 | for i in xrange(self.p.l): |
|
149 | for i in xrange(self.p.l): | |
135 | try: |
|
150 | try: | |
136 |
yield self.p.index[i][ |
|
151 | yield self.p.index[i][-1] | |
137 | except: |
|
152 | except: | |
138 | self.p.load(i) |
|
153 | self.p.load(i) | |
139 |
yield self.p.index[i][ |
|
154 | yield self.p.index[i][-1] | |
140 | def __getitem__(self, key): |
|
155 | def __getitem__(self, key): | |
141 | try: |
|
156 | try: | |
142 | return self.p.map[key] |
|
157 | return self.p.map[key] | |
@@ -178,7 +193,7 class revlog(object): | |||||
178 | remove data, and can use some simple techniques to avoid the need |
|
193 | remove data, and can use some simple techniques to avoid the need | |
179 | for locking while reading. |
|
194 | for locking while reading. | |
180 | """ |
|
195 | """ | |
181 | def __init__(self, opener, indexfile, datafile): |
|
196 | def __init__(self, opener, indexfile, datafile, defversion=0): | |
182 | """ |
|
197 | """ | |
183 | create a revlog object |
|
198 | create a revlog object | |
184 |
|
199 | |||
@@ -192,11 +207,14 class revlog(object): | |||||
192 | self.indexstat = None |
|
207 | self.indexstat = None | |
193 | self.cache = None |
|
208 | self.cache = None | |
194 | self.chunkcache = None |
|
209 | self.chunkcache = None | |
|
210 | self.defversion = defversion | |||
195 | self.load() |
|
211 | self.load() | |
196 |
|
212 | |||
197 | def load(self): |
|
213 | def load(self): | |
|
214 | v = self.defversion | |||
198 | try: |
|
215 | try: | |
199 | f = self.opener(self.indexfile) |
|
216 | f = self.opener(self.indexfile) | |
|
217 | i = f.read() | |||
200 | except IOError, inst: |
|
218 | except IOError, inst: | |
201 | if inst.errno != errno.ENOENT: |
|
219 | if inst.errno != errno.ENOENT: | |
202 | raise |
|
220 | raise | |
@@ -214,55 +232,102 class revlog(object): | |||||
214 | and st.st_ctime == oldst.st_ctime): |
|
232 | and st.st_ctime == oldst.st_ctime): | |
215 | return |
|
233 | return | |
216 | self.indexstat = st |
|
234 | self.indexstat = st | |
217 | i = f.read() |
|
235 | if len(i) > 0: | |
|
236 | v = struct.unpack(versionformat, i[:4])[0] | |||
|
237 | if v != 0: | |||
|
238 | flags = v & ~0xFFFF | |||
|
239 | fmt = v & 0xFFFF | |||
|
240 | if fmt != REVLOGNG or (flags & ~(REVLOGNGINLINEDATA)): | |||
|
241 | raise RevlogError( | |||
|
242 | _("unknown version format %d or flags %x on %s") % | |||
|
243 | (v, flags, self.indexfile)) | |||
|
244 | self.version = v | |||
|
245 | if v == 0: | |||
|
246 | self.indexformat = indexformatv0 | |||
|
247 | else: | |||
|
248 | self.indexformat = indexformatng | |||
218 |
|
249 | |||
219 | if i and i[:4] != "\0\0\0\0": |
|
250 | if i: | |
220 | raise RevlogError(_("incompatible revlog signature on %s") % |
|
251 | if st and st.st_size > 10000: | |
221 | self.indexfile) |
|
|||
222 |
|
||||
223 | if len(i) > 10000: |
|
|||
224 | # big index, let's parse it on demand |
|
252 | # big index, let's parse it on demand | |
225 | parser = lazyparser(i, self) |
|
253 | parser = lazyparser(i, self, self.indexformat) | |
226 | self.index = lazyindex(parser) |
|
254 | self.index = lazyindex(parser) | |
227 | self.nodemap = lazymap(parser) |
|
255 | self.nodemap = lazymap(parser) | |
228 | else: |
|
256 | else: | |
229 | s = struct.calcsize(indexformat) |
|
257 | self.parseindex(i) | |
230 | l = len(i) / s |
|
258 | if self.version != 0: | |
231 |
self.index |
|
259 | e = list(self.index[0]) | |
232 | m = [None] * l |
|
260 | type = self.ngtype(e[0]) | |
|
261 | e[0] = self.offset_type(0, type) | |||
|
262 | self.index[0] = e | |||
|
263 | else: | |||
|
264 | self.nodemap = { nullid: -1} | |||
|
265 | self.index = [] | |||
233 |
|
266 | |||
|
267 | ||||
|
268 | def parseindex(self, data): | |||
|
269 | s = struct.calcsize(self.indexformat) | |||
|
270 | l = len(data) | |||
|
271 | self.index = [] | |||
|
272 | self.nodemap = {nullid: -1} | |||
|
273 | off = 0 | |||
234 |
|
|
274 | n = 0 | |
235 | for f in xrange(0, l * s, s): |
|
275 | while off < l: | |
236 | # offset, size, base, linkrev, p1, p2, nodeid |
|
276 | e = struct.unpack(self.indexformat, data[off:off + s]) | |
237 | e = struct.unpack(indexformat, i[f:f + s]) |
|
277 | self.index.append(e) | |
238 | m[n] = (e[6], n) |
|
278 | self.nodemap[e[-1]] = n | |
239 | self.index[n] = e |
|
|||
240 |
|
|
279 | n += 1 | |
|
280 | off += s | |||
241 |
|
281 | |||
242 | self.nodemap = dict(m) |
|
282 | def ngoffset(self, q): | |
243 | self.nodemap[nullid] = -1 |
|
283 | if q & 0xFFFF: | |
|
284 | raise RevlogError(_('%s: incompatible revision flag %x') % | |||
|
285 | (self.indexfile, type)) | |||
|
286 | return long(q >> 16) | |||
|
287 | ||||
|
288 | def ngtype(self, q): | |||
|
289 | return int(q & 0xFFFF) | |||
|
290 | ||||
|
291 | def offset_type(self, offset, type): | |||
|
292 | return long(long(offset) << 16 | type) | |||
|
293 | ||||
|
294 | def loadindexmap(self): | |||
|
295 | """loads both the map and the index from the lazy parser""" | |||
|
296 | if isinstance(self.index, lazyindex): | |||
|
297 | p = self.index.p | |||
|
298 | p.load() | |||
244 |
|
299 | |||
245 | def tip(self): return self.node(len(self.index) - 1) |
|
300 | def tip(self): return self.node(len(self.index) - 1) | |
246 | def count(self): return len(self.index) |
|
301 | def count(self): return len(self.index) | |
247 | def node(self, rev): return (rev < 0) and nullid or self.index[rev][6] |
|
302 | def node(self, rev): | |
|
303 | return (rev < 0) and nullid or self.index[rev][-1] | |||
248 | def rev(self, node): |
|
304 | def rev(self, node): | |
249 | try: |
|
305 | try: | |
250 | return self.nodemap[node] |
|
306 | return self.nodemap[node] | |
251 | except KeyError: |
|
307 | except KeyError: | |
252 | raise RevlogError(_('%s: no node %s') % (self.indexfile, hex(node))) |
|
308 | raise RevlogError(_('%s: no node %s') % (self.indexfile, hex(node))) | |
253 |
def linkrev(self, node): return self.index[self.rev(node)][ |
|
309 | def linkrev(self, node): return self.index[self.rev(node)][-4] | |
254 | def parents(self, node): |
|
310 | def parents(self, node): | |
255 | if node == nullid: return (nullid, nullid) |
|
311 | if node == nullid: return (nullid, nullid) | |
256 |
r |
|
312 | r = self.rev(node) | |
|
313 | d = self.index[r][-3:-1] | |||
|
314 | if self.version == 0: | |||
|
315 | return d | |||
|
316 | return [ self.node(x) for x in d ] | |||
|
317 | def start(self, rev): | |||
|
318 | if rev < 0: | |||
|
319 | return -1 | |||
|
320 | if self.version != 0: | |||
|
321 | return self.ngoffset(self.index[rev][0]) | |||
|
322 | return self.index[rev][0] | |||
|
323 | def end(self, rev): return self.start(rev) + self.length(rev) | |||
257 |
|
324 | |||
258 | def start(self, rev): return (rev < 0) and -1 or self.index[rev][0] |
|
|||
259 | def length(self, rev): |
|
325 | def length(self, rev): | |
260 | if rev < 0: |
|
326 | if rev < 0: | |
261 | return 0 |
|
327 | return 0 | |
262 | else: |
|
328 | else: | |
263 | return self.index[rev][1] |
|
329 | return self.index[rev][1] | |
264 |
def e |
|
330 | def base(self, rev): return (rev < 0) and rev or self.index[rev][-5] | |
265 | def base(self, rev): return (rev < 0) and rev or self.index[rev][2] |
|
|||
266 |
|
331 | |||
267 | def reachable(self, rev, stop=None): |
|
332 | def reachable(self, rev, stop=None): | |
268 | reachable = {} |
|
333 | reachable = {} | |
@@ -501,18 +566,18 class revlog(object): | |||||
501 | """apply a list of patches to a string""" |
|
566 | """apply a list of patches to a string""" | |
502 | return mdiff.patches(t, pl) |
|
567 | return mdiff.patches(t, pl) | |
503 |
|
568 | |||
504 | def chunk(self, rev): |
|
569 | def chunk(self, rev, df=None, cachelen=4096): | |
505 | start, length = self.start(rev), self.length(rev) |
|
570 | start, length = self.start(rev), self.length(rev) | |
506 | end = start + length |
|
571 | end = start + length | |
507 |
|
572 | def loadcache(df): | ||
508 | def loadcache(): |
|
573 | cache_length = max(cachelen, length) # 4k | |
509 | cache_length = max(4096 * 1024, length) # 4Mo |
|
574 | if not df: | |
510 | df = self.opener(self.datafile) |
|
575 | df = self.opener(self.datafile) | |
511 | df.seek(start) |
|
576 | df.seek(start) | |
512 | self.chunkcache = (start, df.read(cache_length)) |
|
577 | self.chunkcache = (start, df.read(cache_length)) | |
513 |
|
578 | |||
514 | if not self.chunkcache: |
|
579 | if not self.chunkcache: | |
515 | loadcache() |
|
580 | loadcache(df) | |
516 |
|
581 | |||
517 | cache_start = self.chunkcache[0] |
|
582 | cache_start = self.chunkcache[0] | |
518 | cache_end = cache_start + len(self.chunkcache[1]) |
|
583 | cache_end = cache_start + len(self.chunkcache[1]) | |
@@ -520,7 +585,7 class revlog(object): | |||||
520 | # it is cached |
|
585 | # it is cached | |
521 | offset = start - cache_start |
|
586 | offset = start - cache_start | |
522 | else: |
|
587 | else: | |
523 | loadcache() |
|
588 | loadcache(df) | |
524 | offset = 0 |
|
589 | offset = 0 | |
525 |
|
590 | |||
526 | #def checkchunk(): |
|
591 | #def checkchunk(): | |
@@ -555,16 +620,18 class revlog(object): | |||||
555 | rev = self.rev(node) |
|
620 | rev = self.rev(node) | |
556 | base = self.base(rev) |
|
621 | base = self.base(rev) | |
557 |
|
622 | |||
|
623 | df = self.opener(self.datafile) | |||
|
624 | ||||
558 | # do we have useful data cached? |
|
625 | # do we have useful data cached? | |
559 | if self.cache and self.cache[1] >= base and self.cache[1] < rev: |
|
626 | if self.cache and self.cache[1] >= base and self.cache[1] < rev: | |
560 | base = self.cache[1] |
|
627 | base = self.cache[1] | |
561 | text = self.cache[2] |
|
628 | text = self.cache[2] | |
562 | else: |
|
629 | else: | |
563 | text = self.chunk(base) |
|
630 | text = self.chunk(base, df=df) | |
564 |
|
631 | |||
565 | bins = [] |
|
632 | bins = [] | |
566 | for r in xrange(base + 1, rev + 1): |
|
633 | for r in xrange(base + 1, rev + 1): | |
567 | bins.append(self.chunk(r)) |
|
634 | bins.append(self.chunk(r, df=df)) | |
568 |
|
635 | |||
569 | text = self.patches(text, bins) |
|
636 | text = self.patches(text, bins) | |
570 |
|
637 | |||
@@ -621,19 +688,30 class revlog(object): | |||||
621 | if t >= 0: |
|
688 | if t >= 0: | |
622 | offset = self.end(t) |
|
689 | offset = self.end(t) | |
623 |
|
690 | |||
|
691 | if self.version == 0: | |||
624 | e = (offset, l, base, link, p1, p2, node) |
|
692 | e = (offset, l, base, link, p1, p2, node) | |
|
693 | else: | |||
|
694 | e = (self.offset_type(offset, 0), l, len(text), | |||
|
695 | base, link, self.rev(p1), self.rev(p2), node) | |||
625 |
|
696 | |||
626 | self.index.append(e) |
|
697 | self.index.append(e) | |
627 | self.nodemap[node] = n |
|
698 | self.nodemap[node] = n | |
628 | entry = struct.pack(indexformat, *e) |
|
699 | entry = struct.pack(self.indexformat, *e) | |
629 |
|
700 | |||
630 |
transaction.add(self.datafile, |
|
701 | transaction.add(self.datafile, offset) | |
|
702 | transaction.add(self.indexfile, n * len(entry)) | |||
631 | f = self.opener(self.datafile, "a") |
|
703 | f = self.opener(self.datafile, "a") | |
632 | if data[0]: |
|
704 | if data[0]: | |
633 | f.write(data[0]) |
|
705 | f.write(data[0]) | |
634 | f.write(data[1]) |
|
706 | f.write(data[1]) | |
635 | transaction.add(self.indexfile, n * len(entry)) |
|
707 | f = self.opener(self.indexfile, "a") | |
636 | self.opener(self.indexfile, "a").write(entry) |
|
708 | ||
|
709 | if len(self.index) == 1 and self.version != 0: | |||
|
710 | l = struct.pack(versionformat, self.version) | |||
|
711 | f.write(l) | |||
|
712 | entry = entry[4:] | |||
|
713 | ||||
|
714 | f.write(entry) | |||
637 |
|
715 | |||
638 | self.cache = (node, n, text) |
|
716 | self.cache = (node, n, text) | |
639 | return node |
|
717 | return node | |
@@ -748,16 +826,12 class revlog(object): | |||||
748 | base = prev = -1 |
|
826 | base = prev = -1 | |
749 | start = end = measure = 0 |
|
827 | start = end = measure = 0 | |
750 | if r: |
|
828 | if r: | |
751 | base = self.base(t) |
|
|||
752 | start = self.start(base) |
|
|||
753 | end = self.end(t) |
|
829 | end = self.end(t) | |
754 | measure = self.length(base) |
|
|||
755 | prev = self.tip() |
|
|||
756 |
|
830 | |||
|
831 | ifh = self.opener(self.indexfile, "a+") | |||
|
832 | transaction.add(self.indexfile, ifh.tell()) | |||
757 | transaction.add(self.datafile, end) |
|
833 | transaction.add(self.datafile, end) | |
758 | transaction.add(self.indexfile, r * struct.calcsize(indexformat)) |
|
|||
759 | dfh = self.opener(self.datafile, "a") |
|
834 | dfh = self.opener(self.datafile, "a") | |
760 | ifh = self.opener(self.indexfile, "a") |
|
|||
761 |
|
835 | |||
762 | # loop through our set of deltas |
|
836 | # loop through our set of deltas | |
763 | chain = None |
|
837 | chain = None | |
@@ -794,6 +868,7 class revlog(object): | |||||
794 |
|
868 | |||
795 | if chain != prev or (end - start + len(cdelta)) > measure * 2: |
|
869 | if chain != prev or (end - start + len(cdelta)) > measure * 2: | |
796 | # flush our writes here so we can read it in revision |
|
870 | # flush our writes here so we can read it in revision | |
|
871 | if dfh: | |||
797 | dfh.flush() |
|
872 | dfh.flush() | |
798 | ifh.flush() |
|
873 | ifh.flush() | |
799 | text = self.revision(chain) |
|
874 | text = self.revision(chain) | |
@@ -803,19 +878,21 class revlog(object): | |||||
803 | raise RevlogError(_("consistency error adding group")) |
|
878 | raise RevlogError(_("consistency error adding group")) | |
804 | measure = len(text) |
|
879 | measure = len(text) | |
805 | else: |
|
880 | else: | |
|
881 | if self.version == 0: | |||
806 | e = (end, len(cdelta), base, link, p1, p2, node) |
|
882 | e = (end, len(cdelta), base, link, p1, p2, node) | |
|
883 | else: | |||
|
884 | e = (self.offset_type(end, 0), len(cdelta), -1, base, | |||
|
885 | link, self.rev(p1), self.rev(p2), node) | |||
807 | self.index.append(e) |
|
886 | self.index.append(e) | |
808 | self.nodemap[node] = r |
|
887 | self.nodemap[node] = r | |
809 | dfh.write(cdelta) |
|
888 | dfh.write(cdelta) | |
810 | ifh.write(struct.pack(indexformat, *e)) |
|
889 | ifh.write(struct.pack(self.indexformat, *e)) | |
811 |
|
890 | |||
812 | t, r, chain, prev = r, r + 1, node, node |
|
891 | t, r, chain, prev = r, r + 1, node, node | |
813 | base = self.base(t) |
|
892 | base = self.base(t) | |
814 | start = self.start(base) |
|
893 | start = self.start(base) | |
815 | end = self.end(t) |
|
894 | end = self.end(t) | |
816 |
|
895 | |||
817 | dfh.close() |
|
|||
818 | ifh.close() |
|
|||
819 | if node is None: |
|
896 | if node is None: | |
820 | raise RevlogError(_("group to be added is empty")) |
|
897 | raise RevlogError(_("group to be added is empty")) | |
821 | return node |
|
898 | return node | |
@@ -824,32 +901,34 class revlog(object): | |||||
824 | if self.count() == 0 or rev >= self.count(): |
|
901 | if self.count() == 0 or rev >= self.count(): | |
825 | return |
|
902 | return | |
826 |
|
903 | |||
|
904 | if isinstance(self.index, lazyindex): | |||
|
905 | self.loadindexmap() | |||
|
906 | ||||
827 | # When stripping away a revision, we need to make sure it |
|
907 | # When stripping away a revision, we need to make sure it | |
828 | # does not actually belong to an older changeset. |
|
908 | # does not actually belong to an older changeset. | |
829 | # The minlink parameter defines the oldest revision |
|
909 | # The minlink parameter defines the oldest revision | |
830 | # we're allowed to strip away. |
|
910 | # we're allowed to strip away. | |
831 |
while minlink > self.index[rev][ |
|
911 | while minlink > self.index[rev][-4]: | |
832 | rev += 1 |
|
912 | rev += 1 | |
833 | if rev >= self.count(): |
|
913 | if rev >= self.count(): | |
834 | return |
|
914 | return | |
835 |
|
915 | |||
836 | # first truncate the files on disk |
|
916 | # first truncate the files on disk | |
837 | end = self.start(rev) |
|
917 | end = self.start(rev) | |
838 |
self.opener(self.datafile, "a") |
|
918 | df = self.opener(self.datafile, "a") | |
839 | end = rev * struct.calcsize(indexformat) |
|
919 | df.truncate(end) | |
840 | self.opener(self.indexfile, "a").truncate(end) |
|
920 | end = rev * struct.calcsize(self.indexformat) | |
|
921 | ||||
|
922 | indexf = self.opener(self.indexfile, "a") | |||
|
923 | indexf.truncate(end) | |||
841 |
|
924 | |||
842 | # then reset internal state in memory to forget those revisions |
|
925 | # then reset internal state in memory to forget those revisions | |
843 | self.cache = None |
|
926 | self.cache = None | |
844 | self.chunkcache = None |
|
927 | self.chunkcache = None | |
845 | for p in self.index[rev:]: |
|
928 | for x in xrange(rev, self.count()): | |
846 |
del self.nodemap[ |
|
929 | del self.nodemap[self.node(x)] | |
847 | del self.index[rev:] |
|
|||
848 |
|
930 | |||
849 | # truncating the lazyindex also truncates the lazymap. |
|
931 | del self.index[rev:] | |
850 | if isinstance(self.index, lazyindex): |
|
|||
851 | self.index.trunc(end) |
|
|||
852 |
|
||||
853 |
|
932 | |||
854 | def checksize(self): |
|
933 | def checksize(self): | |
855 | expected = 0 |
|
934 | expected = 0 | |
@@ -870,7 +949,7 class revlog(object): | |||||
870 | f = self.opener(self.indexfile) |
|
949 | f = self.opener(self.indexfile) | |
871 | f.seek(0, 2) |
|
950 | f.seek(0, 2) | |
872 | actual = f.tell() |
|
951 | actual = f.tell() | |
873 | s = struct.calcsize(indexformat) |
|
952 | s = struct.calcsize(self.indexformat) | |
874 | i = actual / s |
|
953 | i = actual / s | |
875 | di = actual - (i * s) |
|
954 | di = actual - (i * s) | |
876 | except IOError, inst: |
|
955 | except IOError, inst: |
@@ -32,6 +32,7 class statichttprepository(localrepo.loc | |||||
32 | def __init__(self, ui, path): |
|
32 | def __init__(self, ui, path): | |
33 | self.path = (path + "/.hg") |
|
33 | self.path = (path + "/.hg") | |
34 | self.ui = ui |
|
34 | self.ui = ui | |
|
35 | self.revlogversion = 0 | |||
35 | self.opener = opener(self.path) |
|
36 | self.opener = opener(self.path) | |
36 | self.manifest = manifest.manifest(self.opener) |
|
37 | self.manifest = manifest.manifest(self.opener) | |
37 | self.changelog = changelog.changelog(self.opener) |
|
38 | self.changelog = changelog.changelog(self.opener) |
@@ -29,6 +29,7 class ui(object): | |||||
29 | self.diffcache = None |
|
29 | self.diffcache = None | |
30 | self.header = [] |
|
30 | self.header = [] | |
31 | self.prev_header = [] |
|
31 | self.prev_header = [] | |
|
32 | self.revlogopts = self.configrevlog() | |||
32 | else: |
|
33 | else: | |
33 | # parentui may point to an ui object which is already a child |
|
34 | # parentui may point to an ui object which is already a child | |
34 | self.parentui = parentui.parentui or parentui |
|
35 | self.parentui = parentui.parentui or parentui | |
@@ -134,6 +135,12 class ui(object): | |||||
134 | result.append(path) |
|
135 | result.append(path) | |
135 | return result |
|
136 | return result | |
136 |
|
137 | |||
|
138 | def configrevlog(self): | |||
|
139 | ret = {} | |||
|
140 | for x in self.configitems("revlog"): | |||
|
141 | k = x[0].lower() | |||
|
142 | ret[k] = x[1] | |||
|
143 | return ret | |||
137 | def diffopts(self): |
|
144 | def diffopts(self): | |
138 | if self.diffcache: |
|
145 | if self.diffcache: | |
139 | return self.diffcache |
|
146 | return self.diffcache |
General Comments 0
You need to be logged in to leave comments.
Login now