Add basic Index object based on libgit2. master
authorJelmer Vernooij <jelmer@samba.org>
Mon, 25 Oct 2010 23:11:45 +0000 (16:11 -0700)
committerJelmer Vernooij <jelmer@samba.org>
Mon, 25 Oct 2010 23:11:45 +0000 (16:11 -0700)
dulwich/_index.c [new file with mode: 0644]
dulwich/index.py
setup.py

diff --git a/dulwich/_index.c b/dulwich/_index.c
new file mode 100644 (file)
index 0000000..020f15a
--- /dev/null
@@ -0,0 +1,174 @@
+/**
+ * index.py -- File parser/writer for the git index file
+ * Copyright (C) 2008-2009 Jelmer Vernooij <jelmer@samba.org>
+ *
+ * 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 opinion) any 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 <git/index.h>
+
+staticforward PyTypeObject PyIndexType;
+
+typedef struct {
+       PyObject_HEAD
+       char *path;
+       git_index *index;
+} PyIndexObject;
+
+static PyObject *py_index_read(PyIndexObject *self)
+{
+       git_index *index;
+       PyIndexObject *ret;
+
+       if (self->index != NULL) {
+               git_index_free(self->index);
+               return NULL;
+       }
+
+       index = git_index_alloc(self->path);
+       if (index == NULL) {
+               PyErr_Format(PyExc_RuntimeError, "Unable to open index file %s", self->path);
+               return NULL;
+       }
+
+       ret->index = index;
+
+       return (PyObject *)ret;
+}
+
+static PyMethodDef py_index_type_methods[] = {
+       { "read", (PyCFunction)py_index_read, METH_NOARGS, "Read current contents of index from disk." },
+       { NULL }
+};
+
+static int py_index_type_dealloc(PyIndexObject *self)
+{
+       git_index_free(self->index);
+       PyObject_Del(self);
+       return 0;
+}
+
+static PyObject *py_index_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+       char *kwnames[] = { "path", NULL };
+       PyIndexObject *ret;
+       char *path;
+       git_index *index;
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", &kwnames, &path))
+               return NULL;
+
+       index = git_index_read(path);
+       if (index == NULL) {
+               PyErr_Format(PyExc_RuntimeError, "Unable to open index file %s", path);
+               return NULL;
+       }
+
+       ret = PyObject_New(PyIndexObject, type);
+       if (ret == NULL) {
+               return NULL;
+       }
+       ret->path = strdup(path);
+       ret->index = index;
+
+       return (PyObject *)ret;
+}
+
+static PyTypeObject PyIndexType = {
+       PyObject_HEAD_INIT(NULL) 0,
+       "_index.Index", /*      const char *tp_name;  For printing, in format "<module>.<name>" */
+       sizeof(PyIndexObject), 
+       0,/*    Py_ssize_t tp_basicsize, tp_itemsize;  For allocation */
+
+       /* Methods to implement standard operations */
+
+       (destructor)py_index_type_dealloc, /*   destructor tp_dealloc;  */
+       NULL, /*        printfunc tp_print;     */
+       NULL, /*        getattrfunc tp_getattr; */
+       NULL, /*        setattrfunc tp_setattr; */
+       NULL, /*        cmpfunc tp_compare;     */
+       NULL, /*        reprfunc tp_repr;       */
+
+       /* Method suites for standard classes */
+
+       NULL, /*        PyNumberMethods *tp_as_number;  */
+       NULL, /*        PySequenceMethods *tp_as_sequence;      */
+       NULL, /*        PyMappingMethods *tp_as_mapping;        */
+
+       /* More standard operations (here for binary compatibility) */
+
+       NULL, /*        hashfunc tp_hash;       */
+       NULL, /*        ternaryfunc tp_call;    */
+       NULL, /*        reprfunc tp_str;        */
+       NULL, /*        getattrofunc tp_getattro;       */
+       NULL, /*        setattrofunc tp_setattro;       */
+
+       /* Functions to access object as input/output buffer */
+       NULL, /*        PyBufferProcs *tp_as_buffer;    */
+
+       /* Flags to define presence of optional/expanded features */
+       0, /*   long tp_flags;  */
+
+       NULL, /*        const char *tp_doc;  Documentation string */
+
+       /* Assigned meaning in release 2.0 */
+       /* call function for all accessible objects */
+       NULL, /*        traverseproc tp_traverse;       */
+
+       /* delete references to contained objects */
+       NULL, /*        inquiry tp_clear;       */
+
+       /* Assigned meaning in release 2.1 */
+       /* rich comparisons */
+       NULL, /*        richcmpfunc tp_richcompare;     */
+
+       /* weak reference enabler */
+       0, /*   Py_ssize_t tp_weaklistoffset;   */
+
+       /* Added in release 2.2 */
+       /* Iterators */
+       NULL, /*        getiterfunc tp_iter;    */
+       NULL, /*        iternextfunc tp_iternext;       */
+
+       /* Attribute descriptor and subclassing stuff */
+       py_index_type_methods, /*       struct PyMethodDef *tp_methods; */
+
+       NULL, /* struct PyMemberDef *tp_members; */
+       NULL, /* struct PyGetSetDef *tp_getset; */
+       NULL, /* struct _typeobject *tp_base; */
+       NULL, /* PyObject *tp_dict; */
+       NULL, /* descrgetfunc tp_descr_get; */
+       NULL, /* descrsetfunc tp_descr_set; */
+       0, /* Py_ssize_t tp_dictoffset; */
+       NULL, /* initproc tp_init; */
+       NULL, /* allocfunc tp_alloc; */
+       py_index_new, /* tp_new */
+};
+
+void init_index(void)
+{
+       PyObject *m;
+
+       if (PyType_Ready(&PyIndexType) < 0)
+               return;
+
+       m = Py_InitModule3("_index", NULL, NULL);
+       if (m == NULL)
+               return;
+
+       PyModule_AddObject(m, "Index", (PyObject *)&PyIndexType);
+       Py_INCREF(&PyIndexType);
+}
index c80e62d3ca9ec3e8f0ddae54e94b63793f107ae8..f9d86d4c3ab212550baa4177ef075a45f2368835 100644 (file)
@@ -59,7 +59,7 @@ def pathjoin(*args):
 
 def read_cache_time(f):
     """Read a cache time.
-    
+
     :param f: File-like object to read from
     :return: Tuple with seconds and nanoseconds
     """
@@ -68,7 +68,7 @@ def read_cache_time(f):
 
 def write_cache_time(f, t):
     """Write a cache time.
-    
+
     :param f: File-like object to write to
     :param t: Time to write (as int, float or tuple with secs and nsecs)
     """
@@ -186,7 +186,7 @@ class Index(object):
 
     def __init__(self, filename):
         """Open an index file.
-        
+
         :param filename: Path to the index file
         """
         self._filename = filename
@@ -345,3 +345,12 @@ def commit_index(object_store, index):
     :return: Root tree sha.
     """
     return commit_tree(object_store, index.iterblobs())
+
+
+# Hold on to the pure-python implementations for testing
+_Index_py = Index
+try:
+    # Try to import C versions
+    from dulwich._index import Index
+except ImportError:
+    pass
index 99d87accdeda4776bc6f92b6f9641d09b332c807..fb5dd0fc36ccd78eb2e3d2632bee9ce14f67feef 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -62,6 +62,8 @@ setup(name='dulwich',
       packages=['dulwich', 'dulwich.tests'],
       scripts=['bin/dulwich', 'bin/dul-daemon', 'bin/dul-web'],
       ext_modules = [
+          Extension('dulwich._index', ['dulwich/_index.c'],
+                    **pkgconfig("libgit2", include_dirs=include_dirs)),
           Extension('dulwich._objects', ['dulwich/_objects.c'],
                     **pkgconfig("libgit2", include_dirs=include_dirs)),
           Extension('dulwich._pack', ['dulwich/_pack.c'],