Skip to content

Add Object.peel() #342

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 11, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/objects.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ This is the common interface for all Git objects:
.. autoattribute:: pygit2.Object.id
.. autoattribute:: pygit2.Object.type
.. automethod:: pygit2.Object.read_raw
.. automethod:: pygit2.Object.peel


Blobs
Expand Down
50 changes: 50 additions & 0 deletions src/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,55 @@ 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"
"Peel the current object and returns the first object of the given type\n");

PyObject *
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");
return NULL;
}

err = git_object_peel(&peeled, self->obj, (git_otype)type);
if (err < 0)
return Error_set(err);

return wrap_object(peeled, self->repo);
}

PyGetSetDef Object_getseters[] = {
GETTER(Object, oid),
GETTER(Object, id),
Expand All @@ -137,6 +186,7 @@ PyGetSetDef Object_getseters[] = {

PyMethodDef Object_methods[] = {
METHOD(Object, read_raw, METH_NOARGS),
METHOD(Object, peel, METH_O),
{NULL}
};

Expand Down
82 changes: 82 additions & 0 deletions test/test_object.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# -*- coding: UTF-8 -*-
#
# Copyright 2010-2014 The pygit2 contributors
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2,
# as published by the Free Software Foundation.
#
# In addition to the permissions in the GNU General Public License,
# the authors give you unlimited permission to link the compiled
# version of this file into combinations with other programs,
# and to distribute those combinations without any restriction
# coming from the use of this file. (The General Public License
# restrictions do apply in other respects; for example, they cover
# modification of the file, and distribution when not linked into
# a combined executable.)
#
# This file 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; see the file COPYING. If not, write to
# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.

"""Tests for Object objects."""

from __future__ import absolute_import
from __future__ import unicode_literals
from os.path import dirname, join
import unittest

import pygit2
from pygit2 import GIT_OBJ_TREE, GIT_OBJ_TAG, Tree, Tag
from . import utils


BLOB_SHA = 'a520c24d85fbfc815d385957eed41406ca5a860b'
BLOB_CONTENT = """hello world
hola mundo
bonjour le monde
""".encode()
BLOB_NEW_CONTENT = b'foo bar\n'
BLOB_FILE_CONTENT = b'bye world\n'

class ObjectTest(utils.RepoTestCase):

def test_peel_commit(self):
# start by looking up the commit
commit_id = self.repo.lookup_reference('refs/heads/master').target
commit = self.repo[commit_id]
# and peel to the tree
tree = commit.peel(GIT_OBJ_TREE)

self.assertEqual(type(tree), Tree)
self.assertEqual(str(tree.id), 'fd937514cb799514d4b81bb24c5fcfeb6472b245')

def test_peel_commit_type(self):
commit_id = self.repo.lookup_reference('refs/heads/master').target
commit = self.repo[commit_id]
tree = commit.peel(Tree)

self.assertEqual(type(tree), Tree)
self.assertEqual(str(tree.id), 'fd937514cb799514d4b81bb24c5fcfeb6472b245')


def test_invalid(self):
commit_id = self.repo.lookup_reference('refs/heads/master').target
commit = self.repo[commit_id]

self.assertRaises(ValueError, commit.peel, GIT_OBJ_TAG)

def test_invalid_type(self):
commit_id = self.repo.lookup_reference('refs/heads/master').target
commit = self.repo[commit_id]

self.assertRaises(ValueError, commit.peel, Tag)

if __name__ == '__main__':
unittest.main()