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