]>
Commit | Line | Data |
---|---|---|
65415ea2 BS |
1 | #include "clar_libgit2.h" |
2 | ||
3 | #include "git2/clone.h" | |
520dcc1c | 4 | #include "git2/cred_helpers.h" |
6f748f38 | 5 | #include "remote.h" |
114f5a6c RB |
6 | #include "fileops.h" |
7 | #include "refs.h" | |
65415ea2 | 8 | |
44f36f6e BS |
9 | #define LIVE_REPO_URL "http://github.com/libgit2/TestGitRepository" |
10 | #define LIVE_EMPTYREPO_URL "http://github.com/libgit2/TestEmptyRepository" | |
5f10853e | 11 | #define BB_REPO_URL "https://libgit2@bitbucket.org/libgit2/testgitrepository.git" |
cf7038a6 | 12 | #define BB_REPO_URL_WITH_PASS "https://libgit2:libgit2@bitbucket.org/libgit2/testgitrepository.git" |
54ffc1f7 | 13 | #define BB_REPO_URL_WITH_WRONG_PASS "https://libgit2:wrong@bitbucket.org/libgit2/testgitrepository.git" |
1fd21b03 | 14 | #define ASSEMBLA_REPO_URL "https://libgit2:_Libgit2@git.assembla.com/libgit2-test-repos.git" |
65415ea2 BS |
15 | |
16 | static git_repository *g_repo; | |
18b2d560 | 17 | static git_clone_options g_options; |
65415ea2 | 18 | |
6443eaf2 | 19 | void test_online_clone__initialize(void) |
65415ea2 | 20 | { |
6affd71f | 21 | git_checkout_options dummy_opts = GIT_CHECKOUT_OPTIONS_INIT; |
0e0cf787 | 22 | git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; |
730df6d0 | 23 | |
65415ea2 | 24 | g_repo = NULL; |
18b2d560 BS |
25 | |
26 | memset(&g_options, 0, sizeof(git_clone_options)); | |
27 | g_options.version = GIT_CLONE_OPTIONS_VERSION; | |
730df6d0 BS |
28 | g_options.checkout_opts = dummy_opts; |
29 | g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; | |
0e0cf787 | 30 | g_options.remote_callbacks = dummy_callbacks; |
65415ea2 BS |
31 | } |
32 | ||
6443eaf2 | 33 | void test_online_clone__cleanup(void) |
65415ea2 | 34 | { |
9094d30b | 35 | if (g_repo) { |
65415ea2 | 36 | git_repository_free(g_repo); |
9094d30b SC |
37 | g_repo = NULL; |
38 | } | |
7761ce21 | 39 | cl_fixture_cleanup("./foo"); |
65415ea2 BS |
40 | } |
41 | ||
6443eaf2 | 42 | void test_online_clone__network_full(void) |
65415ea2 BS |
43 | { |
44 | git_remote *origin; | |
45 | ||
b412d563 | 46 | cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); |
65415ea2 BS |
47 | cl_assert(!git_repository_is_bare(g_repo)); |
48 | cl_git_pass(git_remote_load(&origin, g_repo, "origin")); | |
add5efe7 | 49 | |
6f748f38 JM |
50 | cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_AUTO, origin->download_tags); |
51 | ||
add5efe7 | 52 | git_remote_free(origin); |
65415ea2 BS |
53 | } |
54 | ||
6443eaf2 | 55 | void test_online_clone__network_bare(void) |
65415ea2 BS |
56 | { |
57 | git_remote *origin; | |
58 | ||
18b2d560 | 59 | g_options.bare = true; |
65415ea2 | 60 | |
b412d563 | 61 | cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); |
65415ea2 BS |
62 | cl_assert(git_repository_is_bare(g_repo)); |
63 | cl_git_pass(git_remote_load(&origin, g_repo, "origin")); | |
add5efe7 | 64 | |
65 | git_remote_free(origin); | |
65415ea2 BS |
66 | } |
67 | ||
6443eaf2 | 68 | void test_online_clone__empty_repository(void) |
65415ea2 BS |
69 | { |
70 | git_reference *head; | |
71 | ||
b412d563 | 72 | cl_git_pass(git_clone(&g_repo, LIVE_EMPTYREPO_URL, "./foo", &g_options)); |
65415ea2 BS |
73 | |
74 | cl_assert_equal_i(true, git_repository_is_empty(g_repo)); | |
605da51a | 75 | cl_assert_equal_i(true, git_repository_head_unborn(g_repo)); |
65415ea2 BS |
76 | |
77 | cl_git_pass(git_reference_lookup(&head, g_repo, GIT_HEAD_FILE)); | |
78 | cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); | |
2508cc66 | 79 | cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); |
65415ea2 BS |
80 | |
81 | git_reference_free(head); | |
82 | } | |
4d968f13 | 83 | |
9c05c17b | 84 | static void checkout_progress(const char *path, size_t cur, size_t tot, void *payload) |
183d8bdd | 85 | { |
183d8bdd | 86 | bool *was_called = (bool*)payload; |
1fc375e6 | 87 | GIT_UNUSED(path); GIT_UNUSED(cur); GIT_UNUSED(tot); |
183d8bdd BS |
88 | (*was_called) = true; |
89 | } | |
90 | ||
fe95ac1b | 91 | static int fetch_progress(const git_transfer_progress *stats, void *payload) |
aa1e8674 | 92 | { |
aa1e8674 | 93 | bool *was_called = (bool*)payload; |
1fc375e6 | 94 | GIT_UNUSED(stats); |
aa1e8674 | 95 | (*was_called) = true; |
fe95ac1b | 96 | return 0; |
aa1e8674 BS |
97 | } |
98 | ||
6443eaf2 | 99 | void test_online_clone__can_checkout_a_cloned_repo(void) |
4d968f13 | 100 | { |
4d968f13 | 101 | git_buf path = GIT_BUF_INIT; |
c4f68b32 | 102 | git_reference *head; |
aa1e8674 BS |
103 | bool checkout_progress_cb_was_called = false, |
104 | fetch_progress_cb_was_called = false; | |
4d968f13 | 105 | |
b3fb9237 | 106 | g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; |
730df6d0 BS |
107 | g_options.checkout_opts.progress_cb = &checkout_progress; |
108 | g_options.checkout_opts.progress_payload = &checkout_progress_cb_was_called; | |
0e0cf787 CMN |
109 | g_options.remote_callbacks.transfer_progress = &fetch_progress; |
110 | g_options.remote_callbacks.payload = &fetch_progress_cb_was_called; | |
4d968f13 | 111 | |
b412d563 | 112 | cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); |
4d968f13 | 113 | |
114 | cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt")); | |
115 | cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path))); | |
c4f68b32 | 116 | |
117 | cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); | |
118 | cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); | |
2508cc66 | 119 | cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); |
add5efe7 | 120 | |
aa1e8674 BS |
121 | cl_assert_equal_i(true, checkout_progress_cb_was_called); |
122 | cl_assert_equal_i(true, fetch_progress_cb_was_called); | |
183d8bdd | 123 | |
add5efe7 | 124 | git_reference_free(head); |
125 | git_buf_free(&path); | |
4d968f13 | 126 | } |
621b50e4 | 127 | |
d19870d9 CMN |
128 | void test_online_clone__clone_into(void) |
129 | { | |
130 | git_buf path = GIT_BUF_INIT; | |
131 | git_remote *remote; | |
132 | git_reference *head; | |
6affd71f | 133 | git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; |
d19870d9 CMN |
134 | git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; |
135 | ||
136 | bool checkout_progress_cb_was_called = false, | |
137 | fetch_progress_cb_was_called = false; | |
138 | ||
139 | checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; | |
140 | checkout_opts.progress_cb = &checkout_progress; | |
141 | checkout_opts.progress_payload = &checkout_progress_cb_was_called; | |
142 | ||
143 | cl_git_pass(git_repository_init(&g_repo, "./foo", false)); | |
144 | cl_git_pass(git_remote_create(&remote, g_repo, "origin", LIVE_REPO_URL)); | |
145 | ||
146 | callbacks.transfer_progress = &fetch_progress; | |
147 | callbacks.payload = &fetch_progress_cb_was_called; | |
148 | git_remote_set_callbacks(remote, &callbacks); | |
149 | ||
1cc974ab | 150 | cl_git_pass(git_clone_into(g_repo, remote, &checkout_opts, NULL, NULL)); |
d19870d9 CMN |
151 | |
152 | cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt")); | |
153 | cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path))); | |
154 | ||
155 | cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); | |
156 | cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); | |
157 | cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); | |
158 | ||
159 | cl_assert_equal_i(true, checkout_progress_cb_was_called); | |
160 | cl_assert_equal_i(true, fetch_progress_cb_was_called); | |
161 | ||
162 | git_remote_free(remote); | |
163 | git_reference_free(head); | |
164 | git_buf_free(&path); | |
165 | } | |
166 | ||
b2067248 CMN |
167 | void test_online_clone__clone_mirror(void) |
168 | { | |
169 | git_buf path = GIT_BUF_INIT; | |
170 | git_remote *remote; | |
171 | git_reference *head; | |
172 | git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; | |
173 | ||
174 | bool fetch_progress_cb_was_called = false; | |
175 | ||
176 | cl_git_pass(git_repository_init(&g_repo, "./foo.git", true)); | |
177 | cl_git_pass(git_remote_create(&remote, g_repo, "origin", LIVE_REPO_URL)); | |
178 | ||
179 | callbacks.transfer_progress = &fetch_progress; | |
180 | callbacks.payload = &fetch_progress_cb_was_called; | |
181 | git_remote_set_callbacks(remote, &callbacks); | |
182 | ||
183 | git_remote_clear_refspecs(remote); | |
184 | cl_git_pass(git_remote_add_fetch(remote, "+refs/*:refs/*")); | |
185 | ||
186 | cl_git_pass(git_clone_into(g_repo, remote, NULL, NULL, NULL)); | |
187 | ||
188 | cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); | |
189 | cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); | |
190 | cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); | |
191 | ||
192 | cl_assert_equal_i(true, fetch_progress_cb_was_called); | |
193 | ||
194 | git_remote_free(remote); | |
195 | git_reference_free(head); | |
196 | git_buf_free(&path); | |
6d1b0438 PK |
197 | git_repository_free(g_repo); |
198 | g_repo = NULL; | |
199 | ||
b2067248 CMN |
200 | cl_fixture_cleanup("./foo.git"); |
201 | } | |
202 | ||
621b50e4 BS |
203 | static int update_tips(const char *refname, const git_oid *a, const git_oid *b, void *payload) |
204 | { | |
205 | int *callcount = (int*)payload; | |
206 | GIT_UNUSED(refname); GIT_UNUSED(a); GIT_UNUSED(b); | |
207 | *callcount = *callcount + 1; | |
208 | return 0; | |
209 | } | |
210 | ||
ffb02b16 | 211 | void test_online_clone__custom_remote_callbacks(void) |
621b50e4 | 212 | { |
621b50e4 BS |
213 | int callcount = 0; |
214 | ||
0e0cf787 CMN |
215 | g_options.remote_callbacks.update_tips = update_tips; |
216 | g_options.remote_callbacks.payload = &callcount; | |
621b50e4 BS |
217 | |
218 | cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); | |
219 | cl_assert(callcount > 0); | |
220 | } | |
221 | ||
80fc7d6b ET |
222 | static int cred_failure_cb( |
223 | git_cred **cred, | |
224 | const char *url, | |
225 | const char *username_from_url, | |
226 | unsigned int allowed_types, | |
227 | void *data) | |
228 | { | |
8f2a3d62 RB |
229 | GIT_UNUSED(cred); GIT_UNUSED(url); GIT_UNUSED(username_from_url); |
230 | GIT_UNUSED(allowed_types); GIT_UNUSED(data); | |
fe45922d | 231 | return -172; |
80fc7d6b ET |
232 | } |
233 | ||
fe45922d | 234 | void test_online_clone__cred_callback_failure_return_code_is_tunnelled(void) |
80fc7d6b ET |
235 | { |
236 | const char *remote_url = cl_getenv("GITTEST_REMOTE_URL"); | |
5dae3ffe | 237 | const char *remote_user = cl_getenv("GITTEST_REMOTE_USER"); |
80fc7d6b | 238 | |
0f65733b VM |
239 | if (!remote_url || !remote_user) |
240 | clar__skip(); | |
5dae3ffe | 241 | |
80fc7d6b ET |
242 | g_options.remote_callbacks.credentials = cred_failure_cb; |
243 | ||
5dae3ffe | 244 | /* TODO: this should expect -172. */ |
fe45922d | 245 | cl_git_fail_with(git_clone(&g_repo, remote_url, "./foo", &g_options), -1); |
80fc7d6b ET |
246 | } |
247 | ||
ffb02b16 | 248 | void test_online_clone__credentials(void) |
621b50e4 BS |
249 | { |
250 | /* Remote URL environment variable must be set. User and password are optional. */ | |
251 | const char *remote_url = cl_getenv("GITTEST_REMOTE_URL"); | |
520dcc1c | 252 | git_cred_userpass_payload user_pass = { |
621b50e4 BS |
253 | cl_getenv("GITTEST_REMOTE_USER"), |
254 | cl_getenv("GITTEST_REMOTE_PASS") | |
255 | }; | |
256 | ||
257 | if (!remote_url) return; | |
258 | ||
0e0cf787 CMN |
259 | g_options.remote_callbacks.credentials = git_cred_userpass; |
260 | g_options.remote_callbacks.payload = &user_pass; | |
621b50e4 BS |
261 | |
262 | cl_git_pass(git_clone(&g_repo, remote_url, "./foo", &g_options)); | |
5f10853e BS |
263 | git_repository_free(g_repo); g_repo = NULL; |
264 | cl_fixture_cleanup("./foo"); | |
265 | } | |
266 | ||
267 | void test_online_clone__bitbucket_style(void) | |
268 | { | |
269 | git_cred_userpass_payload user_pass = { | |
270 | "libgit2", "libgit2" | |
271 | }; | |
272 | ||
0e0cf787 CMN |
273 | g_options.remote_callbacks.credentials = git_cred_userpass; |
274 | g_options.remote_callbacks.payload = &user_pass; | |
5f10853e BS |
275 | |
276 | cl_git_pass(git_clone(&g_repo, BB_REPO_URL, "./foo", &g_options)); | |
277 | git_repository_free(g_repo); g_repo = NULL; | |
278 | cl_fixture_cleanup("./foo"); | |
cf7038a6 | 279 | |
54ffc1f7 BS |
280 | /* User and pass from URL */ |
281 | user_pass.password = "wrong"; | |
cf7038a6 BS |
282 | cl_git_pass(git_clone(&g_repo, BB_REPO_URL_WITH_PASS, "./foo", &g_options)); |
283 | git_repository_free(g_repo); g_repo = NULL; | |
284 | cl_fixture_cleanup("./foo"); | |
54ffc1f7 BS |
285 | |
286 | /* Wrong password in URL, fall back to user_pass */ | |
287 | user_pass.password = "libgit2"; | |
288 | cl_git_pass(git_clone(&g_repo, BB_REPO_URL_WITH_WRONG_PASS, "./foo", &g_options)); | |
289 | git_repository_free(g_repo); g_repo = NULL; | |
290 | cl_fixture_cleanup("./foo"); | |
621b50e4 | 291 | } |
fe95ac1b | 292 | |
1fd21b03 BS |
293 | void test_online_clone__assembla_style(void) |
294 | { | |
295 | cl_git_pass(git_clone(&g_repo, ASSEMBLA_REPO_URL, "./foo", NULL)); | |
296 | } | |
297 | ||
fe95ac1b BS |
298 | static int cancel_at_half(const git_transfer_progress *stats, void *payload) |
299 | { | |
300 | GIT_UNUSED(payload); | |
301 | ||
302 | if (stats->received_objects > (stats->total_objects/2)) | |
25e0b157 | 303 | return 4321; |
fe95ac1b BS |
304 | return 0; |
305 | } | |
306 | ||
307 | void test_online_clone__can_cancel(void) | |
308 | { | |
0e0cf787 | 309 | g_options.remote_callbacks.transfer_progress = cancel_at_half; |
d31402a3 | 310 | |
25e0b157 RB |
311 | cl_git_fail_with( |
312 | git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options), 4321); | |
fe95ac1b | 313 | } |
d31402a3 CMN |
314 | |
315 | ||
316 | ||
317 | ||
318 | ||
319 |