]> git.proxmox.com Git - libgit2.git/blob - tests/network/fetchlocal.c
dc37c38ab6bace6ef0c2f007b2e4faec6a9db9d3
[libgit2.git] / tests / network / fetchlocal.c
1 #include "clar_libgit2.h"
2
3 #include "path.h"
4 #include "remote.h"
5
6 static const char* tagger_name = "Vicent Marti";
7 static const char* tagger_email = "vicent@github.com";
8 static const char* tagger_message = "This is my tag.\n\nThere are many tags, but this one is mine\n";
9
10 static int transfer_cb(const git_indexer_progress *stats, void *payload)
11 {
12 int *callcount = (int*)payload;
13 GIT_UNUSED(stats);
14 (*callcount)++;
15 return 0;
16 }
17
18 static void cleanup_local_repo(void *path)
19 {
20 cl_fixture_cleanup((char *)path);
21 }
22
23 void test_network_fetchlocal__cleanup(void)
24 {
25 cl_git_sandbox_cleanup();
26 }
27
28 void test_network_fetchlocal__complete(void)
29 {
30 git_repository *repo;
31 git_remote *origin;
32 int callcount = 0;
33 git_strarray refnames = {0};
34
35 const char *url = cl_git_fixture_url("testrepo.git");
36 git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
37
38 options.callbacks.transfer_progress = transfer_cb;
39 options.callbacks.payload = &callcount;
40
41 cl_set_cleanup(&cleanup_local_repo, "foo");
42 cl_git_pass(git_repository_init(&repo, "foo", true));
43
44 cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url));
45 cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
46
47 cl_git_pass(git_reference_list(&refnames, repo));
48 cl_assert_equal_i(20, (int)refnames.count);
49 cl_assert(callcount > 0);
50
51 git_strarray_dispose(&refnames);
52 git_remote_free(origin);
53 git_repository_free(repo);
54 }
55
56 void test_network_fetchlocal__prune(void)
57 {
58 git_repository *repo;
59 git_remote *origin;
60 int callcount = 0;
61 git_strarray refnames = {0};
62 git_reference *ref;
63 git_repository *remote_repo = cl_git_sandbox_init("testrepo.git");
64 const char *url = cl_git_path_url(git_repository_path(remote_repo));
65 git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
66
67 options.callbacks.transfer_progress = transfer_cb;
68 options.callbacks.payload = &callcount;
69
70 cl_set_cleanup(&cleanup_local_repo, "foo");
71 cl_git_pass(git_repository_init(&repo, "foo", true));
72
73 cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url));
74 cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
75
76 cl_git_pass(git_reference_list(&refnames, repo));
77 cl_assert_equal_i(20, (int)refnames.count);
78 cl_assert(callcount > 0);
79 git_strarray_dispose(&refnames);
80 git_remote_free(origin);
81
82 cl_git_pass(git_reference_lookup(&ref, remote_repo, "refs/heads/br2"));
83 cl_git_pass(git_reference_delete(ref));
84 git_reference_free(ref);
85
86 cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN));
87 cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
88 cl_git_pass(git_remote_prune(origin, &options.callbacks));
89
90 cl_git_pass(git_reference_list(&refnames, repo));
91 cl_assert_equal_i(19, (int)refnames.count);
92 git_strarray_dispose(&refnames);
93 git_remote_free(origin);
94
95 cl_git_pass(git_reference_lookup(&ref, remote_repo, "refs/heads/packed"));
96 cl_git_pass(git_reference_delete(ref));
97 git_reference_free(ref);
98
99 cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN));
100 cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
101 cl_git_pass(git_remote_prune(origin, &options.callbacks));
102
103 cl_git_pass(git_reference_list(&refnames, repo));
104 cl_assert_equal_i(18, (int)refnames.count);
105 git_strarray_dispose(&refnames);
106 git_remote_free(origin);
107
108 git_repository_free(repo);
109 }
110
111 static int update_tips_fail_on_call(const char *ref, const git_oid *old, const git_oid *new, void *data)
112 {
113 GIT_UNUSED(ref);
114 GIT_UNUSED(old);
115 GIT_UNUSED(new);
116 GIT_UNUSED(data);
117
118 cl_fail("update tips called");
119 return 0;
120 }
121
122 static void assert_ref_exists(git_repository *repo, const char *name)
123 {
124 git_reference *ref;
125
126 cl_git_pass(git_reference_lookup(&ref, repo, name));
127 git_reference_free(ref);
128 }
129
130 void test_network_fetchlocal__prune_overlapping(void)
131 {
132 git_repository *repo;
133 git_remote *origin;
134 int callcount = 0;
135 git_strarray refnames = {0};
136 git_reference *ref;
137 git_config *config;
138 git_oid target;
139
140 git_repository *remote_repo = cl_git_sandbox_init("testrepo.git");
141 const char *url = cl_git_path_url(git_repository_path(remote_repo));
142
143 git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
144 options.callbacks.transfer_progress = transfer_cb;
145 options.callbacks.payload = &callcount;
146
147 cl_git_pass(git_reference_lookup(&ref, remote_repo, "refs/heads/master"));
148 git_oid_cpy(&target, git_reference_target(ref));
149 git_reference_free(ref);
150 cl_git_pass(git_reference_create(&ref, remote_repo, "refs/pull/42/head", &target, 1, NULL));
151 git_reference_free(ref);
152
153 cl_set_cleanup(&cleanup_local_repo, "foo");
154 cl_git_pass(git_repository_init(&repo, "foo", true));
155
156 cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url));
157
158 cl_git_pass(git_repository_config(&config, repo));
159 cl_git_pass(git_config_set_bool(config, "remote.origin.prune", true));
160 cl_git_pass(git_config_set_multivar(config, "remote.origin.fetch", "^$", "refs/pull/*/head:refs/remotes/origin/pr/*"));
161
162 git_remote_free(origin);
163 cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN));
164 cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
165
166 assert_ref_exists(repo, "refs/remotes/origin/master");
167 assert_ref_exists(repo, "refs/remotes/origin/pr/42");
168 cl_git_pass(git_reference_list(&refnames, repo));
169 cl_assert_equal_i(21, (int)refnames.count);
170 git_strarray_dispose(&refnames);
171
172 cl_git_pass(git_config_delete_multivar(config, "remote.origin.fetch", "refs"));
173 cl_git_pass(git_config_set_multivar(config, "remote.origin.fetch", "^$", "refs/pull/*/head:refs/remotes/origin/pr/*"));
174 cl_git_pass(git_config_set_multivar(config, "remote.origin.fetch", "^$", "refs/heads/*:refs/remotes/origin/*"));
175
176 git_remote_free(origin);
177 cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN));
178 options.callbacks.update_tips = update_tips_fail_on_call;
179 cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
180
181 assert_ref_exists(repo, "refs/remotes/origin/master");
182 assert_ref_exists(repo, "refs/remotes/origin/pr/42");
183 cl_git_pass(git_reference_list(&refnames, repo));
184 cl_assert_equal_i(21, (int)refnames.count);
185 git_strarray_dispose(&refnames);
186
187 cl_git_pass(git_config_delete_multivar(config, "remote.origin.fetch", "refs"));
188 cl_git_pass(git_config_set_multivar(config, "remote.origin.fetch", "^$", "refs/heads/*:refs/remotes/origin/*"));
189 cl_git_pass(git_config_set_multivar(config, "remote.origin.fetch", "^$", "refs/pull/*/head:refs/remotes/origin/pr/*"));
190
191 git_remote_free(origin);
192 cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN));
193 options.callbacks.update_tips = update_tips_fail_on_call;
194 cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
195
196 git_config_free(config);
197 git_strarray_dispose(&refnames);
198 git_remote_free(origin);
199 git_repository_free(repo);
200 }
201
202 void test_network_fetchlocal__fetchprune(void)
203 {
204 git_repository *repo;
205 git_remote *origin;
206 int callcount = 0;
207 git_strarray refnames = {0};
208 git_reference *ref;
209 git_config *config;
210 git_repository *remote_repo = cl_git_sandbox_init("testrepo.git");
211 const char *url = cl_git_path_url(git_repository_path(remote_repo));
212 git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
213
214 options.callbacks.transfer_progress = transfer_cb;
215 options.callbacks.payload = &callcount;
216
217 cl_set_cleanup(&cleanup_local_repo, "foo");
218 cl_git_pass(git_repository_init(&repo, "foo", true));
219
220 cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url));
221 cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
222
223 cl_git_pass(git_reference_list(&refnames, repo));
224 cl_assert_equal_i(20, (int)refnames.count);
225 cl_assert(callcount > 0);
226 git_strarray_dispose(&refnames);
227 git_remote_free(origin);
228
229 cl_git_pass(git_reference_lookup(&ref, remote_repo, "refs/heads/br2"));
230 cl_git_pass(git_reference_delete(ref));
231 git_reference_free(ref);
232
233 cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN));
234 cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
235 cl_git_pass(git_remote_prune(origin, &options.callbacks));
236
237 cl_git_pass(git_reference_list(&refnames, repo));
238 cl_assert_equal_i(19, (int)refnames.count);
239 git_strarray_dispose(&refnames);
240 git_remote_free(origin);
241
242 cl_git_pass(git_reference_lookup(&ref, remote_repo, "refs/heads/packed"));
243 cl_git_pass(git_reference_delete(ref));
244 git_reference_free(ref);
245
246 cl_git_pass(git_repository_config(&config, repo));
247 cl_git_pass(git_config_set_bool(config, "remote.origin.prune", 1));
248 git_config_free(config);
249 cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN));
250 cl_assert_equal_i(1, git_remote_prune_refs(origin));
251 cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
252
253 cl_git_pass(git_reference_list(&refnames, repo));
254 cl_assert_equal_i(18, (int)refnames.count);
255 git_strarray_dispose(&refnames);
256 git_remote_free(origin);
257
258 git_repository_free(repo);
259 }
260
261 void test_network_fetchlocal__prune_tag(void)
262 {
263 git_repository *repo;
264 git_remote *origin;
265 int callcount = 0;
266 git_reference *ref;
267 git_config *config;
268 git_oid tag_id;
269 git_signature *tagger;
270 git_object *obj;
271
272 git_repository *remote_repo = cl_git_sandbox_init("testrepo.git");
273 const char *url = cl_git_path_url(git_repository_path(remote_repo));
274 git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
275
276 options.callbacks.transfer_progress = transfer_cb;
277 options.callbacks.payload = &callcount;
278
279 cl_set_cleanup(&cleanup_local_repo, "foo");
280 cl_git_pass(git_repository_init(&repo, "foo", true));
281
282 cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url));
283 cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
284 git_remote_free(origin);
285
286 cl_git_pass(git_revparse_single(&obj, repo, "origin/master"));
287
288 cl_git_pass(git_reference_create(&ref, repo, "refs/remotes/origin/fake-remote", git_object_id(obj), 1, NULL));
289 git_reference_free(ref);
290
291 /* create signature */
292 cl_git_pass(git_signature_new(&tagger, tagger_name, tagger_email, 123456789, 60));
293
294 cl_git_pass(
295 git_tag_create(&tag_id, repo,
296 "some-tag", obj, tagger, tagger_message, 0)
297 );
298 git_signature_free(tagger);
299
300 cl_git_pass(git_repository_config(&config, repo));
301 cl_git_pass(git_config_set_bool(config, "remote.origin.prune", 1));
302 git_config_free(config);
303 cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN));
304 cl_assert_equal_i(1, git_remote_prune_refs(origin));
305 cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
306
307 assert_ref_exists(repo, "refs/tags/some-tag");
308 cl_git_fail_with(GIT_ENOTFOUND, git_reference_lookup(&ref, repo, "refs/remotes/origin/fake-remote"));
309
310 git_object_free(obj);
311 git_remote_free(origin);
312
313 git_repository_free(repo);
314 }
315
316 void test_network_fetchlocal__partial(void)
317 {
318 git_repository *repo = cl_git_sandbox_init("partial-testrepo");
319 git_remote *origin;
320 int callcount = 0;
321 git_strarray refnames = {0};
322 const char *url;
323 git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
324
325 options.callbacks.transfer_progress = transfer_cb;
326 options.callbacks.payload = &callcount;
327
328 cl_git_pass(git_reference_list(&refnames, repo));
329 cl_assert_equal_i(1, (int)refnames.count);
330
331 url = cl_git_fixture_url("testrepo.git");
332 cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url));
333 cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
334
335 git_strarray_dispose(&refnames);
336
337 cl_git_pass(git_reference_list(&refnames, repo));
338 cl_assert_equal_i(21, (int)refnames.count); /* 18 remote + 1 local */
339 cl_assert(callcount > 0);
340
341 git_strarray_dispose(&refnames);
342 git_remote_free(origin);
343 }
344
345 static int remote_mirror_cb(git_remote **out, git_repository *repo,
346 const char *name, const char *url, void *payload)
347 {
348 int error;
349 git_remote *remote;
350
351 GIT_UNUSED(payload);
352
353 if ((error = git_remote_create_with_fetchspec(&remote, repo, name, url, "+refs/*:refs/*")) < 0)
354 return error;
355
356 *out = remote;
357 return 0;
358 }
359
360 void test_network_fetchlocal__clone_into_mirror(void)
361 {
362 git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
363 git_repository *repo;
364 git_reference *ref;
365
366 opts.bare = true;
367 opts.remote_cb = remote_mirror_cb;
368 cl_git_pass(git_clone(&repo, cl_git_fixture_url("testrepo.git"), "./foo.git", &opts));
369
370 cl_git_pass(git_reference_lookup(&ref, repo, "HEAD"));
371 cl_assert_equal_i(GIT_REFERENCE_SYMBOLIC, git_reference_type(ref));
372 cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(ref));
373
374 git_reference_free(ref);
375 cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/test/master"));
376
377 git_reference_free(ref);
378 git_repository_free(repo);
379 cl_fixture_cleanup("./foo.git");
380 }
381
382 void test_network_fetchlocal__all_refs(void)
383 {
384 git_repository *repo;
385 git_remote *remote;
386 git_reference *ref;
387 char *allrefs = "+refs/*:refs/*";
388 git_strarray refspecs = {
389 &allrefs,
390 1,
391 };
392
393 cl_git_pass(git_repository_init(&repo, "./foo.git", true));
394 cl_git_pass(git_remote_create_anonymous(&remote, repo, cl_git_fixture_url("testrepo.git")));
395 cl_git_pass(git_remote_fetch(remote, &refspecs, NULL, NULL));
396
397 cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/test/master"));
398 git_reference_free(ref);
399
400 cl_git_pass(git_reference_lookup(&ref, repo, "refs/tags/test"));
401 git_reference_free(ref);
402
403 git_remote_free(remote);
404 git_repository_free(repo);
405 cl_fixture_cleanup("./foo.git");
406 }
407
408 void test_network_fetchlocal__multi_remotes(void)
409 {
410 git_repository *repo = cl_git_sandbox_init("testrepo.git");
411 git_remote *test, *test2;
412 git_strarray refnames = {0};
413 git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
414
415 options.callbacks.transfer_progress = transfer_cb;
416 cl_git_pass(git_remote_set_url(repo, "test", cl_git_fixture_url("testrepo.git")));
417 cl_git_pass(git_remote_lookup(&test, repo, "test"));
418 cl_git_pass(git_remote_fetch(test, NULL, &options, NULL));
419
420 cl_git_pass(git_reference_list(&refnames, repo));
421 cl_assert_equal_i(35, (int)refnames.count);
422 git_strarray_dispose(&refnames);
423
424 cl_git_pass(git_remote_set_url(repo, "test_with_pushurl", cl_git_fixture_url("testrepo.git")));
425 cl_git_pass(git_remote_lookup(&test2, repo, "test_with_pushurl"));
426 cl_git_pass(git_remote_fetch(test2, NULL, &options, NULL));
427
428 cl_git_pass(git_reference_list(&refnames, repo));
429 cl_assert_equal_i(48, (int)refnames.count);
430
431 git_strarray_dispose(&refnames);
432 git_remote_free(test);
433 git_remote_free(test2);
434 }
435
436 static int sideband_cb(const char *str, int len, void *payload)
437 {
438 int *count = (int *) payload;
439
440 GIT_UNUSED(str);
441 GIT_UNUSED(len);
442
443 (*count)++;
444 return 0;
445 }
446
447 void test_network_fetchlocal__call_progress(void)
448 {
449 git_repository *repo;
450 git_remote *remote;
451 git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
452 int callcount = 0;
453
454 cl_git_pass(git_repository_init(&repo, "foo.git", true));
455 cl_set_cleanup(cleanup_local_repo, "foo.git");
456
457 cl_git_pass(git_remote_create_with_fetchspec(&remote, repo, "origin", cl_git_fixture_url("testrepo.git"), "+refs/heads/*:refs/heads/*"));
458
459 options.callbacks.sideband_progress = sideband_cb;
460 options.callbacks.payload = &callcount;
461
462 cl_git_pass(git_remote_fetch(remote, NULL, &options, NULL));
463 cl_assert(callcount != 0);
464
465 git_remote_free(remote);
466 git_repository_free(repo);
467 }
468
469 void test_network_fetchlocal__prune_load_remote_prune_config(void)
470 {
471 git_repository *repo;
472 git_remote *origin;
473 git_config *config;
474 git_repository *remote_repo = cl_git_sandbox_init("testrepo.git");
475 const char *url = cl_git_path_url(git_repository_path(remote_repo));
476
477 cl_set_cleanup(&cleanup_local_repo, "foo");
478 cl_git_pass(git_repository_init(&repo, "foo", true));
479
480 cl_git_pass(git_repository_config(&config, repo));
481 cl_git_pass(git_config_set_bool(config, "remote.origin.prune", 1));
482
483 cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url));
484 cl_assert_equal_i(1, git_remote_prune_refs(origin));
485
486 git_config_free(config);
487 git_remote_free(origin);
488 git_repository_free(repo);
489 }
490
491 void test_network_fetchlocal__prune_load_fetch_prune_config(void)
492 {
493 git_repository *repo;
494 git_remote *origin;
495 git_config *config;
496 git_repository *remote_repo = cl_git_sandbox_init("testrepo.git");
497 const char *url = cl_git_path_url(git_repository_path(remote_repo));
498
499 cl_set_cleanup(&cleanup_local_repo, "foo");
500 cl_git_pass(git_repository_init(&repo, "foo", true));
501
502 cl_git_pass(git_repository_config(&config, repo));
503 cl_git_pass(git_config_set_bool(config, "fetch.prune", 1));
504
505 cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url));
506 cl_assert_equal_i(1, git_remote_prune_refs(origin));
507
508 git_config_free(config);
509 git_remote_free(origin);
510 git_repository_free(repo);
511 }
512
513 static int update_tips_error(const char *ref, const git_oid *old, const git_oid *new, void *data)
514 {
515 int *callcount = (int *) data;
516
517 GIT_UNUSED(ref);
518 GIT_UNUSED(old);
519 GIT_UNUSED(new);
520
521 (*callcount)++;
522
523 return -1;
524 }
525
526 void test_network_fetchlocal__update_tips_error_is_propagated(void)
527 {
528 git_repository *repo;
529 git_reference_iterator *iterator;
530 git_reference *ref;
531 git_remote *remote;
532 git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
533 int callcount = 0;
534
535 cl_git_pass(git_repository_init(&repo, "foo.git", true));
536 cl_set_cleanup(cleanup_local_repo, "foo.git");
537
538 cl_git_pass(git_remote_create_with_fetchspec(&remote, repo, "origin", cl_git_fixture_url("testrepo.git"), "+refs/heads/*:refs/remotes/update-tips/*"));
539
540 options.callbacks.update_tips = update_tips_error;
541 options.callbacks.payload = &callcount;
542
543 cl_git_fail(git_remote_fetch(remote, NULL, &options, NULL));
544 cl_assert_equal_i(1, callcount);
545
546 cl_git_pass(git_reference_iterator_glob_new(&iterator, repo, "refs/remotes/update-tips/**/"));
547 cl_assert_equal_i(GIT_ITEROVER, git_reference_next(&ref, iterator));
548
549 git_reference_iterator_free(iterator);
550 git_remote_free(remote);
551 git_repository_free(repo);
552 }