← Back to team overview

dulwich-users team mailing list archive

[PATCH 16/24] diff_tree: C implementation of _is_tree.

 

From: Dave Borowitz <dborowitz@xxxxxxxxxx>

Change-Id: I46cb5a7765381c8cd4038d36c6b7ff257f3787e2
---
 dulwich/_diff_tree.c            |   62 +++++++++++++++++++++++++++++++++++++++
 dulwich/diff_tree.py            |    9 +++++
 dulwich/tests/test_diff_tree.py |   24 ++++++++++----
 setup.py                        |    2 +
 4 files changed, 90 insertions(+), 7 deletions(-)
 create mode 100644 dulwich/_diff_tree.c

diff --git a/dulwich/_diff_tree.c b/dulwich/_diff_tree.c
new file mode 100644
index 0000000..9b87db4
--- /dev/null
+++ b/dulwich/_diff_tree.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License or (at your option) a later version of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ */
+
+#include <Python.h>
+#include <sys/stat.h>
+
+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;
+	} else {
+		lmode = PyInt_AsLong(mode);
+		if (lmode == -1 && PyErr_Occurred()) {
+			Py_DECREF(mode);
+			return NULL;
+		}
+		result = PyBool_FromLong(S_ISDIR((mode_t)lmode));
+	}
+	Py_INCREF(result);
+	Py_DECREF(mode);
+	return result;
+}
+
+static PyMethodDef py_diff_tree_methods[] = {
+	{ "_is_tree", (PyCFunction)py_is_tree, METH_VARARGS, NULL },
+	{ NULL, NULL, 0, NULL }
+};
+
+PyMODINIT_FUNC
+init_diff_tree(void)
+{
+	PyObject *m, *objects_mod, *diff_mod;
+	m = Py_InitModule("_diff_tree", py_diff_tree_methods);
+	if (!m)
+		return;
+}
diff --git a/dulwich/diff_tree.py b/dulwich/diff_tree.py
index 7a00731..40c5bc0 100644
--- a/dulwich/diff_tree.py
+++ b/dulwich/diff_tree.py
@@ -392,3 +392,12 @@ class RenameDetector(object):
         self._find_exact_renames()
         self._find_content_renames()
         return self._sorted_changes()
+
+
+# Hold on to the pure-python implementations for testing.
+_is_tree_py = _is_tree
+try:
+    # Try to import C versions
+    from dulwich._diff_tree import _is_tree
+except ImportError:
+    pass
diff --git a/dulwich/tests/test_diff_tree.py b/dulwich/tests/test_diff_tree.py
index 99a444a..1230f2b 100644
--- a/dulwich/tests/test_diff_tree.py
+++ b/dulwich/tests/test_diff_tree.py
@@ -31,6 +31,7 @@ from dulwich.diff_tree import (
     _tree_change_key,
     RenameDetector,
     _is_tree,
+    _is_tree_py
     )
 from dulwich.index import (
     commit_tree,
@@ -48,6 +49,7 @@ from dulwich.objects import (
     )
 from dulwich.tests import (
     TestCase,
+    TestSkipped,
     )
 from dulwich.tests.utils import (
     make_object,
@@ -120,14 +122,22 @@ class TreeChangesTest(DiffTestCase):
           (('c', 0100755, blob_c2.id), (None, None, None)),
           ], _merge_entries('', tree2, tree1))
 
+    def _do_test_is_tree(self, is_tree):
+        self.assertFalse(is_tree(TreeEntry(None, None, None)))
+        self.assertFalse(is_tree(TreeEntry('a', 0100644, 'a' * 40)))
+        self.assertFalse(is_tree(TreeEntry('a', 0100755, 'a' * 40)))
+        self.assertFalse(is_tree(TreeEntry('a', 0120000, 'a' * 40)))
+        self.assertTrue(is_tree(TreeEntry('a', 0040000, 'a' * 40)))
+        self.assertRaises(TypeError, is_tree, TreeEntry('a', 'x', 'a' * 40))
+        self.assertRaises(AttributeError, is_tree, 1234)
+
     def test_is_tree(self):
-        self.assertFalse(_is_tree(TreeEntry(None, None, None)))
-        self.assertFalse(_is_tree(TreeEntry('a', 0100644, 'a' * 40)))
-        self.assertFalse(_is_tree(TreeEntry('a', 0100755, 'a' * 40)))
-        self.assertFalse(_is_tree(TreeEntry('a', 0120000, 'a' * 40)))
-        self.assertTrue(_is_tree(TreeEntry('a', 0040000, 'a' * 40)))
-        self.assertRaises(TypeError, _is_tree, TreeEntry('a', 'x', 'a' * 40))
-        self.assertRaises(AttributeError, _is_tree, 1234)
+        self._do_test_is_tree(_is_tree_py)
+
+    def test_is_tree_extension(self):
+        if _is_tree is _is_tree_py:
+            raise TestSkipped('is_tree extension not found')
+        self._do_test_is_tree(_is_tree)
 
     def assertChangesEqual(self, expected, tree1, tree2, **kwargs):
         actual = list(tree_changes(self.store, tree1.id, tree2.id, **kwargs))
diff --git a/setup.py b/setup.py
index bd03739..5f9b594 100755
--- a/setup.py
+++ b/setup.py
@@ -54,6 +54,8 @@ setup(name='dulwich',
                     include_dirs=include_dirs),
           Extension('dulwich._pack', ['dulwich/_pack.c'],
               include_dirs=include_dirs),
+          Extension('dulwich._diff_tree', ['dulwich/_diff_tree.c'],
+              include_dirs=include_dirs),
           ],
       distclass=DulwichDistribution,
       )
-- 
1.7.3.2.168.gd6b63




References