From d31402a3fc4aa1b7d48ba43fd3bb072e7d69a527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 16 Sep 2013 04:20:05 +0200 Subject: [PATCH 01/14] remote: put the _download() callback with the others The text progress and update_tips callbacks are already part of the struct, which was meant to unify the callback setup, but the download one was left out. --- examples/network/clone.c | 6 ++++-- examples/network/fetch.c | 2 +- include/git2/clone.h | 2 -- include/git2/remote.h | 11 ++--------- src/clone.c | 3 +-- src/fetch.c | 8 +++----- src/fetch.h | 5 +---- src/remote.c | 7 ++----- tests-clar/network/fetchlocal.c | 14 ++++++++++++-- tests-clar/network/remote/local.c | 10 +++++----- tests-clar/online/clone.c | 20 +++++++++++++++++--- tests-clar/online/fetch.c | 18 +++++++++++++++--- tests-clar/online/fetchhead.c | 2 +- tests-clar/online/push.c | 2 +- tests-clar/online/push_util.h | 2 +- 15 files changed, 66 insertions(+), 46 deletions(-) diff --git a/examples/network/clone.c b/examples/network/clone.c index a09a94728..f1002656c 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -57,6 +57,7 @@ int do_clone(git_repository *repo, int argc, char **argv) git_repository *cloned_repo = NULL; git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; const char *url = argv[1]; const char *path = argv[2]; int error; @@ -74,8 +75,9 @@ int do_clone(git_repository *repo, int argc, char **argv) checkout_opts.progress_cb = checkout_progress; checkout_opts.progress_payload = &pd; clone_opts.checkout_opts = checkout_opts; - clone_opts.fetch_progress_cb = &fetch_progress; - clone_opts.fetch_progress_payload = &pd; + callbacks.transfer_progress = &fetch_progress; + callbacks.payload = &pd; + clone_opts.remote_callbacks = &callbacks; clone_opts.cred_acquire_cb = cred_acquire_cb; // Do the clone diff --git a/examples/network/fetch.c b/examples/network/fetch.c index ce016ce0b..1de223373 100644 --- a/examples/network/fetch.c +++ b/examples/network/fetch.c @@ -35,7 +35,7 @@ static void *download(void *ptr) // Download the packfile and index it. This function updates the // amount of received data and the indexer stats which lets you // inform the user about progress. - if (git_remote_download(data->remote, NULL, NULL) < 0) { + if (git_remote_download(data->remote) < 0) { data->ret = -1; goto exit; } diff --git a/include/git2/clone.h b/include/git2/clone.h index 580352ac1..122806ad5 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -69,8 +69,6 @@ typedef struct git_clone_options { git_checkout_opts checkout_opts; git_repository_init_options *init_options; int bare; - git_transfer_progress_callback fetch_progress_cb; - void *fetch_progress_payload; const char *remote_name; const char *pushurl; diff --git a/include/git2/remote.h b/include/git2/remote.h index fa8b378c6..2bde5e365 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -257,17 +257,9 @@ GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void * The .idx file will be created and both it and the packfile with be * renamed to their final name. * - * @param remote the remote to download from - * @param progress_cb function to call with progress information. Be aware that - * this is called inline with network and indexing operations, so performance - * may be affected. - * @param payload payload for the progress callback * @return 0 or an error code */ -GIT_EXTERN(int) git_remote_download( - git_remote *remote, - git_transfer_progress_callback progress_cb, - void *payload); +GIT_EXTERN(int) git_remote_download(git_remote *remote); /** * Check whether the remote is connected @@ -403,6 +395,7 @@ struct git_remote_callbacks { unsigned int version; void (*progress)(const char *str, int len, void *data); int (*completion)(git_remote_completion_type type, void *data); + int (*transfer_progress)(const git_transfer_progress *stats, void *data); int (*update_tips)(const char *refname, const git_oid *a, const git_oid *b, void *data); void *payload; }; diff --git a/src/clone.c b/src/clone.c index ff251be1b..90d677bbb 100644 --- a/src/clone.c +++ b/src/clone.c @@ -380,8 +380,7 @@ static int setup_remotes_and_fetch( if ((retcode = git_remote_connect(origin, GIT_DIRECTION_FETCH)) < 0) goto on_error; - if ((retcode = git_remote_download(origin, options->fetch_progress_cb, - options->fetch_progress_payload)) < 0) + if ((retcode = git_remote_download(origin)) < 0) goto on_error; /* Create "origin/foo" branches for all remote branches */ diff --git a/src/fetch.c b/src/fetch.c index 03fad5fec..5d97913e8 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -119,15 +119,13 @@ int git_fetch_negotiate(git_remote *remote) remote->refs.length); } -int git_fetch_download_pack( - git_remote *remote, - git_transfer_progress_callback progress_cb, - void *progress_payload) +int git_fetch_download_pack(git_remote *remote) { git_transport *t = remote->transport; if(!remote->need_pack) return 0; - return t->download_pack(t, remote->repo, &remote->stats, progress_cb, progress_payload); + return t->download_pack(t, remote->repo, &remote->stats, + remote->callbacks.transfer_progress, remote->callbacks.payload); } diff --git a/src/fetch.h b/src/fetch.h index 059251d04..9605da1b5 100644 --- a/src/fetch.h +++ b/src/fetch.h @@ -11,10 +11,7 @@ int git_fetch_negotiate(git_remote *remote); -int git_fetch_download_pack( - git_remote *remote, - git_transfer_progress_callback progress_cb, - void *progress_payload); +int git_fetch_download_pack(git_remote *remote); int git_fetch__download_pack( git_transport *t, diff --git a/src/remote.c b/src/remote.c index 95b907ff1..e4696c4ec 100644 --- a/src/remote.c +++ b/src/remote.c @@ -742,10 +742,7 @@ static int remote_head_cmp(const void *_a, const void *_b) return git__strcmp_cb(a->name, b->name); } -int git_remote_download( - git_remote *remote, - git_transfer_progress_callback progress_cb, - void *progress_payload) +int git_remote_download(git_remote *remote) { int error; git_vector refs; @@ -767,7 +764,7 @@ int git_remote_download( if ((error = git_fetch_negotiate(remote)) < 0) return error; - return git_fetch_download_pack(remote, progress_cb, progress_payload); + return git_fetch_download_pack(remote); } static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *update_heads, const char *fetchspec_src) diff --git a/tests-clar/network/fetchlocal.c b/tests-clar/network/fetchlocal.c index 09335b3df..28c7115bf 100644 --- a/tests-clar/network/fetchlocal.c +++ b/tests-clar/network/fetchlocal.c @@ -25,13 +25,18 @@ void test_network_fetchlocal__complete(void) git_strarray refnames = {0}; const char *url = cl_git_fixture_url("testrepo.git"); + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + + callbacks.transfer_progress = transfer_cb; + callbacks.payload = &callcount; cl_set_cleanup(&cleanup_local_repo, "foo"); cl_git_pass(git_repository_init(&repo, "foo", true)); cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); + git_remote_set_callbacks(origin, &callbacks); cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(origin, transfer_cb, &callcount)); + cl_git_pass(git_remote_download(origin)); cl_git_pass(git_remote_update_tips(origin)); cl_git_pass(git_reference_list(&refnames, repo)); @@ -56,6 +61,10 @@ void test_network_fetchlocal__partial(void) int callcount = 0; git_strarray refnames = {0}; const char *url; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + + callbacks.transfer_progress = transfer_cb; + callbacks.payload = &callcount; cl_set_cleanup(&cleanup_sandbox, NULL); cl_git_pass(git_reference_list(&refnames, repo)); @@ -63,8 +72,9 @@ void test_network_fetchlocal__partial(void) url = cl_git_fixture_url("testrepo.git"); cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); + git_remote_set_callbacks(origin, &callbacks); cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(origin, transfer_cb, &callcount)); + cl_git_pass(git_remote_download(origin)); cl_git_pass(git_remote_update_tips(origin)); git_strarray_free(&refnames); diff --git a/tests-clar/network/remote/local.c b/tests-clar/network/remote/local.c index c8edd37f5..6d658a2e4 100644 --- a/tests-clar/network/remote/local.c +++ b/tests-clar/network/remote/local.c @@ -123,7 +123,7 @@ void test_network_remote_local__shorthand_fetch_refspec0(void) cl_git_pass(git_remote_add_fetch(remote, refspec)); cl_git_pass(git_remote_add_fetch(remote, refspec2)); - cl_git_pass(git_remote_download(remote, NULL, NULL)); + cl_git_pass(git_remote_download(remote)); cl_git_pass(git_remote_update_tips(remote)); cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/sloppy/master")); @@ -145,7 +145,7 @@ void test_network_remote_local__shorthand_fetch_refspec1(void) cl_git_pass(git_remote_add_fetch(remote, refspec)); cl_git_pass(git_remote_add_fetch(remote, refspec2)); - cl_git_pass(git_remote_download(remote, NULL, NULL)); + cl_git_pass(git_remote_download(remote)); cl_git_pass(git_remote_update_tips(remote)); cl_git_fail(git_reference_lookup(&ref, repo, "refs/remotes/master")); @@ -160,7 +160,7 @@ void test_network_remote_local__tagopt(void) connect_to_local_repository(cl_fixture("testrepo.git")); git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_ALL); - cl_git_pass(git_remote_download(remote, NULL, NULL)); + cl_git_pass(git_remote_download(remote)); cl_git_pass(git_remote_update_tips(remote)); @@ -179,7 +179,7 @@ void test_network_remote_local__push_to_bare_remote(void) /* Get some commits */ connect_to_local_repository(cl_fixture("testrepo.git")); cl_git_pass(git_remote_add_fetch(remote, "master:master")); - cl_git_pass(git_remote_download(remote, NULL, NULL)); + cl_git_pass(git_remote_download(remote)); cl_git_pass(git_remote_update_tips(remote)); git_remote_disconnect(remote); @@ -215,7 +215,7 @@ void test_network_remote_local__push_to_non_bare_remote(void) /* Get some commits */ connect_to_local_repository(cl_fixture("testrepo.git")); cl_git_pass(git_remote_add_fetch(remote, "master:master")); - cl_git_pass(git_remote_download(remote, NULL, NULL)); + cl_git_pass(git_remote_download(remote)); cl_git_pass(git_remote_update_tips(remote)); git_remote_disconnect(remote); diff --git a/tests-clar/online/clone.c b/tests-clar/online/clone.c index dc5aa4150..bda260858 100644 --- a/tests-clar/online/clone.c +++ b/tests-clar/online/clone.c @@ -100,11 +100,15 @@ void test_online_clone__can_checkout_a_cloned_repo(void) bool checkout_progress_cb_was_called = false, fetch_progress_cb_was_called = false; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; g_options.checkout_opts.progress_cb = &checkout_progress; g_options.checkout_opts.progress_payload = &checkout_progress_cb_was_called; - g_options.fetch_progress_cb = &fetch_progress; - g_options.fetch_progress_payload = &fetch_progress_cb_was_called; + + callbacks.transfer_progress = &fetch_progress; + callbacks.payload = &fetch_progress_cb_was_called; + g_options.remote_callbacks = &callbacks; cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); @@ -199,6 +203,16 @@ static int cancel_at_half(const git_transfer_progress *stats, void *payload) void test_online_clone__can_cancel(void) { - g_options.fetch_progress_cb = cancel_at_half; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + + callbacks.transfer_progress = cancel_at_half; + g_options.remote_callbacks = &callbacks; + cl_git_fail_with(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options), GIT_EUSER); } + + + + + + diff --git a/tests-clar/online/fetch.c b/tests-clar/online/fetch.c index f76c6cff9..df1b2e288 100644 --- a/tests-clar/online/fetch.c +++ b/tests-clar/online/fetch.c @@ -38,14 +38,16 @@ static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n) git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; size_t bytes_received = 0; + callbacks.transfer_progress = progress; callbacks.update_tips = update_tips; + callbacks.payload = &bytes_received; counter = 0; cl_git_pass(git_remote_create(&remote, _repo, "test", url)); git_remote_set_callbacks(remote, &callbacks); git_remote_set_autotag(remote, flag); cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(remote, progress, &bytes_received)); + cl_git_pass(git_remote_download(remote)); cl_git_pass(git_remote_update_tips(remote)); git_remote_disconnect(remote); cl_assert_equal_i(counter, n); @@ -93,6 +95,7 @@ void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date git_repository *_repository; bool invoked = false; git_remote *remote; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; git_clone_options opts = GIT_CLONE_OPTIONS_INIT; opts.bare = true; @@ -107,7 +110,10 @@ void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date cl_assert_equal_i(false, invoked); - cl_git_pass(git_remote_download(remote, &transferProgressCallback, &invoked)); + callbacks.transfer_progress = &transferProgressCallback; + callbacks.payload = &invoked; + git_remote_set_callbacks(remote, &callbacks); + cl_git_pass(git_remote_download(remote)); cl_assert_equal_i(false, invoked); @@ -131,11 +137,17 @@ void test_online_fetch__can_cancel(void) { git_remote *remote; size_t bytes_received = 0; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; cl_git_pass(git_remote_create(&remote, _repo, "test", "http://github.com/libgit2/TestGitRepository.git")); + + callbacks.transfer_progress = cancel_at_half; + callbacks.payload = &bytes_received; + git_remote_set_callbacks(remote, &callbacks); + cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - cl_git_fail_with(git_remote_download(remote, cancel_at_half, &bytes_received), GIT_EUSER); + cl_git_fail_with(git_remote_download(remote), GIT_EUSER); git_remote_disconnect(remote); git_remote_free(remote); } diff --git a/tests-clar/online/fetchhead.c b/tests-clar/online/fetchhead.c index 58717eef8..5d9eb1318 100644 --- a/tests-clar/online/fetchhead.c +++ b/tests-clar/online/fetchhead.c @@ -48,7 +48,7 @@ static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fet } cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(remote, NULL, NULL)); + cl_git_pass(git_remote_download(remote)); cl_git_pass(git_remote_update_tips(remote)); git_remote_disconnect(remote); git_remote_free(remote); diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index 6a4a9b281..d0d4ed05b 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -326,7 +326,7 @@ void test_online_push__initialize(void) /* Now that we've deleted everything, fetch from the remote */ cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(_remote, NULL, NULL)); + cl_git_pass(git_remote_download(_remote)); cl_git_pass(git_remote_update_tips(_remote)); git_remote_disconnect(_remote); } else diff --git a/tests-clar/online/push_util.h b/tests-clar/online/push_util.h index 759122aa6..659c6dd54 100644 --- a/tests-clar/online/push_util.h +++ b/tests-clar/online/push_util.h @@ -12,7 +12,7 @@ extern const git_oid OID_ZERO; * @param data pointer to a record_callbacks_data instance */ #define RECORD_CALLBACKS_INIT(data) \ - { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, record_update_tips_cb, data } + { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, NULL, record_update_tips_cb, data } typedef struct { char *name; From e3c131c544bc79573ebefab4931b5ca89836ace1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 16 Sep 2013 05:02:25 +0200 Subject: [PATCH 02/14] remote: move the credentials callback to the struct Move this one as well, letting us have a single way of setting the callbacks for the remote, and removing fields from the clone options. --- examples/network/clone.c | 2 +- examples/network/fetch.c | 2 +- examples/network/ls-remote.c | 4 +++- include/git2/clone.h | 5 ----- include/git2/remote.h | 1 + src/clone.c | 2 -- src/remote.c | 13 +------------ src/remote.h | 2 -- src/transports/local.c | 2 +- tests-clar/online/clone.c | 13 +++++++++---- tests-clar/online/push.c | 3 ++- tests-clar/online/push_util.h | 2 +- 12 files changed, 20 insertions(+), 31 deletions(-) diff --git a/examples/network/clone.c b/examples/network/clone.c index f1002656c..f553c4077 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -76,9 +76,9 @@ int do_clone(git_repository *repo, int argc, char **argv) checkout_opts.progress_payload = &pd; clone_opts.checkout_opts = checkout_opts; callbacks.transfer_progress = &fetch_progress; + callbacks.credentials = cred_acquire_cb; callbacks.payload = &pd; clone_opts.remote_callbacks = &callbacks; - clone_opts.cred_acquire_cb = cred_acquire_cb; // Do the clone error = git_clone(&cloned_repo, url, path, &clone_opts); diff --git a/examples/network/fetch.c b/examples/network/fetch.c index 1de223373..0c545ad7e 100644 --- a/examples/network/fetch.c +++ b/examples/network/fetch.c @@ -91,8 +91,8 @@ int fetch(git_repository *repo, int argc, char **argv) // Set up the callbacks (only update_tips for now) callbacks.update_tips = &update_cb; callbacks.progress = &progress_cb; + callbacks.credentials = cred_acquire_cb; git_remote_set_callbacks(remote, &callbacks); - git_remote_set_cred_acquire_cb(remote, &cred_acquire_cb, NULL); // Set up the information for the background worker thread data.remote = remote; diff --git a/examples/network/ls-remote.c b/examples/network/ls-remote.c index b22ac47a0..b65759ed3 100644 --- a/examples/network/ls-remote.c +++ b/examples/network/ls-remote.c @@ -18,6 +18,7 @@ static int use_remote(git_repository *repo, char *name) { git_remote *remote = NULL; int error; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; // Find the remote by name error = git_remote_load(&remote, repo, name); @@ -27,7 +28,8 @@ static int use_remote(git_repository *repo, char *name) goto cleanup; } - git_remote_set_cred_acquire_cb(remote, &cred_acquire_cb, NULL); + callbacks.credentials = cred_acquire_cb; + git_remote_set_callbacks(remote, &callbacks); error = git_remote_connect(remote, GIT_DIRECTION_FETCH); if (error < 0) diff --git a/include/git2/clone.h b/include/git2/clone.h index 122806ad5..38c759f6e 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -48,9 +48,6 @@ GIT_BEGIN_DECL * results in the same behavior as GIT_REMOTE_DEFAULT_FETCH. * - `push_spec` is the fetch specification to be used for pushing. NULL means * use the same spec as for fetching. - * - `cred_acquire_cb` is a callback to be used if credentials are required - * during the initial fetch. - * - `cred_acquire_payload` is the payload for the above callback. * - `transport_flags` is flags used to create transport if no transport is * provided. * - `transport` is a custom transport to be used for the initial fetch. NULL @@ -74,8 +71,6 @@ typedef struct git_clone_options { const char *pushurl; const char *fetch_spec; const char *push_spec; - git_cred_acquire_cb cred_acquire_cb; - void *cred_acquire_payload; git_transport_flags_t transport_flags; git_transport *transport; git_remote_callbacks *remote_callbacks; diff --git a/include/git2/remote.h b/include/git2/remote.h index 2bde5e365..83ad195f4 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -395,6 +395,7 @@ struct git_remote_callbacks { unsigned int version; void (*progress)(const char *str, int len, void *data); int (*completion)(git_remote_completion_type type, void *data); + int (*credentials)(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *data); int (*transfer_progress)(const git_transfer_progress *stats, void *data); int (*update_tips)(const char *refname, const git_oid *a, const git_oid *b, void *data); void *payload; diff --git a/src/clone.c b/src/clone.c index 90d677bbb..8385fb264 100644 --- a/src/clone.c +++ b/src/clone.c @@ -310,8 +310,6 @@ static int create_and_configure_origin( if ((error = git_remote_create(&origin, repo, options->remote_name, url)) < 0) goto on_error; - git_remote_set_cred_acquire_cb(origin, options->cred_acquire_cb, - options->cred_acquire_payload); git_remote_set_autotag(origin, options->remote_autotag); /* * Don't write FETCH_HEAD, we'll check out the remote tracking diff --git a/src/remote.c b/src/remote.c index e4696c4ec..2d0321eb3 100644 --- a/src/remote.c +++ b/src/remote.c @@ -591,7 +591,7 @@ int git_remote_connect(git_remote *remote, git_direction direction) if (!remote->check_cert) flags |= GIT_TRANSPORTFLAGS_NO_CHECK_CERT; - if (t->connect(t, url, remote->cred_acquire_cb, remote->cred_acquire_payload, direction, flags) < 0) + if (t->connect(t, url, remote->callbacks.credentials, remote->callbacks.payload, direction, flags) < 0) goto on_error; remote->transport = t; @@ -1152,17 +1152,6 @@ int git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks return 0; } -void git_remote_set_cred_acquire_cb( - git_remote *remote, - git_cred_acquire_cb cred_acquire_cb, - void *payload) -{ - assert(remote); - - remote->cred_acquire_cb = cred_acquire_cb; - remote->cred_acquire_payload = payload; -} - int git_remote_set_transport(git_remote *remote, git_transport *transport) { assert(remote && transport); diff --git a/src/remote.h b/src/remote.h index dce4803ed..269584d96 100644 --- a/src/remote.h +++ b/src/remote.h @@ -21,8 +21,6 @@ struct git_remote { char *pushurl; git_vector refs; git_vector refspecs; - git_cred_acquire_cb cred_acquire_cb; - void *cred_acquire_payload; git_transport *transport; git_repository *repo; git_remote_callbacks callbacks; diff --git a/src/transports/local.c b/src/transports/local.c index 9ebea979c..3c1f98804 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -434,7 +434,7 @@ static int local_push( if (!url || t->parent.close(&t->parent) < 0 || t->parent.connect(&t->parent, url, - push->remote->cred_acquire_cb, NULL, GIT_DIRECTION_PUSH, flags)) + push->remote->callbacks.credentials, NULL, GIT_DIRECTION_PUSH, flags)) goto on_error; } diff --git a/tests-clar/online/clone.c b/tests-clar/online/clone.c index bda260858..b82cbcd46 100644 --- a/tests-clar/online/clone.c +++ b/tests-clar/online/clone.c @@ -155,11 +155,13 @@ void test_online_clone__credentials(void) cl_getenv("GITTEST_REMOTE_USER"), cl_getenv("GITTEST_REMOTE_PASS") }; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; if (!remote_url) return; - g_options.cred_acquire_cb = git_cred_userpass; - g_options.cred_acquire_payload = &user_pass; + callbacks.credentials = git_cred_userpass; + callbacks.payload = &user_pass; + g_options.remote_callbacks = &callbacks; cl_git_pass(git_clone(&g_repo, remote_url, "./foo", &g_options)); git_repository_free(g_repo); g_repo = NULL; @@ -172,8 +174,11 @@ void test_online_clone__bitbucket_style(void) "libgit2", "libgit2" }; - g_options.cred_acquire_cb = git_cred_userpass; - g_options.cred_acquire_payload = &user_pass; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + + callbacks.credentials = git_cred_userpass; + callbacks.payload = &user_pass; + g_options.remote_callbacks = &callbacks; cl_git_pass(git_clone(&g_repo, BB_REPO_URL, "./foo", &g_options)); git_repository_free(g_repo); g_repo = NULL; diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index d0d4ed05b..05cef56e7 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -17,6 +17,8 @@ static char *_remote_url; static char *_remote_user; static char *_remote_pass; +static int cred_acquire_cb(git_cred **, const char *, const char *, unsigned int, void *); + static git_remote *_remote; static bool _cred_acquire_called; static record_callbacks_data _record_cbs_data = {{ 0 }}; @@ -294,7 +296,6 @@ void test_online_push__initialize(void) if (_remote_url) { cl_git_pass(git_remote_create(&_remote, _repo, "test", _remote_url)); - git_remote_set_cred_acquire_cb(_remote, cred_acquire_cb, &_cred_acquire_called); record_callbacks_data_clear(&_record_cbs_data); git_remote_set_callbacks(_remote, &_record_cbs); diff --git a/tests-clar/online/push_util.h b/tests-clar/online/push_util.h index 659c6dd54..64f02cf2f 100644 --- a/tests-clar/online/push_util.h +++ b/tests-clar/online/push_util.h @@ -12,7 +12,7 @@ extern const git_oid OID_ZERO; * @param data pointer to a record_callbacks_data instance */ #define RECORD_CALLBACKS_INIT(data) \ - { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, NULL, record_update_tips_cb, data } + { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, record_update_tips_cb, data } typedef struct { char *name; From d19870d947eef17008ae0b4b7ebc9e9d0038a770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 16 Sep 2013 05:10:55 +0200 Subject: [PATCH 03/14] clone: implement git_clone_into This allows you to set up the repository and remote as you which to have them before performing the clone operation. --- include/git2/clone.h | 16 ++++++++ src/clone.c | 78 +++++++++++++++++++++++++++++++-------- tests-clar/online/clone.c | 39 ++++++++++++++++++++ 3 files changed, 118 insertions(+), 15 deletions(-) diff --git a/include/git2/clone.h b/include/git2/clone.h index 38c759f6e..c3936f6b0 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -99,6 +99,22 @@ GIT_EXTERN(int) git_clone( const char *local_path, const git_clone_options *options); +/** + * Clone into a repository + * + * After creating the repository and remote and configuring them for + * paths and callbacks respectively, you can call this function to + * perform the clone operation and optionally checkout files. + * + * @param repo the repository to use + * @param remote the remote repository to clone from + * @param co_opts options to use during checkout + * @param branch the branch to checkout after the clone, pass NULL for the remote's + * default branch + * @return 0 on success or an error code + */ +GIT_EXTERN(int) git_clone_into(git_repository *repo, git_remote *remote, git_checkout_opts *co_opts, const char *branch); + /** @} */ GIT_END_DECL #endif diff --git a/src/clone.c b/src/clone.c index 8385fb264..436fdff43 100644 --- a/src/clone.c +++ b/src/clone.c @@ -270,23 +270,23 @@ cleanup: static int update_head_to_branch( git_repository *repo, - const git_clone_options *options) + const char *remote_name, + const char *branch) { int retcode; git_buf remote_branch_name = GIT_BUF_INIT; git_reference* remote_ref = NULL; - assert(options->checkout_branch); + assert(remote_name && branch); if ((retcode = git_buf_printf(&remote_branch_name, GIT_REFS_REMOTES_DIR "%s/%s", - options->remote_name, options->checkout_branch)) < 0 ) + remote_name, branch)) < 0 ) goto cleanup; if ((retcode = git_reference_lookup(&remote_ref, repo, git_buf_cstr(&remote_branch_name))) < 0) goto cleanup; - retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), - options->checkout_branch); + retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), branch); cleanup: git_reference_free(remote_ref); @@ -350,6 +350,23 @@ on_error: return error; } +static int do_fetch(git_remote *origin) +{ + int retcode; + + /* Connect and download everything */ + if ((retcode = git_remote_connect(origin, GIT_DIRECTION_FETCH)) < 0) + return retcode; + + if ((retcode = git_remote_download(origin)) < 0) + return retcode; + + /* Create "origin/foo" branches for all remote branches */ + if ((retcode = git_remote_update_tips(origin)) < 0) + return retcode; + + return 0; +} static int setup_remotes_and_fetch( git_repository *repo, @@ -374,20 +391,12 @@ static int setup_remotes_and_fetch( ((retcode = git_remote_add_fetch(origin, "refs/tags/*:refs/tags/*")) < 0)) goto on_error; - /* Connect and download everything */ - if ((retcode = git_remote_connect(origin, GIT_DIRECTION_FETCH)) < 0) - goto on_error; - - if ((retcode = git_remote_download(origin)) < 0) - goto on_error; - - /* Create "origin/foo" branches for all remote branches */ - if ((retcode = git_remote_update_tips(origin)) < 0) + if ((retcode = do_fetch(origin)) < 0) goto on_error; /* Point HEAD to the requested branch */ if (options->checkout_branch) - retcode = update_head_to_branch(repo, options); + retcode = update_head_to_branch(repo, options->remote_name, options->checkout_branch); /* Point HEAD to the same ref as the remote's head */ else retcode = update_head_to_remote(repo, origin); @@ -432,6 +441,45 @@ static void normalize_options(git_clone_options *dst, const git_clone_options *s } } +int git_clone_into(git_repository *repo, git_remote *remote, git_checkout_opts *co_opts, const char *branch) +{ + int error = 0, old_fetchhead; + size_t nspecs; + + assert(repo && remote); + + if (!git_repository_is_empty(repo)) { + giterr_set(GITERR_INVALID, "the repository is not empty"); + return -1; + } + + if ((error = git_remote_add_fetch(remote, "refs/tags/*:refs/tags/*")) < 0) + return error; + + old_fetchhead = git_remote_update_fetchhead(remote); + git_remote_set_update_fetchhead(remote, 0); + + if ((error = do_fetch(remote)) < 0) + goto cleanup; + + if (branch) + error = update_head_to_branch(repo, git_remote_name(remote), branch); + /* Point HEAD to the same ref as the remote's head */ + else + error = update_head_to_remote(repo, remote); + + if (!error && should_checkout(repo, git_repository_is_bare(repo), co_opts)) + error = git_checkout_head(repo, co_opts); + +cleanup: + git_remote_set_update_fetchhead(remote, old_fetchhead); + /* Remove the tags refspec */ + nspecs = git_remote_refspec_count(remote); + git_remote_remove_refspec(remote, nspecs); + + return error; +} + int git_clone( git_repository **out, const char *url, diff --git a/tests-clar/online/clone.c b/tests-clar/online/clone.c index b82cbcd46..9a64ba166 100644 --- a/tests-clar/online/clone.c +++ b/tests-clar/online/clone.c @@ -126,6 +126,45 @@ void test_online_clone__can_checkout_a_cloned_repo(void) git_buf_free(&path); } +void test_online_clone__clone_into(void) +{ + git_buf path = GIT_BUF_INIT; + git_remote *remote; + git_reference *head; + git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + + bool checkout_progress_cb_was_called = false, + fetch_progress_cb_was_called = false; + + checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + checkout_opts.progress_cb = &checkout_progress; + checkout_opts.progress_payload = &checkout_progress_cb_was_called; + + cl_git_pass(git_repository_init(&g_repo, "./foo", false)); + cl_git_pass(git_remote_create(&remote, g_repo, "origin", LIVE_REPO_URL)); + + callbacks.transfer_progress = &fetch_progress; + callbacks.payload = &fetch_progress_cb_was_called; + git_remote_set_callbacks(remote, &callbacks); + + cl_git_pass(git_clone_into(g_repo, remote, &checkout_opts, NULL)); + + cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt")); + cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path))); + + cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); + cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); + cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); + + cl_assert_equal_i(true, checkout_progress_cb_was_called); + cl_assert_equal_i(true, fetch_progress_cb_was_called); + + git_remote_free(remote); + git_reference_free(head); + git_buf_free(&path); +} + static int update_tips(const char *refname, const git_oid *a, const git_oid *b, void *payload) { int *callcount = (int*)payload; From fe3a40a4ff056400cde6e456211d6b5f2ec1008e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 16 Sep 2013 16:54:37 +0200 Subject: [PATCH 04/14] remote: add a convenience 'fetch' function. --- include/git2/remote.h | 11 +++++++++++ src/clone.c | 22 ++-------------------- src/remote.c | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 83ad195f4..8c21870de 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -310,6 +310,17 @@ GIT_EXTERN(void) git_remote_free(git_remote *remote); */ GIT_EXTERN(int) git_remote_update_tips(git_remote *remote); +/** + * Download new data and update tips + * + * Convenience function to connect to a remote, download the data, + * disconnect and update the remote-tracking branches. + * + * @param remote the remote to fetch from + * @return 0 or an error code + */ +GIT_EXTERN(int) git_remote_fetch(git_remote *remote); + /** * Return whether a string is a valid remote URL * diff --git a/src/clone.c b/src/clone.c index 436fdff43..13f2a8eea 100644 --- a/src/clone.c +++ b/src/clone.c @@ -350,24 +350,6 @@ on_error: return error; } -static int do_fetch(git_remote *origin) -{ - int retcode; - - /* Connect and download everything */ - if ((retcode = git_remote_connect(origin, GIT_DIRECTION_FETCH)) < 0) - return retcode; - - if ((retcode = git_remote_download(origin)) < 0) - return retcode; - - /* Create "origin/foo" branches for all remote branches */ - if ((retcode = git_remote_update_tips(origin)) < 0) - return retcode; - - return 0; -} - static int setup_remotes_and_fetch( git_repository *repo, const char *url, @@ -391,7 +373,7 @@ static int setup_remotes_and_fetch( ((retcode = git_remote_add_fetch(origin, "refs/tags/*:refs/tags/*")) < 0)) goto on_error; - if ((retcode = do_fetch(origin)) < 0) + if ((retcode = git_remote_fetch(origin)) < 0) goto on_error; /* Point HEAD to the requested branch */ @@ -459,7 +441,7 @@ int git_clone_into(git_repository *repo, git_remote *remote, git_checkout_opts * old_fetchhead = git_remote_update_fetchhead(remote); git_remote_set_update_fetchhead(remote, 0); - if ((error = do_fetch(remote)) < 0) + if ((error = git_remote_fetch(remote)) < 0) goto cleanup; if (branch) diff --git a/src/remote.c b/src/remote.c index 2d0321eb3..ace886502 100644 --- a/src/remote.c +++ b/src/remote.c @@ -767,6 +767,24 @@ int git_remote_download(git_remote *remote) return git_fetch_download_pack(remote); } +int git_remote_fetch(git_remote *remote) +{ + int error; + + /* Connect and download everything */ + if ((error = git_remote_connect(remote, GIT_DIRECTION_FETCH)) < 0) + return error; + + if ((error = git_remote_download(remote)) < 0) + return error; + + /* We don't need to be connected anymore */ + git_remote_disconnect(remote); + + /* Create "remote/foo" branches for all remote branches */ + return git_remote_update_tips(remote); +} + static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *update_heads, const char *fetchspec_src) { unsigned int i; From c8dbec4803aa7d8300f19a97431bbf631ac5a392 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 16 Sep 2013 18:42:53 +0200 Subject: [PATCH 05/14] clone: remove the autotag option Downloading all tags is part of what makes it a clone instead of simply a fetch. --- include/git2/clone.h | 3 --- src/clone.c | 13 +++++-------- tests-clar/clone/nonetwork.c | 33 --------------------------------- 3 files changed, 5 insertions(+), 44 deletions(-) diff --git a/include/git2/clone.h b/include/git2/clone.h index c3936f6b0..c80bf9baa 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -54,8 +54,6 @@ GIT_BEGIN_DECL * means use the transport autodetected from the URL. * - `remote_callbacks` may be used to specify custom progress callbacks for * the origin remote before the fetch is initiated. - * - `remote_autotag` may be used to specify the autotag setting before the - * initial fetch. The default is GIT_REMOTE_DOWNLOAD_TAGS_ALL. * - `checkout_branch` gives the name of the branch to checkout. NULL means * use the remote's HEAD. */ @@ -74,7 +72,6 @@ typedef struct git_clone_options { git_transport_flags_t transport_flags; git_transport *transport; git_remote_callbacks *remote_callbacks; - git_remote_autotag_option_t remote_autotag; const char* checkout_branch; } git_clone_options; diff --git a/src/clone.c b/src/clone.c index 13f2a8eea..d720907cc 100644 --- a/src/clone.c +++ b/src/clone.c @@ -310,7 +310,6 @@ static int create_and_configure_origin( if ((error = git_remote_create(&origin, repo, options->remote_name, url)) < 0) goto on_error; - git_remote_set_autotag(origin, options->remote_autotag); /* * Don't write FETCH_HEAD, we'll check out the remote tracking * branch ourselves based on the server's default. @@ -364,13 +363,11 @@ static int setup_remotes_and_fetch( git_remote_set_update_fetchhead(origin, 0); - /* If the download_tags value has not been specified, then make sure to - * download tags as well. It is set here because we want to download tags - * on the initial clone, but do not want to persist the value in the - * configuration file. - */ - if (origin->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_AUTO && - ((retcode = git_remote_add_fetch(origin, "refs/tags/*:refs/tags/*")) < 0)) + /* Make sure to download all tags as well. It is set here because + * we want to download tags on the initial clone, but do not + * want to persist the value in the configuration file. + */ + if((retcode = git_remote_add_fetch(origin, "refs/tags/*:refs/tags/*")) < 0) goto on_error; if ((retcode = git_remote_fetch(origin)) < 0) diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index 5b9faa645..382491610 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -171,39 +171,6 @@ void test_clone_nonetwork__custom_push_spec(void) cl_assert_equal_s("refs/heads/foo", git_refspec_dst(actual_fs)); } -void test_clone_nonetwork__custom_autotag(void) -{ - git_remote *origin; - git_strarray tags = {0}; - - g_options.remote_autotag = GIT_REMOTE_DOWNLOAD_TAGS_NONE; - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); - - cl_git_pass(git_tag_list(&tags, g_repo)); - cl_assert_equal_sz(0, tags.count); - - cl_git_pass(git_remote_load(&origin, g_repo, "origin")); - cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_NONE, origin->download_tags); - - git_strarray_free(&tags); - git_remote_free(origin); -} - -void test_clone_nonetwork__custom_autotag_tags_all(void) -{ - git_strarray tags = {0}; - git_remote *origin; - - g_options.remote_autotag = GIT_REMOTE_DOWNLOAD_TAGS_ALL; - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); - - cl_git_pass(git_remote_load(&origin, g_repo, "origin")); - cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_ALL, origin->download_tags); - - git_strarray_free(&tags); - git_remote_free(origin); -} - void test_clone_nonetwork__cope_with_already_existing_directory(void) { p_mkdir("./foo", GIT_DIR_MODE); From e3a92f0dfc28e423a2f06688338f81b8d17abaf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 17 Sep 2013 05:31:34 +0200 Subject: [PATCH 06/14] clone: implement git_clone on top of git_clone_into Unify the code bases. --- src/clone.c | 77 +++++++++++++---------------------------------------- 1 file changed, 19 insertions(+), 58 deletions(-) diff --git a/src/clone.c b/src/clone.c index d720907cc..3df317045 100644 --- a/src/clone.c +++ b/src/clone.c @@ -310,12 +310,6 @@ static int create_and_configure_origin( if ((error = git_remote_create(&origin, repo, options->remote_name, url)) < 0) goto on_error; - /* - * Don't write FETCH_HEAD, we'll check out the remote tracking - * branch ourselves based on the server's default. - */ - git_remote_set_update_fetchhead(origin, 0); - if (options->remote_callbacks && (error = git_remote_set_callbacks(origin, options->remote_callbacks)) < 0) goto on_error; @@ -349,43 +343,6 @@ on_error: return error; } -static int setup_remotes_and_fetch( - git_repository *repo, - const char *url, - const git_clone_options *options) -{ - int retcode = GIT_ERROR; - git_remote *origin = NULL; - - /* Construct an origin remote */ - if ((retcode = create_and_configure_origin(&origin, repo, url, options)) < 0) - goto on_error; - - git_remote_set_update_fetchhead(origin, 0); - - /* Make sure to download all tags as well. It is set here because - * we want to download tags on the initial clone, but do not - * want to persist the value in the configuration file. - */ - if((retcode = git_remote_add_fetch(origin, "refs/tags/*:refs/tags/*")) < 0) - goto on_error; - - if ((retcode = git_remote_fetch(origin)) < 0) - goto on_error; - - /* Point HEAD to the requested branch */ - if (options->checkout_branch) - retcode = update_head_to_branch(repo, options->remote_name, options->checkout_branch); - /* Point HEAD to the same ref as the remote's head */ - else - retcode = update_head_to_remote(repo, origin); - -on_error: - git_remote_free(origin); - return retcode; -} - - static bool should_checkout( git_repository *repo, bool is_bare, @@ -467,6 +424,7 @@ int git_clone( { int retcode = GIT_ERROR; git_repository *repo = NULL; + git_remote *origin; git_clone_options normOptions; int remove_directory_on_failure = 0; git_repository_init_options initOptions = GIT_REPOSITORY_INIT_OPTIONS_INIT; @@ -486,24 +444,27 @@ int git_clone( /* Only remove the directory on failure if we create it */ remove_directory_on_failure = !git_path_exists(local_path); - if (!(retcode = git_repository_init_ext(&repo, local_path, normOptions.init_options))) { - if ((retcode = setup_remotes_and_fetch(repo, url, &normOptions)) < 0) { - /* Failed to fetch; clean up */ - git_repository_free(repo); + if ((retcode = git_repository_init_ext(&repo, local_path, normOptions.init_options)) < 0) + return retcode; - if (remove_directory_on_failure) - git_futils_rmdir_r(local_path, NULL, GIT_RMDIR_REMOVE_FILES); - else - git_futils_cleanupdir_r(local_path); + if ((retcode = create_and_configure_origin(&origin, repo, url, &normOptions)) < 0) + goto cleanup; - } else { - *out = repo; - retcode = 0; - } - } + retcode = git_clone_into(repo, origin, &normOptions.checkout_opts, normOptions.checkout_branch); + git_remote_free(origin); - if (!retcode && should_checkout(repo, normOptions.bare, &normOptions.checkout_opts)) - retcode = git_checkout_head(*out, &normOptions.checkout_opts); + if (retcode < 0) + goto cleanup; + + *out = repo; + return 0; + +cleanup: + git_repository_free(repo); + if (remove_directory_on_failure) + git_futils_rmdir_r(local_path, NULL, GIT_RMDIR_REMOVE_FILES); + else + git_futils_cleanupdir_r(local_path); return retcode; } From 6ac15eff6d173674d9f17e9d5ddb98997eb97cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 20 Sep 2013 22:34:05 +0200 Subject: [PATCH 07/14] clone: remove more options from basic clone The basic clone function is there to make it easy to create a "normal" clone. Remove a bunch of options that are about changing the remote's configuration. --- include/git2/clone.h | 7 ------ src/clone.c | 48 ++++------------------------------- tests-clar/clone/nonetwork.c | 49 ------------------------------------ 3 files changed, 5 insertions(+), 99 deletions(-) diff --git a/include/git2/clone.h b/include/git2/clone.h index c80bf9baa..0a89b5712 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -62,15 +62,8 @@ typedef struct git_clone_options { unsigned int version; git_checkout_opts checkout_opts; - git_repository_init_options *init_options; int bare; - const char *remote_name; - const char *pushurl; - const char *fetch_spec; - const char *push_spec; - git_transport_flags_t transport_flags; - git_transport *transport; git_remote_callbacks *remote_callbacks; const char* checkout_branch; } git_clone_options; diff --git a/src/clone.c b/src/clone.c index 3df317045..abea0bd8f 100644 --- a/src/clone.c +++ b/src/clone.c @@ -307,31 +307,13 @@ static int create_and_configure_origin( int error; git_remote *origin = NULL; - if ((error = git_remote_create(&origin, repo, options->remote_name, url)) < 0) + if ((error = git_remote_create(&origin, repo, "origin", url)) < 0) goto on_error; if (options->remote_callbacks && (error = git_remote_set_callbacks(origin, options->remote_callbacks)) < 0) goto on_error; - if (options->fetch_spec) { - git_remote_clear_refspecs(origin); - if ((error = git_remote_add_fetch(origin, options->fetch_spec)) < 0) - goto on_error; - } - - if (options->push_spec && - (error = git_remote_add_push(origin, options->push_spec)) < 0) - goto on_error; - - if (options->pushurl && - (error = git_remote_set_pushurl(origin, options->pushurl)) < 0) - goto on_error; - - if (options->transport_flags == GIT_TRANSPORTFLAGS_NO_CHECK_CERT) { - git_remote_check_cert(origin, 0); - } - if ((error = git_remote_save(origin)) < 0) goto on_error; @@ -360,23 +342,6 @@ static bool should_checkout( return !git_repository_head_unborn(repo); } -static void normalize_options(git_clone_options *dst, const git_clone_options *src, git_repository_init_options *initOptions) -{ - git_clone_options default_options = GIT_CLONE_OPTIONS_INIT; - if (!src) src = &default_options; - - *dst = *src; - - /* Provide defaults for null pointers */ - if (!dst->remote_name) dst->remote_name = "origin"; - if (!dst->init_options) { - dst->init_options = initOptions; - initOptions->flags = GIT_REPOSITORY_INIT_MKPATH; - if (dst->bare) - initOptions->flags |= GIT_REPOSITORY_INIT_BARE; - } -} - int git_clone_into(git_repository *repo, git_remote *remote, git_checkout_opts *co_opts, const char *branch) { int error = 0, old_fetchhead; @@ -425,14 +390,11 @@ int git_clone( int retcode = GIT_ERROR; git_repository *repo = NULL; git_remote *origin; - git_clone_options normOptions; int remove_directory_on_failure = 0; - git_repository_init_options initOptions = GIT_REPOSITORY_INIT_OPTIONS_INIT; assert(out && url && local_path); - normalize_options(&normOptions, options, &initOptions); - GITERR_CHECK_VERSION(&normOptions, GIT_CLONE_OPTIONS_VERSION, "git_clone_options"); + GITERR_CHECK_VERSION(options, GIT_CLONE_OPTIONS_VERSION, "git_clone_options"); /* Only clone to a new directory or an empty directory */ if (git_path_exists(local_path) && !git_path_is_empty_dir(local_path)) { @@ -444,13 +406,13 @@ int git_clone( /* Only remove the directory on failure if we create it */ remove_directory_on_failure = !git_path_exists(local_path); - if ((retcode = git_repository_init_ext(&repo, local_path, normOptions.init_options)) < 0) + if ((retcode = git_repository_init(&repo, local_path, options->bare)) < 0) return retcode; - if ((retcode = create_and_configure_origin(&origin, repo, url, &normOptions)) < 0) + if ((retcode = create_and_configure_origin(&origin, repo, url, options)) < 0) goto cleanup; - retcode = git_clone_into(repo, origin, &normOptions.checkout_opts, normOptions.checkout_branch); + retcode = git_clone_into(repo, origin, &options->checkout_opts, options->checkout_branch); git_remote_free(origin); if (retcode < 0) diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index 382491610..84654fa5a 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -122,55 +122,6 @@ void test_clone_nonetwork__fail_with_already_existing_but_non_empty_directory(vo cl_git_fail(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); } -void test_clone_nonetwork__custom_origin_name(void) -{ - g_options.remote_name = "my_origin"; - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); - - cl_git_pass(git_remote_load(&g_remote, g_repo, "my_origin")); -} - -void test_clone_nonetwork__custom_push_url(void) -{ - const char *url = "http://example.com"; - - g_options.pushurl = url; - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); - - cl_git_pass(git_remote_load(&g_remote, g_repo, "origin")); - cl_assert_equal_s(url, git_remote_pushurl(g_remote)); -} - -void test_clone_nonetwork__custom_fetch_spec(void) -{ - const git_refspec *actual_fs; - const char *spec = "+refs/heads/master:refs/heads/foo"; - - g_options.fetch_spec = spec; - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); - - cl_git_pass(git_remote_load(&g_remote, g_repo, "origin")); - actual_fs = git_remote_get_refspec(g_remote, 0); - cl_assert_equal_s("refs/heads/master", git_refspec_src(actual_fs)); - cl_assert_equal_s("refs/heads/foo", git_refspec_dst(actual_fs)); - - cl_git_pass(git_reference_lookup(&g_ref, g_repo, "refs/heads/foo")); -} - -void test_clone_nonetwork__custom_push_spec(void) -{ - const git_refspec *actual_fs; - const char *spec = "+refs/heads/master:refs/heads/foo"; - - g_options.push_spec = spec; - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); - - cl_git_pass(git_remote_load(&g_remote, g_repo, "origin")); - actual_fs = git_remote_get_refspec(g_remote, git_remote_refspec_count(g_remote) - 1); - cl_assert_equal_s("refs/heads/master", git_refspec_src(actual_fs)); - cl_assert_equal_s("refs/heads/foo", git_refspec_dst(actual_fs)); -} - void test_clone_nonetwork__cope_with_already_existing_directory(void) { p_mkdir("./foo", GIT_DIR_MODE); From b9bf5d701dd6dfcfcb41d2655f59f7669cd50ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 20 Sep 2013 22:46:32 +0200 Subject: [PATCH 08/14] clone: re-add a way to ignore certificate errors This used to be done via transport flags, which was removed in a previous commit. --- include/git2/clone.h | 1 + src/clone.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/include/git2/clone.h b/include/git2/clone.h index 0a89b5712..cf759ab5c 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -63,6 +63,7 @@ typedef struct git_clone_options { git_checkout_opts checkout_opts; int bare; + int ignore_cert_errors; git_remote_callbacks *remote_callbacks; const char* checkout_branch; diff --git a/src/clone.c b/src/clone.c index abea0bd8f..904be1b57 100644 --- a/src/clone.c +++ b/src/clone.c @@ -310,6 +310,9 @@ static int create_and_configure_origin( if ((error = git_remote_create(&origin, repo, "origin", url)) < 0) goto on_error; + if (options->ignore_cert_errors) + git_remote_check_cert(origin, 0); + if (options->remote_callbacks && (error = git_remote_set_callbacks(origin, options->remote_callbacks)) < 0) goto on_error; From eec1c1fe1e9a12b57c4014be25ce4ed390c8e199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 20 Sep 2013 22:49:20 +0200 Subject: [PATCH 09/14] clone: const-ify checkout options The removal of many options which lead to the direct usage of the user's checkout options means we should make sure they remain const. --- include/git2/checkout.h | 2 +- include/git2/clone.h | 2 +- src/checkout.c | 6 +++--- src/checkout.h | 2 +- src/clone.c | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/git2/checkout.h b/include/git2/checkout.h index aa48069cd..844f0a9e2 100644 --- a/include/git2/checkout.h +++ b/include/git2/checkout.h @@ -255,7 +255,7 @@ typedef struct git_checkout_opts { */ GIT_EXTERN(int) git_checkout_head( git_repository *repo, - git_checkout_opts *opts); + const git_checkout_opts *opts); /** * Updates files in the working tree to match the content of the index. diff --git a/include/git2/clone.h b/include/git2/clone.h index cf759ab5c..a59de1bc7 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -104,7 +104,7 @@ GIT_EXTERN(int) git_clone( * default branch * @return 0 on success or an error code */ -GIT_EXTERN(int) git_clone_into(git_repository *repo, git_remote *remote, git_checkout_opts *co_opts, const char *branch); +GIT_EXTERN(int) git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, const char *branch); /** @} */ GIT_END_DECL diff --git a/src/checkout.c b/src/checkout.c index 0e9d11bff..5d741d393 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -1119,7 +1119,7 @@ static void checkout_data_clear(checkout_data *data) static int checkout_data_init( checkout_data *data, git_iterator *target, - git_checkout_opts *proposed) + const git_checkout_opts *proposed) { int error = 0; git_repository *repo = git_iterator_owner(target); @@ -1229,7 +1229,7 @@ cleanup: int git_checkout_iterator( git_iterator *target, - git_checkout_opts *opts) + const git_checkout_opts *opts) { int error = 0; git_iterator *baseline = NULL, *workdir = NULL; @@ -1404,7 +1404,7 @@ int git_checkout_tree( int git_checkout_head( git_repository *repo, - git_checkout_opts *opts) + const git_checkout_opts *opts) { int error; git_tree *head = NULL; diff --git a/src/checkout.h b/src/checkout.h index b1dc80c38..6d7186860 100644 --- a/src/checkout.h +++ b/src/checkout.h @@ -19,6 +19,6 @@ */ extern int git_checkout_iterator( git_iterator *target, - git_checkout_opts *opts); + const git_checkout_opts *opts); #endif diff --git a/src/clone.c b/src/clone.c index 904be1b57..60525939f 100644 --- a/src/clone.c +++ b/src/clone.c @@ -331,7 +331,7 @@ on_error: static bool should_checkout( git_repository *repo, bool is_bare, - git_checkout_opts *opts) + const git_checkout_opts *opts) { if (is_bare) return false; @@ -345,7 +345,7 @@ static bool should_checkout( return !git_repository_head_unborn(repo); } -int git_clone_into(git_repository *repo, git_remote *remote, git_checkout_opts *co_opts, const char *branch) +int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, const char *branch) { int error = 0, old_fetchhead; size_t nspecs; From c833893c64d28d4c017fdbf90bbeb714314a8dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 20 Sep 2013 22:57:01 +0200 Subject: [PATCH 10/14] clone: re-allow using a custom remote name This is a small thing that by itself doesn't quite justify making the user use clone_into. --- include/git2/clone.h | 22 +++++----------------- src/clone.c | 4 +++- tests-clar/clone/nonetwork.c | 9 +++++++++ 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/include/git2/clone.h b/include/git2/clone.h index a59de1bc7..bd602fb7a 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -35,25 +35,12 @@ GIT_BEGIN_DECL * set the `checkout_strategy` to GIT_CHECKOUT_DEFAULT. * - `bare` should be set to zero to create a standard repo, non-zero for * a bare repo - * - `fetch_progress_cb` is optional callback for fetch progress. Be aware that - * this is called inline with network and indexing operations, so performance - * may be affected. - * - `fetch_progress_payload` is payload for fetch_progress_cb + * - `ignore_cert_errors` should be set to 1 if errors validating the remote host's + * certificate should be ignored. * * ** "origin" remote options: ** * - `remote_name` is the name given to the "origin" remote. The default is * "origin". - * - `pushurl` is a URL to be used for pushing. NULL means use the fetch url. - * - `fetch_spec` is the fetch specification to be used for fetching. NULL - * results in the same behavior as GIT_REMOTE_DEFAULT_FETCH. - * - `push_spec` is the fetch specification to be used for pushing. NULL means - * use the same spec as for fetching. - * - `transport_flags` is flags used to create transport if no transport is - * provided. - * - `transport` is a custom transport to be used for the initial fetch. NULL - * means use the transport autodetected from the URL. - * - `remote_callbacks` may be used to specify custom progress callbacks for - * the origin remote before the fetch is initiated. * - `checkout_branch` gives the name of the branch to checkout. NULL means * use the remote's HEAD. */ @@ -62,10 +49,11 @@ typedef struct git_clone_options { unsigned int version; git_checkout_opts checkout_opts; + git_remote_callbacks *remote_callbacks; + int bare; int ignore_cert_errors; - - git_remote_callbacks *remote_callbacks; + const char *remote_name; const char* checkout_branch; } git_clone_options; diff --git a/src/clone.c b/src/clone.c index 60525939f..cad9ea1dc 100644 --- a/src/clone.c +++ b/src/clone.c @@ -306,8 +306,10 @@ static int create_and_configure_origin( { int error; git_remote *origin = NULL; + const char *name; - if ((error = git_remote_create(&origin, repo, "origin", url)) < 0) + name = options->remote_name ? options->remote_name : "origin"; + if ((error = git_remote_create(&origin, repo, name, url)) < 0) goto on_error; if (options->ignore_cert_errors) diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index 84654fa5a..c7a219259 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -122,6 +122,15 @@ void test_clone_nonetwork__fail_with_already_existing_but_non_empty_directory(vo cl_git_fail(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); } +void test_clone_nonetwork__custom_origin_name(void) +{ + g_options.remote_name = "my_origin"; + cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); + + cl_git_pass(git_remote_load(&g_remote, g_repo, "my_origin")); +} + + void test_clone_nonetwork__cope_with_already_existing_directory(void) { p_mkdir("./foo", GIT_DIR_MODE); From fdc7e5e35efa072a145cf318457055f60c9b21eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 20 Sep 2013 23:14:12 +0200 Subject: [PATCH 11/14] clone: bring back NULL as defaults This wasremoved as part of the large culling a few commits ago. --- src/clone.c | 14 +++++++++----- tests-clar/clone/nonetwork.c | 6 ++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/clone.c b/src/clone.c index cad9ea1dc..1af6e393f 100644 --- a/src/clone.c +++ b/src/clone.c @@ -390,16 +390,20 @@ int git_clone( git_repository **out, const char *url, const char *local_path, - const git_clone_options *options) + const git_clone_options *_options) { int retcode = GIT_ERROR; git_repository *repo = NULL; git_remote *origin; + git_clone_options options = GIT_CLONE_OPTIONS_INIT; int remove_directory_on_failure = 0; assert(out && url && local_path); - GITERR_CHECK_VERSION(options, GIT_CLONE_OPTIONS_VERSION, "git_clone_options"); + if (_options) + memcpy(&options, _options, sizeof(git_clone_options)); + + GITERR_CHECK_VERSION(&options, GIT_CLONE_OPTIONS_VERSION, "git_clone_options"); /* Only clone to a new directory or an empty directory */ if (git_path_exists(local_path) && !git_path_is_empty_dir(local_path)) { @@ -411,13 +415,13 @@ int git_clone( /* Only remove the directory on failure if we create it */ remove_directory_on_failure = !git_path_exists(local_path); - if ((retcode = git_repository_init(&repo, local_path, options->bare)) < 0) + if ((retcode = git_repository_init(&repo, local_path, options.bare)) < 0) return retcode; - if ((retcode = create_and_configure_origin(&origin, repo, url, options)) < 0) + if ((retcode = create_and_configure_origin(&origin, repo, url, &options)) < 0) goto cleanup; - retcode = git_clone_into(repo, origin, &options->checkout_opts, options->checkout_branch); + retcode = git_clone_into(repo, origin, &options.checkout_opts, options.checkout_branch); git_remote_free(origin); if (retcode < 0) diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index c7a219259..9b666b3f7 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -130,6 +130,12 @@ void test_clone_nonetwork__custom_origin_name(void) cl_git_pass(git_remote_load(&g_remote, g_repo, "my_origin")); } +void test_clone_nonetwork__defaults(void) +{ + cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", NULL)); + cl_assert(g_repo); + cl_git_pass(git_remote_load(&g_remote, g_repo, "origin")); +} void test_clone_nonetwork__cope_with_already_existing_directory(void) { From 36a241acbb39aa46cf5f7807aebd92e45f2f5eaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 20 Sep 2013 23:14:52 +0200 Subject: [PATCH 12/14] clone: mention clone_into in the clone documentation Make the difference more explicit. --- include/git2/clone.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/git2/clone.h b/include/git2/clone.h index bd602fb7a..a341a413c 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -61,8 +61,11 @@ typedef struct git_clone_options { #define GIT_CLONE_OPTIONS_INIT {GIT_CLONE_OPTIONS_VERSION, {GIT_CHECKOUT_OPTS_VERSION, GIT_CHECKOUT_SAFE_CREATE}} /** - * Clone a remote repository, and checkout the branch pointed to by the remote - * HEAD. + * Clone a remote repository. + * + * This version handles the simple case. If you'd like to create the + * repository or remote with non-default settings, you can create and + * configure them and then use `git_clone_into()`. * * @param out pointer that will receive the resulting repository object * @param url the remote repository to clone From ffc97d51264f8af435ccf52d33a62a6925b174c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 20 Sep 2013 23:23:42 +0200 Subject: [PATCH 13/14] remote: add some comments to the callback struct Hopefully clear up what they're for. --- include/git2/remote.h | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 8c21870de..8145de180 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -400,15 +400,47 @@ typedef enum git_remote_completion_type { /** * The callback settings structure * - * Set the calbacks to be called by the remote. + * Set the callbacks to be called by the remote when informing the user + * about the progress of the network operations. */ struct git_remote_callbacks { unsigned int version; + /** + * Textual progress from the remote. Text send over the + * progress side-band will be passed to this function (this is + * the 'counting objects' output. + */ void (*progress)(const char *str, int len, void *data); + + /** + * Completion is called when different parts of the download + * process are done (currently unused). + */ int (*completion)(git_remote_completion_type type, void *data); + + /** + * This will be called if the remote host requires + * authentication in order to connect to it. + */ int (*credentials)(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *data); + + /** + * During the download of new data, this will be regularly + * called with the current count of progress done by the + * indexer. + */ int (*transfer_progress)(const git_transfer_progress *stats, void *data); + + /** + * Each time a reference is updated locally, this function + * will be called with information about it. + */ int (*update_tips)(const char *refname, const git_oid *a, const git_oid *b, void *data); + + /** + * This will be passed to each of the callbacks in this struct + * as the last parameter. + */ void *payload; }; From 0e0cf78773bea0d06298ba3bf981a3be839041df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 2 Oct 2013 14:04:44 +0200 Subject: [PATCH 14/14] clone: put the callbacks struct directly in the clone options There's no need for this to be a pointer to somewhere else. --- examples/network/clone.c | 8 +++----- include/git2/clone.h | 4 ++-- include/git2/remote.h | 2 +- src/clone.c | 3 +-- src/remote.c | 4 ++-- tests-clar/clone/empty.c | 2 ++ tests-clar/clone/nonetwork.c | 2 ++ tests-clar/online/clone.c | 34 +++++++++++----------------------- tests-clar/online/fetchhead.c | 2 ++ 9 files changed, 26 insertions(+), 35 deletions(-) diff --git a/examples/network/clone.c b/examples/network/clone.c index f553c4077..db35bd7db 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -57,7 +57,6 @@ int do_clone(git_repository *repo, int argc, char **argv) git_repository *cloned_repo = NULL; git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; const char *url = argv[1]; const char *path = argv[2]; int error; @@ -75,10 +74,9 @@ int do_clone(git_repository *repo, int argc, char **argv) checkout_opts.progress_cb = checkout_progress; checkout_opts.progress_payload = &pd; clone_opts.checkout_opts = checkout_opts; - callbacks.transfer_progress = &fetch_progress; - callbacks.credentials = cred_acquire_cb; - callbacks.payload = &pd; - clone_opts.remote_callbacks = &callbacks; + clone_opts.remote_callbacks.transfer_progress = &fetch_progress; + clone_opts.remote_callbacks.credentials = cred_acquire_cb; + clone_opts.remote_callbacks.payload = &pd; // Do the clone error = git_clone(&cloned_repo, url, path, &clone_opts); diff --git a/include/git2/clone.h b/include/git2/clone.h index a341a413c..331cf92e7 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -49,7 +49,7 @@ typedef struct git_clone_options { unsigned int version; git_checkout_opts checkout_opts; - git_remote_callbacks *remote_callbacks; + git_remote_callbacks remote_callbacks; int bare; int ignore_cert_errors; @@ -58,7 +58,7 @@ typedef struct git_clone_options { } git_clone_options; #define GIT_CLONE_OPTIONS_VERSION 1 -#define GIT_CLONE_OPTIONS_INIT {GIT_CLONE_OPTIONS_VERSION, {GIT_CHECKOUT_OPTS_VERSION, GIT_CHECKOUT_SAFE_CREATE}} +#define GIT_CLONE_OPTIONS_INIT {GIT_CLONE_OPTIONS_VERSION, {GIT_CHECKOUT_OPTS_VERSION, GIT_CHECKOUT_SAFE_CREATE}, GIT_REMOTE_CALLBACKS_INIT} /** * Clone a remote repository. diff --git a/include/git2/remote.h b/include/git2/remote.h index 8145de180..9858634cc 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -457,7 +457,7 @@ struct git_remote_callbacks { * @param callbacks a pointer to the user's callback settings * @return 0 or an error code */ -GIT_EXTERN(int) git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks); +GIT_EXTERN(int) git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *callbacks); /** * Get the statistics structure that is filled in by the fetch operation. diff --git a/src/clone.c b/src/clone.c index 1af6e393f..f3e365c07 100644 --- a/src/clone.c +++ b/src/clone.c @@ -315,8 +315,7 @@ static int create_and_configure_origin( if (options->ignore_cert_errors) git_remote_check_cert(origin, 0); - if (options->remote_callbacks && - (error = git_remote_set_callbacks(origin, options->remote_callbacks)) < 0) + if ((error = git_remote_set_callbacks(origin, &options->remote_callbacks)) < 0) goto on_error; if ((error = git_remote_save(origin)) < 0) diff --git a/src/remote.c b/src/remote.c index ace886502..ccedf2386 100644 --- a/src/remote.c +++ b/src/remote.c @@ -1153,7 +1153,7 @@ void git_remote_check_cert(git_remote *remote, int check) remote->check_cert = check; } -int git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks) +int git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *callbacks) { assert(remote && callbacks); @@ -1162,7 +1162,7 @@ int git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks memcpy(&remote->callbacks, callbacks, sizeof(git_remote_callbacks)); if (remote->transport && remote->transport->set_callbacks) - remote->transport->set_callbacks(remote->transport, + return remote->transport->set_callbacks(remote->transport, remote->callbacks.progress, NULL, remote->callbacks.payload); diff --git a/tests-clar/clone/empty.c b/tests-clar/clone/empty.c index d9dc24fde..6d19244cc 100644 --- a/tests-clar/clone/empty.c +++ b/tests-clar/clone/empty.c @@ -10,12 +10,14 @@ static git_repository *g_repo_cloned; void test_clone_empty__initialize(void) { git_repository *sandbox = cl_git_sandbox_init("empty_bare.git"); + git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; cl_git_remove_placeholders(git_repository_path(sandbox), "dummy-marker.txt"); g_repo = NULL; memset(&g_options, 0, sizeof(git_clone_options)); g_options.version = GIT_CLONE_OPTIONS_VERSION; + g_options.remote_callbacks = dummy_callbacks; } void test_clone_empty__cleanup(void) diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index 9b666b3f7..4bcb5be1e 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -15,6 +15,7 @@ static git_remote* g_remote; void test_clone_nonetwork__initialize(void) { git_checkout_opts dummy_opts = GIT_CHECKOUT_OPTS_INIT; + git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; g_repo = NULL; @@ -22,6 +23,7 @@ void test_clone_nonetwork__initialize(void) g_options.version = GIT_CLONE_OPTIONS_VERSION; g_options.checkout_opts = dummy_opts; g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + g_options.remote_callbacks = dummy_callbacks; } void test_clone_nonetwork__cleanup(void) diff --git a/tests-clar/online/clone.c b/tests-clar/online/clone.c index 9a64ba166..4a6ade52d 100644 --- a/tests-clar/online/clone.c +++ b/tests-clar/online/clone.c @@ -18,6 +18,7 @@ static git_clone_options g_options; void test_online_clone__initialize(void) { git_checkout_opts dummy_opts = GIT_CHECKOUT_OPTS_INIT; + git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; g_repo = NULL; @@ -25,6 +26,7 @@ void test_online_clone__initialize(void) g_options.version = GIT_CLONE_OPTIONS_VERSION; g_options.checkout_opts = dummy_opts; g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + g_options.remote_callbacks = dummy_callbacks; } void test_online_clone__cleanup(void) @@ -100,15 +102,11 @@ void test_online_clone__can_checkout_a_cloned_repo(void) bool checkout_progress_cb_was_called = false, fetch_progress_cb_was_called = false; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; - g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; g_options.checkout_opts.progress_cb = &checkout_progress; g_options.checkout_opts.progress_payload = &checkout_progress_cb_was_called; - - callbacks.transfer_progress = &fetch_progress; - callbacks.payload = &fetch_progress_cb_was_called; - g_options.remote_callbacks = &callbacks; + g_options.remote_callbacks.transfer_progress = &fetch_progress; + g_options.remote_callbacks.payload = &fetch_progress_cb_was_called; cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); @@ -175,12 +173,10 @@ static int update_tips(const char *refname, const git_oid *a, const git_oid *b, void test_online_clone__custom_remote_callbacks(void) { - git_remote_callbacks remote_callbacks = GIT_REMOTE_CALLBACKS_INIT; int callcount = 0; - g_options.remote_callbacks = &remote_callbacks; - remote_callbacks.update_tips = update_tips; - remote_callbacks.payload = &callcount; + g_options.remote_callbacks.update_tips = update_tips; + g_options.remote_callbacks.payload = &callcount; cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); cl_assert(callcount > 0); @@ -194,13 +190,11 @@ void test_online_clone__credentials(void) cl_getenv("GITTEST_REMOTE_USER"), cl_getenv("GITTEST_REMOTE_PASS") }; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; if (!remote_url) return; - callbacks.credentials = git_cred_userpass; - callbacks.payload = &user_pass; - g_options.remote_callbacks = &callbacks; + g_options.remote_callbacks.credentials = git_cred_userpass; + g_options.remote_callbacks.payload = &user_pass; cl_git_pass(git_clone(&g_repo, remote_url, "./foo", &g_options)); git_repository_free(g_repo); g_repo = NULL; @@ -213,11 +207,8 @@ void test_online_clone__bitbucket_style(void) "libgit2", "libgit2" }; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; - - callbacks.credentials = git_cred_userpass; - callbacks.payload = &user_pass; - g_options.remote_callbacks = &callbacks; + g_options.remote_callbacks.credentials = git_cred_userpass; + g_options.remote_callbacks.payload = &user_pass; cl_git_pass(git_clone(&g_repo, BB_REPO_URL, "./foo", &g_options)); git_repository_free(g_repo); g_repo = NULL; @@ -247,10 +238,7 @@ static int cancel_at_half(const git_transfer_progress *stats, void *payload) void test_online_clone__can_cancel(void) { - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; - - callbacks.transfer_progress = cancel_at_half; - g_options.remote_callbacks = &callbacks; + g_options.remote_callbacks.transfer_progress = cancel_at_half; cl_git_fail_with(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options), GIT_EUSER); } diff --git a/tests-clar/online/fetchhead.c b/tests-clar/online/fetchhead.c index 5d9eb1318..57b183f88 100644 --- a/tests-clar/online/fetchhead.c +++ b/tests-clar/online/fetchhead.c @@ -12,10 +12,12 @@ static git_clone_options g_options; void test_online_fetchhead__initialize(void) { + git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; g_repo = NULL; memset(&g_options, 0, sizeof(git_clone_options)); g_options.version = GIT_CLONE_OPTIONS_VERSION; + g_options.remote_callbacks = dummy_callbacks; } void test_online_fetchhead__cleanup(void)