diff --git a/include/pygit2/repository.h b/include/pygit2/repository.h index 32780e0..0f6616a 100644 --- a/include/pygit2/repository.h +++ b/include/pygit2/repository.h @@ -55,8 +55,7 @@ PyObject* Repository_create_commit(Repository *self, PyObject *args); PyObject* Repository_create_tag(Repository *self, PyObject *args); PyObject* Repository_listall_references(Repository *self, PyObject *args); PyObject* Repository_lookup_reference(Repository *self, PyObject *py_name); -PyObject* Repository_create_reference(Repository *self, PyObject *args); -PyObject* Repository_create_symbolic_reference(Repository *self, PyObject *args); +PyObject* Repository_create_reference(Repository *self, PyObject *args, PyObject* keywds); PyObject* Repository_packall_references(Repository *self, PyObject *args); PyObject* Repository_status(Repository *self, PyObject *args); PyObject* Repository_status_file(Repository *self, PyObject *value); diff --git a/src/pygit2/repository.c b/src/pygit2/repository.c index 8ba3704..3f31805 100644 --- a/src/pygit2/repository.c +++ b/src/pygit2/repository.c @@ -641,53 +641,60 @@ Repository_lookup_reference(Repository *self, PyObject *py_name) return wrap_reference(c_reference); } -PyObject * -Repository_create_reference(Repository *self, PyObject *args) -{ - PyObject *py_oid; - git_reference *c_reference; - char *c_name; - git_oid oid; - int err; - - /* 1- Get the C variables */ - if (!PyArg_ParseTuple(args, "sO", &c_name, &py_oid)) - return NULL; - - err = py_str_to_git_oid_expand(self->repo, py_oid, &oid); - if (err < 0) - return Error_set(err); - - /* 2- Create the reference */ - err = git_reference_create_oid(&c_reference, self->repo, c_name, &oid, 0); - if (err < 0) - return Error_set(err); - - /* 3- Make an instance of Reference and return it */ - return wrap_reference(c_reference); -} +PyDoc_STRVAR( + Repository_create_reference_doc, + "Create a new reference \"name\" which points to a object or another reference\n\n" + "Arguments: (name, source, force=False, symbolic=False)\n\n" + "With force=True references will be overridden. Otherwise an exception is raised" + "You can create either a normal reference or a symbolic one:\n" + " * normal reference: source has to be a valid sha hash\n" + " * symbolic reference: source has to be a valid existing reference name\n\n" + "Examples:\n" + " repo.create_reference('refs/heads/foo', repo.head.hex)\n" + " repo.create_reference('refs/tags/foo', 'refs/heads/master', symbolic = True)\n" +); PyObject * -Repository_create_symbolic_reference(Repository *self, PyObject *args) +Repository_create_reference(Repository *self, PyObject *args, PyObject* keywds) { + PyObject *py_obj; git_reference *c_reference; char *c_name, *c_target; - int err; + git_oid oid; + int err, symbolic = 0, force = 0; - /* 1- Get the C variables */ - if (!PyArg_ParseTuple(args, "ss", &c_name, &c_target)) + static char *kwlist[] = {"name", "source", "force", "symbolic", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, keywds, "sO|ii", kwlist, + &c_name, &py_obj, &force, &symbolic)) return NULL; - /* 2- Create the reference */ - err = git_reference_create_symbolic(&c_reference, self->repo, c_name, - c_target, 0); + if(symbolic) { + #if PY_MAJOR_VERSION == 2 + c_target = PyString_AsString(py_obj); + #else + c_target = PyString_AsString(PyUnicode_AsASCIIString(py_obj)); + #endif + if(c_target == NULL) + return NULL; + + err = git_reference_create_symbolic(&c_reference, self->repo, c_name, + c_target, force); + } else { + err = py_str_to_git_oid_expand(self->repo, py_obj, &oid); + if (err < 0) + return Error_set(err); + + err = git_reference_create_oid(&c_reference, self->repo, c_name, &oid, force); + } + if (err < 0) return Error_set(err); - /* 3- Make an instance of Reference and return it */ return wrap_reference(c_reference); } + PyObject * Repository_packall_references(Repository *self, PyObject *args) { @@ -827,13 +834,8 @@ PyMethodDef Repository_methods[] = { METH_VARARGS, "Create a new blob from file"}, {"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\n" - "\"target\"."}, + METH_VARARGS|METH_KEYWORDS, + Repository_create_reference_doc}, {"packall_references", (PyCFunction)Repository_packall_references, METH_NOARGS, "Pack all the loose references in the repository."}, {"status", (PyCFunction)Repository_status, METH_NOARGS, "Reads the " diff --git a/test/test_refs.py b/test/test_refs.py index ec4b5cc..56e918b 100644 --- a/test/test_refs.py +++ b/test/test_refs.py @@ -49,8 +49,7 @@ class ReferencesTest(utils.RepoTestCase): ['refs/heads/i18n', 'refs/heads/master']) # We add a symbolic reference - repo.create_symbolic_reference('refs/tags/version1', - 'refs/heads/master') + repo.create_reference('refs/tags/version1','refs/heads/master', symbolic=True) self.assertEqual(sorted(repo.listall_references()), ['refs/heads/i18n', 'refs/heads/master', 'refs/tags/version1']) @@ -145,7 +144,7 @@ class ReferencesTest(utils.RepoTestCase): def test_reload(self): name = 'refs/tags/version1' - ref = self.repo.create_symbolic_reference(name, "refs/heads/master") + ref = self.repo.create_reference(name, "refs/heads/master", symbolic=True) ref2 = self.repo.lookup_reference(name) ref.delete() self.assertEqual(ref2.name, name) @@ -176,12 +175,27 @@ class ReferencesTest(utils.RepoTestCase): reference = self.repo.lookup_reference('refs/tags/version1') self.assertEqual(reference.hex, LAST_COMMIT) + self.assertRaises(GitError, self.repo.create_reference, + 'refs/tags/version1', LAST_COMMIT) + + reference = self.repo.create_reference('refs/tags/version1', + LAST_COMMIT, force=True) + self.assertEqual(reference.hex, 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') + reference = self.repo.create_reference('refs/tags/beta', + 'refs/heads/master', symbolic=True) + self.assertEqual(reference.type, GIT_REF_SYMBOLIC) + self.assertEqual(reference.target, 'refs/heads/master') + + self.assertRaises(GitError, self.repo.create_reference, + 'refs/tags/beta','refs/heads/master', symbolic=True) + + reference = self.repo.create_reference('refs/tags/beta', + 'refs/heads/master', force=True, symbolic=True) self.assertEqual(reference.type, GIT_REF_SYMBOLIC) self.assertEqual(reference.target, 'refs/heads/master')