Migrate to 0.22

Apart from the usual API changes, we now need to introduce the concept
of whether we still own the C object underneath our Repository and
Remote objects.

When using the custom callbacks for repository and remote creation
during clone, we pass the pointer and thus ownership of the object back
to the library. We will then get the repository back at the end.

We return the object which was handed to us rather than opening the
repository again with the local path as there is now a much higher
chance that the cloned repository does not use the standard backends.
This commit is contained in:
Carlos Martín Nieto
2014-12-11 12:47:34 +01:00
parent 4cbfade973
commit 1dbf94011a
11 changed files with 264 additions and 140 deletions

View File

@@ -41,7 +41,7 @@ from .index import Index, IndexEntry
from .remote import Remote, get_credentials
from .repository import Repository
from .settings import Settings
from .utils import to_bytes
from .utils import to_bytes, to_str
from ._utils import __version__
@@ -113,7 +113,7 @@ def init_repository(path, bare=False,
check_error(err)
# Ok
return Repository(path)
return Repository(to_str(path))
@ffi.callback('int (*credentials)(git_cred **cred, const char *url,'
@@ -123,7 +123,7 @@ def _credentials_cb(cred_out, url, username_from_url, allowed, data):
d = ffi.from_handle(data)
try:
ccred = get_credentials(d['callback'], url, username_from_url, allowed)
ccred = get_credentials(d['credentials_cb'], url, username_from_url, allowed)
cred_out[0] = ccred[0]
except Exception as e:
d['exception'] = e
@@ -131,10 +131,39 @@ def _credentials_cb(cred_out, url, username_from_url, allowed, data):
return 0
@ffi.callback('int (*git_repository_create_cb)(git_repository **out,'
'const char *path, int bare, void *payload)')
def _repository_create_cb(repo_out, path, bare, data):
d = ffi.from_handle(data)
try:
repository = d['repository_cb'](ffi.string(path), bare != 0)
# we no longer own the C object
repository._disown()
repo_out[0] = repository._repo
except Exception as e:
d['exception'] = e
return C.GIT_EUSER
return 0
@ffi.callback('int (*git_remote_create_cb)(git_remote **out, git_repository *repo,'
'const char *name, const char *url, void *payload)')
def _remote_create_cb(remote_out, repo, name, url, data):
d = ffi.from_handle(data)
try:
remote = d['remote_cb'](Repository._from_c(repo, False), ffi.string(name), ffi.string(url))
remote_out[0] = remote._remote
# we no longer own the C object
remote._remote = ffi.NULL
except Exception as e:
d['exception'] = e
return C.GIT_EUSER
return 0
def clone_repository(
url, path, bare=False, ignore_cert_errors=False,
remote_name="origin", checkout_branch=None, credentials=None):
url, path, bare=False, repository=None, remote=None, checkout_branch=None, credentials=None):
"""Clones a new Git repository from *url* in the given *path*.
Returns a Repository class pointing to the newly cloned repository.
@@ -145,7 +174,9 @@ def clone_repository(
:param bool bare: Whether the local repository should be bare
:param str remote_name: Name to give the remote at *url*.
:param callable remote: Callback for the remote to use.
:param callable repository: Callback for the repository to use.
:param str checkout_branch: Branch to checkout after the
clone. The default is to use the remote's default branch.
@@ -155,6 +186,13 @@ def clone_repository(
:rtype: Repository
The repository callback has `(path, bare) -> Repository` as a
signature. The Repository it returns will be used instead of
creating a new one.
The remote callback has `(Repository, name, url) -> Remote` as a
signature. The Remote it returns will be used instead of the default
one.
"""
opts = ffi.new('git_clone_options *')
@@ -164,7 +202,9 @@ def clone_repository(
# Data, let's use a dict as we don't really want much more
d = {}
d['callback'] = credentials
d['credentials_cb'] = credentials
d['repository_cb'] = repository
d['remote_cb'] = remote
d_handle = ffi.new_handle(d)
# Perform the initialization with the version we compiled
@@ -176,48 +216,26 @@ def clone_repository(
checkout_branch_ref = ffi.new('char []', to_bytes(branch))
opts.checkout_branch = checkout_branch_ref
remote_name_ref = ffi.new('char []', to_bytes(remote_name))
opts.remote_name = remote_name_ref
if repository:
opts.repository_cb = _repository_create_cb
opts.repository_cb_payload = d_handle
if remote:
opts.remote_cb = _remote_create_cb
opts.remote_cb_payload = d_handle
opts.ignore_cert_errors = ignore_cert_errors
opts.bare = bare
if credentials:
opts.remote_callbacks.credentials = _credentials_cb
opts.remote_callbacks.payload = d_handle
err = C.git_clone(crepo, to_bytes(url), to_bytes(path), opts)
C.git_repository_free(crepo[0])
if 'exception' in d:
raise d['exception']
check_error(err)
return Repository(path)
def clone_into(repo, remote, branch=None):
"""Clone into an empty repository from the specified remote
:param Repository repo: The empty repository into which to clone
:param Remote remote: The remote from which to clone
:param str branch: Branch to checkout after the clone. Pass None
to use the remotes's default branch.
This allows you specify arbitrary repository and remote configurations
before performing the clone step itself. E.g. you can replicate git-clone's
'--mirror' option by setting a refspec of '+refs/*:refs/*', 'core.mirror'
to true and calling this function.
"""
err = C.git_clone_into(repo._repo, remote._remote, ffi.NULL,
to_bytes(branch), ffi.NULL)
if remote._stored_exception:
raise remote._stored_exception
check_error(err)
return Repository._from_c(crepo[0], owned=True)
settings = Settings()

View File

@@ -106,9 +106,38 @@ typedef enum {
GIT_CREDTYPE_SSH_KEY,
GIT_CREDTYPE_SSH_CUSTOM,
GIT_CREDTYPE_DEFAULT,
GIT_CREDTYPE_SSH_INTERACTIVE,
GIT_CREDTYPE_USERNAME,
...
} git_credtype_t;
typedef enum git_cert_t {
GIT_CERT_X509,
GIT_CERT_HOSTKEY_LIBSSH2,
} git_cert_t;
typedef enum {
GIT_CERT_SSH_MD5 = 1,
GIT_CERT_SSH_SHA1 = 2,
} git_cert_ssh_t;
typedef struct {
git_cert_t cert_type;
git_cert_ssh_t type;
unsigned char hash_md5[16];
unsigned char hash_sha1[20];
} git_cert_hostkey;
typedef struct {
git_cert_t cert_type;
void *data;
size_t len;
} git_cert_x509;
typedef struct {
git_cert_t cert_type;
} git_cert;
typedef int (*git_transport_message_cb)(const char *str, int len, void *data);
typedef int (*git_cred_acquire_cb)(
git_cred **cred,
@@ -117,40 +146,53 @@ typedef int (*git_cred_acquire_cb)(
unsigned int allowed_types,
void *payload);
typedef int (*git_transfer_progress_cb)(const git_transfer_progress *stats, void *payload);
typedef int (*git_transport_certificate_check_cb)(git_cert *cert, int valid, const char *host, void *payload);
typedef int (*git_packbuilder_progress)(
int stage,
unsigned int current,
unsigned int total,
void *payload);
typedef int (*git_push_transfer_progress)(
unsigned int current,
unsigned int total,
size_t bytes,
void* payload);
struct git_remote_callbacks {
unsigned int version;
git_transport_message_cb sideband_progress;
int (*completion)(git_remote_completion_type type, void *data);
git_cred_acquire_cb credentials;
git_transport_certificate_check_cb certificate_check;
git_transfer_progress_cb transfer_progress;
int (*update_tips)(const char *refname, const git_oid *a, const git_oid *b, void *data);
git_packbuilder_progress pack_progress;
git_push_transfer_progress push_transfer_progress;
int (*push_update_reference)(const char *refname, const char *status, void *data);
void *payload;
};
typedef struct git_remote_callbacks git_remote_callbacks;
int git_remote_list(git_strarray *out, git_repository *repo);
int git_remote_load(git_remote **out, git_repository *repo, const char *name);
int git_remote_lookup(git_remote **out, git_repository *repo, const char *name);
int git_remote_create(
git_remote **out,
git_repository *repo,
const char *name,
const char *url);
int git_remote_delete(git_remote *remote);
int git_remote_delete(git_repository *repo, const char *name);
int git_repository_state_cleanup(git_repository *repo);
const char * git_remote_name(const git_remote *remote);
int git_remote_rename(
git_strarray *problems,
git_remote *remote,
const char *new_name);
int git_remote_rename(git_strarray *problems, git_repository *repo, const char *name, const char *new_name);
const char * git_remote_url(const git_remote *remote);
int git_remote_set_url(git_remote *remote, const char* url);
const char * git_remote_pushurl(const git_remote *remote);
int git_remote_set_pushurl(git_remote *remote, const char* url);
int git_remote_fetch(git_remote *remote, const git_signature *signature, const char *reflog_message);
int git_remote_fetch(git_remote *remote, const git_strarray *refspecs, const git_signature *signature, const char *reflog_message);
const git_transfer_progress * git_remote_stats(git_remote *remote);
int git_remote_add_push(git_remote *remote, const char *refspec);
int git_remote_add_fetch(git_remote *remote, const char *refspec);
@@ -170,7 +212,6 @@ void git_remote_free(git_remote *remote);
int git_push_new(git_push **push, git_remote *remote);
int git_push_add_refspec(git_push *push, const char *refspec);
int git_push_finish(git_push *push);
int git_push_unpack_ok(git_push *push);
int git_push_status_foreach(
git_push *push,
@@ -261,14 +302,12 @@ typedef int (*git_diff_notify_cb)(
typedef struct {
unsigned int version;
uint32_t flags;
git_submodule_ignore_t ignore_submodules;
git_strarray pathspec;
git_diff_notify_cb notify_cb;
void *notify_payload;
uint16_t context_lines;
uint16_t interhunk_lines;
uint32_t context_lines;
uint32_t interhunk_lines;
uint16_t id_abbrev;
git_off_t max_size;
const char *old_prefix;
@@ -339,13 +378,6 @@ typedef struct git_checkout_options {
const char *their_label;
} git_checkout_options;
typedef enum {
GIT_CLONE_LOCAL_AUTO,
GIT_CLONE_LOCAL,
GIT_CLONE_NO_LOCAL,
GIT_CLONE_LOCAL_NO_LINKS,
} git_clone_local_t;
int git_checkout_init_options(git_checkout_options *opts, unsigned int version);
int git_checkout_tree(git_repository *repo, const git_object *treeish, const git_checkout_options *opts);
int git_checkout_head(git_repository *repo, const git_checkout_options *opts);
@@ -355,18 +387,38 @@ int git_checkout_index(git_repository *repo, git_index *index, const git_checkou
* git_clone
*/
typedef int (*git_remote_create_cb)(
git_remote **out,
git_repository *repo,
const char *name,
const char *url,
void *payload);
typedef int (*git_repository_create_cb)(
git_repository **out,
const char *path,
int bare,
void *payload);
typedef enum {
GIT_CLONE_LOCAL_AUTO,
GIT_CLONE_LOCAL,
GIT_CLONE_NO_LOCAL,
GIT_CLONE_LOCAL_NO_LINKS,
} git_clone_local_t;
typedef struct git_clone_options {
unsigned int version;
git_checkout_options checkout_opts;
git_remote_callbacks remote_callbacks;
int bare;
int ignore_cert_errors;
git_clone_local_t local;
const char *remote_name;
const char* checkout_branch;
git_signature *signature;
git_repository_create_cb repository_cb;
void *repository_cb_payload;
git_remote_create_cb remote_cb;
void *remote_cb_payload;
} git_clone_options;
#define GIT_CLONE_OPTIONS_VERSION ...
@@ -377,13 +429,6 @@ int git_clone(git_repository **out,
const char *local_path,
const git_clone_options *options);
int git_clone_into(
git_repository *repo,
git_remote *remote,
const git_checkout_options *co_opts,
const char *branch,
const git_signature *signature);
/*
* git_config
*/

View File

@@ -137,25 +137,6 @@ class Remote(object):
return maybe_string(C.git_remote_name(self._remote))
def rename(self, new_name):
"""Rename this remote
Returns a list of fetch refspecs which were not in the standard format
and thus could not be remapped
"""
if not new_name:
raise ValueError("New remote name must be a non-empty string")
problems = ffi.new('git_strarray *')
err = C.git_remote_rename(problems, self._remote, to_bytes(new_name))
check_error(err)
ret = strarray_to_strings(problems)
C.git_strarray_free(problems)
return ret
@property
def url(self):
"""Url of the remote"""
@@ -178,14 +159,6 @@ class Remote(object):
err = C.git_remote_set_pushurl(self._remote, to_bytes(value))
check_error(err)
def delete(self):
"""Remove this remote
All remote-tracking branches and configuration settings for the remote will be removed.
"""
err = C.git_remote_delete(self._remote)
check_error(err)
def save(self):
"""save()
@@ -231,7 +204,7 @@ class Remote(object):
self._stored_exception = None
try:
err = C.git_remote_fetch(self._remote, ptr, to_bytes(message))
err = C.git_remote_fetch(self._remote, ffi.NULL, ptr, to_bytes(message))
if self._stored_exception:
raise self._stored_exception
@@ -361,9 +334,6 @@ class Remote(object):
err = C.git_push_finish(push)
check_error(err)
if not C.git_push_unpack_ok(push):
raise GitError("remote failed to unpack objects")
err = C.git_push_status_foreach(push, self._push_cb,
ffi.new_handle(self))
check_error(err)
@@ -529,7 +499,7 @@ class RemoteCollection(object):
cremote = ffi.new('git_remote **')
for i in range(names.count):
err = C.git_remote_load(cremote, self._repo._repo, names.strings[i])
err = C.git_remote_lookup(cremote, self._repo._repo, names.strings[i])
check_error(err)
yield Remote(self._repo, cremote[0])
@@ -541,7 +511,7 @@ class RemoteCollection(object):
return list(self)[name]
cremote = ffi.new('git_remote **')
err = C.git_remote_load(cremote, self._repo._repo, to_bytes(name))
err = C.git_remote_lookup(cremote, self._repo._repo, to_bytes(name))
check_error(err)
return Remote(self._repo, cremote[0])
@@ -558,3 +528,36 @@ class RemoteCollection(object):
check_error(err)
return Remote(self._repo, cremote[0])
def rename(self, name, new_name):
"""rename(name, new_name) -> [str]
Rename a remote in the configuration. The refspecs in strandard
format will be renamed.
Returns a list of fetch refspecs which were not in the standard format
and thus could not be remapped
"""
if not new_name:
raise ValueError("Current remote name must be a non-empty string")
if not new_name:
raise ValueError("New remote name must be a non-empty string")
problems = ffi.new('git_strarray *')
err = C.git_remote_rename(problems, self._repo._repo, to_bytes(name), to_bytes(new_name))
check_error(err)
ret = strarray_to_strings(problems)
C.git_strarray_free(problems)
return ret
def delete(self, name):
"""Remove a remote from the configuration
All remote-tracking branches and configuration settings for the remote will be removed.
"""
err = C.git_remote_delete(self._repo._repo, to_bytes(name))
check_error(err)

View File

@@ -57,7 +57,18 @@ class Repository(_Repository):
def __init__(self, *args, **kwargs):
super(Repository, self).__init__(*args, **kwargs)
self._common_init()
@classmethod
def _from_c(cls, ptr, owned):
cptr = ffi.new('git_repository **')
cptr[0] = ptr
repo = cls.__new__(cls)
super(cls, repo)._from_c(bytes(ffi.buffer(cptr)[:]), owned)
repo._common_init()
return repo
def _common_init(self):
self.remotes = RemoteCollection(self)
# Get the pointer as the contents of a buffer and store it for

View File

@@ -296,14 +296,14 @@ Diff_patch__get__(Diff *self)
git_patch* patch;
git_buf buf = {NULL};
int err = GIT_ERROR;
size_t i, len, num;
size_t i, num;
PyObject *py_patch = NULL;
num = git_diff_num_deltas(self->diff);
if (num == 0)
Py_RETURN_NONE;
for (i = 0, len = 1; i < num ; ++i) {
for (i = 0; i < num ; ++i) {
err = git_patch_from_diff(&patch, self->diff, i);
if (err < 0)
goto cleanup;

View File

@@ -210,7 +210,6 @@ moduleinit(PyObject* m)
ADD_CONSTANT_INT(m, GIT_OBJ_BLOB)
ADD_CONSTANT_INT(m, GIT_OBJ_TAG)
/* Valid modes for index and tree entries. */
ADD_CONSTANT_INT(m, GIT_FILEMODE_NEW)
ADD_CONSTANT_INT(m, GIT_FILEMODE_TREE)
ADD_CONSTANT_INT(m, GIT_FILEMODE_BLOB)
ADD_CONSTANT_INT(m, GIT_FILEMODE_BLOB_EXECUTABLE)
@@ -347,7 +346,7 @@ moduleinit(PyObject* m)
ADD_CONSTANT_INT(m, GIT_MERGE_ANALYSIS_UNBORN)
/* Global initialization of libgit2 */
git_threads_init();
git_libgit2_init();
return m;
}

View File

@@ -55,6 +55,9 @@ extern PyTypeObject ReferenceType;
extern PyTypeObject NoteType;
extern PyTypeObject NoteIterType;
/* forward-declaration for Repsository._from_c() */
PyTypeObject RepositoryType;
git_otype
int_to_loose_object_type(int type_id)
{
@@ -88,19 +91,62 @@ Repository_init(Repository *self, PyObject *args, PyObject *kwds)
return -1;
}
self->owned = 1;
self->config = NULL;
self->index = NULL;
return 0;
}
PyDoc_STRVAR(Repository__from_c__doc__, "Init a Repository from a pointer. For internal use only.");
PyObject *
Repository__from_c(Repository *py_repo, PyObject *args)
{
PyObject *py_pointer, *py_free;
char *buffer;
Py_ssize_t len;
int err;
py_repo->repo = NULL;
py_repo->config = NULL;
py_repo->index = NULL;
if (!PyArg_ParseTuple(args, "OO!", &py_pointer, &PyBool_Type, &py_free))
return NULL;
err = PyBytes_AsStringAndSize(py_pointer, &buffer, &len);
if (err < 0)
return NULL;
if (len != sizeof(git_repository *)) {
PyErr_SetString(PyExc_TypeError, "invalid pointer length");
return NULL;
}
py_repo->repo = *((git_repository **) buffer);
py_repo->owned = py_free == Py_True;
Py_RETURN_NONE;
}
PyDoc_STRVAR(Repository__disown__doc__, "Mark the object as not-owned by us. For internal use only.");
PyObject *
Repository__disown(Repository *py_repo)
{
py_repo->owned = 0;
Py_RETURN_NONE;
}
void
Repository_dealloc(Repository *self)
{
PyObject_GC_UnTrack(self);
Py_CLEAR(self->index);
Py_CLEAR(self->config);
if (self->owned)
git_repository_free(self->repo);
Py_TYPE(self)->tp_free(self);
}
@@ -526,7 +572,7 @@ Repository_merge_analysis(Repository *self, PyObject *py_id)
int err;
size_t len;
git_oid id;
git_merge_head *merge_head;
git_annotated_commit *commit;
git_merge_analysis_t analysis;
git_merge_preference_t preference;
@@ -534,12 +580,12 @@ Repository_merge_analysis(Repository *self, PyObject *py_id)
if (len == 0)
return NULL;
err = git_merge_head_from_id(&merge_head, self->repo, &id);
err = git_annotated_commit_lookup(&commit, self->repo, &id);
if (err < 0)
return Error_set(err);
err = git_merge_analysis(&analysis, &preference, self->repo, (const git_merge_head **) &merge_head, 1);
git_merge_head_free(merge_head);
err = git_merge_analysis(&analysis, &preference, self->repo, (const git_annotated_commit **) &commit, 1);
git_annotated_commit_free(commit);
if (err < 0)
return Error_set(err);
@@ -561,7 +607,7 @@ PyDoc_STRVAR(Repository_merge__doc__,
PyObject *
Repository_merge(Repository *self, PyObject *py_oid)
{
git_merge_head *oid_merge_head;
git_annotated_commit *commit;
git_oid oid;
int err;
size_t len;
@@ -572,16 +618,16 @@ Repository_merge(Repository *self, PyObject *py_oid)
if (len == 0)
return NULL;
err = git_merge_head_from_id(&oid_merge_head, self->repo, &oid);
err = git_annotated_commit_lookup(&commit, self->repo, &oid);
if (err < 0)
return Error_set(err);
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
err = git_merge(self->repo,
(const git_merge_head **)&oid_merge_head, 1,
(const git_annotated_commit **)&commit, 1,
&merge_opts, &checkout_opts);
git_merge_head_free(oid_merge_head);
git_annotated_commit_free(commit);
if (err < 0)
return Error_set(err);
@@ -1225,7 +1271,7 @@ Repository_TreeBuilder(Repository *self, PyObject *args)
}
}
err = git_treebuilder_create(&bld, tree);
err = git_treebuilder_new(&bld, self->repo, tree);
if (must_free != NULL)
git_tree_free(must_free);
@@ -1318,8 +1364,8 @@ Repository_create_note(Repository *self, PyObject* args)
if (err < 0)
return Error_set(err);
err = git_note_create(&note_id, self->repo, py_author->signature,
py_committer->signature, ref,
err = git_note_create(&note_id, self->repo, ref, py_author->signature,
py_committer->signature,
&annotated_id, message, force);
if (err < 0)
return Error_set(err);
@@ -1380,7 +1426,7 @@ Repository_reset(Repository *self, PyObject* args)
err = git_object_lookup_prefix(&target, self->repo, &oid, len,
GIT_OBJ_ANY);
err = err < 0 ? err : git_reset(self->repo, target, reset_type, NULL, NULL);
err = err < 0 ? err : git_reset(self->repo, target, reset_type, NULL, NULL, NULL);
git_object_free(target);
if (err < 0)
return Error_set_oid(err, &oid, len);
@@ -1415,6 +1461,8 @@ PyMethodDef Repository_methods[] = {
METHOD(Repository, listall_branches, METH_VARARGS),
METHOD(Repository, create_branch, METH_VARARGS),
METHOD(Repository, reset, METH_VARARGS),
METHOD(Repository, _from_c, METH_VARARGS),
METHOD(Repository, _disown, METH_NOARGS),
{NULL}
};

View File

@@ -88,7 +88,7 @@ TreeBuilder_write(TreeBuilder *self)
int err;
git_oid oid;
err = git_treebuilder_write(&oid, self->repo->repo, self->bld);
err = git_treebuilder_write(&oid, self->bld);
if (err < 0)
return Error_set(err);

View File

@@ -47,6 +47,7 @@ typedef struct {
git_repository *repo;
PyObject *index; /* It will be None for a bare repository */
PyObject *config; /* It will be None for a bare repository */
int owned; /* _from_c() sometimes means we don't own the C pointer */
} Repository;

View File

@@ -71,19 +71,19 @@ class RepositoryTest(utils.RepoTestCase):
remote = self.repo.remotes[1]
self.assertEqual(name, remote.name)
remote.delete()
self.repo.remotes.delete(remote.name)
self.assertEqual(1, len(self.repo.remotes))
def test_remote_rename(self):
remote = self.repo.remotes[0]
self.assertEqual(REMOTE_NAME, remote.name)
problems = remote.rename('new')
problems = self.repo.remotes.rename(remote.name, "new")
self.assertEqual([], problems)
self.assertEqual('new', remote.name)
self.assertNotEqual('new', remote.name)
self.assertRaises(ValueError, remote.rename, '')
self.assertRaises(ValueError, remote.rename, None)
self.assertRaises(ValueError, self.repo.remotes.rename, '', '')
self.assertRaises(ValueError, self.repo.remotes.rename, None, None)
def test_remote_set_url(self):
@@ -183,13 +183,9 @@ class RepositoryTest(utils.RepoTestCase):
def test_remote_save(self):
remote = self.repo.remotes[0]
remote.rename('new-name')
remote.url = 'http://example.com/test.git'
remote.save()
self.assertEqual('new-name', self.repo.remotes[0].name)
self.assertEqual('http://example.com/test.git',
self.repo.remotes[0].url)

View File

@@ -41,7 +41,7 @@ import sys
# Import from pygit2
from pygit2 import GIT_OBJ_ANY, GIT_OBJ_BLOB, GIT_OBJ_COMMIT
from pygit2 import init_repository, clone_repository, clone_into, discover_repository
from pygit2 import init_repository, clone_repository, discover_repository
from pygit2 import Oid, Reference, hashfile
import pygit2
from . import utils
@@ -440,19 +440,22 @@ class CloneRepositoryTest(utils.NoRepoTestCase):
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_repository_and_remote_callbacks(self):
src_repo_relpath = "./test/data/testrepo.git/"
repo_path = os.path.join(self._temp_dir, "clone-into")
url = 'file://' + os.path.realpath(src_repo_relpath)
def test_clone_into(self):
repo_path = "./test/data/testrepo.git/"
repo = init_repository(os.path.join(self._temp_dir, "clone-into"))
remote = repo.create_remote("origin", 'file://' + os.path.realpath(repo_path))
clone_into(repo, remote)
self.assertTrue('refs/remotes/origin/master' in repo.listall_references())
def create_repository(path, bare):
return init_repository(path, bare)
# here we override the name
def create_remote(repo, name, url):
return repo.remotes.create("custom_remote", url)
repo = clone_repository(url, repo_path, repository=create_repository, remote=create_remote)
self.assertFalse(repo.is_empty)
self.assertTrue('refs/remotes/custom_remote/master' in repo.listall_references())
self.assertIsNotNone(repo.remotes["custom_remote"])
def test_clone_with_credentials(self):
credentials = pygit2.UserPass("libgit2", "libgit2")