Merge remote-tracking branch 'heynemann/master'

This commit is contained in:
J. David Ibáñez
2013-05-16 22:23:56 +02:00
4 changed files with 193 additions and 7 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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__},

View File

@@ -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()