Show More
@@ -10,7 +10,7 b' of the GNU General Public License, incor' | |||||
10 | from node import nullid |
|
10 | from node import nullid | |
11 | from i18n import _ |
|
11 | from i18n import _ | |
12 | import struct, os, stat, util, errno, ignore |
|
12 | import struct, os, stat, util, errno, ignore | |
13 | import cStringIO, osutil, sys |
|
13 | import cStringIO, osutil, sys, parsers | |
14 |
|
14 | |||
15 | _unknown = ('?', 0, 0, 0) |
|
15 | _unknown = ('?', 0, 0, 0) | |
16 | _format = ">cllll" |
|
16 | _format = ">cllll" | |
@@ -190,8 +190,6 b' class dirstate(object):' | |||||
190 | def _read(self): |
|
190 | def _read(self): | |
191 | self._map = {} |
|
191 | self._map = {} | |
192 | self._copymap = {} |
|
192 | self._copymap = {} | |
193 | if not self._dirtypl: |
|
|||
194 | self._pl = [nullid, nullid] |
|
|||
195 | try: |
|
193 | try: | |
196 | st = self._opener("dirstate").read() |
|
194 | st = self._opener("dirstate").read() | |
197 | except IOError, err: |
|
195 | except IOError, err: | |
@@ -200,27 +198,9 b' class dirstate(object):' | |||||
200 | if not st: |
|
198 | if not st: | |
201 | return |
|
199 | return | |
202 |
|
200 | |||
|
201 | p = parsers.parse_dirstate(self._map, self._copymap, st); | |||
203 | if not self._dirtypl: |
|
202 | if not self._dirtypl: | |
204 |
self._pl = |
|
203 | self._pl = p | |
205 |
|
||||
206 | # deref fields so they will be local in loop |
|
|||
207 | dmap = self._map |
|
|||
208 | copymap = self._copymap |
|
|||
209 | unpack = struct.unpack |
|
|||
210 | e_size = struct.calcsize(_format) |
|
|||
211 | pos1 = 40 |
|
|||
212 | l = len(st) |
|
|||
213 |
|
||||
214 | # the inner loop |
|
|||
215 | while pos1 < l: |
|
|||
216 | pos2 = pos1 + e_size |
|
|||
217 | e = unpack(">cllll", st[pos1:pos2]) # a literal here is faster |
|
|||
218 | pos1 = pos2 + e[4] |
|
|||
219 | f = st[pos2:pos1] |
|
|||
220 | if '\0' in f: |
|
|||
221 | f, c = f.split('\0') |
|
|||
222 | copymap[f] = c |
|
|||
223 | dmap[f] = e # we hold onto e[4] because making a subtuple is slow |
|
|||
224 |
|
204 | |||
225 | def invalidate(self): |
|
205 | def invalidate(self): | |
226 | for a in "_map _copymap _foldmap _branch _pl _dirs _ignore".split(): |
|
206 | for a in "_map _copymap _foldmap _branch _pl _dirs _ignore".split(): | |
@@ -274,7 +254,7 b' class dirstate(object):' | |||||
274 | self._dirty = True |
|
254 | self._dirty = True | |
275 | self._addpath(f) |
|
255 | self._addpath(f) | |
276 | s = os.lstat(self._join(f)) |
|
256 | s = os.lstat(self._join(f)) | |
277 |
self._map[f] = ('n', s.st_mode, s.st_size, s.st_mtime |
|
257 | self._map[f] = ('n', s.st_mode, s.st_size, s.st_mtime) | |
278 | if f in self._copymap: |
|
258 | if f in self._copymap: | |
279 | del self._copymap[f] |
|
259 | del self._copymap[f] | |
280 |
|
260 | |||
@@ -297,7 +277,7 b' class dirstate(object):' | |||||
297 | return |
|
277 | return | |
298 | self._dirty = True |
|
278 | self._dirty = True | |
299 | self._addpath(f) |
|
279 | self._addpath(f) | |
300 |
self._map[f] = ('n', 0, -1, -1 |
|
280 | self._map[f] = ('n', 0, -1, -1) | |
301 | if f in self._copymap: |
|
281 | if f in self._copymap: | |
302 | del self._copymap[f] |
|
282 | del self._copymap[f] | |
303 |
|
283 | |||
@@ -305,7 +285,7 b' class dirstate(object):' | |||||
305 | 'mark a file normal, but dirty' |
|
285 | 'mark a file normal, but dirty' | |
306 | self._dirty = True |
|
286 | self._dirty = True | |
307 | self._addpath(f) |
|
287 | self._addpath(f) | |
308 |
self._map[f] = ('n', 0, -2, -1 |
|
288 | self._map[f] = ('n', 0, -2, -1) | |
309 | if f in self._copymap: |
|
289 | if f in self._copymap: | |
310 | del self._copymap[f] |
|
290 | del self._copymap[f] | |
311 |
|
291 | |||
@@ -313,7 +293,7 b' class dirstate(object):' | |||||
313 | 'mark a file added' |
|
293 | 'mark a file added' | |
314 | self._dirty = True |
|
294 | self._dirty = True | |
315 | self._addpath(f, True) |
|
295 | self._addpath(f, True) | |
316 |
self._map[f] = ('a', 0, -1, -1 |
|
296 | self._map[f] = ('a', 0, -1, -1) | |
317 | if f in self._copymap: |
|
297 | if f in self._copymap: | |
318 | del self._copymap[f] |
|
298 | del self._copymap[f] | |
319 |
|
299 | |||
@@ -328,7 +308,7 b' class dirstate(object):' | |||||
328 | size = -1 |
|
308 | size = -1 | |
329 | elif entry[0] == 'n' and entry[2] == -2: |
|
309 | elif entry[0] == 'n' and entry[2] == -2: | |
330 | size = -2 |
|
310 | size = -2 | |
331 |
self._map[f] = ('r', 0, size, 0 |
|
311 | self._map[f] = ('r', 0, size, 0) | |
332 | if size == 0 and f in self._copymap: |
|
312 | if size == 0 and f in self._copymap: | |
333 | del self._copymap[f] |
|
313 | del self._copymap[f] | |
334 |
|
314 | |||
@@ -337,7 +317,7 b' class dirstate(object):' | |||||
337 | self._dirty = True |
|
317 | self._dirty = True | |
338 | s = os.lstat(self._join(f)) |
|
318 | s = os.lstat(self._join(f)) | |
339 | self._addpath(f) |
|
319 | self._addpath(f) | |
340 |
self._map[f] = ('m', s.st_mode, s.st_size, s.st_mtime |
|
320 | self._map[f] = ('m', s.st_mode, s.st_size, s.st_mtime) | |
341 | if f in self._copymap: |
|
321 | if f in self._copymap: | |
342 | del self._copymap[f] |
|
322 | del self._copymap[f] | |
343 |
|
323 | |||
@@ -373,9 +353,9 b' class dirstate(object):' | |||||
373 | self.clear() |
|
353 | self.clear() | |
374 | for f in files: |
|
354 | for f in files: | |
375 | if 'x' in files.flags(f): |
|
355 | if 'x' in files.flags(f): | |
376 |
self._map[f] = ('n', 0777, -1, 0 |
|
356 | self._map[f] = ('n', 0777, -1, 0) | |
377 | else: |
|
357 | else: | |
378 |
self._map[f] = ('n', 0666, -1, 0 |
|
358 | self._map[f] = ('n', 0666, -1, 0) | |
379 | self._pl = (parent, nullid) |
|
359 | self._pl = (parent, nullid) | |
380 | self._dirty = True |
|
360 | self._dirty = True | |
381 |
|
361 | |||
@@ -401,7 +381,7 b' class dirstate(object):' | |||||
401 | if f in copymap: |
|
381 | if f in copymap: | |
402 | f = "%s\0%s" % (f, copymap[f]) |
|
382 | f = "%s\0%s" % (f, copymap[f]) | |
403 | if e[3] > limit and e[0] == 'n': |
|
383 | if e[3] > limit and e[0] == 'n': | |
404 |
e = (e[0], 0, -1, -1 |
|
384 | e = (e[0], 0, -1, -1) | |
405 | e = pack(_format, e[0], e[1], e[2], e[3], len(f)) |
|
385 | e = pack(_format, e[0], e[1], e[2], e[3], len(f)) | |
406 | write(e) |
|
386 | write(e) | |
407 | write(f) |
|
387 | write(f) | |
@@ -577,7 +557,7 b' class dirstate(object):' | |||||
577 | uadd(fn) |
|
557 | uadd(fn) | |
578 | continue |
|
558 | continue | |
579 |
|
559 | |||
580 |
state, mode, size, time |
|
560 | state, mode, size, time = dmap[fn] | |
581 |
|
561 | |||
582 | if not st and state in "nma": |
|
562 | if not st and state in "nma": | |
583 | dadd(fn) |
|
563 | dadd(fn) |
@@ -128,15 +128,117 b' static PyObject *parse_manifest(PyObject' | |||||
128 |
|
128 | |||
129 | Py_INCREF(Py_None); |
|
129 | Py_INCREF(Py_None); | |
130 | return Py_None; |
|
130 | return Py_None; | |
131 |
|
||||
132 | quit: |
|
131 | quit: | |
133 | return NULL; |
|
132 | return NULL; | |
134 | } |
|
133 | } | |
135 |
|
134 | |||
|
135 | #ifdef _WIN32 | |||
|
136 | # ifdef _MSC_VER | |||
|
137 | /* msvc 6.0 has problems */ | |||
|
138 | # define inline __inline | |||
|
139 | typedef unsigned long uint32_t; | |||
|
140 | # else | |||
|
141 | # include <stdint.h> | |||
|
142 | # endif | |||
|
143 | static uint32_t ntohl(uint32_t x) | |||
|
144 | { | |||
|
145 | return ((x & 0x000000ffUL) << 24) | | |||
|
146 | ((x & 0x0000ff00UL) << 8) | | |||
|
147 | ((x & 0x00ff0000UL) >> 8) | | |||
|
148 | ((x & 0xff000000UL) >> 24); | |||
|
149 | } | |||
|
150 | #else | |||
|
151 | /* not windows */ | |||
|
152 | # include <sys/types.h> | |||
|
153 | # if defined __BEOS__ && !defined __HAIKU__ | |||
|
154 | # include <ByteOrder.h> | |||
|
155 | # else | |||
|
156 | # include <arpa/inet.h> | |||
|
157 | # endif | |||
|
158 | # include <inttypes.h> | |||
|
159 | #endif | |||
|
160 | ||||
|
161 | static PyObject *parse_dirstate(PyObject *self, PyObject *args) | |||
|
162 | { | |||
|
163 | PyObject *dmap, *cmap, *parents = NULL, *ret = NULL; | |||
|
164 | PyObject *fname = NULL, *cname = NULL, *entry = NULL; | |||
|
165 | char *str, *cur, *end, *cpos; | |||
|
166 | int state, mode, size, mtime, flen; | |||
|
167 | int len; | |||
|
168 | char decode[16]; /* for alignment */ | |||
|
169 | ||||
|
170 | if (!PyArg_ParseTuple(args, "O!O!s#:parse_dirstate", | |||
|
171 | &PyDict_Type, &dmap, | |||
|
172 | &PyDict_Type, &cmap, | |||
|
173 | &str, &len)) | |||
|
174 | goto quit; | |||
|
175 | ||||
|
176 | /* read parents */ | |||
|
177 | if (len < 40) | |||
|
178 | goto quit; | |||
|
179 | ||||
|
180 | parents = Py_BuildValue("s#s#", str, 20, str + 20, 20); | |||
|
181 | if (!parents) | |||
|
182 | goto quit; | |||
|
183 | ||||
|
184 | /* read filenames */ | |||
|
185 | cur = str + 40; | |||
|
186 | end = str + len; | |||
|
187 | ||||
|
188 | while (cur < end - 17) { | |||
|
189 | /* unpack header */ | |||
|
190 | state = *cur; | |||
|
191 | memcpy(decode, cur + 1, 16); | |||
|
192 | mode = ntohl(*(uint32_t *)(decode)); | |||
|
193 | size = ntohl(*(uint32_t *)(decode + 4)); | |||
|
194 | mtime = ntohl(*(uint32_t *)(decode + 8)); | |||
|
195 | flen = ntohl(*(uint32_t *)(decode + 12)); | |||
|
196 | cur += 17; | |||
|
197 | if (cur + flen > end) | |||
|
198 | goto quit; | |||
|
199 | ||||
|
200 | entry = Py_BuildValue("ciii", state, mode, size, mtime); | |||
|
201 | PyObject_GC_UnTrack(entry); /* don't waste time with this */ | |||
|
202 | if (!entry) | |||
|
203 | goto quit; | |||
|
204 | ||||
|
205 | cpos = memchr(cur, 0, flen); | |||
|
206 | if (cpos) { | |||
|
207 | fname = PyString_FromStringAndSize(cur, cpos - cur); | |||
|
208 | cname = PyString_FromStringAndSize(cpos + 1, | |||
|
209 | flen - (cpos - cur) - 1); | |||
|
210 | if (!fname || !cname || | |||
|
211 | PyDict_SetItem(cmap, fname, cname) == -1 || | |||
|
212 | PyDict_SetItem(dmap, fname, entry) == -1) | |||
|
213 | goto quit; | |||
|
214 | Py_DECREF(cname); | |||
|
215 | } else { | |||
|
216 | fname = PyString_FromStringAndSize(cur, flen); | |||
|
217 | if (!fname || | |||
|
218 | PyDict_SetItem(dmap, fname, entry) == -1) | |||
|
219 | goto quit; | |||
|
220 | } | |||
|
221 | cur += flen; | |||
|
222 | Py_DECREF(fname); | |||
|
223 | Py_DECREF(entry); | |||
|
224 | fname = cname = entry = NULL; | |||
|
225 | } | |||
|
226 | ||||
|
227 | ret = parents; | |||
|
228 | Py_INCREF(ret); | |||
|
229 | quit: | |||
|
230 | Py_XDECREF(fname); | |||
|
231 | Py_XDECREF(cname); | |||
|
232 | Py_XDECREF(entry); | |||
|
233 | Py_XDECREF(parents); | |||
|
234 | return ret; | |||
|
235 | } | |||
|
236 | ||||
136 | static char parsers_doc[] = "Efficient content parsing."; |
|
237 | static char parsers_doc[] = "Efficient content parsing."; | |
137 |
|
238 | |||
138 | static PyMethodDef methods[] = { |
|
239 | static PyMethodDef methods[] = { | |
139 | {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"}, |
|
240 | {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"}, | |
|
241 | {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"}, | |||
140 | {NULL, NULL} |
|
242 | {NULL, NULL} | |
141 | }; |
|
243 | }; | |
142 |
|
244 |
General Comments 0
You need to be logged in to leave comments.
Login now