diff options
-rw-r--r-- | include/git2/clone.h | 9 | ||||
-rw-r--r-- | src/clone.c | 22 | ||||
-rw-r--r-- | tests-clar/clone/network.c | 42 |
3 files changed, 67 insertions, 6 deletions
diff --git a/include/git2/clone.h b/include/git2/clone.h index 40292ed59..c4dfc652b 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -29,9 +29,12 @@ GIT_BEGIN_DECL * @param out pointer that will receive the resulting repository object * @param origin_url repository to clone from * @param workdir_path local directory to clone to - * @param fetch_stats pointer to structure that receives fetch progress information (may be NULL) - * @param checkout_opts options for the checkout step (may be NULL) - * @return 0 on success, GIT_ERROR otherwise (use giterr_last for information about the error) + * @param fetch_stats pointer to structure that receives fetch progress + * information (may be NULL) + * @param checkout_opts options for the checkout step. If NULL, no checkout + * is performed + * @return 0 on success, GIT_ERROR otherwise (use giterr_last for information + * about the error) */ GIT_EXTERN(int) git_clone(git_repository **out, const char *origin_url, diff --git a/src/clone.c b/src/clone.c index 00e39d3b5..82042a46a 100644 --- a/src/clone.c +++ b/src/clone.c @@ -18,6 +18,7 @@ #include "common.h" #include "remote.h" +#include "pkt.h" #include "fileops.h" #include "refs.h" #include "path.h" @@ -174,6 +175,7 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote) { int retcode = -1; git_remote_head *remote_head; + git_pkt_ref *pkt; struct head_info head_info; git_buf remote_master_name = GIT_BUF_INIT; @@ -187,7 +189,8 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote) } /* Get the remote's HEAD. This is always the first ref in remote->refs. */ - remote_head = remote->refs.contents[0]; + pkt = remote->transport->refs.contents[0]; + remote_head = &pkt->head; git_oid_cpy(&head_info.remote_head_oid, &remote_head->oid); git_buf_init(&head_info.branchname, 16); head_info.repo = repo; @@ -290,6 +293,19 @@ static bool path_is_okay(const char *path) return true; } +static bool should_checkout( + git_repository *repo, + bool is_bare, + git_checkout_opts *opts) +{ + if (is_bare) + return false; + + if (!opts) + return false; + + return !git_repository_head_orphan(repo); +} static int clone_internal( git_repository **out, @@ -298,7 +314,7 @@ static int clone_internal( git_indexer_stats *fetch_stats, git_indexer_stats *checkout_stats, git_checkout_opts *checkout_opts, - int is_bare) + bool is_bare) { int retcode = GIT_ERROR; git_repository *repo = NULL; @@ -321,7 +337,7 @@ static int clone_internal( } } - if (!retcode && !is_bare && !git_repository_head_orphan(repo)) + if (!retcode && should_checkout(repo, is_bare, checkout_opts)) retcode = git_checkout_head(*out, checkout_opts, checkout_stats); return retcode; diff --git a/tests-clar/clone/network.c b/tests-clar/clone/network.c index cf3c73bb6..1ebdfb5d1 100644 --- a/tests-clar/clone/network.c +++ b/tests-clar/clone/network.c @@ -32,6 +32,8 @@ void test_clone_network__network_full(void) cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./test2", NULL, NULL, NULL)); cl_assert(!git_repository_is_bare(g_repo)); cl_git_pass(git_remote_load(&origin, g_repo, "origin")); + + git_remote_free(origin); } @@ -44,6 +46,8 @@ void test_clone_network__network_bare(void) cl_git_pass(git_clone_bare(&g_repo, LIVE_REPO_URL, "./test", NULL)); cl_assert(git_repository_is_bare(g_repo)); cl_git_pass(git_remote_load(&origin, g_repo, "origin")); + + git_remote_free(origin); } void test_clone_network__cope_with_already_existing_directory(void) @@ -72,3 +76,41 @@ void test_clone_network__empty_repository(void) git_reference_free(head); } + +void test_clone_network__can_prevent_the_checkout_of_a_standard_repo(void) +{ + git_buf path = GIT_BUF_INIT; + + cl_set_cleanup(&cleanup_repository, "./no-checkout"); + + cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./no-checkout", NULL, NULL, NULL)); + + cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt")); + cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&path))); + + git_buf_free(&path); +} + +void test_clone_network__can_checkout_a_cloned_repo(void) +{ + git_checkout_opts opts; + git_buf path = GIT_BUF_INIT; + git_reference *head; + + memset(&opts, 0, sizeof(opts)); + opts.checkout_strategy = GIT_CHECKOUT_CREATE_MISSING; + + cl_set_cleanup(&cleanup_repository, "./default-checkout"); + + cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./default-checkout", NULL, NULL, &opts)); + + 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_target(head)); + + git_reference_free(head); + git_buf_free(&path); +} |