Merge remote-tracking branch 'heynemann/master'
This commit is contained in:
@@ -20,6 +20,17 @@ Functions
|
||||
>>> repo = init_repository('test') # Creates a non-bare repository
|
||||
>>> repo = init_repository('test', bare=True) # Creates a bare repository
|
||||
|
||||
.. autofunction:: pygit2.clone_repository
|
||||
|
||||
Example::
|
||||
|
||||
>>> from pygit2 import clone_repository
|
||||
>>> repo_url = 'git://github.com/libgit2/pygit2.git'
|
||||
>>> repo_path = '/path/to/create/repository'
|
||||
>>> repo = clone_repository(repo_url, repo_path) # Clones a non-bare repository
|
||||
>>> repo = clone_repository(repo_url, repo_path, bare=True) # Clones a bare repository
|
||||
|
||||
|
||||
.. autofunction:: pygit2.discover_repository
|
||||
|
||||
|
||||
|
@@ -47,3 +47,43 @@ 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*.
|
||||
|
||||
**bare** indicates whether a bare git repository should 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 *url* parameter.
|
||||
|
||||
**fetch_spec** defines the the default fetch spec.
|
||||
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*.
|
||||
|
||||
Returns a Repository class pointing to the newly cloned repository.
|
||||
|
||||
If you wish to use the repo, you need to do a checkout for one of
|
||||
the available branches, like this:
|
||||
|
||||
>>> repo = repo.clone_repository("url", "path")
|
||||
>>> repo.checkout(branch) # i.e.: refs/heads/master
|
||||
|
||||
"""
|
||||
|
||||
_pygit2.clone_repository(
|
||||
url, path, bare, remote_name, push_url,
|
||||
fetch_spec, push_spec, checkout_branch)
|
||||
return Repository(path)
|
||||
|
65
src/pygit2.c
65
src/pygit2.c
@@ -97,6 +97,69 @@ 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;
|
||||
const char *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 +235,8 @@ 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__},
|
||||
|
@@ -40,7 +40,10 @@ 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
|
||||
@@ -101,7 +104,7 @@ class RepositoryTest(utils.BareRepoTestCase):
|
||||
self.assertFalse('a' * 20 in self.repo)
|
||||
|
||||
def test_iterable(self):
|
||||
l = [ obj for obj in self.repo ]
|
||||
l = [obj for obj in self.repo]
|
||||
oid = Oid(hex=BLOB_HEX)
|
||||
self.assertTrue(oid in l)
|
||||
|
||||
@@ -135,9 +138,10 @@ class RepositoryTest(utils.BareRepoTestCase):
|
||||
commit = self.repo[commit_sha_prefix]
|
||||
self.assertEqual(commit_sha, commit.hex)
|
||||
self.assertEqual(GIT_OBJ_COMMIT, commit.type)
|
||||
self.assertEqual(('Second test data commit.\n\n'
|
||||
'This commit has some additional text.\n'),
|
||||
commit.message)
|
||||
self.assertEqual(
|
||||
('Second test data commit.\n\n'
|
||||
'This commit has some additional text.\n'),
|
||||
commit.message)
|
||||
self.assertRaises(ValueError, self.repo.__getitem__, too_short_prefix)
|
||||
|
||||
def test_get_path(self):
|
||||
@@ -208,7 +212,7 @@ class RepositoryTest_II(utils.RepoTestCase):
|
||||
def test_checkout_index(self):
|
||||
# some changes to working dir
|
||||
with open(os.path.join(self.repo.workdir, 'hello.txt'), 'w') as f:
|
||||
f.write('new content')
|
||||
f.write('new content')
|
||||
|
||||
# checkout index
|
||||
self.assertTrue('hello.txt' in self.repo.status())
|
||||
@@ -218,7 +222,7 @@ class RepositoryTest_II(utils.RepoTestCase):
|
||||
def test_checkout_head(self):
|
||||
# some changes to the index
|
||||
with open(os.path.join(self.repo.workdir, 'bye.txt'), 'w') as f:
|
||||
f.write('new content')
|
||||
f.write('new content')
|
||||
self.repo.index.add('bye.txt')
|
||||
|
||||
# checkout from index should not change anything
|
||||
@@ -272,6 +276,7 @@ class InitRepositoryTest(utils.NoRepoTestCase):
|
||||
repo = init_repository(self._temp_dir, bare=True)
|
||||
self.assertTrue(repo.is_bare)
|
||||
|
||||
|
||||
class DiscoverRepositoryTest(utils.NoRepoTestCase):
|
||||
def test_discover_repo(self):
|
||||
repo = init_repository(self._temp_dir, False)
|
||||
@@ -279,6 +284,7 @@ class DiscoverRepositoryTest(utils.NoRepoTestCase):
|
||||
os.makedirs(subdir)
|
||||
self.assertEqual(repo.path, discover_repository(subdir))
|
||||
|
||||
|
||||
class EmptyRepositoryTest(utils.EmptyRepoTestCase):
|
||||
|
||||
def test_is_empty(self):
|
||||
@@ -292,5 +298,69 @@ class EmptyRepositoryTest(utils.EmptyRepoTestCase):
|
||||
self.assertFalse(self.repo.head_is_detached)
|
||||
|
||||
|
||||
class CloneRepositoryTest(utils.NoRepoTestCase):
|
||||
def test_clone_repository(self):
|
||||
repo_path = "./test/data/testrepo.git/"
|
||||
repo = clone_repository(repo_path, self._temp_dir)
|
||||
self.assertFalse(repo.is_empty)
|
||||
self.assertFalse(repo.is_bare)
|
||||
|
||||
def test_clone_bare_repository(self):
|
||||
repo_path = "./test/data/testrepo.git/"
|
||||
repo = clone_repository(repo_path, self._temp_dir, bare=True)
|
||||
self.assertFalse(repo.is_empty)
|
||||
self.assertTrue(repo.is_bare)
|
||||
|
||||
def test_clone_remote_name(self):
|
||||
repo_path = "./test/data/testrepo.git/"
|
||||
repo = clone_repository(
|
||||
repo_path, 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_path = "./test/data/testrepo.git/"
|
||||
repo = clone_repository(
|
||||
repo_path, self._temp_dir, push_url="custom_push_url"
|
||||
)
|
||||
self.assertFalse(repo.is_empty)
|
||||
# FIXME: When pygit2 supports retrieving the pushurl parameter,
|
||||
# enable this test
|
||||
# self.assertEqual(repo.remotes[0].pushurl, "custom_push_url")
|
||||
|
||||
def test_clone_fetch_spec(self):
|
||||
repo_path = "./test/data/testrepo.git/"
|
||||
repo = clone_repository(
|
||||
repo_path, self._temp_dir, fetch_spec="refs/heads/test"
|
||||
)
|
||||
self.assertFalse(repo.is_empty)
|
||||
# FIXME: When pygit2 retrieve the fetchspec we passed to git clone.
|
||||
# fetchspec seems to be going through, but the Repository class is
|
||||
# not getting it.
|
||||
# self.assertEqual(repo.remotes[0].fetchspec, "refs/heads/test")
|
||||
|
||||
def test_clone_push_spec(self):
|
||||
repo_path = "./test/data/testrepo.git/"
|
||||
repo = clone_repository(
|
||||
repo_path, self._temp_dir, push_spec="refs/heads/test"
|
||||
)
|
||||
self.assertFalse(repo.is_empty)
|
||||
# FIXME: When pygit2 supports retrieving the pushspec parameter,
|
||||
# enable this test
|
||||
# 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_path = "./test/data/testrepo.git/"
|
||||
repo = clone_repository(
|
||||
repo_path, self._temp_dir, checkout_branch="test"
|
||||
)
|
||||
self.assertFalse(repo.is_empty)
|
||||
# FIXME: When pygit2 supports retrieving the current branch,
|
||||
# enable this test
|
||||
# self.assertEqual(repo.remotes[0].current_branch, "test")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Reference in New Issue
Block a user