1 #include "clar_libgit2.h"
6 #include "fetchhead_data.h"
8 #define DO_LOCAL_TEST 0
10 static git_repository
*g_repo
;
12 void test_fetchhead_nonetwork__initialize(void)
17 static void cleanup_repository(void *path
)
20 git_repository_free(g_repo
);
24 cl_fixture_cleanup((const char *)path
);
27 static void populate_fetchhead(git_vector
*out
, git_repository
*repo
)
29 git_fetchhead_ref
*fetchhead_ref
;
32 cl_git_pass(git_oid_fromstr(&oid
,
33 "49322bb17d3acc9146f98c97d078513228bbf3c0"));
34 cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref
, &oid
, 1,
36 "https://github.com/libgit2/TestGitRepository"));
37 cl_git_pass(git_vector_insert(out
, fetchhead_ref
));
39 cl_git_pass(git_oid_fromstr(&oid
,
40 "0966a434eb1a025db6b71485ab63a3bfbea520b6"));
41 cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref
, &oid
, 0,
42 "refs/heads/first-merge",
43 "https://github.com/libgit2/TestGitRepository"));
44 cl_git_pass(git_vector_insert(out
, fetchhead_ref
));
46 cl_git_pass(git_oid_fromstr(&oid
,
47 "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1"));
48 cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref
, &oid
, 0,
49 "refs/heads/no-parent",
50 "https://github.com/libgit2/TestGitRepository"));
51 cl_git_pass(git_vector_insert(out
, fetchhead_ref
));
53 cl_git_pass(git_oid_fromstr(&oid
,
54 "d96c4e80345534eccee5ac7b07fc7603b56124cb"));
55 cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref
, &oid
, 0,
56 "refs/tags/annotated_tag",
57 "https://github.com/libgit2/TestGitRepository"));
58 cl_git_pass(git_vector_insert(out
, fetchhead_ref
));
60 cl_git_pass(git_oid_fromstr(&oid
,
61 "55a1a760df4b86a02094a904dfa511deb5655905"));
62 cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref
, &oid
, 0,
64 "https://github.com/libgit2/TestGitRepository"));
65 cl_git_pass(git_vector_insert(out
, fetchhead_ref
));
67 cl_git_pass(git_oid_fromstr(&oid
,
68 "8f50ba15d49353813cc6e20298002c0d17b0a9ee"));
69 cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref
, &oid
, 0,
70 "refs/tags/commit_tree",
71 "https://github.com/libgit2/TestGitRepository"));
72 cl_git_pass(git_vector_insert(out
, fetchhead_ref
));
74 cl_git_pass(git_fetchhead_write(repo
, out
));
77 void test_fetchhead_nonetwork__write(void)
79 git_vector fetchhead_vector
= GIT_VECTOR_INIT
;
80 git_fetchhead_ref
*fetchhead_ref
;
81 git_str fetchhead_buf
= GIT_STR_INIT
;
85 cl_git_pass(git_vector_init(&fetchhead_vector
, 6, NULL
));
87 cl_set_cleanup(&cleanup_repository
, "./test1");
88 cl_git_pass(git_repository_init(&g_repo
, "./test1", 0));
90 populate_fetchhead(&fetchhead_vector
, g_repo
);
92 cl_git_pass(git_futils_readbuffer(&fetchhead_buf
,
93 "./test1/.git/FETCH_HEAD"));
95 equals
= (strcmp(fetchhead_buf
.ptr
, FETCH_HEAD_WILDCARD_DATA_LOCAL
) == 0);
97 git_str_dispose(&fetchhead_buf
);
99 git_vector_foreach(&fetchhead_vector
, i
, fetchhead_ref
) {
100 git_fetchhead_ref_free(fetchhead_ref
);
103 git_vector_free(&fetchhead_vector
);
109 git_vector
*fetchhead_vector
;
111 } fetchhead_ref_cb_data
;
113 static int fetchhead_ref_cb(const char *name
, const char *url
,
114 const git_oid
*oid
, unsigned int is_merge
, void *payload
)
116 fetchhead_ref_cb_data
*cb_data
= payload
;
117 git_fetchhead_ref
*expected
;
121 expected
= git_vector_get(cb_data
->fetchhead_vector
, cb_data
->idx
);
123 cl_assert_equal_oid(&expected
->oid
, oid
);
124 cl_assert(expected
->is_merge
== is_merge
);
126 if (expected
->ref_name
)
127 cl_assert_equal_s(expected
->ref_name
, name
);
129 cl_assert(name
== NULL
);
131 if (expected
->remote_url
)
132 cl_assert_equal_s(expected
->remote_url
, url
);
134 cl_assert(url
== NULL
);
141 void test_fetchhead_nonetwork__read(void)
143 git_vector fetchhead_vector
= GIT_VECTOR_INIT
;
144 git_fetchhead_ref
*fetchhead_ref
;
145 fetchhead_ref_cb_data cb_data
;
148 memset(&cb_data
, 0x0, sizeof(fetchhead_ref_cb_data
));
150 cl_set_cleanup(&cleanup_repository
, "./test1");
151 cl_git_pass(git_repository_init(&g_repo
, "./test1", 0));
153 populate_fetchhead(&fetchhead_vector
, g_repo
);
155 cb_data
.fetchhead_vector
= &fetchhead_vector
;
157 cl_git_pass(git_repository_fetchhead_foreach(g_repo
, fetchhead_ref_cb
, &cb_data
));
159 git_vector_foreach(&fetchhead_vector
, i
, fetchhead_ref
) {
160 git_fetchhead_ref_free(fetchhead_ref
);
163 git_vector_free(&fetchhead_vector
);
166 static int read_old_style_cb(const char *name
, const char *url
,
167 const git_oid
*oid
, unsigned int is_merge
, void *payload
)
173 git_oid_fromstr(&expected
, "49322bb17d3acc9146f98c97d078513228bbf3c0");
175 cl_assert(name
== NULL
);
176 cl_assert(url
== NULL
);
177 cl_assert_equal_oid(&expected
, oid
);
178 cl_assert(is_merge
== 1);
183 void test_fetchhead_nonetwork__read_old_style(void)
185 cl_set_cleanup(&cleanup_repository
, "./test1");
186 cl_git_pass(git_repository_init(&g_repo
, "./test1", 0));
188 cl_git_rewritefile("./test1/.git/FETCH_HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0\n");
190 cl_git_pass(git_repository_fetchhead_foreach(g_repo
, read_old_style_cb
, NULL
));
193 static int read_type_missing(const char *ref_name
, const char *remote_url
,
194 const git_oid
*oid
, unsigned int is_merge
, void *payload
)
200 git_oid_fromstr(&expected
, "49322bb17d3acc9146f98c97d078513228bbf3c0");
202 cl_assert_equal_s("name", ref_name
);
203 cl_assert_equal_s("remote_url", remote_url
);
204 cl_assert_equal_oid(&expected
, oid
);
205 cl_assert(is_merge
== 0);
210 void test_fetchhead_nonetwork__type_missing(void)
212 cl_set_cleanup(&cleanup_repository
, "./test1");
213 cl_git_pass(git_repository_init(&g_repo
, "./test1", 0));
215 cl_git_rewritefile("./test1/.git/FETCH_HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0\tnot-for-merge\t'name' of remote_url\n");
217 cl_git_pass(git_repository_fetchhead_foreach(g_repo
, read_type_missing
, NULL
));
220 static int read_name_missing(const char *ref_name
, const char *remote_url
,
221 const git_oid
*oid
, unsigned int is_merge
, void *payload
)
227 git_oid_fromstr(&expected
, "49322bb17d3acc9146f98c97d078513228bbf3c0");
229 cl_assert(ref_name
== NULL
);
230 cl_assert_equal_s("remote_url", remote_url
);
231 cl_assert_equal_oid(&expected
, oid
);
232 cl_assert(is_merge
== 0);
237 void test_fetchhead_nonetwork__name_missing(void)
239 cl_set_cleanup(&cleanup_repository
, "./test1");
240 cl_git_pass(git_repository_init(&g_repo
, "./test1", 0));
242 cl_git_rewritefile("./test1/.git/FETCH_HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0\tnot-for-merge\tremote_url\n");
244 cl_git_pass(git_repository_fetchhead_foreach(g_repo
, read_name_missing
, NULL
));
247 static int read_noop(const char *ref_name
, const char *remote_url
,
248 const git_oid
*oid
, unsigned int is_merge
, void *payload
)
250 GIT_UNUSED(ref_name
);
251 GIT_UNUSED(remote_url
);
253 GIT_UNUSED(is_merge
);
259 void test_fetchhead_nonetwork__nonexistent(void)
263 cl_set_cleanup(&cleanup_repository
, "./test1");
264 cl_git_pass(git_repository_init(&g_repo
, "./test1", 0));
266 cl_git_fail((error
= git_repository_fetchhead_foreach(g_repo
, read_noop
, NULL
)));
267 cl_assert(error
== GIT_ENOTFOUND
);
270 void test_fetchhead_nonetwork__invalid_unterminated_last_line(void)
272 cl_set_cleanup(&cleanup_repository
, "./test1");
273 cl_git_pass(git_repository_init(&g_repo
, "./test1", 0));
275 cl_git_rewritefile("./test1/.git/FETCH_HEAD", "unterminated");
276 cl_git_fail(git_repository_fetchhead_foreach(g_repo
, read_noop
, NULL
));
279 void test_fetchhead_nonetwork__invalid_oid(void)
281 cl_set_cleanup(&cleanup_repository
, "./test1");
282 cl_git_pass(git_repository_init(&g_repo
, "./test1", 0));
284 cl_git_rewritefile("./test1/.git/FETCH_HEAD", "shortoid\n");
285 cl_git_fail(git_repository_fetchhead_foreach(g_repo
, read_noop
, NULL
));
288 void test_fetchhead_nonetwork__invalid_for_merge(void)
290 cl_set_cleanup(&cleanup_repository
, "./test1");
291 cl_git_pass(git_repository_init(&g_repo
, "./test1", 0));
293 cl_git_rewritefile("./test1/.git/FETCH_HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0\tinvalid-merge\t\n");
294 cl_git_fail(git_repository_fetchhead_foreach(g_repo
, read_noop
, NULL
));
296 cl_assert(git__prefixcmp(git_error_last()->message
, "invalid for-merge") == 0);
299 void test_fetchhead_nonetwork__invalid_description(void)
301 cl_set_cleanup(&cleanup_repository
, "./test1");
302 cl_git_pass(git_repository_init(&g_repo
, "./test1", 0));
304 cl_git_rewritefile("./test1/.git/FETCH_HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0\tnot-for-merge\n");
305 cl_git_fail(git_repository_fetchhead_foreach(g_repo
, read_noop
, NULL
));
307 cl_assert(git__prefixcmp(git_error_last()->message
, "invalid description") == 0);
310 static int assert_master_for_merge(const char *ref
, const char *url
, const git_oid
*id
, unsigned int is_merge
, void *data
)
316 if (!strcmp("refs/heads/master", ref
) && !is_merge
)
322 static int assert_none_for_merge(const char *ref
, const char *url
, const git_oid
*id
, unsigned int is_merge
, void *data
)
329 return is_merge
? -1 : 0;
332 void test_fetchhead_nonetwork__unborn_with_upstream(void)
334 git_repository
*repo
;
337 /* Create an empty repo to clone from */
338 cl_set_cleanup(&cleanup_repository
, "./test1");
339 cl_git_pass(git_repository_init(&g_repo
, "./test1", 0));
340 cl_set_cleanup(&cleanup_repository
, "./repowithunborn");
341 cl_git_pass(git_clone(&repo
, "./test1", "./repowithunborn", NULL
));
343 /* Simulate someone pushing to it by changing to one that has stuff */
344 cl_git_pass(git_remote_set_url(repo
, "origin", cl_fixture("testrepo.git")));
345 cl_git_pass(git_remote_lookup(&remote
, repo
, "origin"));
347 cl_git_pass(git_remote_fetch(remote
, NULL
, NULL
, NULL
));
348 git_remote_free(remote
);
350 cl_git_pass(git_repository_fetchhead_foreach(repo
, assert_master_for_merge
, NULL
));
352 git_repository_free(repo
);
353 cl_fixture_cleanup("./repowithunborn");
356 void test_fetchhead_nonetwork__fetch_into_repo_with_symrefs(void)
358 git_repository
*repo
;
360 git_reference
*symref
;
362 repo
= cl_git_sandbox_init("empty_standard_repo");
365 * Testing for a specific constellation where the repository has at
366 * least one symbolic reference in its refdb.
368 cl_git_pass(git_reference_symbolic_create(&symref
, repo
, "refs/heads/symref", "refs/heads/master", 0, NULL
));
370 cl_git_pass(git_remote_set_url(repo
, "origin", cl_fixture("testrepo.git")));
371 cl_git_pass(git_remote_lookup(&remote
, repo
, "origin"));
372 cl_git_pass(git_remote_fetch(remote
, NULL
, NULL
, NULL
));
374 git_remote_free(remote
);
375 git_reference_free(symref
);
376 cl_git_sandbox_cleanup();
379 void test_fetchhead_nonetwork__fetch_into_repo_with_invalid_head(void)
382 char *strings
[] = { "refs/heads/*:refs/remotes/origin/*" };
383 git_strarray refspecs
= { strings
, 1 };
385 cl_set_cleanup(&cleanup_repository
, "./test1");
386 cl_git_pass(git_repository_init(&g_repo
, "./test1", 0));
388 /* HEAD pointing to nonexistent branch */
389 cl_git_rewritefile("./test1/.git/HEAD", "ref: refs/heads/\n");
391 cl_git_pass(git_remote_create_anonymous(&remote
, g_repo
, cl_fixture("testrepo.git")));
392 cl_git_pass(git_remote_fetch(remote
, &refspecs
, NULL
, NULL
));
393 cl_git_pass(git_repository_fetchhead_foreach(g_repo
, assert_none_for_merge
, NULL
));
395 git_remote_free(remote
);
398 void test_fetchhead_nonetwork__quote_in_branch_name(void)
400 cl_set_cleanup(&cleanup_repository
, "./test1");
401 cl_git_pass(git_repository_init(&g_repo
, "./test1", 0));
403 cl_git_rewritefile("./test1/.git/FETCH_HEAD", FETCH_HEAD_QUOTE_DATA
);
404 cl_git_pass(git_repository_fetchhead_foreach(g_repo
, read_noop
, NULL
));
407 static bool found_master
;
408 static bool found_haacked
;
409 static bool find_master_haacked_called
;
411 static int find_master_haacked(const char *ref_name
, const char *remote_url
, const git_oid
*oid
, unsigned int is_merge
, void *payload
)
413 GIT_UNUSED(remote_url
);
417 find_master_haacked_called
= true;
419 if (!strcmp("refs/heads/master", ref_name
)) {
423 if (!strcmp("refs/heads/haacked", ref_name
)) {
425 found_haacked
= true;
431 void test_fetchhead_nonetwork__create_when_refpecs_given(void)
434 git_str path
= GIT_STR_INIT
;
435 char *refspec1
= "refs/heads/master";
436 char *refspec2
= "refs/heads/haacked";
437 char *refspecs
[] = { refspec1
, refspec2
};
438 git_strarray specs
= {
443 cl_set_cleanup(&cleanup_repository
, "./test1");
444 cl_git_pass(git_repository_init(&g_repo
, "./test1", 0));
446 cl_git_pass(git_str_joinpath(&path
, git_repository_path(g_repo
), "FETCH_HEAD"));
447 cl_git_pass(git_remote_create(&remote
, g_repo
, "origin", cl_fixture("testrepo.git")));
449 cl_assert(!git_fs_path_exists(path
.ptr
));
450 cl_git_pass(git_remote_fetch(remote
, &specs
, NULL
, NULL
));
451 cl_assert(git_fs_path_exists(path
.ptr
));
453 cl_git_pass(git_repository_fetchhead_foreach(g_repo
, find_master_haacked
, NULL
));
454 cl_assert(find_master_haacked_called
);
455 cl_assert(found_master
);
456 cl_assert(found_haacked
);
458 git_remote_free(remote
);
459 git_str_dispose(&path
);
462 static bool count_refs_called
;
463 struct prefix_count
{
469 static int count_refs(const char *ref_name
, const char *remote_url
, const git_oid
*oid
, unsigned int is_merge
, void *payload
)
472 struct prefix_count
*prefix_counts
= (struct prefix_count
*) payload
;
474 GIT_UNUSED(remote_url
);
476 GIT_UNUSED(is_merge
);
478 count_refs_called
= true;
480 for (i
= 0; prefix_counts
[i
].prefix
; i
++) {
481 if (!git__prefixcmp(ref_name
, prefix_counts
[i
].prefix
))
482 prefix_counts
[i
].count
++;
488 void test_fetchhead_nonetwork__create_with_multiple_refspecs(void)
491 git_str path
= GIT_STR_INIT
;
493 cl_set_cleanup(&cleanup_repository
, "./test1");
494 cl_git_pass(git_repository_init(&g_repo
, "./test1", 0));
496 cl_git_pass(git_remote_create(&remote
, g_repo
, "origin", cl_fixture("testrepo.git")));
497 git_remote_free(remote
);
498 cl_git_pass(git_remote_add_fetch(g_repo
, "origin", "+refs/notes/*:refs/origin/notes/*"));
499 /* Pick up the new refspec */
500 cl_git_pass(git_remote_lookup(&remote
, g_repo
, "origin"));
502 cl_git_pass(git_str_joinpath(&path
, git_repository_path(g_repo
), "FETCH_HEAD"));
503 cl_assert(!git_fs_path_exists(path
.ptr
));
504 cl_git_pass(git_remote_fetch(remote
, NULL
, NULL
, NULL
));
505 cl_assert(git_fs_path_exists(path
.ptr
));
509 struct prefix_count prefix_counts
[] = {
510 {"refs/notes/", 0, 1},
511 {"refs/heads/", 0, 13},
512 {"refs/tags/", 0, 7},
516 cl_git_pass(git_repository_fetchhead_foreach(g_repo
, count_refs
, &prefix_counts
));
517 cl_assert(count_refs_called
);
518 for (i
= 0; prefix_counts
[i
].prefix
; i
++)
519 cl_assert_equal_i(prefix_counts
[i
].expected
, prefix_counts
[i
].count
);
522 git_remote_free(remote
);
523 git_str_dispose(&path
);
526 void test_fetchhead_nonetwork__credentials_are_stripped(void)
528 git_fetchhead_ref
*ref
;
531 cl_git_pass(git_oid_fromstr(&oid
, "49322bb17d3acc9146f98c97d078513228bbf3c0"));
532 cl_git_pass(git_fetchhead_ref_create(&ref
, &oid
, 0,
533 "refs/tags/commit_tree", "http://foo:bar@github.com/libgit2/TestGitRepository"));
534 cl_assert_equal_s(ref
->remote_url
, "http://github.com/libgit2/TestGitRepository");
535 git_fetchhead_ref_free(ref
);
537 cl_git_pass(git_oid_fromstr(&oid
, "49322bb17d3acc9146f98c97d078513228bbf3c0"));
538 cl_git_pass(git_fetchhead_ref_create(&ref
, &oid
, 0,
539 "refs/tags/commit_tree", "https://foo:bar@github.com/libgit2/TestGitRepository"));
540 cl_assert_equal_s(ref
->remote_url
, "https://github.com/libgit2/TestGitRepository");
541 git_fetchhead_ref_free(ref
);