Supporting clone in pygit2

This commit is contained in:
Bernardo Heynemann
2013-05-15 18:15:00 -03:00
parent 8c69751d4f
commit 3dd998c061
3 changed files with 116 additions and 1 deletions

View File

@@ -47,3 +47,22 @@ def init_repository(path, bare=False):
"""
_pygit2.init_repository(path, bare)
return Repository(path)
def clone_repository(
url, path, bare=False, remote_name="origin", push_url=None, fetch_spec=None,
push_spec=None, checkout_branch=None):
"""
Clones a new Git repository from *url* in the given *path*.
Parameters:
* If 'bare' is True, then a bare git repository will be created.
* 'remote_name' is the name given to the "origin" remote. The default is "origin".
* 'push_url' is a URL to be used for pushing. None means use the fetch url.
* 'fetch_spec' is the fetch specification to be used for fetching. None results in the same behavior as GIT_REMOTE_DEFAULT_FETCH.
* 'push_spec' is the fetch specification to be used for pushing. None means use the same spec as for 'fetch_spec'.
* 'checkout_branch' gives the name of the branch to checkout. None means use the remote's HEAD
"""
_pygit2.clone_repository(url, path, bare, remote_name, push_url, fetch_spec, push_spec, checkout_branch)
return Repository(path)

View File

@@ -97,6 +97,61 @@ init_repository(PyObject *self, PyObject *args) {
Py_RETURN_NONE;
};
PyDoc_STRVAR(clone_repository__doc__,
"clone_repository(url, path, bare, remote_name, push_url, fetch_spec, push_spec, checkout_branch)\n"
"\n"
"Clones a Git repository in the given url to the given path with the specified options.\n"
"\n"
"Arguments:\n"
"\n"
"url\n"
" Git repository remote url.\n"
"path\n"
" Path where to create the repository.\n"
"bare\n"
" If 'bare' is not 0, then a bare git repository will be created.\n"
"remote_name\n"
" The name given to the 'origin' remote. The default is 'origin'.\n"
"push_url\n"
" URL to be used for pushing.\n"
"fetch_spec\n"
" The fetch specification to be used for fetching. None results in the same behavior as GIT_REMOTE_DEFAULT_FETCH.\n"
"push_spec\n"
" The fetch specification to be used for pushing. None means use the same spec as for 'fetch_spec'\n"
"checkout_branch\n"
" The name of the branch to checkout. None means use the remote's HEAD.\n");
PyObject *
clone_repository(PyObject *self, PyObject *args) {
git_repository *repo;
const char *url;
const char *path;
unsigned int bare;
const char *remote_name, *push_url, *fetch_spec, *push_spec, *checkout_branch;
int err;
if (!PyArg_ParseTuple(args, "zzIzzzzz", &url, &path, &bare, &remote_name, &push_url, &fetch_spec, &push_spec, &checkout_branch))
return NULL;
git_clone_options opts = {
.version=1,
.bare=bare,
.remote_name=remote_name,
.pushurl=push_url,
.fetch_spec=fetch_spec,
.push_spec=push_spec,
.checkout_branch=checkout_branch
};
err = git_clone(&repo, url, path, &opts);
if (err < 0)
return Error_set_str(err, path);
git_repository_free(repo);
Py_RETURN_NONE;
};
PyDoc_STRVAR(discover_repository__doc__,
"discover_repository(path[, across_fs[, ceiling_dirs]]) -> str\n"
@@ -172,6 +227,7 @@ hash(PyObject *self, PyObject *args)
PyMethodDef module_methods[] = {
{"init_repository", init_repository, METH_VARARGS, init_repository__doc__},
{"clone_repository", clone_repository, METH_VARARGS, clone_repository__doc__},
{"discover_repository", discover_repository, METH_VARARGS,
discover_repository__doc__},
{"hashfile", hashfile, METH_VARARGS, hashfile__doc__},

View File

@@ -40,7 +40,7 @@ from os.path import join, realpath
# Import from pygit2
from pygit2 import GIT_OBJ_ANY, GIT_OBJ_BLOB, GIT_OBJ_COMMIT
from pygit2 import init_repository, discover_repository, Reference, hashfile
from pygit2 import init_repository, clone_repository, discover_repository, Reference, hashfile
from pygit2 import Oid
import pygit2
from . import utils
@@ -291,6 +291,46 @@ class EmptyRepositoryTest(utils.EmptyRepoTestCase):
self.assertTrue(self.repo.head_is_orphaned)
self.assertFalse(self.repo.head_is_detached)
class CloneRepositoryTest(utils.NoRepoTestCase):
def test_clone_repository(self):
repo = clone_repository("./test/data/testrepo.git/", self._temp_dir)
self.assertFalse(repo.is_empty)
self.assertFalse(repo.is_bare)
def test_clone_bare_repository(self):
repo = clone_repository("./test/data/testrepo.git/", self._temp_dir, bare=True)
self.assertFalse(repo.is_empty)
self.assertTrue(repo.is_bare)
def test_clone_remote_name(self):
repo = clone_repository("./test/data/testrepo.git/", self._temp_dir, remote_name="custom_remote")
self.assertFalse(repo.is_empty)
self.assertEqual(repo.remotes[0].name, "custom_remote")
def test_clone_push_url(self):
repo = clone_repository("./test/data/testrepo.git/", self._temp_dir, push_url="custom_push_url")
self.assertFalse(repo.is_empty)
# not sure how to test this... couldn't find pushurl
# self.assertEqual(repo.remotes[0].pushurl, "custom_push_url")
def test_clone_fetch_spec(self):
repo = clone_repository("./test/data/testrepo.git/", self._temp_dir, fetch_spec="refs/heads/test")
self.assertFalse(repo.is_empty)
# not sure how to test this either... fetchspec seems to be going through, but repo is not getting it.
# self.assertEqual(repo.remotes[0].fetchspec, "refs/heads/test")
def test_clone_push_spec(self):
repo = clone_repository("./test/data/testrepo.git/", self._temp_dir, push_spec="refs/heads/test")
self.assertFalse(repo.is_empty)
# not sure how to test this either... couldn't find pushspec
# self.assertEqual(repo.remotes[0].fetchspec, "refs/heads/test")
def test_clone_checkout_branch(self):
repo = clone_repository("./test/data/testrepo.git/", self._temp_dir, checkout_branch="test")
self.assertFalse(repo.is_empty)
# not sure how to test this either... couldn't find current branch
# self.assertEqual(repo.remotes[0].current_branch, "test")
if __name__ == '__main__':
unittest.main()