Implement the References (part II)

This commit is contained in:
David Versmisse 2011-04-27 09:31:04 +02:00
parent aac4cf1b86
commit 858adab759
2 changed files with 208 additions and 28 deletions

163
pygit2.c

@ -500,26 +500,29 @@ Repository_create_tag(Repository *self, PyObject *args) {
} }
static PyObject * static PyObject *
Repository_listall_references(Repository *self, PyObject *args) Repository_listall_references(Repository *self, PyObject *args) {
{ unsigned list_flags=GIT_REF_LISTALL;
git_strarray c_result; git_strarray c_result;
PyObject *py_result, *py_string; PyObject *py_result, *py_string;
unsigned index; unsigned index;
int err; int err;
/* 1- Get the C result */ /* 1- Get list_flags */
/* TODO We can choose an other option (instead of GIT_REF_LISTALL) */ if (!PyArg_ParseTuple(args, "|I", &list_flags))
err = git_reference_listall (&c_result, self->repo, GIT_REF_LISTALL); return NULL;
/* 2- Get the C result */
err = git_reference_listall(&c_result, self->repo, list_flags);
if (err < 0) if (err < 0)
return Error_set(err); return Error_set(err);
/* 2- Create a new PyTuple */ /* 3- Create a new PyTuple */
if ( (py_result = PyTuple_New(c_result.count)) == NULL) { if ( (py_result = PyTuple_New(c_result.count)) == NULL) {
git_strarray_free(&c_result); git_strarray_free(&c_result);
return NULL; return NULL;
} }
/* 3- Fill it */ /* 4- Fill it */
for (index=0; index < c_result.count; index++) { for (index=0; index < c_result.count; index++) {
if ((py_string = PyString_FromString( (c_result.strings)[index] )) if ((py_string = PyString_FromString( (c_result.strings)[index] ))
== NULL) { == NULL) {
@ -530,16 +533,15 @@ Repository_listall_references(Repository *self, PyObject *args)
PyTuple_SET_ITEM(py_result, index, py_string); PyTuple_SET_ITEM(py_result, index, py_string);
} }
/* 4- Destroy the c_result */ /* 5- Destroy the c_result */
git_strarray_free(&c_result); git_strarray_free(&c_result);
/* 5- And return the py_result */ /* 6- And return the py_result */
return py_result; return py_result;
} }
static PyObject * static PyObject *
Repository_lookup_reference(Repository *self, PyObject *py_name) Repository_lookup_reference(Repository *self, PyObject *py_name) {
{
git_reference *c_reference; git_reference *c_reference;
char *c_name; char *c_name;
int err; int err;
@ -559,8 +561,7 @@ Repository_lookup_reference(Repository *self, PyObject *py_name)
} }
static PyObject * static PyObject *
Repository_create_reference(Repository *self, PyObject *args) Repository_create_reference(Repository *self, PyObject *args) {
{
git_reference *c_reference; git_reference *c_reference;
char *c_name; char *c_name;
git_oid oid; git_oid oid;
@ -580,6 +581,39 @@ Repository_create_reference(Repository *self, PyObject *args)
return wrap_reference(c_reference); return wrap_reference(c_reference);
} }
static PyObject *
Repository_create_symbolic_reference(Repository *self, PyObject *args) {
git_reference *c_reference;
char *c_name, *c_target;
int err;
/* 1- Get the C variables */
if (!PyArg_ParseTuple(args, "ss", &c_name, &c_target))
return NULL;
/* 2- Create the reference */
err = git_reference_create_symbolic(&c_reference, self->repo, c_name,
c_target);
if (err < 0)
return Error_set(err);
/* 3- Make an instance of Reference and return it */
return wrap_reference(c_reference);
}
static PyObject *
Repository_packall_references(Repository *self, PyObject *args) {
int err;
/* 1- Pack */
err = git_reference_packall(self->repo);
if (err < 0)
return Error_set(err);
/* 2- Return None */
Py_RETURN_NONE;
}
static PyMethodDef Repository_methods[] = { static PyMethodDef Repository_methods[] = {
{"create_commit", (PyCFunction)Repository_create_commit, METH_VARARGS, {"create_commit", (PyCFunction)Repository_create_commit, METH_VARARGS,
"Create a new commit object, return its SHA."}, "Create a new commit object, return its SHA."},
@ -590,7 +624,7 @@ static PyMethodDef Repository_methods[] = {
{"read", (PyCFunction)Repository_read, METH_O, {"read", (PyCFunction)Repository_read, METH_O,
"Read raw object data from the repository."}, "Read raw object data from the repository."},
{"listall_references", (PyCFunction)Repository_listall_references, {"listall_references", (PyCFunction)Repository_listall_references,
METH_NOARGS, METH_VARARGS,
"Return a list with all the references that can be found in a " "Return a list with all the references that can be found in a "
"repository."}, "repository."},
{"lookup_reference", (PyCFunction)Repository_lookup_reference, METH_O, {"lookup_reference", (PyCFunction)Repository_lookup_reference, METH_O,
@ -598,6 +632,12 @@ static PyMethodDef Repository_methods[] = {
{"create_reference", (PyCFunction)Repository_create_reference, METH_VARARGS, {"create_reference", (PyCFunction)Repository_create_reference, METH_VARARGS,
"Create a new reference \"name\" that points to the object given by its " "Create a new reference \"name\" that points to the object given by its "
"\"sha\"."}, "\"sha\"."},
{"create_symbolic_reference",
(PyCFunction)Repository_create_symbolic_reference, METH_VARARGS,
"Create a new symbolic reference \"name\" that points to the reference "
"\"target\"."},
{"packall_references", (PyCFunction)Repository_packall_references,
METH_NOARGS, "Pack all the loose references in the repository."},
{NULL} {NULL}
}; };
@ -1817,8 +1857,42 @@ static PyTypeObject WalkerType = {
}; };
static PyObject * static PyObject *
Reference_resolve(Reference *self, PyObject *args) Reference_delete(Reference *self, PyObject *args) {
{ int err;
/* 1- Delete the reference */
err = git_reference_delete(self->reference);
if (err < 0)
return Error_set(err);
/* 2- Invalidate the pointer */
self->reference = NULL;
/* 3- Return None */
Py_RETURN_NONE;
}
static PyObject *
Reference_rename(Reference *self, PyObject *py_name) {
char *c_name;
int err;
/* 1- Get the C name */
c_name = PyString_AsString(py_name);
if (c_name == NULL)
return NULL;
/* 2- Rename */
err = git_reference_rename(self->reference, c_name);
if (err < 0)
return Error_set(err);
/* 3- Return None */
Py_RETURN_NONE;
}
static PyObject *
Reference_resolve(Reference *self, PyObject *args) {
git_reference *c_reference; git_reference *c_reference;
int err; int err;
@ -1832,8 +1906,7 @@ Reference_resolve(Reference *self, PyObject *args)
} }
static PyObject * static PyObject *
Reference_get_target(Reference *self, PyObject *args) Reference_get_target(Reference *self) {
{
const char * c_name; const char * c_name;
/* 1- Get the target */ /* 1- Get the target */
@ -1847,6 +1920,27 @@ Reference_get_target(Reference *self, PyObject *args)
return PyString_FromString(c_name); return PyString_FromString(c_name);
} }
static int
Reference_set_target(Reference *self, PyObject *py_name) {
char *c_name;
int err;
/* 1- Get the C name */
c_name = PyString_AsString(py_name);
if (c_name == NULL)
return -1;
/* 2- Set the new target */
err = git_reference_set_target(self->reference, c_name);
if (err < 0) {
Error_set(err);
return -1;
}
/* 3- All OK */
return 0;
}
static PyObject * static PyObject *
Reference_get_name(Reference *self) { Reference_get_name(Reference *self) {
const char *c_name; const char *c_name;
@ -1874,6 +1968,26 @@ Reference_get_sha(Reference *self) {
return PyString_FromStringAndSize(hex, GIT_OID_HEXSZ); return PyString_FromStringAndSize(hex, GIT_OID_HEXSZ);
} }
static int
Reference_set_sha(Reference *self, PyObject *py_sha) {
git_oid oid;
int err;
/* 1- Get the oid from the py_sha */
if (!py_str_to_git_oid(py_sha, &oid))
return -1;
/* 2- Set the oid */
err = git_reference_set_oid (self->reference, &oid);
if (err < 0) {
Error_set(err);
return -1;
}
/* 3- All OK */
return 0;
}
static PyObject * static PyObject *
Reference_get_type(Reference *self) { Reference_get_type(Reference *self) {
git_rtype c_type; git_rtype c_type;
@ -1883,17 +1997,22 @@ Reference_get_type(Reference *self) {
} }
static PyMethodDef Reference_methods[] = { static PyMethodDef Reference_methods[] = {
{"delete", (PyCFunction)Reference_delete, METH_NOARGS,
"Delete this reference. It will no longer be valid!"},
{"rename", (PyCFunction)Reference_rename, METH_O,
"Rename the reference."},
{"resolve", (PyCFunction)Reference_resolve, METH_NOARGS, {"resolve", (PyCFunction)Reference_resolve, METH_NOARGS,
"Resolve a symbolic reference and return a direct reference"}, "Resolve a symbolic reference and return a direct reference."},
{"get_target", (PyCFunction)Reference_get_target, METH_NOARGS,
"Get full name to the reference pointed by this symbolic reference."},
{NULL} {NULL}
}; };
static PyGetSetDef Reference_getseters[] = { static PyGetSetDef Reference_getseters[] = {
{"name", (getter)Reference_get_name, NULL, {"name", (getter)Reference_get_name, NULL,
"The full name of a reference.", NULL}, "The full name of a reference.", NULL},
{"sha", (getter)Reference_get_sha, NULL, "hex SHA", NULL}, {"sha", (getter)Reference_get_sha, (setter)Reference_set_sha, "hex SHA",
NULL},
{"target", (getter)Reference_get_target, (setter)Reference_set_target,
"target", NULL},
{"type", (getter)Reference_get_type, NULL, {"type", (getter)Reference_get_type, NULL,
"type (GIT_REF_OID, GIT_REF_SYMBOLIC or GIT_REF_PACKED).", NULL}, "type (GIT_REF_OID, GIT_REF_SYMBOLIC or GIT_REF_PACKED).", NULL},
{NULL} {NULL}

@ -33,7 +33,7 @@ __author__ = 'david.versmisse@itaapy.com (David Versmisse)'
import unittest import unittest
import utils import utils
from pygit2 import GIT_REF_OID from pygit2 import GIT_REF_OID, GIT_REF_SYMBOLIC
@ -44,9 +44,23 @@ LAST_COMMIT = '2be5719152d4f82c7302b1c0932d8e5f0a4a0e98'
class ReferencesTest(utils.RepoTestCase): class ReferencesTest(utils.RepoTestCase):
def test_list_all_references(self): def test_list_all_references(self):
self.assertEqual(self.repo.listall_references(), repo = self.repo
# Without argument
self.assertEqual(repo.listall_references(),
('refs/heads/i18n', 'refs/heads/master')) ('refs/heads/i18n', 'refs/heads/master'))
# We add a symbolic reference
reference = repo.create_symbolic_reference('refs/tags/version1',
'refs/heads/master')
self.assertEqual(repo.listall_references(),
('refs/heads/i18n', 'refs/heads/master',
'refs/tags/version1'))
# Now we list only the symbolic references
self.assertEqual(repo.listall_references(GIT_REF_SYMBOLIC),
('refs/tags/version1', ))
def test_lookup_reference(self): def test_lookup_reference(self):
repo = self.repo repo = self.repo
@ -64,19 +78,54 @@ class ReferencesTest(utils.RepoTestCase):
self.assertEqual(reference.sha, LAST_COMMIT) self.assertEqual(reference.sha, LAST_COMMIT)
def test_reference_set_sha(self):
NEW_COMMIT = '5ebeeebb320790caf276b9fc8b24546d63316533'
reference = self.repo.lookup_reference('refs/heads/master')
reference.sha = NEW_COMMIT
self.assertEqual(reference.sha, NEW_COMMIT)
def test_reference_get_type(self): def test_reference_get_type(self):
reference = self.repo.lookup_reference('refs/heads/master') reference = self.repo.lookup_reference('refs/heads/master')
self.assertEqual(reference.type, GIT_REF_OID) self.assertEqual(reference.type, GIT_REF_OID)
def test_get_target(self): def test_get_target(self):
# XXX We must have a symbolic reference to make this test reference = self.repo.lookup_reference('HEAD')
pass self.assertEqual(reference.target, 'refs/heads/master')
def test_set_target(self):
reference = self.repo.lookup_reference('HEAD')
self.assertEqual(reference.target, 'refs/heads/master')
reference.target = 'refs/heads/i18n'
self.assertEqual(reference.target, 'refs/heads/i18n')
def test_delete(self):
repo = self.repo
# We add a tag as a new reference that points to "origin/master"
reference = repo.create_reference('refs/tags/version1', LAST_COMMIT)
self.assertTrue('refs/tags/version1' in repo.listall_references())
# And we delete it
reference.delete()
self.assertFalse('refs/tags/version1' in repo.listall_references())
def test_rename(self):
# We add a tag as a new reference that points to "origin/master"
reference = self.repo.create_reference('refs/tags/version1',
LAST_COMMIT)
self.assertEqual(reference.name, 'refs/tags/version1')
reference.rename('refs/tags/version2')
self.assertEqual(reference.name, 'refs/tags/version2')
def test_reference_resolve(self): def test_reference_resolve(self):
# XXX We must have a symbolic reference to make a better test reference = self.repo.lookup_reference('HEAD')
reference = self.repo.lookup_reference('refs/heads/master') self.assertEqual(reference.type, GIT_REF_SYMBOLIC)
reference = reference.resolve() reference = reference.resolve()
self.assertEqual(reference.type, GIT_REF_OID) self.assertEqual(reference.type, GIT_REF_OID)
self.assertEqual(reference.sha, LAST_COMMIT) self.assertEqual(reference.sha, LAST_COMMIT)
@ -92,6 +141,18 @@ class ReferencesTest(utils.RepoTestCase):
self.assertEqual(reference.sha, LAST_COMMIT) self.assertEqual(reference.sha, LAST_COMMIT)
def test_create_symbolic_reference(self):
# We add a tag as a new symbolic reference that always points to
# "refs/heads/master"
reference = self.repo.create_symbolic_reference('refs/tags/beta',
'refs/heads/master')
self.assertEqual(reference.type, GIT_REF_SYMBOLIC)
self.assertEqual(reference.target, 'refs/heads/master')
def test_packall_references(self):
self.repo.packall_references()
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()