|
@@ -36,6 +36,7 @@ size_t strnlen(char *text, size_t maxlen)
|
|
|
#define bytehex(x) (((x)<0xa)?('0'+(x)):('a'-0xa+(x)))
|
|
|
|
|
|
static PyObject *tree_entry_cls;
|
|
|
+static PyObject *object_format_exception_cls;
|
|
|
|
|
|
static PyObject *sha_to_pyhex(const unsigned char *sha)
|
|
|
{
|
|
@@ -49,15 +50,20 @@ static PyObject *sha_to_pyhex(const unsigned char *sha)
|
|
|
return PyString_FromStringAndSize(hexsha, 40);
|
|
|
}
|
|
|
|
|
|
-static PyObject *py_parse_tree(PyObject *self, PyObject *args)
|
|
|
+static PyObject *py_parse_tree(PyObject *self, PyObject *args, PyObject *kw)
|
|
|
{
|
|
|
char *text, *start, *end;
|
|
|
- int len, namelen;
|
|
|
- PyObject *ret, *item, *name;
|
|
|
+ int len, namelen, strict;
|
|
|
+ PyObject *ret, *item, *name, *py_strict = NULL;
|
|
|
+ static char *kwlist[] = {"text", "strict", NULL};
|
|
|
|
|
|
- if (!PyArg_ParseTuple(args, "s#", &text, &len))
|
|
|
+ if (!PyArg_ParseTupleAndKeywords(args, kw, "s#|O", kwlist,
|
|
|
+ &text, &len, &py_strict))
|
|
|
return NULL;
|
|
|
|
|
|
+
|
|
|
+ strict = py_strict ? PyObject_IsTrue(py_strict) : 0;
|
|
|
+
|
|
|
/* TODO: currently this returns a list; if memory usage is a concern,
|
|
|
* consider rewriting as a custom iterator object */
|
|
|
ret = PyList_New(0);
|
|
@@ -71,6 +77,13 @@ static PyObject *py_parse_tree(PyObject *self, PyObject *args)
|
|
|
|
|
|
while (text < end) {
|
|
|
long mode;
|
|
|
+ if (strict && text[0] == '0') {
|
|
|
+ PyErr_SetString(object_format_exception_cls,
|
|
|
+ "Illegal leading zero on mode");
|
|
|
+ Py_DECREF(ret);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
mode = strtol(text, &text, 8);
|
|
|
|
|
|
if (*text != ' ') {
|
|
@@ -236,7 +249,8 @@ error:
|
|
|
}
|
|
|
|
|
|
static PyMethodDef py_objects_methods[] = {
|
|
|
- { "parse_tree", (PyCFunction)py_parse_tree, METH_VARARGS, NULL },
|
|
|
+ { "parse_tree", (PyCFunction)py_parse_tree, METH_VARARGS | METH_KEYWORDS,
|
|
|
+ NULL },
|
|
|
{ "sorted_tree_items", py_sorted_tree_items, METH_VARARGS, NULL },
|
|
|
{ NULL, NULL, 0, NULL }
|
|
|
};
|
|
@@ -244,12 +258,23 @@ static PyMethodDef py_objects_methods[] = {
|
|
|
PyMODINIT_FUNC
|
|
|
init_objects(void)
|
|
|
{
|
|
|
- PyObject *m, *objects_mod;
|
|
|
+ PyObject *m, *objects_mod, *errors_mod;
|
|
|
|
|
|
m = Py_InitModule3("_objects", py_objects_methods, NULL);
|
|
|
if (m == NULL)
|
|
|
return;
|
|
|
|
|
|
+
|
|
|
+ errors_mod = PyImport_ImportModule("dulwich.errors");
|
|
|
+ if (errors_mod == NULL)
|
|
|
+ return;
|
|
|
+
|
|
|
+ object_format_exception_cls = PyObject_GetAttrString(
|
|
|
+ errors_mod, "ObjectFormatException");
|
|
|
+ Py_DECREF(errors_mod);
|
|
|
+ if (object_format_exception_cls == NULL)
|
|
|
+ return;
|
|
|
+
|
|
|
/* This is a circular import but should be safe since this module is
|
|
|
* imported at at the very bottom of objects.py. */
|
|
|
objects_mod = PyImport_ImportModule("dulwich.objects");
|