Add TreeBuilder.get and remove TreeEntry.to_object

Also, check errors from git_tree_entry_dup
This commit is contained in:
J. David Ibáñez
2013-05-04 00:31:03 +02:00
parent f5082b320b
commit 42aed417d4
7 changed files with 85 additions and 63 deletions

View File

@@ -187,7 +187,6 @@ interfaces::
.. autoattribute:: pygit2.TreeEntry.oid .. autoattribute:: pygit2.TreeEntry.oid
.. autoattribute:: pygit2.TreeEntry.hex .. autoattribute:: pygit2.TreeEntry.hex
.. autoattribute:: pygit2.TreeEntry.filemode .. autoattribute:: pygit2.TreeEntry.filemode
.. automethod:: pygit2.TreeEntry.to_object
Creating trees Creating trees

View File

@@ -42,7 +42,6 @@ extern PyTypeObject IndexType;
void void
TreeEntry_dealloc(TreeEntry *self) TreeEntry_dealloc(TreeEntry *self)
{ {
Py_CLEAR(self->owner);
git_tree_entry_free((git_tree_entry*)self->entry); git_tree_entry_free((git_tree_entry*)self->entry);
PyObject_Del(self); PyObject_Del(self);
} }
@@ -87,22 +86,6 @@ TreeEntry_hex__get__(TreeEntry *self)
} }
PyDoc_STRVAR(TreeEntry_to_object__doc__,
"to_object() -> Object\n"
"\n"
"Look up the corresponding object in the repo.");
PyObject *
TreeEntry_to_object(TreeEntry *self)
{
const git_oid *entry_oid;
Repository *repo;
repo = ((Object*)(self->owner))->repo;
entry_oid = git_tree_entry_id(self->entry);
return lookup_object(repo, entry_oid, GIT_OBJ_ANY);
}
PyGetSetDef TreeEntry_getseters[] = { PyGetSetDef TreeEntry_getseters[] = {
GETTER(TreeEntry, filemode), GETTER(TreeEntry, filemode),
GETTER(TreeEntry, name), GETTER(TreeEntry, name),
@@ -111,11 +94,6 @@ PyGetSetDef TreeEntry_getseters[] = {
{NULL} {NULL}
}; };
PyMethodDef TreeEntry_methods[] = {
METHOD(TreeEntry, to_object, METH_NOARGS),
{NULL}
};
PyDoc_STRVAR(TreeEntry__doc__, "TreeEntry objects."); PyDoc_STRVAR(TreeEntry__doc__, "TreeEntry objects.");
@@ -147,7 +125,7 @@ PyTypeObject TreeEntryType = {
0, /* tp_weaklistoffset */ 0, /* tp_weaklistoffset */
0, /* tp_iter */ 0, /* tp_iter */
0, /* tp_iternext */ 0, /* tp_iternext */
TreeEntry_methods, /* tp_methods */ 0, /* tp_methods */
0, /* tp_members */ 0, /* tp_members */
TreeEntry_getseters, /* tp_getset */ TreeEntry_getseters, /* tp_getset */
0, /* tp_base */ 0, /* tp_base */
@@ -181,16 +159,14 @@ Tree_contains(Tree *self, PyObject *py_name)
} }
TreeEntry * TreeEntry *
wrap_tree_entry(const git_tree_entry *entry, Tree *tree) wrap_tree_entry(const git_tree_entry *entry)
{ {
TreeEntry *py_entry; TreeEntry *py_entry;
py_entry = PyObject_New(TreeEntry, &TreeEntryType); py_entry = PyObject_New(TreeEntry, &TreeEntryType);
if (py_entry) { if (py_entry)
py_entry->entry = entry; py_entry->entry = entry;
py_entry->owner = (PyObject*)tree;
Py_INCREF(tree);
}
return py_entry; return py_entry;
} }
@@ -252,7 +228,14 @@ Tree_getitem_by_index(Tree *self, PyObject *py_index)
PyErr_SetObject(PyExc_IndexError, py_index); PyErr_SetObject(PyExc_IndexError, py_index);
return NULL; return NULL;
} }
return wrap_tree_entry(git_tree_entry_dup(entry), self);
entry = git_tree_entry_dup(entry);
if (entry == NULL) {
PyErr_SetNone(PyExc_MemoryError);
return NULL;
}
return wrap_tree_entry(entry);
} }
TreeEntry * TreeEntry *
@@ -283,7 +266,7 @@ Tree_getitem(Tree *self, PyObject *value)
return (TreeEntry*)Error_set(err); return (TreeEntry*)Error_set(err);
/* git_tree_entry_dup is already done in git_tree_entry_bypath */ /* git_tree_entry_dup is already done in git_tree_entry_bypath */
return wrap_tree_entry(entry, self); return wrap_tree_entry(entry);
} }
@@ -431,15 +414,20 @@ TreeIter_dealloc(TreeIter *self)
TreeEntry * TreeEntry *
TreeIter_iternext(TreeIter *self) TreeIter_iternext(TreeIter *self)
{ {
const git_tree_entry *tree_entry; const git_tree_entry *entry;
tree_entry = git_tree_entry_byindex(self->owner->tree, self->i); entry = git_tree_entry_byindex(self->owner->tree, self->i);
if (!tree_entry) if (!entry)
return NULL; return NULL;
self->i += 1; self->i += 1;
return (TreeEntry*)wrap_tree_entry(git_tree_entry_dup(tree_entry),
self->owner); entry = git_tree_entry_dup(entry);
if (entry == NULL) {
PyErr_SetNone(PyExc_MemoryError);
return NULL;
}
return wrap_tree_entry(entry);
} }

View File

@@ -33,11 +33,11 @@
#include <git2.h> #include <git2.h>
#include "types.h" #include "types.h"
TreeEntry * wrap_tree_entry(const git_tree_entry *entry);
PyObject* TreeEntry_get_filemode(TreeEntry *self); PyObject* TreeEntry_get_filemode(TreeEntry *self);
PyObject* TreeEntry_get_name(TreeEntry *self); PyObject* TreeEntry_get_name(TreeEntry *self);
PyObject* TreeEntry_get_oid(TreeEntry *self); PyObject* TreeEntry_get_oid(TreeEntry *self);
PyObject* TreeEntry_get_hex(TreeEntry *self); PyObject* TreeEntry_get_hex(TreeEntry *self);
PyObject* TreeEntry_to_object(TreeEntry *self);
TreeEntry* Tree_getitem_by_index(Tree *self, PyObject *py_index); TreeEntry* Tree_getitem_by_index(Tree *self, PyObject *py_index);
TreeEntry* Tree_getitem(Tree *self, PyObject *value); TreeEntry* Tree_getitem(Tree *self, PyObject *value);

View File

@@ -32,6 +32,7 @@
#include "utils.h" #include "utils.h"
#include "oid.h" #include "oid.h"
#include "treebuilder.h" #include "treebuilder.h"
#include "tree.h"
void void
@@ -44,9 +45,9 @@ TreeBuilder_dealloc(TreeBuilder *self)
PyDoc_STRVAR(TreeBuilder_insert__doc__, PyDoc_STRVAR(TreeBuilder_insert__doc__,
"insert(name, oid, attr)\n" "insert(name, oid, attr)\n"
"\n" "\n"
"Insert or replace an entry in the treebuilder."); "Insert or replace an entry in the treebuilder.");
PyObject * PyObject *
TreeBuilder_insert(TreeBuilder *self, PyObject *args) TreeBuilder_insert(TreeBuilder *self, PyObject *args)
@@ -72,9 +73,9 @@ TreeBuilder_insert(TreeBuilder *self, PyObject *args)
PyDoc_STRVAR(TreeBuilder_write__doc__, PyDoc_STRVAR(TreeBuilder_write__doc__,
"write() -> bytes\n" "write() -> bytes\n"
"\n" "\n"
"Write the tree to the given repository."); "Write the tree to the given repository.");
PyObject * PyObject *
TreeBuilder_write(TreeBuilder *self) TreeBuilder_write(TreeBuilder *self)
@@ -90,10 +91,38 @@ TreeBuilder_write(TreeBuilder *self)
} }
PyDoc_STRVAR(TreeBuilder_get__doc__,
"get(name) -> TreeEntry\n"
"\n"
"Return the TreeEntry for the given name, or None if there is not.");
PyObject *
TreeBuilder_get(TreeBuilder *self, PyObject *py_filename)
{
char *filename;
const git_tree_entry *entry;
filename = py_path_to_c_str(py_filename);
if (filename == NULL)
return NULL;
entry = git_treebuilder_get(self->bld, filename);
if (entry == NULL)
Py_RETURN_NONE;
entry = git_tree_entry_dup(entry);
if (entry == NULL) {
PyErr_SetNone(PyExc_MemoryError);
return NULL;
}
return (PyObject*)wrap_tree_entry(entry);
}
PyDoc_STRVAR(TreeBuilder_remove__doc__, PyDoc_STRVAR(TreeBuilder_remove__doc__,
"remove(name)\n" "remove(name)\n"
"\n" "\n"
"Remove an entry from the builder."); "Remove an entry from the builder.");
PyObject * PyObject *
TreeBuilder_remove(TreeBuilder *self, PyObject *py_filename) TreeBuilder_remove(TreeBuilder *self, PyObject *py_filename)
@@ -114,9 +143,9 @@ TreeBuilder_remove(TreeBuilder *self, PyObject *py_filename)
PyDoc_STRVAR(TreeBuilder_clear__doc__, PyDoc_STRVAR(TreeBuilder_clear__doc__,
"clear()\n" "clear()\n"
"\n" "\n"
"Clear all the entries in the builder."); "Clear all the entries in the builder.");
PyObject * PyObject *
TreeBuilder_clear(TreeBuilder *self) TreeBuilder_clear(TreeBuilder *self)
@@ -126,10 +155,11 @@ TreeBuilder_clear(TreeBuilder *self)
} }
PyMethodDef TreeBuilder_methods[] = { PyMethodDef TreeBuilder_methods[] = {
METHOD(TreeBuilder, insert, METH_VARARGS),
METHOD(TreeBuilder, write, METH_NOARGS),
METHOD(TreeBuilder, remove, METH_O),
METHOD(TreeBuilder, clear, METH_NOARGS), METHOD(TreeBuilder, clear, METH_NOARGS),
METHOD(TreeBuilder, get, METH_O),
METHOD(TreeBuilder, insert, METH_VARARGS),
METHOD(TreeBuilder, remove, METH_O),
METHOD(TreeBuilder, write, METH_NOARGS),
{NULL} {NULL}
}; };

View File

@@ -130,7 +130,6 @@ SIMPLE_TYPE(TreeBuilder, git_treebuilder, bld)
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
PyObject *owner; /* Tree or TreeBuilder */
const git_tree_entry *entry; const git_tree_entry *entry;
} TreeEntry; } TreeEntry;

View File

@@ -71,23 +71,26 @@ class TreeTest(utils.BareRepoTestCase):
self.assertTreeEntryEqual(tree['c/d'], sha, 'd', 0o0100644) self.assertTreeEntryEqual(tree['c/d'], sha, 'd', 0o0100644)
self.assertRaisesWithArg(KeyError, 'ab/cd', lambda: tree['ab/cd']) self.assertRaisesWithArg(KeyError, 'ab/cd', lambda: tree['ab/cd'])
def test_read_subtree(self): def test_read_subtree(self):
tree = self.repo[TREE_SHA] tree = self.repo[TREE_SHA]
subtree_entry = tree['c'] subtree_entry = tree['c']
self.assertTreeEntryEqual(subtree_entry, SUBTREE_SHA, 'c', 0o0040000) self.assertTreeEntryEqual(subtree_entry, SUBTREE_SHA, 'c', 0o0040000)
subtree = subtree_entry.to_object() subtree = self.repo[subtree_entry.oid]
self.assertEqual(1, len(subtree)) self.assertEqual(1, len(subtree))
sha = '297efb891a47de80be0cfe9c639e4b8c9b450989' sha = '297efb891a47de80be0cfe9c639e4b8c9b450989'
self.assertTreeEntryEqual(subtree[0], sha, 'd', 0o0100644) self.assertTreeEntryEqual(subtree[0], sha, 'd', 0o0100644)
def test_new_tree(self): def test_new_tree(self):
b0 = self.repo.create_blob('1') repo = self.repo
b1 = self.repo.create_blob('2') b0 = repo.create_blob('1')
t = self.repo.TreeBuilder() b1 = repo.create_blob('2')
t = repo.TreeBuilder()
t.insert('x', b0, 0o0100644) t.insert('x', b0, 0o0100644)
t.insert('y', b1, 0o0100755) t.insert('y', b1, 0o0100755)
tree = self.repo[t.write()] tree = repo[t.write()]
self.assertTrue('x' in tree) self.assertTrue('x' in tree)
self.assertTrue('y' in tree) self.assertTrue('y' in tree)
@@ -97,9 +100,8 @@ class TreeTest(utils.BareRepoTestCase):
self.assertEqual(x.filemode, 0o0100644) self.assertEqual(x.filemode, 0o0100644)
self.assertEqual(y.filemode, 0o0100755) self.assertEqual(y.filemode, 0o0100755)
self.assertEqual(x.to_object().oid, b0) self.assertEqual(repo[x.oid].oid, b0)
self.assertEqual(y.to_object().oid, b1) self.assertEqual(repo[y.oid].oid, b1)
def test_modify_tree(self): def test_modify_tree(self):
@@ -107,6 +109,7 @@ class TreeTest(utils.BareRepoTestCase):
self.assertRaises(TypeError, operator.setitem, 'c', tree['a']) self.assertRaises(TypeError, operator.setitem, 'c', tree['a'])
self.assertRaises(TypeError, operator.delitem, 'c') self.assertRaises(TypeError, operator.delitem, 'c')
def test_iterate_tree(self): def test_iterate_tree(self):
""" """
Testing that we're able to iterate of a Tree object and that the Testing that we're able to iterate of a Tree object and that the

View File

@@ -63,8 +63,11 @@ class TreeBuilderTest(utils.BareRepoTestCase):
def test_rebuild_treebuilder(self): def test_rebuild_treebuilder(self):
tree = self.repo[TREE_SHA] tree = self.repo[TREE_SHA]
bld = self.repo.TreeBuilder() bld = self.repo.TreeBuilder()
for e in tree: for entry in tree:
bld.insert(e.name, e.hex, e.filemode) name = entry.name
self.assertIsNone(bld.get(name))
bld.insert(name, entry.hex, entry.filemode)
self.assertEqual(bld.get(name).oid, entry.oid)
result = bld.write() result = bld.write()
self.assertEqual(len(bld), len(tree)) self.assertEqual(len(bld), len(tree))