diff --git a/docs/references.rst b/docs/references.rst index db97ff8..3391392 100644 --- a/docs/references.rst +++ b/docs/references.rst @@ -28,6 +28,7 @@ The Reference type .. automethod:: pygit2.Reference.delete .. automethod:: pygit2.Reference.rename .. automethod:: pygit2.Reference.resolve +.. automethod:: pygit2.Reference.peel .. automethod:: pygit2.Reference.log Example:: diff --git a/src/object.c b/src/object.c index e169a33..4a6d991 100644 --- a/src/object.c +++ b/src/object.c @@ -135,24 +135,6 @@ Object_read_raw(Object *self) return aux; } -static git_otype -py_type_to_git_type(PyTypeObject *py_type) -{ - git_otype type = GIT_OBJ_BAD; - - if (py_type == &CommitType) { - type = GIT_OBJ_COMMIT; - } else if (py_type == &TreeType) { - type = GIT_OBJ_TREE; - } else if (py_type == &BlobType) { - type = GIT_OBJ_BLOB; - } else if (py_type == &TagType) { - type = GIT_OBJ_TAG; - } - - return type; -} - PyDoc_STRVAR(Object_peel__doc__, "peel(target_type) -> Object\n" "\n" @@ -164,18 +146,9 @@ Object_peel(Object *self, PyObject *py_type) int type = -1, err; git_object *peeled; - if (PyLong_Check(py_type)) { - type = PyLong_AsLong(py_type); - if (type == -1 && PyErr_Occurred()) - return NULL; - } else if (PyType_Check(py_type)) { - type = py_type_to_git_type((PyTypeObject *) py_type); - } - - if (type == -1) { - PyErr_SetString(PyExc_ValueError, "invalid target type"); + type = py_object_to_object_type(py_type); + if (type == -1) return NULL; - } err = git_object_peel(&peeled, self->obj, (git_otype)type); if (err < 0) diff --git a/src/reference.c b/src/reference.c index b89f023..20fc1f7 100644 --- a/src/reference.c +++ b/src/reference.c @@ -384,6 +384,29 @@ Reference_get_object(Reference *self) return wrap_object(obj, self->repo); } +PyDoc_STRVAR(Reference_peel__doc__, + "peel(type) -> object\n" + "\n" + "Retrieve an object of the given type by recursive peeling."); + +PyObject * +Reference_peel(Reference *self, PyObject *py_type) +{ + int err, type; + git_object *obj; + + CHECK_REFERENCE(self); + + type = py_object_to_object_type(py_type); + if (type == -1) + return NULL; + + err = git_reference_peel(&obj, self->reference, type); + if (err < 0) + return Error_set(err); + + return wrap_object(obj, self->repo); +} PyDoc_STRVAR(RefLogEntry_committer__doc__, "Committer."); @@ -479,6 +502,7 @@ PyMethodDef Reference_methods[] = { METHOD(Reference, log, METH_NOARGS), METHOD(Reference, get_object, METH_NOARGS), METHOD(Reference, set_target, METH_VARARGS | METH_KEYWORDS), + METHOD(Reference, peel, METH_O), {NULL} }; diff --git a/src/utils.c b/src/utils.c index 44acf5c..1c16624 100644 --- a/src/utils.c +++ b/src/utils.c @@ -31,6 +31,10 @@ #include "utils.h" extern PyTypeObject ReferenceType; +extern PyTypeObject TreeType; +extern PyTypeObject CommitType; +extern PyTypeObject BlobType; +extern PyTypeObject TagType; /** * py_str_to_c_str() returns a newly allocated C string holding the string @@ -153,3 +157,41 @@ on_error: return -1; } + +static git_otype +py_type_to_git_type(PyTypeObject *py_type) +{ + git_otype type = GIT_OBJ_BAD; + + if (py_type == &CommitType) { + type = GIT_OBJ_COMMIT; + } else if (py_type == &TreeType) { + type = GIT_OBJ_TREE; + } else if (py_type == &BlobType) { + type = GIT_OBJ_BLOB; + } else if (py_type == &TagType) { + type = GIT_OBJ_TAG; + } + + return type; +} + +int +py_object_to_object_type(PyObject *py_type) +{ + int type = -1; + + if (PyLong_Check(py_type)) { + type = PyLong_AsLong(py_type); + if (type == -1 && PyErr_Occurred()) + return -1; + } else if (PyType_Check(py_type)) { + type = py_type_to_git_type((PyTypeObject *) py_type); + } + + if (type == -1) { + PyErr_SetString(PyExc_ValueError, "invalid target type"); + } + + return type; +} diff --git a/src/utils.h b/src/utils.h index e321ea1..7fd1690 100644 --- a/src/utils.h +++ b/src/utils.h @@ -119,6 +119,8 @@ const char *py_str_borrow_c_str(PyObject **tvaue, PyObject *value, const char *e PyObject * get_pylist_from_git_strarray(git_strarray *strarray); int get_strarraygit_from_pylist(git_strarray *array, PyObject *pylist); +int py_object_to_object_type(PyObject *py_type); + #define py_path_to_c_str(py_path) \ py_str_to_c_str(py_path, Py_FileSystemDefaultEncoding) diff --git a/test/test_refs.py b/test/test_refs.py index 35aea55..1e78eb5 100644 --- a/test/test_refs.py +++ b/test/test_refs.py @@ -32,6 +32,7 @@ from __future__ import unicode_literals import unittest from pygit2 import GitError, GIT_REF_OID, GIT_REF_SYMBOLIC, Signature +from pygit2 import Commit, Tree from . import utils @@ -223,6 +224,11 @@ class ReferencesTest(utils.RepoTestCase): ref = repo.lookup_reference('refs/heads/master') self.assertEqual(repo[ref.target].id, ref.get_object().id) + def test_peel(self): + ref = self.repo.lookup_reference('refs/heads/master') + commit = ref.peel(Commit) + self.assertEqual(commit.tree.id, ref.peel(Tree).id) + if __name__ == '__main__': unittest.main()