diff --git a/README.rst b/README.rst index 081972f..cf095a4 100644 --- a/README.rst +++ b/README.rst @@ -199,7 +199,7 @@ This is the interface of a tree entry:: TreeEntry.name -- name of the tree entry TreeEntry.oid -- the id of the git object TreeEntry.hex -- hexadecimal representation of the oid - TreeEntry.attributes -- the Unix file attributes + TreeEntry.filemode -- the Unix file attributes TreeEntry.to_object() -- returns the git object (equivalent to repo[entry.oid]) @@ -269,6 +269,12 @@ The interface for RefLogEntry:: RefLogEntry.oid_old -- oid of old reference RefLogEntry.oid_new -- oid of new reference +Revision parsing +================ + +You can use any of the fancy `<rev>` forms supported by libgit2:: + + >>> commit = repo.revparse_single('HEAD^') Revision walking ================= diff --git a/include/pygit2/object.h b/include/pygit2/object.h index 5255996..64bf612 100644 --- a/include/pygit2/object.h +++ b/include/pygit2/object.h @@ -37,5 +37,6 @@ PyObject* Object_get_oid(Object *self); PyObject* Object_get_hex(Object *self); PyObject* Object_get_type(Object *self); PyObject* Object_read_raw(Object *self); +PyObject* wrap_object(git_object *c_object, Repository *repo); #endif diff --git a/include/pygit2/tree.h b/include/pygit2/tree.h index e4b086f..68218f7 100644 --- a/include/pygit2/tree.h +++ b/include/pygit2/tree.h @@ -33,7 +33,7 @@ #include <git2.h> #include <pygit2/types.h> -PyObject* TreeEntry_get_attributes(TreeEntry *self); +PyObject* TreeEntry_get_filemode(TreeEntry *self); PyObject* TreeEntry_get_name(TreeEntry *self); PyObject* TreeEntry_get_oid(TreeEntry *self); PyObject* TreeEntry_get_hex(TreeEntry *self); diff --git a/src/pygit2/object.c b/src/pygit2/object.c index 12a0855..172cf3f 100644 --- a/src/pygit2/object.c +++ b/src/pygit2/object.c @@ -34,6 +34,12 @@ #include <pygit2/repository.h> #include <pygit2/object.h> +extern PyTypeObject TreeType; +extern PyTypeObject CommitType; +extern PyTypeObject BlobType; +extern PyTypeObject TagType; + + void Object_dealloc(Object* self) { @@ -145,3 +151,35 @@ PyTypeObject ObjectType = { 0, /* tp_alloc */ 0, /* tp_new */ }; + +PyObject * +wrap_object(git_object *c_object, Repository *repo) +{ + Object *py_obj = NULL; + + switch (git_object_type(c_object)) { + case GIT_OBJ_COMMIT: + py_obj = PyObject_New(Object, &CommitType); + break; + case GIT_OBJ_TREE: + py_obj = PyObject_New(Object, &TreeType); + break; + case GIT_OBJ_BLOB: + py_obj = PyObject_New(Object, &BlobType); + break; + case GIT_OBJ_TAG: + py_obj = PyObject_New(Object, &TagType); + break; + default: + assert(0); + } + + if (py_obj) { + py_obj->obj = c_object; + if (repo) { + py_obj->repo = repo; + Py_INCREF(repo); + } + } + return (PyObject *)py_obj; +} diff --git a/src/pygit2/repository.c b/src/pygit2/repository.c index 7650388..8ba3704 100644 --- a/src/pygit2/repository.c +++ b/src/pygit2/repository.c @@ -31,6 +31,7 @@ #include <pygit2/types.h> #include <pygit2/reference.h> #include <pygit2/utils.h> +#include <pygit2/object.h> #include <pygit2/oid.h> #include <pygit2/repository.h> @@ -40,9 +41,6 @@ extern PyTypeObject IndexType; extern PyTypeObject WalkerType; extern PyTypeObject SignatureType; extern PyTypeObject TreeType; -extern PyTypeObject CommitType; -extern PyTypeObject BlobType; -extern PyTypeObject TagType; extern PyTypeObject TreeBuilderType; extern PyTypeObject ConfigType; extern PyTypeObject DiffType; @@ -72,29 +70,7 @@ lookup_object_prefix(Repository *repo, const git_oid *oid, size_t len, if (err < 0) return Error_set_oid(err, oid, len); - switch (git_object_type(obj)) { - case GIT_OBJ_COMMIT: - py_obj = PyObject_New(Object, &CommitType); - break; - case GIT_OBJ_TREE: - py_obj = PyObject_New(Object, &TreeType); - break; - case GIT_OBJ_BLOB: - py_obj = PyObject_New(Object, &BlobType); - break; - case GIT_OBJ_TAG: - py_obj = PyObject_New(Object, &TagType); - break; - default: - assert(0); - } - - if (py_obj) { - py_obj->obj = obj; - py_obj->repo = repo; - Py_INCREF(repo); - } - return (PyObject*)py_obj; + return wrap_object(obj, repo); } PyObject * @@ -222,6 +198,30 @@ Repository_getitem(Repository *self, PyObject *value) return lookup_object_prefix(self, &oid, len, GIT_OBJ_ANY); } +PyObject * +Repository_revparse_single(Repository *self, PyObject *py_spec) +{ + git_object *c_obj; + char *c_spec; + char *encoding = "ascii"; + int err; + + /* 1- Get the C revision spec */ + c_spec = py_str_to_c_str(py_spec, encoding); + if (c_spec == NULL) + return NULL; + + /* 2- Lookup */ + err = git_revparse_single(&c_obj, self->repo, c_spec); + if (err < 0) { + PyObject *err_obj = Error_set_str(err, c_spec); + free(c_spec); + return err_obj; + } + + return wrap_object(c_obj, self); +} + git_odb_object * Repository_read_raw(git_repository *repo, const git_oid *oid, size_t len) { @@ -816,6 +816,10 @@ PyMethodDef Repository_methods[] = { "Return a list with all the references in the repository."}, {"lookup_reference", (PyCFunction)Repository_lookup_reference, METH_O, "Lookup a reference by its name in a repository."}, + {"revparse_single", (PyCFunction)Repository_revparse_single, METH_O, + "Find an object, as specified by a revision string. See " + "`man gitrevisions`, or the documentation for `git rev-parse` for " + "information on the syntax accepted."}, {"create_blob", (PyCFunction)Repository_create_blob, METH_VARARGS, "Create a new blob from memory"}, diff --git a/src/pygit2/tree.c b/src/pygit2/tree.c index e81dc3c..76cefcb 100644 --- a/src/pygit2/tree.c +++ b/src/pygit2/tree.c @@ -47,7 +47,7 @@ TreeEntry_dealloc(TreeEntry *self) } PyObject * -TreeEntry_get_attributes(TreeEntry *self) +TreeEntry_get_filemode(TreeEntry *self) { return PyInt_FromLong(git_tree_entry_filemode(self->entry)); } @@ -85,7 +85,7 @@ TreeEntry_to_object(TreeEntry *self) } PyGetSetDef TreeEntry_getseters[] = { - {"attributes", (getter)TreeEntry_get_attributes, NULL, "attributes", NULL}, + {"filemode", (getter)TreeEntry_get_filemode, NULL, "filemode", NULL}, {"name", (getter)TreeEntry_get_name, NULL, "name", NULL}, {"oid", (getter)TreeEntry_get_oid, NULL, "object id", NULL}, {"hex", (getter)TreeEntry_get_hex, NULL, "hex oid", NULL}, diff --git a/test/test_diff.py b/test/test_diff.py index 7133bb0..5f61b09 100644 --- a/test/test_diff.py +++ b/test/test_diff.py @@ -123,9 +123,9 @@ class DiffTest(utils.BareRepoTestCase): hunk = diff.changes['hunks'][0] self.assertEqual(hunk.old_start, 1) - self.assertEqual(hunk.old_lines, 0) + self.assertEqual(hunk.old_lines, 1) self.assertEqual(hunk.new_start, 1) - self.assertEqual(hunk.new_lines, 0) + self.assertEqual(hunk.new_lines, 1) self.assertEqual(hunk.old_file, 'a') self.assertEqual(hunk.new_file, 'a') @@ -157,9 +157,9 @@ class DiffTest(utils.BareRepoTestCase): hunk = diff_b.changes['hunks'][1] self.assertEqual(hunk.old_start, 1) - self.assertEqual(hunk.old_lines, 0) + self.assertEqual(hunk.old_lines, 1) self.assertEqual(hunk.new_start, 1) - self.assertEqual(hunk.new_lines, 0) + self.assertEqual(hunk.new_lines, 1) self.assertEqual(hunk.old_file, 'b') self.assertEqual(hunk.new_file, 'b') diff --git a/test/test_repository.py b/test/test_repository.py index bdb4c1a..fa3a932 100644 --- a/test/test_repository.py +++ b/test/test_repository.py @@ -40,6 +40,7 @@ from . import utils HEAD_SHA = '2cdae28389c059815e951d0bb9eed6533f61a46b' +PARENT_SHA = '5fe808e8953c12735680c257f56600cb0de44b10' # HEAD^ A_HEX_SHA = 'af431f20fc541ed6d5afede3e2dc7160f6f01f16' A_BIN_SHA = binascii.unhexlify(A_HEX_SHA.encode('ascii')) @@ -127,6 +128,9 @@ class RepositoryTest(utils.BareRepoTestCase): def test_get_workdir(self): self.assertEqual(self.repo.workdir, None) + def test_revparse_single(self): + parent = self.repo.revparse_single('HEAD^') + self.assertEqual(parent.hex, PARENT_SHA) class RepositoryTest_II(utils.RepoTestCase): diff --git a/test/test_tree.py b/test/test_tree.py index 44e85c6..a88d0d1 100644 --- a/test/test_tree.py +++ b/test/test_tree.py @@ -42,11 +42,11 @@ SUBTREE_SHA = '614fd9a3094bf618ea938fffc00e7d1a54f89ad0' class TreeTest(utils.BareRepoTestCase): - def assertTreeEntryEqual(self, entry, sha, name, attributes): + def assertTreeEntryEqual(self, entry, sha, name, filemode): self.assertEqual(entry.hex, sha) self.assertEqual(entry.name, name) - self.assertEqual(entry.attributes, attributes, - '0%o != 0%o' % (entry.attributes, attributes)) + self.assertEqual(entry.filemode, filemode, + '0%o != 0%o' % (entry.filemode, filemode)) def test_read_tree(self): tree = self.repo[TREE_SHA] diff --git a/test/test_treebuilder.py b/test/test_treebuilder.py index 8dbea77..de6e85d 100644 --- a/test/test_treebuilder.py +++ b/test/test_treebuilder.py @@ -57,7 +57,7 @@ class TreeBuilderTest(utils.BareRepoTestCase): tree = self.repo[TREE_SHA] bld = self.repo.TreeBuilder() for e in tree: - bld.insert(e.name, e.hex, e.attributes) + bld.insert(e.name, e.hex, e.filemode) result = bld.write() self.assertEqual(tree.oid, result)