Merge pull request #982 from nulltoken/clone/no-checkout clone: Explicit support of no-checkout option
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
diff --git a/include/git2/clone.h b/include/git2/clone.h
index 40292ed..c4dfc65 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 00e39d3..82042a4 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 cf3c73b..30c4a47 100644
--- a/tests-clar/clone/network.c
+++ b/tests-clar/clone/network.c
@@ -72,3 +72,36 @@ 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)));
+}
+
+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));
+}