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 *
Repository_listall_references(Repository *self, PyObject *args)
{
Repository_listall_references(Repository *self, PyObject *args) {
unsigned list_flags=GIT_REF_LISTALL;
git_strarray c_result;
PyObject *py_result, *py_string;
unsigned index;
int err;
/* 1- Get the C result */
/* TODO We can choose an other option (instead of GIT_REF_LISTALL) */
err = git_reference_listall (&c_result, self->repo, GIT_REF_LISTALL);
/* 1- Get list_flags */
if (!PyArg_ParseTuple(args, "|I", &list_flags))
return NULL;
/* 2- Get the C result */
err = git_reference_listall(&c_result, self->repo, list_flags);
if (err < 0)
return Error_set(err);
/* 2- Create a new PyTuple */
/* 3- Create a new PyTuple */
if ( (py_result = PyTuple_New(c_result.count)) == NULL) {
git_strarray_free(&c_result);
return NULL;
}
/* 3- Fill it */
/* 4- Fill it */
for (index=0; index < c_result.count; index++) {
if ((py_string = PyString_FromString( (c_result.strings)[index] ))
== NULL) {
@ -530,16 +533,15 @@ Repository_listall_references(Repository *self, PyObject *args)
PyTuple_SET_ITEM(py_result, index, py_string);
}
/* 4- Destroy the c_result */
/* 5- Destroy the c_result */
git_strarray_free(&c_result);
/* 5- And return the py_result */
/* 6- And return the py_result */
return py_result;
}
static PyObject *
Repository_lookup_reference(Repository *self, PyObject *py_name)
{
Repository_lookup_reference(Repository *self, PyObject *py_name) {
git_reference *c_reference;
char *c_name;
int err;
@ -559,8 +561,7 @@ Repository_lookup_reference(Repository *self, PyObject *py_name)
}
static PyObject *
Repository_create_reference(Repository *self, PyObject *args)
{
Repository_create_reference(Repository *self, PyObject *args) {
git_reference *c_reference;
char *c_name;
git_oid oid;
@ -580,6 +581,39 @@ Repository_create_reference(Repository *self, PyObject *args)
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[] = {
{"create_commit", (PyCFunction)Repository_create_commit, METH_VARARGS,
"Create a new commit object, return its SHA."},
@ -590,7 +624,7 @@ static PyMethodDef Repository_methods[] = {
{"read", (PyCFunction)Repository_read, METH_O,
"Read raw object data from the repository."},
{"listall_references", (PyCFunction)Repository_listall_references,
METH_NOARGS,
METH_VARARGS,
"Return a list with all the references that can be found in a "
"repository."},
{"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 a new reference \"name\" that points to the object given by its "
"\"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}
};
@ -1817,8 +1857,42 @@ static PyTypeObject WalkerType = {
};
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;
int err;
@ -1832,8 +1906,7 @@ Reference_resolve(Reference *self, PyObject *args)
}
static PyObject *
Reference_get_target(Reference *self, PyObject *args)
{
Reference_get_target(Reference *self) {
const char * c_name;
/* 1- Get the target */
@ -1847,6 +1920,27 @@ Reference_get_target(Reference *self, PyObject *args)
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 *
Reference_get_name(Reference *self) {
const char *c_name;
@ -1874,6 +1968,26 @@ Reference_get_sha(Reference *self) {
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 *
Reference_get_type(Reference *self) {
git_rtype c_type;
@ -1883,17 +1997,22 @@ Reference_get_type(Reference *self) {
}
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 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."},
"Resolve a symbolic reference and return a direct reference."},
{NULL}
};
static PyGetSetDef Reference_getseters[] = {
{"name", (getter)Reference_get_name, 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 (GIT_REF_OID, GIT_REF_SYMBOLIC or GIT_REF_PACKED).", NULL},
{NULL}

@ -33,7 +33,7 @@ __author__ = 'david.versmisse@itaapy.com (David Versmisse)'
import unittest
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):
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'))
# 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):
repo = self.repo
@ -64,19 +78,54 @@ class ReferencesTest(utils.RepoTestCase):
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):
reference = self.repo.lookup_reference('refs/heads/master')
self.assertEqual(reference.type, GIT_REF_OID)
def test_get_target(self):
# XXX We must have a symbolic reference to make this test
pass
reference = self.repo.lookup_reference('HEAD')
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):
# XXX We must have a symbolic reference to make a better test
reference = self.repo.lookup_reference('refs/heads/master')
reference = self.repo.lookup_reference('HEAD')
self.assertEqual(reference.type, GIT_REF_SYMBOLIC)
reference = reference.resolve()
self.assertEqual(reference.type, GIT_REF_OID)
self.assertEqual(reference.sha, LAST_COMMIT)
@ -92,6 +141,18 @@ class ReferencesTest(utils.RepoTestCase):
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__':
unittest.main()