Show More
@@ -498,12 +498,24 b' class dirstate(object):' | |||||
498 | return |
|
498 | return | |
499 | st = self._opener("dirstate", "w", atomictemp=True) |
|
499 | st = self._opener("dirstate", "w", atomictemp=True) | |
500 |
|
500 | |||
|
501 | def finish(s): | |||
|
502 | st.write(s) | |||
|
503 | st.close() | |||
|
504 | self._lastnormaltime = 0 | |||
|
505 | self._dirty = self._dirtypl = False | |||
|
506 | ||||
501 | # use the modification time of the newly created temporary file as the |
|
507 | # use the modification time of the newly created temporary file as the | |
502 | # filesystem's notion of 'now' |
|
508 | # filesystem's notion of 'now' | |
503 |
now = |
|
509 | now = util.fstat(st).st_mtime | |
|
510 | copymap = self._copymap | |||
|
511 | try: | |||
|
512 | finish(parsers.pack_dirstate(self._map, copymap, self._pl, now)) | |||
|
513 | return | |||
|
514 | except AttributeError: | |||
|
515 | pass | |||
504 |
|
516 | |||
|
517 | now = int(now) | |||
505 | cs = cStringIO.StringIO() |
|
518 | cs = cStringIO.StringIO() | |
506 | copymap = self._copymap |
|
|||
507 | pack = struct.pack |
|
519 | pack = struct.pack | |
508 | write = cs.write |
|
520 | write = cs.write | |
509 | write("".join(self._pl)) |
|
521 | write("".join(self._pl)) | |
@@ -526,10 +538,7 b' class dirstate(object):' | |||||
526 | e = pack(_format, e[0], e[1], e[2], e[3], len(f)) |
|
538 | e = pack(_format, e[0], e[1], e[2], e[3], len(f)) | |
527 | write(e) |
|
539 | write(e) | |
528 | write(f) |
|
540 | write(f) | |
529 |
|
|
541 | finish(cs.getvalue()) | |
530 | st.close() |
|
|||
531 | self._lastnormaltime = 0 |
|
|||
532 | self._dirty = self._dirtypl = False |
|
|||
533 |
|
542 | |||
534 | def _dirignore(self, f): |
|
543 | def _dirignore(self, f): | |
535 | if f == '.': |
|
544 | if f == '.': |
@@ -214,6 +214,154 b' quit:' | |||||
214 | return ret; |
|
214 | return ret; | |
215 | } |
|
215 | } | |
216 |
|
216 | |||
|
217 | static inline int getintat(PyObject *tuple, int off, uint32_t *v) | |||
|
218 | { | |||
|
219 | PyObject *o = PyTuple_GET_ITEM(tuple, off); | |||
|
220 | long val; | |||
|
221 | ||||
|
222 | if (PyInt_Check(o)) | |||
|
223 | val = PyInt_AS_LONG(o); | |||
|
224 | else if (PyLong_Check(o)) { | |||
|
225 | val = PyLong_AsLong(o); | |||
|
226 | if (val == -1 && PyErr_Occurred()) | |||
|
227 | return -1; | |||
|
228 | } else { | |||
|
229 | PyErr_SetString(PyExc_TypeError, "expected an int or long"); | |||
|
230 | return -1; | |||
|
231 | } | |||
|
232 | if (LONG_MAX > INT_MAX && (val > INT_MAX || val < INT_MIN)) { | |||
|
233 | PyErr_SetString(PyExc_OverflowError, | |||
|
234 | "Python value to large to convert to uint32_t"); | |||
|
235 | return -1; | |||
|
236 | } | |||
|
237 | *v = (uint32_t)val; | |||
|
238 | return 0; | |||
|
239 | } | |||
|
240 | ||||
|
241 | static PyObject *dirstate_unset; | |||
|
242 | ||||
|
243 | /* | |||
|
244 | * Efficiently pack a dirstate object into its on-disk format. | |||
|
245 | */ | |||
|
246 | static PyObject *pack_dirstate(PyObject *self, PyObject *args) | |||
|
247 | { | |||
|
248 | PyObject *packobj = NULL; | |||
|
249 | PyObject *map, *copymap, *pl; | |||
|
250 | Py_ssize_t nbytes, pos, l; | |||
|
251 | PyObject *k, *v, *pn; | |||
|
252 | char *p, *s; | |||
|
253 | double now; | |||
|
254 | ||||
|
255 | if (!PyArg_ParseTuple(args, "O!O!Od:pack_dirstate", | |||
|
256 | &PyDict_Type, &map, &PyDict_Type, ©map, | |||
|
257 | &pl, &now)) | |||
|
258 | return NULL; | |||
|
259 | ||||
|
260 | if (!PySequence_Check(pl) || PySequence_Size(pl) != 2) { | |||
|
261 | PyErr_SetString(PyExc_TypeError, "expected 2-element sequence"); | |||
|
262 | return NULL; | |||
|
263 | } | |||
|
264 | ||||
|
265 | /* Figure out how much we need to allocate. */ | |||
|
266 | for (nbytes = 40, pos = 0; PyDict_Next(map, &pos, &k, &v);) { | |||
|
267 | PyObject *c; | |||
|
268 | if (!PyString_Check(k)) { | |||
|
269 | PyErr_SetString(PyExc_TypeError, "expected string key"); | |||
|
270 | goto bail; | |||
|
271 | } | |||
|
272 | nbytes += PyString_GET_SIZE(k) + 17; | |||
|
273 | c = PyDict_GetItem(copymap, k); | |||
|
274 | if (c) { | |||
|
275 | if (!PyString_Check(c)) { | |||
|
276 | PyErr_SetString(PyExc_TypeError, | |||
|
277 | "expected string key"); | |||
|
278 | goto bail; | |||
|
279 | } | |||
|
280 | nbytes += PyString_GET_SIZE(c) + 1; | |||
|
281 | } | |||
|
282 | } | |||
|
283 | ||||
|
284 | packobj = PyString_FromStringAndSize(NULL, nbytes); | |||
|
285 | if (packobj == NULL) | |||
|
286 | goto bail; | |||
|
287 | ||||
|
288 | p = PyString_AS_STRING(packobj); | |||
|
289 | ||||
|
290 | pn = PySequence_ITEM(pl, 0); | |||
|
291 | if (PyString_AsStringAndSize(pn, &s, &l) == -1 || l != 20) { | |||
|
292 | PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash"); | |||
|
293 | goto bail; | |||
|
294 | } | |||
|
295 | memcpy(p, s, l); | |||
|
296 | p += 20; | |||
|
297 | pn = PySequence_ITEM(pl, 1); | |||
|
298 | if (PyString_AsStringAndSize(pn, &s, &l) == -1 || l != 20) { | |||
|
299 | PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash"); | |||
|
300 | goto bail; | |||
|
301 | } | |||
|
302 | memcpy(p, s, l); | |||
|
303 | p += 20; | |||
|
304 | ||||
|
305 | for (pos = 0; PyDict_Next(map, &pos, &k, &v); ) { | |||
|
306 | uint32_t mode, size, mtime; | |||
|
307 | Py_ssize_t len, l; | |||
|
308 | PyObject *o; | |||
|
309 | char *s, *t; | |||
|
310 | int err; | |||
|
311 | ||||
|
312 | if (!PyTuple_Check(v) || PyTuple_GET_SIZE(v) != 4) { | |||
|
313 | PyErr_SetString(PyExc_TypeError, "expected a 4-tuple"); | |||
|
314 | goto bail; | |||
|
315 | } | |||
|
316 | o = PyTuple_GET_ITEM(v, 0); | |||
|
317 | if (PyString_AsStringAndSize(o, &s, &l) == -1 || l != 1) { | |||
|
318 | PyErr_SetString(PyExc_TypeError, "expected one byte"); | |||
|
319 | goto bail; | |||
|
320 | } | |||
|
321 | *p++ = *s; | |||
|
322 | err = getintat(v, 1, &mode); | |||
|
323 | err |= getintat(v, 2, &size); | |||
|
324 | err |= getintat(v, 3, &mtime); | |||
|
325 | if (err) | |||
|
326 | goto bail; | |||
|
327 | if (*s == 'n' && mtime == (uint32_t)now) { | |||
|
328 | /* See dirstate.py:write for why we do this. */ | |||
|
329 | if (PyDict_SetItem(map, k, dirstate_unset) == -1) | |||
|
330 | goto bail; | |||
|
331 | mode = 0, size = -1, mtime = -1; | |||
|
332 | } | |||
|
333 | putbe32(mode, p); | |||
|
334 | putbe32(size, p + 4); | |||
|
335 | putbe32(mtime, p + 8); | |||
|
336 | t = p + 12; | |||
|
337 | p += 16; | |||
|
338 | len = PyString_GET_SIZE(k); | |||
|
339 | memcpy(p, PyString_AS_STRING(k), len); | |||
|
340 | p += len; | |||
|
341 | o = PyDict_GetItem(copymap, k); | |||
|
342 | if (o) { | |||
|
343 | *p++ = '\0'; | |||
|
344 | l = PyString_GET_SIZE(o); | |||
|
345 | memcpy(p, PyString_AS_STRING(o), l); | |||
|
346 | p += l; | |||
|
347 | len += l + 1; | |||
|
348 | } | |||
|
349 | putbe32((uint32_t)len, t); | |||
|
350 | } | |||
|
351 | ||||
|
352 | pos = p - PyString_AS_STRING(packobj); | |||
|
353 | if (pos != nbytes) { | |||
|
354 | PyErr_Format(PyExc_SystemError, "bad dirstate size: %ld != %ld", | |||
|
355 | (long)pos, (long)nbytes); | |||
|
356 | goto bail; | |||
|
357 | } | |||
|
358 | ||||
|
359 | return packobj; | |||
|
360 | bail: | |||
|
361 | Py_XDECREF(packobj); | |||
|
362 | return NULL; | |||
|
363 | } | |||
|
364 | ||||
217 | /* |
|
365 | /* | |
218 | * A base-16 trie for fast node->rev mapping. |
|
366 | * A base-16 trie for fast node->rev mapping. | |
219 | * |
|
367 | * | |
@@ -1356,6 +1504,7 b' bail:' | |||||
1356 | static char parsers_doc[] = "Efficient content parsing."; |
|
1504 | static char parsers_doc[] = "Efficient content parsing."; | |
1357 |
|
1505 | |||
1358 | static PyMethodDef methods[] = { |
|
1506 | static PyMethodDef methods[] = { | |
|
1507 | {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"}, | |||
1359 | {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"}, |
|
1508 | {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"}, | |
1360 | {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"}, |
|
1509 | {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"}, | |
1361 | {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"}, |
|
1510 | {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"}, | |
@@ -1375,6 +1524,8 b' static void module_init(PyObject *mod)' | |||||
1375 | -1, -1, -1, -1, nullid, 20); |
|
1524 | -1, -1, -1, -1, nullid, 20); | |
1376 | if (nullentry) |
|
1525 | if (nullentry) | |
1377 | PyObject_GC_UnTrack(nullentry); |
|
1526 | PyObject_GC_UnTrack(nullentry); | |
|
1527 | ||||
|
1528 | dirstate_unset = Py_BuildValue("ciii", 'n', 0, -1, -1); | |||
1378 | } |
|
1529 | } | |
1379 |
|
1530 | |||
1380 | #ifdef IS_PY3K |
|
1531 | #ifdef IS_PY3K |
General Comments 0
You need to be logged in to leave comments.
Login now