diff options
-rw-r--r-- | include/git2/clone.h | 57 | ||||
-rw-r--r-- | src/clone.c | 3 | ||||
-rw-r--r-- | tests/clone/nonetwork.c | 57 |
3 files changed, 91 insertions, 26 deletions
diff --git a/include/git2/clone.h b/include/git2/clone.h index 331cf92e7..59a73aa15 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -26,23 +26,25 @@ GIT_BEGIN_DECL /** * Clone options structure * - * Use zeros to indicate default settings. It's easiest to use the - * `GIT_CLONE_OPTIONS_INIT` macro: + * Use the GIT_CLONE_OPTIONS_INIT to get the default settings, like this: * * git_clone_options opts = GIT_CLONE_OPTIONS_INIT; * - * - `checkout_opts` is options for the checkout step. To disable checkout, - * 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 - * - `ignore_cert_errors` should be set to 1 if errors validating the remote host's - * certificate should be ignored. + * - `checkout_opts` are option passed to the checkout step. To disable + * checkout, set the `checkout_strategy` to GIT_CHECKOUT_NONE. + * Generally you will want the use GIT_CHECKOUT_SAFE_CREATE to create + * all files in the working directory for the newly cloned repository. + * - `bare` should be set to zero (false) to create a standard repo, + * or non-zero for a bare repo + * - `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". - * - `checkout_branch` gives the name of the branch to checkout. NULL means - * use the remote's HEAD. + * + * - `remote_name` is the name to be given to the "origin" remote. The + * default is "origin". + * - `checkout_branch` gives the name of the branch to checkout. NULL + * means use the remote's HEAD. */ typedef struct git_clone_options { @@ -70,16 +72,17 @@ typedef struct git_clone_options { * @param out pointer that will receive the resulting repository object * @param url the remote repository to clone * @param local_path local directory to clone to - * @param options configuration options for the clone. If NULL, the function - * works as though GIT_OPTIONS_INIT were passed. - * @return 0 on success, GIT_ERROR otherwise (use giterr_last for information - * about the error) + * @param options configuration options for the clone. If NULL, the + * function works as though GIT_OPTIONS_INIT were passed. + * @return 0 on success, any non-zero return value from a callback + * function, or a negative value to indicate an error (use + * `giterr_last` for a detailed error message) */ GIT_EXTERN(int) git_clone( - git_repository **out, - const char *url, - const char *local_path, - const git_clone_options *options); + git_repository **out, + const char *url, + const char *local_path, + const git_clone_options *options); /** * Clone into a repository @@ -91,11 +94,17 @@ GIT_EXTERN(int) git_clone( * @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 + * @param branch the branch to checkout after the clone, pass NULL for the + * remote's default branch + * @return 0 on success, any non-zero return value from a callback + * function, or a negative value to indicate an error (use + * `giterr_last` for a detailed error message) */ -GIT_EXTERN(int) git_clone_into(git_repository *repo, git_remote *remote, const 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/clone.c b/src/clone.c index ffbe8f8af..828c47ffb 100644 --- a/src/clone.c +++ b/src/clone.c @@ -408,9 +408,10 @@ int git_clone( git_remote_free(origin); } - if (error < 0) { + if (error != 0) { git_repository_free(repo); repo = NULL; + (void)git_futils_rmdir_r(local_path, NULL, rmdir_flags); } diff --git a/tests/clone/nonetwork.c b/tests/clone/nonetwork.c index a286e2a8f..3cd5fb7f6 100644 --- a/tests/clone/nonetwork.c +++ b/tests/clone/nonetwork.c @@ -22,7 +22,7 @@ void test_clone_nonetwork__initialize(void) memset(&g_options, 0, sizeof(git_clone_options)); g_options.version = GIT_CLONE_OPTIONS_VERSION; g_options.checkout_opts = dummy_opts; - g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; g_options.remote_callbacks = dummy_callbacks; } @@ -151,6 +151,61 @@ void test_clone_nonetwork__can_checkout_given_branch(void) cl_git_pass(git_repository_head(&g_ref, g_repo)); cl_assert_equal_s(git_reference_name(g_ref), "refs/heads/test"); + + cl_assert(git_path_exists("foo/readme.txt")); +} + +static int clone_cancel_fetch_transfer_progress_cb( + const git_transfer_progress *stats, void *data) +{ + GIT_UNUSED(stats); GIT_UNUSED(data); + return -54321; +} + +void test_clone_nonetwork__can_cancel_clone_in_fetch(void) +{ + g_options.checkout_branch = "test"; + + g_options.remote_callbacks.transfer_progress = + clone_cancel_fetch_transfer_progress_cb; + + cl_git_fail_with(git_clone( + &g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options), + -54321); + + cl_assert(!g_repo); + cl_assert(!git_path_exists("foo/readme.txt")); +} + +static int clone_cancel_checkout_cb( + git_checkout_notify_t why, + const char *path, + const git_diff_file *b, + const git_diff_file *t, + const git_diff_file *w, + void *payload) +{ + const char *at_file = payload; + GIT_UNUSED(why); GIT_UNUSED(b); GIT_UNUSED(t); GIT_UNUSED(w); + if (!strcmp(path, at_file)) + return -12345; + return 0; +} + +void test_clone_nonetwork__can_cancel_clone_in_checkout(void) +{ + g_options.checkout_branch = "test"; + + g_options.checkout_opts.notify_flags = GIT_CHECKOUT_NOTIFY_UPDATED; + g_options.checkout_opts.notify_cb = clone_cancel_checkout_cb; + g_options.checkout_opts.notify_payload = "readme.txt"; + + cl_git_fail_with(git_clone( + &g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options), + -12345); + + cl_assert(!g_repo); + cl_assert(!git_path_exists("foo/readme.txt")); } void test_clone_nonetwork__can_detached_head(void) |