diff --git a/pygit2/__init__.py b/pygit2/__init__.py index 995fe6c..800fb00 100644 --- a/pygit2/__init__.py +++ b/pygit2/__init__.py @@ -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() diff --git a/pygit2/decl.h b/pygit2/decl.h index 5c4d9a6..7af2bd6 100644 --- a/pygit2/decl.h +++ b/pygit2/decl.h @@ -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 */ diff --git a/pygit2/remote.py b/pygit2/remote.py index 9a58213..1385e48 100644 --- a/pygit2/remote.py +++ b/pygit2/remote.py @@ -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) diff --git a/pygit2/repository.py b/pygit2/repository.py index 7a3f8a6..3dd14f1 100644 --- a/pygit2/repository.py +++ b/pygit2/repository.py @@ -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 diff --git a/src/diff.c b/src/diff.c index d40c3e6..1874c50 100644 --- a/src/diff.c +++ b/src/diff.c @@ -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; diff --git a/src/pygit2.c b/src/pygit2.c index 2fec0c1..cf2decd 100644 --- a/src/pygit2.c +++ b/src/pygit2.c @@ -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; } diff --git a/src/repository.c b/src/repository.c index 1920438..9eabbb9 100644 --- a/src/repository.c +++ b/src/repository.c @@ -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); - git_repository_free(self->repo); + + 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(¬e_id, self->repo, py_author->signature, - py_committer->signature, ref, + err = git_note_create(¬e_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} }; diff --git a/src/treebuilder.c b/src/treebuilder.c index 5957040..dbec825 100644 --- a/src/treebuilder.c +++ b/src/treebuilder.c @@ -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); diff --git a/src/types.h b/src/types.h index 78747cf..3b797b6 100644 --- a/src/types.h +++ b/src/types.h @@ -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; diff --git a/test/test_remote.py b/test/test_remote.py index ee28743..be50b77 100644 --- a/test/test_remote.py +++ b/test/test_remote.py @@ -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) diff --git a/test/test_repository.py b/test/test_repository.py index 72a5e64..7640f39 100644 --- a/test/test_repository.py +++ b/test/test_repository.py @@ -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")