210 Py_XDECREF(fname); |
210 Py_XDECREF(fname); |
211 Py_XDECREF(cname); |
211 Py_XDECREF(cname); |
212 Py_XDECREF(entry); |
212 Py_XDECREF(entry); |
213 Py_XDECREF(parents); |
213 Py_XDECREF(parents); |
214 return ret; |
214 return ret; |
|
215 } |
|
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; |
215 } |
363 } |
216 |
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 * |
1354 } |
1502 } |
1355 |
1503 |
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"}, |
1362 {NULL, NULL} |
1511 {NULL, NULL} |
1363 }; |
1512 }; |
1373 |
1522 |
1374 nullentry = Py_BuildValue("iiiiiiis#", 0, 0, 0, |
1523 nullentry = Py_BuildValue("iiiiiiis#", 0, 0, 0, |
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 |
1381 static struct PyModuleDef parsers_module = { |
1532 static struct PyModuleDef parsers_module = { |
1382 PyModuleDef_HEAD_INIT, |
1533 PyModuleDef_HEAD_INIT, |