diff --git a/dulwich/_diff_tree.c b/dulwich/_diff_tree.c
index ebed2d7f..88d17ed9 100644
--- a/dulwich/_diff_tree.c
+++ b/dulwich/_diff_tree.c
@@ -1,510 +1,470 @@
/*
* Copyright (C) 2010 Google, Inc.
*
* Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
* General Public License as public by the Free Software Foundation; version 2.0
* or (at your option) any later version. You can redistribute it and/or
* modify it under the terms of either of these two licenses.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* You should have received a copy of the licenses; if not, see
* for a copy of the GNU General Public License
* and for a copy of the Apache
* License, Version 2.0.
*/
#define PY_SSIZE_T_CLEAN
#include
#include
#ifdef _MSC_VER
typedef unsigned short mode_t;
#endif
-#if PY_MAJOR_VERSION < 3
-typedef long Py_hash_t;
-#endif
-
-#if PY_MAJOR_VERSION >= 3
-#define PyInt_FromLong PyLong_FromLong
-#define PyInt_AsLong PyLong_AsLong
-#define PyInt_AS_LONG PyLong_AS_LONG
-#define PyString_AS_STRING PyBytes_AS_STRING
-#define PyString_AsStringAndSize PyBytes_AsStringAndSize
-#define PyString_Check PyBytes_Check
-#define PyString_CheckExact PyBytes_CheckExact
-#define PyString_FromStringAndSize PyBytes_FromStringAndSize
-#define PyString_FromString PyBytes_FromString
-#define PyString_GET_SIZE PyBytes_GET_SIZE
-#define PyString_Size PyBytes_Size
-#define _PyString_Join _PyBytes_Join
-#endif
-
static PyObject *tree_entry_cls = NULL, *null_entry = NULL,
*defaultdict_cls = NULL, *int_cls = NULL;
static int block_size;
/**
* Free an array of PyObject pointers, decrementing any references.
*/
static void free_objects(PyObject **objs, Py_ssize_t n)
{
Py_ssize_t i;
for (i = 0; i < n; i++)
Py_XDECREF(objs[i]);
PyMem_Free(objs);
}
/**
* Get the entries of a tree, prepending the given path.
*
* Args:
* path: The path to prepend, without trailing slashes.
* path_len: The length of path.
* tree: The Tree object to iterate.
* n: Set to the length of result.
* Returns: A (C) array of PyObject pointers to TreeEntry objects for each path
* in tree.
*/
static PyObject **tree_entries(char *path, Py_ssize_t path_len, PyObject *tree,
Py_ssize_t *n)
{
PyObject *iteritems, *items, **result = NULL;
PyObject *old_entry, *name, *sha;
Py_ssize_t i = 0, name_len, new_path_len;
char *new_path;
if (tree == Py_None) {
*n = 0;
result = PyMem_New(PyObject*, 0);
if (!result) {
PyErr_NoMemory();
return NULL;
}
return result;
}
iteritems = PyObject_GetAttrString(tree, "iteritems");
if (!iteritems)
return NULL;
items = PyObject_CallFunctionObjArgs(iteritems, Py_True, NULL);
Py_DECREF(iteritems);
if (items == NULL) {
return NULL;
}
/* The C implementation of iteritems returns a list, so depend on that. */
if (!PyList_Check(items)) {
PyErr_SetString(PyExc_TypeError,
"Tree.iteritems() did not return a list");
return NULL;
}
*n = PyList_Size(items);
result = PyMem_New(PyObject*, *n);
if (!result) {
PyErr_NoMemory();
goto error;
}
for (i = 0; i < *n; i++) {
old_entry = PyList_GetItem(items, i);
if (!old_entry)
goto error;
sha = PyTuple_GetItem(old_entry, 2);
if (!sha)
goto error;
name = PyTuple_GET_ITEM(old_entry, 0);
- name_len = PyString_Size(name);
+ name_len = PyBytes_Size(name);
if (PyErr_Occurred())
goto error;
new_path_len = name_len;
if (path_len)
new_path_len += path_len + 1;
new_path = PyMem_Malloc(new_path_len);
if (!new_path) {
PyErr_NoMemory();
goto error;
}
if (path_len) {
memcpy(new_path, path, path_len);
new_path[path_len] = '/';
- memcpy(new_path + path_len + 1, PyString_AS_STRING(name), name_len);
+ memcpy(new_path + path_len + 1, PyBytes_AS_STRING(name), name_len);
} else {
- memcpy(new_path, PyString_AS_STRING(name), name_len);
+ memcpy(new_path, PyBytes_AS_STRING(name), name_len);
}
-#if PY_MAJOR_VERSION >= 3
result[i] = PyObject_CallFunction(tree_entry_cls, "y#OO", new_path,
new_path_len, PyTuple_GET_ITEM(old_entry, 1), sha);
-#else
- result[i] = PyObject_CallFunction(tree_entry_cls, "s#OO", new_path,
- new_path_len, PyTuple_GET_ITEM(old_entry, 1), sha);
-#endif
PyMem_Free(new_path);
if (!result[i]) {
goto error;
}
}
Py_DECREF(items);
return result;
error:
if (result)
free_objects(result, i);
Py_DECREF(items);
return NULL;
}
/**
* Use strcmp to compare the paths of two TreeEntry objects.
*/
static int entry_path_cmp(PyObject *entry1, PyObject *entry2)
{
PyObject *path1 = NULL, *path2 = NULL;
int result = 0;
path1 = PyObject_GetAttrString(entry1, "path");
if (!path1)
goto done;
- if (!PyString_Check(path1)) {
+ if (!PyBytes_Check(path1)) {
PyErr_SetString(PyExc_TypeError, "path is not a (byte)string");
goto done;
}
path2 = PyObject_GetAttrString(entry2, "path");
if (!path2)
goto done;
- if (!PyString_Check(path2)) {
+ if (!PyBytes_Check(path2)) {
PyErr_SetString(PyExc_TypeError, "path is not a (byte)string");
goto done;
}
- result = strcmp(PyString_AS_STRING(path1), PyString_AS_STRING(path2));
+ result = strcmp(PyBytes_AS_STRING(path1), PyBytes_AS_STRING(path2));
done:
Py_XDECREF(path1);
Py_XDECREF(path2);
return result;
}
static PyObject *py_merge_entries(PyObject *self, PyObject *args)
{
PyObject *tree1, *tree2, **entries1 = NULL, **entries2 = NULL;
PyObject *e1, *e2, *pair, *result = NULL;
Py_ssize_t n1 = 0, n2 = 0, i1 = 0, i2 = 0, path_len;
char *path_str;
int cmp;
-#if PY_MAJOR_VERSION >= 3
if (!PyArg_ParseTuple(args, "y#OO", &path_str, &path_len, &tree1, &tree2))
-#else
- if (!PyArg_ParseTuple(args, "s#OO", &path_str, &path_len, &tree1, &tree2))
-#endif
return NULL;
entries1 = tree_entries(path_str, path_len, tree1, &n1);
if (!entries1)
goto error;
entries2 = tree_entries(path_str, path_len, tree2, &n2);
if (!entries2)
goto error;
result = PyList_New(0);
if (!result)
goto error;
while (i1 < n1 && i2 < n2) {
cmp = entry_path_cmp(entries1[i1], entries2[i2]);
if (PyErr_Occurred())
goto error;
if (!cmp) {
e1 = entries1[i1++];
e2 = entries2[i2++];
} else if (cmp < 0) {
e1 = entries1[i1++];
e2 = null_entry;
} else {
e1 = null_entry;
e2 = entries2[i2++];
}
pair = PyTuple_Pack(2, e1, e2);
if (!pair)
goto error;
PyList_Append(result, pair);
Py_DECREF(pair);
}
while (i1 < n1) {
pair = PyTuple_Pack(2, entries1[i1++], null_entry);
if (!pair)
goto error;
PyList_Append(result, pair);
Py_DECREF(pair);
}
while (i2 < n2) {
pair = PyTuple_Pack(2, null_entry, entries2[i2++]);
if (!pair)
goto error;
PyList_Append(result, pair);
Py_DECREF(pair);
}
goto done;
error:
Py_XDECREF(result);
result = NULL;
done:
if (entries1)
free_objects(entries1, n1);
if (entries2)
free_objects(entries2, n2);
return result;
}
/* Not all environments define S_ISDIR */
#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
static PyObject *py_is_tree(PyObject *self, PyObject *args)
{
PyObject *entry, *mode, *result;
long lmode;
if (!PyArg_ParseTuple(args, "O", &entry))
return NULL;
mode = PyObject_GetAttrString(entry, "mode");
if (!mode)
return NULL;
if (mode == Py_None) {
result = Py_False;
Py_INCREF(result);
} else {
- lmode = PyInt_AsLong(mode);
+ lmode = PyLong_AsLong(mode);
if (lmode == -1 && PyErr_Occurred()) {
Py_DECREF(mode);
return NULL;
}
result = PyBool_FromLong(S_ISDIR((mode_t)lmode));
}
Py_DECREF(mode);
return result;
}
static Py_hash_t add_hash(PyObject *get, PyObject *set, char *str, int n)
{
PyObject *str_obj = NULL, *hash_obj = NULL, *value = NULL,
*set_value = NULL;
Py_hash_t hash;
/* It would be nice to hash without copying str into a PyString, but that
* isn't exposed by the API. */
- str_obj = PyString_FromStringAndSize(str, n);
+ str_obj = PyBytes_FromStringAndSize(str, n);
if (!str_obj)
goto error;
hash = PyObject_Hash(str_obj);
if (hash == -1)
goto error;
- hash_obj = PyInt_FromLong(hash);
+ hash_obj = PyLong_FromLong(hash);
if (!hash_obj)
goto error;
value = PyObject_CallFunctionObjArgs(get, hash_obj, NULL);
if (!value)
goto error;
set_value = PyObject_CallFunction(set, "(Ol)", hash_obj,
- PyInt_AS_LONG(value) + n);
+ PyLong_AS_LONG(value) + n);
if (!set_value)
goto error;
Py_DECREF(str_obj);
Py_DECREF(hash_obj);
Py_DECREF(value);
Py_DECREF(set_value);
return 0;
error:
Py_XDECREF(str_obj);
Py_XDECREF(hash_obj);
Py_XDECREF(value);
Py_XDECREF(set_value);
return -1;
}
static PyObject *py_count_blocks(PyObject *self, PyObject *args)
{
PyObject *obj, *chunks = NULL, *chunk, *counts = NULL, *get = NULL,
*set = NULL;
char *chunk_str, *block = NULL;
Py_ssize_t num_chunks, chunk_len;
int i, j, n = 0;
char c;
if (!PyArg_ParseTuple(args, "O", &obj))
goto error;
counts = PyObject_CallFunctionObjArgs(defaultdict_cls, int_cls, NULL);
if (!counts)
goto error;
get = PyObject_GetAttrString(counts, "__getitem__");
set = PyObject_GetAttrString(counts, "__setitem__");
chunks = PyObject_CallMethod(obj, "as_raw_chunks", NULL);
if (!chunks)
goto error;
if (!PyList_Check(chunks)) {
PyErr_SetString(PyExc_TypeError,
"as_raw_chunks() did not return a list");
goto error;
}
num_chunks = PyList_GET_SIZE(chunks);
block = PyMem_New(char, block_size);
if (!block) {
PyErr_NoMemory();
goto error;
}
for (i = 0; i < num_chunks; i++) {
chunk = PyList_GET_ITEM(chunks, i);
- if (!PyString_Check(chunk)) {
+ if (!PyBytes_Check(chunk)) {
PyErr_SetString(PyExc_TypeError, "chunk is not a string");
goto error;
}
- if (PyString_AsStringAndSize(chunk, &chunk_str, &chunk_len) == -1)
+ if (PyBytes_AsStringAndSize(chunk, &chunk_str, &chunk_len) == -1)
goto error;
for (j = 0; j < chunk_len; j++) {
c = chunk_str[j];
block[n++] = c;
if (c == '\n' || n == block_size) {
if (add_hash(get, set, block, n) == -1)
goto error;
n = 0;
}
}
}
if (n && add_hash(get, set, block, n) == -1)
goto error;
Py_DECREF(chunks);
Py_DECREF(get);
Py_DECREF(set);
PyMem_Free(block);
return counts;
error:
Py_XDECREF(chunks);
Py_XDECREF(get);
Py_XDECREF(set);
Py_XDECREF(counts);
PyMem_Free(block);
return NULL;
}
static PyMethodDef py_diff_tree_methods[] = {
{ "_is_tree", (PyCFunction)py_is_tree, METH_VARARGS, NULL },
{ "_merge_entries", (PyCFunction)py_merge_entries, METH_VARARGS, NULL },
{ "_count_blocks", (PyCFunction)py_count_blocks, METH_VARARGS, NULL },
{ NULL, NULL, 0, NULL }
};
static PyObject *
moduleinit(void)
{
PyObject *m, *objects_mod = NULL, *diff_tree_mod = NULL;
PyObject *block_size_obj = NULL;
-#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"_diff_tree", /* m_name */
NULL, /* m_doc */
-1, /* m_size */
py_diff_tree_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear*/
NULL, /* m_free */
};
m = PyModule_Create(&moduledef);
-#else
- m = Py_InitModule("_diff_tree", py_diff_tree_methods);
-#endif
if (!m)
goto error;
objects_mod = PyImport_ImportModule("dulwich.objects");
if (!objects_mod)
goto error;
tree_entry_cls = PyObject_GetAttrString(objects_mod, "TreeEntry");
Py_DECREF(objects_mod);
if (!tree_entry_cls)
goto error;
diff_tree_mod = PyImport_ImportModule("dulwich.diff_tree");
if (!diff_tree_mod)
goto error;
null_entry = PyObject_GetAttrString(diff_tree_mod, "_NULL_ENTRY");
if (!null_entry)
goto error;
block_size_obj = PyObject_GetAttrString(diff_tree_mod, "_BLOCK_SIZE");
if (!block_size_obj)
goto error;
- block_size = (int)PyInt_AsLong(block_size_obj);
+ block_size = (int)PyLong_AsLong(block_size_obj);
if (PyErr_Occurred())
goto error;
defaultdict_cls = PyObject_GetAttrString(diff_tree_mod, "defaultdict");
if (!defaultdict_cls)
goto error;
/* This is kind of hacky, but I don't know of a better way to get the
* PyObject* version of int. */
int_cls = PyDict_GetItemString(PyEval_GetBuiltins(), "int");
if (!int_cls) {
PyErr_SetString(PyExc_NameError, "int");
goto error;
}
Py_DECREF(diff_tree_mod);
return m;
error:
Py_XDECREF(objects_mod);
Py_XDECREF(diff_tree_mod);
Py_XDECREF(null_entry);
Py_XDECREF(block_size_obj);
Py_XDECREF(defaultdict_cls);
Py_XDECREF(int_cls);
return NULL;
}
-#if PY_MAJOR_VERSION >= 3
PyMODINIT_FUNC
PyInit__diff_tree(void)
{
return moduleinit();
}
-#else
-PyMODINIT_FUNC
-init_diff_tree(void)
-{
- moduleinit();
-}
-#endif
diff --git a/dulwich/_objects.c b/dulwich/_objects.c
index eb8b9e5b..34635e82 100644
--- a/dulwich/_objects.c
+++ b/dulwich/_objects.c
@@ -1,335 +1,309 @@
/*
* Copyright (C) 2009 Jelmer Vernooij
*
* Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
* General Public License as public by the Free Software Foundation; version 2.0
* or (at your option) any later version. You can redistribute it and/or
* modify it under the terms of either of these two licenses.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* You should have received a copy of the licenses; if not, see
* for a copy of the GNU General Public License
* and for a copy of the Apache
* License, Version 2.0.
*/
#define PY_SSIZE_T_CLEAN
#include
#include
#include
-#if PY_MAJOR_VERSION >= 3
-#define PyInt_Check(obj) 0
-#define PyInt_CheckExact(obj) 0
-#define PyInt_AsLong PyLong_AsLong
-#define PyString_AS_STRING PyBytes_AS_STRING
-#define PyString_Check PyBytes_Check
-#define PyString_FromStringAndSize PyBytes_FromStringAndSize
-#endif
-
#if defined(__MINGW32_VERSION) || defined(__APPLE__)
size_t rep_strnlen(char *text, size_t maxlen);
size_t rep_strnlen(char *text, size_t maxlen)
{
const char *last = memchr(text, '\0', maxlen);
return last ? (size_t) (last - text) : maxlen;
}
#define strnlen rep_strnlen
#endif
#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)
{
char hexsha[41];
int i;
for (i = 0; i < 20; i++) {
hexsha[i*2] = bytehex((sha[i] & 0xF0) >> 4);
hexsha[i*2+1] = bytehex(sha[i] & 0x0F);
}
- return PyString_FromStringAndSize(hexsha, 40);
+ return PyBytes_FromStringAndSize(hexsha, 40);
}
static PyObject *py_parse_tree(PyObject *self, PyObject *args, PyObject *kw)
{
char *text, *start, *end;
Py_ssize_t len; int strict;
size_t namelen;
PyObject *ret, *item, *name, *sha, *py_strict = NULL;
static char *kwlist[] = {"text", "strict", NULL};
-#if PY_MAJOR_VERSION >= 3
if (!PyArg_ParseTupleAndKeywords(args, kw, "y#|O", kwlist,
&text, &len, &py_strict))
-#else
- if (!PyArg_ParseTupleAndKeywords(args, kw, "s#|O", kwlist,
- &text, &len, &py_strict))
-#endif
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);
if (ret == NULL) {
return NULL;
}
start = text;
end = text + len;
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 != ' ') {
PyErr_SetString(PyExc_ValueError, "Expected space");
Py_DECREF(ret);
return NULL;
}
text++;
namelen = strnlen(text, len - (text - start));
- name = PyString_FromStringAndSize(text, namelen);
+ name = PyBytes_FromStringAndSize(text, namelen);
if (name == NULL) {
Py_DECREF(ret);
return NULL;
}
if (text + namelen + 20 >= end) {
PyErr_SetString(PyExc_ValueError, "SHA truncated");
Py_DECREF(ret);
Py_DECREF(name);
return NULL;
}
sha = sha_to_pyhex((unsigned char *)text+namelen+1);
if (sha == NULL) {
Py_DECREF(ret);
Py_DECREF(name);
return NULL;
}
item = Py_BuildValue("(NlN)", name, mode, sha);
if (item == NULL) {
Py_DECREF(ret);
Py_DECREF(sha);
Py_DECREF(name);
return NULL;
}
if (PyList_Append(ret, item) == -1) {
Py_DECREF(ret);
Py_DECREF(item);
return NULL;
}
Py_DECREF(item);
text += namelen+21;
}
return ret;
}
struct tree_item {
const char *name;
int mode;
PyObject *tuple;
};
/* Not all environments define S_ISDIR */
#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
int cmp_tree_item(const void *_a, const void *_b)
{
const struct tree_item *a = _a, *b = _b;
const char *remain_a, *remain_b;
int ret;
size_t common;
if (strlen(a->name) > strlen(b->name)) {
common = strlen(b->name);
remain_a = a->name + common;
remain_b = (S_ISDIR(b->mode)?"/":"");
} else if (strlen(b->name) > strlen(a->name)) {
common = strlen(a->name);
remain_a = (S_ISDIR(a->mode)?"/":"");
remain_b = b->name + common;
} else { /* strlen(a->name) == strlen(b->name) */
common = 0;
remain_a = a->name;
remain_b = b->name;
}
ret = strncmp(a->name, b->name, common);
if (ret != 0)
return ret;
return strcmp(remain_a, remain_b);
}
int cmp_tree_item_name_order(const void *_a, const void *_b) {
const struct tree_item *a = _a, *b = _b;
return strcmp(a->name, b->name);
}
static PyObject *py_sorted_tree_items(PyObject *self, PyObject *args)
{
struct tree_item *qsort_entries = NULL;
int name_order, n = 0, i;
PyObject *entries, *py_name_order, *ret, *key, *value, *py_mode, *py_sha;
Py_ssize_t pos = 0, num_entries;
int (*cmp)(const void *, const void *);
if (!PyArg_ParseTuple(args, "OO", &entries, &py_name_order))
goto error;
if (!PyDict_Check(entries)) {
PyErr_SetString(PyExc_TypeError, "Argument not a dictionary");
goto error;
}
name_order = PyObject_IsTrue(py_name_order);
if (name_order == -1)
goto error;
cmp = name_order ? cmp_tree_item_name_order : cmp_tree_item;
num_entries = PyDict_Size(entries);
if (PyErr_Occurred())
goto error;
qsort_entries = PyMem_New(struct tree_item, num_entries);
if (!qsort_entries) {
PyErr_NoMemory();
goto error;
}
while (PyDict_Next(entries, &pos, &key, &value)) {
- if (!PyString_Check(key)) {
+ if (!PyBytes_Check(key)) {
PyErr_SetString(PyExc_TypeError, "Name is not a string");
goto error;
}
if (PyTuple_Size(value) != 2) {
PyErr_SetString(PyExc_ValueError, "Tuple has invalid size");
goto error;
}
py_mode = PyTuple_GET_ITEM(value, 0);
- if (!PyInt_Check(py_mode) && !PyLong_Check(py_mode)) {
+ if (!PyLong_Check(py_mode)) {
PyErr_SetString(PyExc_TypeError, "Mode is not an integral type");
goto error;
}
py_sha = PyTuple_GET_ITEM(value, 1);
- if (!PyString_Check(py_sha)) {
+ if (!PyBytes_Check(py_sha)) {
PyErr_SetString(PyExc_TypeError, "SHA is not a string");
goto error;
}
- qsort_entries[n].name = PyString_AS_STRING(key);
- qsort_entries[n].mode = PyInt_AsLong(py_mode);
+ qsort_entries[n].name = PyBytes_AS_STRING(key);
+ qsort_entries[n].mode = PyLong_AsLong(py_mode);
qsort_entries[n].tuple = PyObject_CallFunctionObjArgs(
tree_entry_cls, key, py_mode, py_sha, NULL);
if (qsort_entries[n].tuple == NULL)
goto error;
n++;
}
qsort(qsort_entries, num_entries, sizeof(struct tree_item), cmp);
ret = PyList_New(num_entries);
if (ret == NULL) {
PyErr_NoMemory();
goto error;
}
for (i = 0; i < num_entries; i++) {
PyList_SET_ITEM(ret, i, qsort_entries[i].tuple);
}
PyMem_Free(qsort_entries);
return ret;
error:
for (i = 0; i < n; i++) {
Py_XDECREF(qsort_entries[i].tuple);
}
PyMem_Free(qsort_entries);
return NULL;
}
static PyMethodDef py_objects_methods[] = {
{ "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 }
};
static PyObject *
moduleinit(void)
{
PyObject *m, *objects_mod, *errors_mod;
-#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"_objects", /* m_name */
NULL, /* m_doc */
-1, /* m_size */
py_objects_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear*/
NULL, /* m_free */
};
m = PyModule_Create(&moduledef);
-#else
- m = Py_InitModule3("_objects", py_objects_methods, NULL);
-#endif
if (m == NULL) {
return NULL;
}
errors_mod = PyImport_ImportModule("dulwich.errors");
if (errors_mod == NULL) {
return NULL;
}
object_format_exception_cls = PyObject_GetAttrString(
errors_mod, "ObjectFormatException");
Py_DECREF(errors_mod);
if (object_format_exception_cls == NULL) {
return NULL;
}
/* 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");
if (objects_mod == NULL) {
return NULL;
}
tree_entry_cls = PyObject_GetAttrString(objects_mod, "TreeEntry");
Py_DECREF(objects_mod);
if (tree_entry_cls == NULL) {
return NULL;
}
return m;
}
-#if PY_MAJOR_VERSION >= 3
PyMODINIT_FUNC
PyInit__objects(void)
{
return moduleinit();
}
-#else
-PyMODINIT_FUNC
-init_objects(void)
-{
- moduleinit();
-}
-#endif
diff --git a/dulwich/_pack.c b/dulwich/_pack.c
index f2ef0649..3ee9828d 100644
--- a/dulwich/_pack.c
+++ b/dulwich/_pack.c
@@ -1,314 +1,282 @@
/*
* Copyright (C) 2009 Jelmer Vernooij
*
* Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
* General Public License as public by the Free Software Foundation; version 2.0
* or (at your option) any later version. You can redistribute it and/or
* modify it under the terms of either of these two licenses.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* You should have received a copy of the licenses; if not, see
* for a copy of the GNU General Public License
* and for a copy of the Apache
* License, Version 2.0.
*/
#define PY_SSIZE_T_CLEAN
#include
#include
-#if PY_MAJOR_VERSION >= 3
-#define PyInt_FromLong PyLong_FromLong
-#define PyString_AS_STRING PyBytes_AS_STRING
-#define PyString_AS_STRING PyBytes_AS_STRING
-#define PyString_Check PyBytes_Check
-#define PyString_CheckExact PyBytes_CheckExact
-#define PyString_FromStringAndSize PyBytes_FromStringAndSize
-#define PyString_FromString PyBytes_FromString
-#define PyString_GET_SIZE PyBytes_GET_SIZE
-#define PyString_Size PyBytes_Size
-#define _PyString_Join _PyBytes_Join
-#endif
-
static PyObject *PyExc_ApplyDeltaError = NULL;
static int py_is_sha(PyObject *sha)
{
- if (!PyString_CheckExact(sha))
+ if (!PyBytes_CheckExact(sha))
return 0;
- if (PyString_Size(sha) != 20)
+ if (PyBytes_Size(sha) != 20)
return 0;
return 1;
}
static size_t get_delta_header_size(uint8_t *delta, size_t *index, size_t length)
{
size_t size = 0;
size_t i = 0;
while ((*index) < length) {
uint8_t cmd = delta[*index];
(*index)++;
size |= (cmd & ~0x80) << i;
i += 7;
if (!(cmd & 0x80))
break;
}
return size;
}
static PyObject *py_chunked_as_string(PyObject *py_buf)
{
if (PyList_Check(py_buf)) {
- PyObject *sep = PyString_FromString("");
+ PyObject *sep = PyBytes_FromString("");
if (sep == NULL) {
PyErr_NoMemory();
return NULL;
}
- py_buf = _PyString_Join(sep, py_buf);
+ py_buf = _PyBytes_Join(sep, py_buf);
Py_DECREF(sep);
if (py_buf == NULL) {
PyErr_NoMemory();
return NULL;
}
- } else if (PyString_Check(py_buf)) {
+ } else if (PyBytes_Check(py_buf)) {
Py_INCREF(py_buf);
} else {
PyErr_SetString(PyExc_TypeError,
"src_buf is not a string or a list of chunks");
return NULL;
}
return py_buf;
}
static PyObject *py_apply_delta(PyObject *self, PyObject *args)
{
uint8_t *src_buf, *delta;
size_t src_buf_len, delta_len;
size_t src_size, dest_size;
size_t outindex = 0;
size_t index;
uint8_t *out;
PyObject *ret, *py_src_buf, *py_delta, *ret_list;
if (!PyArg_ParseTuple(args, "OO", &py_src_buf, &py_delta))
return NULL;
py_src_buf = py_chunked_as_string(py_src_buf);
if (py_src_buf == NULL)
return NULL;
py_delta = py_chunked_as_string(py_delta);
if (py_delta == NULL) {
Py_DECREF(py_src_buf);
return NULL;
}
- src_buf = (uint8_t *)PyString_AS_STRING(py_src_buf);
- src_buf_len = (size_t)PyString_GET_SIZE(py_src_buf);
+ src_buf = (uint8_t *)PyBytes_AS_STRING(py_src_buf);
+ src_buf_len = (size_t)PyBytes_GET_SIZE(py_src_buf);
- delta = (uint8_t *)PyString_AS_STRING(py_delta);
- delta_len = (size_t)PyString_GET_SIZE(py_delta);
+ delta = (uint8_t *)PyBytes_AS_STRING(py_delta);
+ delta_len = (size_t)PyBytes_GET_SIZE(py_delta);
index = 0;
src_size = get_delta_header_size(delta, &index, delta_len);
if (src_size != src_buf_len) {
PyErr_Format(PyExc_ApplyDeltaError,
"Unexpected source buffer size: %lu vs %ld", src_size, src_buf_len);
Py_DECREF(py_src_buf);
Py_DECREF(py_delta);
return NULL;
}
dest_size = get_delta_header_size(delta, &index, delta_len);
- ret = PyString_FromStringAndSize(NULL, dest_size);
+ ret = PyBytes_FromStringAndSize(NULL, dest_size);
if (ret == NULL) {
PyErr_NoMemory();
Py_DECREF(py_src_buf);
Py_DECREF(py_delta);
return NULL;
}
- out = (uint8_t *)PyString_AS_STRING(ret);
+ out = (uint8_t *)PyBytes_AS_STRING(ret);
while (index < delta_len) {
uint8_t cmd = delta[index];
index++;
if (cmd & 0x80) {
size_t cp_off = 0, cp_size = 0;
int i;
for (i = 0; i < 4; i++) {
if (cmd & (1 << i)) {
uint8_t x = delta[index];
index++;
cp_off |= x << (i * 8);
}
}
for (i = 0; i < 3; i++) {
if (cmd & (1 << (4+i))) {
uint8_t x = delta[index];
index++;
cp_size |= x << (i * 8);
}
}
if (cp_size == 0)
cp_size = 0x10000;
if (cp_off + cp_size < cp_size ||
cp_off + cp_size > src_size ||
cp_size > dest_size)
break;
memcpy(out+outindex, src_buf+cp_off, cp_size);
outindex += cp_size;
dest_size -= cp_size;
} else if (cmd != 0) {
if (cmd > dest_size)
break;
memcpy(out+outindex, delta+index, cmd);
outindex += cmd;
index += cmd;
dest_size -= cmd;
} else {
PyErr_SetString(PyExc_ApplyDeltaError, "Invalid opcode 0");
Py_DECREF(ret);
Py_DECREF(py_delta);
Py_DECREF(py_src_buf);
return NULL;
}
}
Py_DECREF(py_src_buf);
Py_DECREF(py_delta);
if (index != delta_len) {
PyErr_SetString(PyExc_ApplyDeltaError, "delta not empty");
Py_DECREF(ret);
return NULL;
}
if (dest_size != 0) {
PyErr_SetString(PyExc_ApplyDeltaError, "dest size incorrect");
Py_DECREF(ret);
return NULL;
}
ret_list = Py_BuildValue("[N]", ret);
if (ret_list == NULL) {
Py_DECREF(ret);
return NULL;
}
return ret_list;
}
static PyObject *py_bisect_find_sha(PyObject *self, PyObject *args)
{
PyObject *unpack_name;
char *sha;
Py_ssize_t sha_len;
int start, end;
-#if PY_MAJOR_VERSION >= 3
if (!PyArg_ParseTuple(args, "iiy#O", &start, &end,
&sha, &sha_len, &unpack_name))
-#else
- if (!PyArg_ParseTuple(args, "iis#O", &start, &end,
- &sha, &sha_len, &unpack_name))
-#endif
return NULL;
if (sha_len != 20) {
PyErr_SetString(PyExc_ValueError, "Sha is not 20 bytes long");
return NULL;
}
if (start > end) {
PyErr_SetString(PyExc_AssertionError, "start > end");
return NULL;
}
while (start <= end) {
PyObject *file_sha;
Py_ssize_t i = (start + end)/2;
int cmp;
file_sha = PyObject_CallFunction(unpack_name, "i", i);
if (file_sha == NULL) {
return NULL;
}
if (!py_is_sha(file_sha)) {
PyErr_SetString(PyExc_TypeError, "unpack_name returned non-sha object");
Py_DECREF(file_sha);
return NULL;
}
- cmp = memcmp(PyString_AS_STRING(file_sha), sha, 20);
+ cmp = memcmp(PyBytes_AS_STRING(file_sha), sha, 20);
Py_DECREF(file_sha);
if (cmp < 0)
start = i + 1;
else if (cmp > 0)
end = i - 1;
else {
- return PyInt_FromLong(i);
+ return PyLong_FromLong(i);
}
}
Py_RETURN_NONE;
}
static PyMethodDef py_pack_methods[] = {
{ "apply_delta", (PyCFunction)py_apply_delta, METH_VARARGS, NULL },
{ "bisect_find_sha", (PyCFunction)py_bisect_find_sha, METH_VARARGS, NULL },
{ NULL, NULL, 0, NULL }
};
static PyObject *
moduleinit(void)
{
PyObject *m;
PyObject *errors_module;
-#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"_pack", /* m_name */
NULL, /* m_doc */
-1, /* m_size */
py_pack_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear*/
NULL, /* m_free */
};
-#endif
errors_module = PyImport_ImportModule("dulwich.errors");
if (errors_module == NULL)
return NULL;
PyExc_ApplyDeltaError = PyObject_GetAttrString(errors_module, "ApplyDeltaError");
Py_DECREF(errors_module);
if (PyExc_ApplyDeltaError == NULL)
return NULL;
-#if PY_MAJOR_VERSION >= 3
m = PyModule_Create(&moduledef);
-#else
- m = Py_InitModule3("_pack", py_pack_methods, NULL);
-#endif
if (m == NULL)
return NULL;
return m;
}
-#if PY_MAJOR_VERSION >= 3
PyMODINIT_FUNC
PyInit__pack(void)
{
return moduleinit();
}
-#else
-PyMODINIT_FUNC
-init_pack(void)
-{
- moduleinit();
-}
-#endif