diff --git a/pygit2.c b/pygit2.c index d52a331..4896cd8 100644 --- a/pygit2.c +++ b/pygit2.c @@ -36,8 +36,8 @@ typedef struct { PyObject *index; /* It will be None for a bare repository */ } Repository; -/* The structs for some of the object subtypes are identical except for the type - * of their object pointers. */ +/* The structs for some of the object subtypes are identical except for the + * type of their object pointers. */ #define OBJECT_STRUCT(_name, _ptr_type, _ptr_name) \ typedef struct {\ PyObject_HEAD\ @@ -583,14 +583,27 @@ signature_converter(PyObject *value, git_signature **out) { return 1; } +static int +free_parents(git_oid **parents, int n) { + int i; + + for (i = 0; i < n; i++) + free(parents[i]); + free(parents); + return -1; +} + static int Commit_init(Commit *py_commit, PyObject *args, PyObject *kwds) { Repository *repo = NULL; git_signature *author, *committer; char *message; git_oid tree_oid, oid; + PyObject *py_parents, *py_parent; + int parent_count; + git_oid **parents; git_commit *commit; - int err; + int err, i; if (kwds) { PyErr_Format(PyExc_TypeError, "%s takes no keyword arugments", @@ -598,26 +611,45 @@ Commit_init(Commit *py_commit, PyObject *args, PyObject *kwds) { return -1; } - /* TODO Support parents */ - if (!PyArg_ParseTuple(args, "O!O&O&sO&", &RepositoryType, &repo, + if (!PyArg_ParseTuple(args, "O!O&O&sO&O!", &RepositoryType, &repo, signature_converter, &author, signature_converter, &committer, &message, - py_str_to_git_oid, &tree_oid)) + py_str_to_git_oid, &tree_oid, + &PyList_Type, &py_parents)) return -1; - err = git_commit_create(&oid, repo->repo, NULL, - author, committer, message, &tree_oid, 0, NULL); - if (err < 0) + parent_count = (int)PyList_Size(py_parents); + parents = malloc(parent_count * sizeof(git_oid*)); + if (parents == NULL) { + PyErr_SetNone(PyExc_MemoryError); return -1; + } + for (i = 0; i < parent_count; i++) { + parents[i] = malloc(sizeof(git_oid)); + if (parents[i] == NULL) { + PyErr_SetNone(PyExc_MemoryError); + return free_parents(parents, i); + } + py_parent = PyList_GET_ITEM(py_parents, i); + if (!py_str_to_git_oid(py_parent, parents[i])) + return free_parents(parents, i); + } + + err = git_commit_create(&oid, repo->repo, NULL, + author, committer, message, &tree_oid, + parent_count, (const git_oid**)parents); + if (err < 0) + return free_parents(parents, parent_count); err = git_commit_lookup(&commit, repo->repo, &oid); if (err < 0) - return -1; + return free_parents(parents, parent_count); Py_INCREF(repo); py_commit->repo = repo; py_commit->commit = commit; + free_parents(parents, parent_count); return 0; } diff --git a/test/test_commit.py b/test/test_commit.py index 611cc8a..74a4220 100644 --- a/test/test_commit.py +++ b/test/test_commit.py @@ -31,7 +31,7 @@ __author__ = 'dborowitz@google.com (Dave Borowitz)' import unittest -import pygit2 +from pygit2 import Commit, GIT_OBJ_COMMIT import utils COMMIT_SHA = '5fe808e8953c12735680c257f56600cb0de44b10' @@ -64,24 +64,20 @@ class CommitTest(utils.BareRepoTestCase): message = 'New commit.\n\nMessage.\n' committer = ('John Doe', 'jdoe@example.com', 12346) author = ('Jane Doe', 'jdoe2@example.com', 12345) + tree = '967fce8df97cc71722d3c2a5930ef3e6f1d27b12' - commit = pygit2.Commit(self.repo) - commit.message = message - commit.committer = committer - commit.author = author + parents = [COMMIT_SHA] + commit = Commit(self.repo, author, committer, message, tree, parents) - self.assertEqual(0, len(commit.parents)) - - commit.add_parent(COMMIT_SHA) - - self.assertEqual(None, commit.sha) - self.assertEqual(pygit2.GIT_OBJ_COMMIT, commit.type) + self.assertEqual(GIT_OBJ_COMMIT, commit.type) + self.assertEqual('30bb126a4959290987fc07ea49f92be276dce9d6', + commit.sha) self.assertEqual(message, commit.message) self.assertEqual('New commit.', commit.message_short) self.assertEqual(12346, commit.commit_time) self.assertEqual(committer, commit.committer) self.assertEqual(author, commit.author) - self.assertEqual(None, commit.tree) + self.assertEqual(tree, commit.tree.sha) self.assertEqual(1, len(commit.parents)) self.assertEqual(COMMIT_SHA, commit.parents[0].sha) @@ -91,15 +87,12 @@ class CommitTest(utils.BareRepoTestCase): author = ('Jane Doe', 'jdoe2@example.com', 12345) commit = self.repo[COMMIT_SHA] - commit.message = message - commit.committer = committer - commit.author = author - - self.assertEqual(message, commit.message) - self.assertEqual('New commit.', commit.message_short) - self.assertEqual(12346, commit.commit_time) - self.assertEqual(committer, commit.committer) - self.assertEqual(author, commit.author) + self.assertRaises(AttributeError, setattr, commit, 'message', message) + self.assertRaises(AttributeError, setattr, commit, 'committer', + committer) + self.assertRaises(AttributeError, setattr, commit, 'author', author) + self.assertRaises(AttributeError, setattr, commit, 'tree', None) + self.assertRaises(AttributeError, setattr, commit, 'parents', None) if __name__ == '__main__':