]>
Commit | Line | Data |
---|---|---|
764df57e BS |
1 | #include "clar_libgit2.h" |
2 | ||
3 | #include "git2/clone.h" | |
4330ab26 | 4 | #include "remote.h" |
114f5a6c RB |
5 | #include "fileops.h" |
6 | #include "repository.h" | |
764df57e | 7 | |
86a2da6e | 8 | #define LIVE_REPO_URL "git://github.com/libgit2/TestGitRepository" |
822d9dd5 | 9 | |
18b2d560 | 10 | static git_clone_options g_options; |
764df57e | 11 | static git_repository *g_repo; |
b5b28120 SC |
12 | static git_reference* g_ref; |
13 | static git_remote* g_remote; | |
764df57e | 14 | |
65415ea2 | 15 | void test_clone_nonetwork__initialize(void) |
764df57e | 16 | { |
6affd71f | 17 | git_checkout_options dummy_opts = GIT_CHECKOUT_OPTIONS_INIT; |
0e0cf787 | 18 | git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; |
730df6d0 | 19 | |
1c7eb971 | 20 | g_repo = NULL; |
18b2d560 BS |
21 | |
22 | memset(&g_options, 0, sizeof(git_clone_options)); | |
23 | g_options.version = GIT_CLONE_OPTIONS_VERSION; | |
730df6d0 | 24 | g_options.checkout_opts = dummy_opts; |
8f1066a0 | 25 | g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; |
0e0cf787 | 26 | g_options.remote_callbacks = dummy_callbacks; |
a1710a28 | 27 | cl_git_pass(git_signature_now(&g_options.signature, "Me", "foo@example.com")); |
764df57e BS |
28 | } |
29 | ||
24393ea6 | 30 | void test_clone_nonetwork__cleanup(void) |
764df57e | 31 | { |
9094d30b | 32 | if (g_repo) { |
1c7eb971 | 33 | git_repository_free(g_repo); |
9094d30b SC |
34 | g_repo = NULL; |
35 | } | |
36 | ||
b5b28120 SC |
37 | if (g_ref) { |
38 | git_reference_free(g_ref); | |
39 | g_ref = NULL; | |
40 | } | |
41 | ||
42 | if (g_remote) { | |
43 | git_remote_free(g_remote); | |
44 | g_remote = NULL; | |
45 | } | |
46 | ||
a1710a28 | 47 | git_signature_free(g_options.signature); |
f46769e5 | 48 | cl_fixture_cleanup("./foo"); |
764df57e BS |
49 | } |
50 | ||
ff0ef88c | 51 | void test_clone_nonetwork__bad_urls(void) |
764df57e | 52 | { |
1c7eb971 | 53 | /* Clone should clean up the mess if the URL isn't a git repository */ |
b412d563 | 54 | cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); |
18b2d560 BS |
55 | cl_assert(!git_path_exists("./foo")); |
56 | g_options.bare = true; | |
b412d563 | 57 | cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); |
1c7eb971 | 58 | cl_assert(!git_path_exists("./foo")); |
ff0ef88c BS |
59 | |
60 | cl_git_fail(git_clone(&g_repo, "git://example.com:asdf", "./foo", &g_options)); | |
ff0ef88c | 61 | cl_git_fail(git_clone(&g_repo, "https://example.com:asdf/foo", "./foo", &g_options)); |
7be5104d | 62 | cl_git_fail(git_clone(&g_repo, "git://github.com/git://github.com/foo/bar.git.git", |
887df99f BS |
63 | "./foo", &g_options)); |
64 | cl_git_fail(git_clone(&g_repo, "arrbee:my/bad:password@github.com:1111/strange:words.git", | |
65 | "./foo", &g_options)); | |
764df57e BS |
66 | } |
67 | ||
219d3457 RB |
68 | void test_clone_nonetwork__do_not_clean_existing_directory(void) |
69 | { | |
926acbcf JM |
70 | /* Clone should not remove the directory if it already exists, but |
71 | * Should clean up entries it creates. */ | |
72 | p_mkdir("./foo", GIT_DIR_MODE); | |
73 | cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); | |
d0849f83 | 74 | cl_assert(git_path_is_empty_dir("./foo")); |
926acbcf JM |
75 | |
76 | /* Try again with a bare repository. */ | |
77 | g_options.bare = true; | |
78 | cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); | |
d0849f83 | 79 | cl_assert(git_path_is_empty_dir("./foo")); |
926acbcf JM |
80 | } |
81 | ||
65415ea2 | 82 | void test_clone_nonetwork__local(void) |
764df57e | 83 | { |
b412d563 | 84 | cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); |
764df57e BS |
85 | } |
86 | ||
8a8820d8 JM |
87 | void test_clone_nonetwork__local_absolute_path(void) |
88 | { | |
6bd09ecc | 89 | const char *local_src; |
6bd09ecc | 90 | local_src = cl_fixture("testrepo.git"); |
b412d563 | 91 | cl_git_pass(git_clone(&g_repo, local_src, "./foo", &g_options)); |
8a8820d8 JM |
92 | } |
93 | ||
65415ea2 | 94 | void test_clone_nonetwork__local_bare(void) |
ebecf1e7 | 95 | { |
18b2d560 | 96 | g_options.bare = true; |
b412d563 | 97 | cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); |
ebecf1e7 | 98 | } |
764df57e | 99 | |
65415ea2 | 100 | void test_clone_nonetwork__fail_when_the_target_is_a_file(void) |
ebecf1e7 | 101 | { |
1c7eb971 | 102 | cl_git_mkfile("./foo", "Bar!"); |
b412d563 | 103 | cl_git_fail(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); |
ebecf1e7 | 104 | } |
105 | ||
65415ea2 | 106 | void test_clone_nonetwork__fail_with_already_existing_but_non_empty_directory(void) |
ebecf1e7 | 107 | { |
1c7eb971 BS |
108 | p_mkdir("./foo", GIT_DIR_MODE); |
109 | cl_git_mkfile("./foo/bar", "Baz!"); | |
b412d563 | 110 | cl_git_fail(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); |
764df57e | 111 | } |
621b50e4 | 112 | |
c833893c CMN |
113 | void test_clone_nonetwork__custom_origin_name(void) |
114 | { | |
115 | g_options.remote_name = "my_origin"; | |
116 | cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); | |
117 | ||
118 | cl_git_pass(git_remote_load(&g_remote, g_repo, "my_origin")); | |
119 | } | |
120 | ||
fdc7e5e3 CMN |
121 | void test_clone_nonetwork__defaults(void) |
122 | { | |
123 | cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", NULL)); | |
124 | cl_assert(g_repo); | |
125 | cl_git_pass(git_remote_load(&g_remote, g_repo, "origin")); | |
126 | } | |
c833893c | 127 | |
922dd978 BS |
128 | void test_clone_nonetwork__cope_with_already_existing_directory(void) |
129 | { | |
922dd978 BS |
130 | p_mkdir("./foo", GIT_DIR_MODE); |
131 | cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); | |
132 | } | |
133 | ||
134 | void test_clone_nonetwork__can_prevent_the_checkout_of_a_standard_repo(void) | |
135 | { | |
136 | git_buf path = GIT_BUF_INIT; | |
922dd978 BS |
137 | |
138 | g_options.checkout_opts.checkout_strategy = 0; | |
139 | cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); | |
140 | ||
141 | cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt")); | |
142 | cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&path))); | |
143 | ||
144 | git_buf_free(&path); | |
145 | } | |
146 | ||
f1d4a35e SC |
147 | void test_clone_nonetwork__can_checkout_given_branch(void) |
148 | { | |
149 | g_options.checkout_branch = "test"; | |
150 | cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); | |
151 | ||
605da51a | 152 | cl_assert_equal_i(0, git_repository_head_unborn(g_repo)); |
f1d4a35e SC |
153 | |
154 | cl_git_pass(git_repository_head(&g_ref, g_repo)); | |
155 | cl_assert_equal_s(git_reference_name(g_ref), "refs/heads/test"); | |
8f1066a0 RB |
156 | |
157 | cl_assert(git_path_exists("foo/readme.txt")); | |
158 | } | |
159 | ||
160 | static int clone_cancel_fetch_transfer_progress_cb( | |
161 | const git_transfer_progress *stats, void *data) | |
162 | { | |
163 | GIT_UNUSED(stats); GIT_UNUSED(data); | |
164 | return -54321; | |
165 | } | |
166 | ||
167 | void test_clone_nonetwork__can_cancel_clone_in_fetch(void) | |
168 | { | |
169 | g_options.checkout_branch = "test"; | |
170 | ||
171 | g_options.remote_callbacks.transfer_progress = | |
172 | clone_cancel_fetch_transfer_progress_cb; | |
173 | ||
174 | cl_git_fail_with(git_clone( | |
175 | &g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options), | |
176 | -54321); | |
177 | ||
178 | cl_assert(!g_repo); | |
179 | cl_assert(!git_path_exists("foo/readme.txt")); | |
180 | } | |
181 | ||
182 | static int clone_cancel_checkout_cb( | |
183 | git_checkout_notify_t why, | |
184 | const char *path, | |
185 | const git_diff_file *b, | |
186 | const git_diff_file *t, | |
187 | const git_diff_file *w, | |
188 | void *payload) | |
189 | { | |
190 | const char *at_file = payload; | |
191 | GIT_UNUSED(why); GIT_UNUSED(b); GIT_UNUSED(t); GIT_UNUSED(w); | |
192 | if (!strcmp(path, at_file)) | |
193 | return -12345; | |
194 | return 0; | |
195 | } | |
196 | ||
197 | void test_clone_nonetwork__can_cancel_clone_in_checkout(void) | |
198 | { | |
199 | g_options.checkout_branch = "test"; | |
200 | ||
201 | g_options.checkout_opts.notify_flags = GIT_CHECKOUT_NOTIFY_UPDATED; | |
202 | g_options.checkout_opts.notify_cb = clone_cancel_checkout_cb; | |
203 | g_options.checkout_opts.notify_payload = "readme.txt"; | |
204 | ||
205 | cl_git_fail_with(git_clone( | |
206 | &g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options), | |
207 | -12345); | |
208 | ||
209 | cl_assert(!g_repo); | |
210 | cl_assert(!git_path_exists("foo/readme.txt")); | |
f1d4a35e SC |
211 | } |
212 | ||
aa928de0 FL |
213 | void test_clone_nonetwork__can_detached_head(void) |
214 | { | |
2ebc3c66 | 215 | git_object *obj; |
aa928de0 FL |
216 | git_repository *cloned; |
217 | git_reference *cloned_head; | |
a1710a28 BS |
218 | git_reflog *log; |
219 | const git_reflog_entry *entry; | |
aa928de0 FL |
220 | |
221 | cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); | |
222 | ||
2ebc3c66 | 223 | cl_git_pass(git_revparse_single(&obj, g_repo, "master~1")); |
94f263f5 | 224 | cl_git_pass(git_repository_set_head_detached(g_repo, git_object_id(obj), NULL, NULL)); |
aa928de0 FL |
225 | |
226 | cl_git_pass(git_clone(&cloned, "./foo", "./foo1", &g_options)); | |
227 | ||
228 | cl_assert(git_repository_head_detached(cloned)); | |
229 | ||
230 | cl_git_pass(git_repository_head(&cloned_head, cloned)); | |
2ebc3c66 | 231 | cl_assert(!git_oid_cmp(git_object_id(obj), git_reference_target(cloned_head))); |
aa928de0 | 232 | |
a1710a28 BS |
233 | cl_git_pass(git_reflog_read(&log, cloned, "HEAD")); |
234 | entry = git_reflog_entry_byindex(log, 0); | |
235 | cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry)->email); | |
236 | ||
2ebc3c66 | 237 | git_object_free(obj); |
aa928de0 | 238 | git_reference_free(cloned_head); |
a1710a28 | 239 | git_reflog_free(log); |
aa928de0 FL |
240 | git_repository_free(cloned); |
241 | ||
242 | cl_fixture_cleanup("./foo1"); | |
243 | } | |
1cc974ab BS |
244 | |
245 | static void assert_correct_reflog(const char *name) | |
246 | { | |
247 | git_reflog *log; | |
248 | const git_reflog_entry *entry; | |
249 | char expected_log_message[128] = {0}; | |
250 | ||
251 | sprintf(expected_log_message, "clone: from %s", cl_git_fixture_url("testrepo.git")); | |
252 | ||
253 | cl_git_pass(git_reflog_read(&log, g_repo, name)); | |
254 | cl_assert_equal_i(1, git_reflog_entrycount(log)); | |
255 | entry = git_reflog_entry_byindex(log, 0); | |
256 | cl_assert_equal_s(expected_log_message, git_reflog_entry_message(entry)); | |
257 | cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry)->email); | |
258 | ||
259 | git_reflog_free(log); | |
260 | } | |
261 | ||
262 | void test_clone_nonetwork__clone_updates_reflog_properly(void) | |
263 | { | |
1cc974ab BS |
264 | cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); |
265 | assert_correct_reflog("HEAD"); | |
266 | assert_correct_reflog("refs/heads/master"); | |
1cc974ab BS |
267 | } |
268 | ||
269 | void test_clone_nonetwork__clone_into_updates_reflog_properly(void) | |
270 | { | |
271 | git_remote *remote; | |
272 | git_signature *sig; | |
273 | cl_git_pass(git_signature_now(&sig, "Me", "foo@example.com")); | |
274 | ||
275 | cl_git_pass(git_repository_init(&g_repo, "./foo", false)); | |
276 | cl_git_pass(git_remote_create(&remote, g_repo, "origin", cl_git_fixture_url("testrepo.git"))); | |
277 | cl_git_pass(git_clone_into(g_repo, remote, NULL, NULL, sig)); | |
278 | ||
279 | assert_correct_reflog("HEAD"); | |
280 | assert_correct_reflog("refs/heads/master"); | |
281 | ||
282 | git_remote_free(remote); | |
a1710a28 | 283 | git_signature_free(sig); |
1cc974ab | 284 | } |
6f6be8fe CMN |
285 | |
286 | static void cleanup_repository(void *path) | |
287 | { | |
288 | if (g_repo) { | |
289 | git_repository_free(g_repo); | |
290 | g_repo = NULL; | |
291 | } | |
292 | ||
293 | cl_fixture_cleanup((const char *)path); | |
294 | } | |
295 | ||
296 | void test_clone_nonetwork__clone_from_empty_sets_upstream(void) | |
297 | { | |
298 | git_config *config; | |
299 | git_repository *repo; | |
300 | const char *str; | |
301 | ||
302 | /* Create an empty repo to clone from */ | |
303 | cl_set_cleanup(&cleanup_repository, "./test1"); | |
304 | cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); | |
305 | cl_set_cleanup(&cleanup_repository, "./repowithunborn"); | |
306 | cl_git_pass(git_clone(&repo, "./test1", "./repowithunborn", NULL)); | |
307 | ||
308 | cl_git_pass(git_repository_config(&config, repo)); | |
309 | ||
310 | cl_git_pass(git_config_get_string(&str, config, "branch.master.remote")); | |
311 | cl_assert_equal_s("origin", str); | |
312 | cl_git_pass(git_config_get_string(&str, config, "branch.master.merge")); | |
313 | cl_assert_equal_s("refs/heads/master", str); | |
314 | ||
315 | git_config_free(config); | |
316 | git_repository_free(repo); | |
317 | cl_fixture_cleanup("./repowithunborn"); | |
318 | } |