Show More
@@ -498,12 +498,24 b' class dirstate(object):' | |||
|
498 | 498 | return |
|
499 | 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 | 507 | # use the modification time of the newly created temporary file as the |
|
502 | 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 | 518 | cs = cStringIO.StringIO() |
|
506 | copymap = self._copymap | |
|
507 | 519 | pack = struct.pack |
|
508 | 520 | write = cs.write |
|
509 | 521 | write("".join(self._pl)) |
@@ -526,10 +538,7 b' class dirstate(object):' | |||
|
526 | 538 | e = pack(_format, e[0], e[1], e[2], e[3], len(f)) |
|
527 | 539 | write(e) |
|
528 | 540 | write(f) |
|
529 |
|
|
|
530 | st.close() | |
|
531 | self._lastnormaltime = 0 | |
|
532 | self._dirty = self._dirtypl = False | |
|
541 | finish(cs.getvalue()) | |
|
533 | 542 | |
|
534 | 543 | def _dirignore(self, f): |
|
535 | 544 | if f == '.': |
@@ -214,6 +214,154 b' quit:' | |||
|
214 | 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 | 366 | * A base-16 trie for fast node->rev mapping. |
|
219 | 367 | * |
@@ -1356,6 +1504,7 b' bail:' | |||
|
1356 | 1504 | static char parsers_doc[] = "Efficient content parsing."; |
|
1357 | 1505 | |
|
1358 | 1506 | static PyMethodDef methods[] = { |
|
1507 | {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"}, | |
|
1359 | 1508 | {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"}, |
|
1360 | 1509 | {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"}, |
|
1361 | 1510 | {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"}, |
@@ -1375,6 +1524,8 b' static void module_init(PyObject *mod)' | |||
|
1375 | 1524 | -1, -1, -1, -1, nullid, 20); |
|
1376 | 1525 | if (nullentry) |
|
1377 | 1526 | PyObject_GC_UnTrack(nullentry); |
|
1527 | ||
|
1528 | dirstate_unset = Py_BuildValue("ciii", 'n', 0, -1, -1); | |
|
1378 | 1529 | } |
|
1379 | 1530 | |
|
1380 | 1531 | #ifdef IS_PY3K |
General Comments 0
You need to be logged in to leave comments.
Login now