1 #include "clar_libgit2.h"
3 #include "git2/clone.h"
4 #include "../submodule/submodule_helpers.h"
7 #include "repository.h"
9 #define LIVE_REPO_URL "git://github.com/libgit2/TestGitRepository"
11 static git_clone_options g_options
;
12 static git_repository
*g_repo
;
13 static git_reference
* g_ref
;
14 static git_remote
* g_remote
;
16 void test_clone_nonetwork__initialize(void)
18 git_checkout_options dummy_opts
= GIT_CHECKOUT_OPTIONS_INIT
;
19 git_fetch_options dummy_fetch
= GIT_FETCH_OPTIONS_INIT
;
23 memset(&g_options
, 0, sizeof(git_clone_options
));
24 g_options
.version
= GIT_CLONE_OPTIONS_VERSION
;
25 g_options
.checkout_opts
= dummy_opts
;
26 g_options
.checkout_opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
;
27 g_options
.fetch_opts
= dummy_fetch
;
30 void test_clone_nonetwork__cleanup(void)
33 git_repository_free(g_repo
);
38 git_reference_free(g_ref
);
43 git_remote_free(g_remote
);
47 cl_fixture_cleanup("./foo");
50 void test_clone_nonetwork__bad_urls(void)
52 /* Clone should clean up the mess if the URL isn't a git repository */
53 cl_git_fail(git_clone(&g_repo
, "not_a_repo", "./foo", &g_options
));
54 cl_assert(!git_path_exists("./foo"));
55 g_options
.bare
= true;
56 cl_git_fail(git_clone(&g_repo
, "not_a_repo", "./foo", &g_options
));
57 cl_assert(!git_path_exists("./foo"));
59 cl_git_fail(git_clone(&g_repo
, "git://example.com:asdf", "./foo", &g_options
));
60 cl_git_fail(git_clone(&g_repo
, "https://example.com:asdf/foo", "./foo", &g_options
));
61 cl_git_fail(git_clone(&g_repo
, "git://github.com/git://github.com/foo/bar.git.git",
62 "./foo", &g_options
));
63 cl_git_fail(git_clone(&g_repo
, "arrbee:my/bad:password@github.com:1111/strange:words.git",
64 "./foo", &g_options
));
67 void test_clone_nonetwork__do_not_clean_existing_directory(void)
69 /* Clone should not remove the directory if it already exists, but
70 * Should clean up entries it creates. */
71 p_mkdir("./foo", GIT_DIR_MODE
);
72 cl_git_fail(git_clone(&g_repo
, "not_a_repo", "./foo", &g_options
));
73 cl_assert(git_path_is_empty_dir("./foo"));
75 /* Try again with a bare repository. */
76 g_options
.bare
= true;
77 cl_git_fail(git_clone(&g_repo
, "not_a_repo", "./foo", &g_options
));
78 cl_assert(git_path_is_empty_dir("./foo"));
81 void test_clone_nonetwork__local(void)
83 cl_git_pass(git_clone(&g_repo
, cl_git_fixture_url("testrepo.git"), "./foo", &g_options
));
86 void test_clone_nonetwork__local_absolute_path(void)
88 const char *local_src
;
89 local_src
= cl_fixture("testrepo.git");
90 cl_git_pass(git_clone(&g_repo
, local_src
, "./foo", &g_options
));
93 void test_clone_nonetwork__local_bare(void)
95 g_options
.bare
= true;
96 cl_git_pass(git_clone(&g_repo
, cl_git_fixture_url("testrepo.git"), "./foo", &g_options
));
99 void test_clone_nonetwork__fail_when_the_target_is_a_file(void)
101 cl_git_mkfile("./foo", "Bar!");
102 cl_git_fail(git_clone(&g_repo
, cl_git_fixture_url("testrepo.git"), "./foo", &g_options
));
105 void test_clone_nonetwork__fail_with_already_existing_but_non_empty_directory(void)
107 p_mkdir("./foo", GIT_DIR_MODE
);
108 cl_git_mkfile("./foo/bar", "Baz!");
109 cl_git_fail(git_clone(&g_repo
, cl_git_fixture_url("testrepo.git"), "./foo", &g_options
));
112 int custom_origin_name_remote_create(
114 git_repository
*repo
,
122 return git_remote_create(out
, repo
, "my_origin", url
);
125 void test_clone_nonetwork__custom_origin_name(void)
127 g_options
.remote_cb
= custom_origin_name_remote_create
;
128 cl_git_pass(git_clone(&g_repo
, cl_git_fixture_url("testrepo.git"), "./foo", &g_options
));
130 cl_git_pass(git_remote_lookup(&g_remote
, g_repo
, "my_origin"));
133 void test_clone_nonetwork__defaults(void)
135 cl_git_pass(git_clone(&g_repo
, cl_git_fixture_url("testrepo.git"), "./foo", NULL
));
137 cl_git_pass(git_remote_lookup(&g_remote
, g_repo
, "origin"));
140 void test_clone_nonetwork__cope_with_already_existing_directory(void)
142 p_mkdir("./foo", GIT_DIR_MODE
);
143 cl_git_pass(git_clone(&g_repo
, cl_git_fixture_url("testrepo.git"), "./foo", &g_options
));
146 void test_clone_nonetwork__can_prevent_the_checkout_of_a_standard_repo(void)
148 git_buf path
= GIT_BUF_INIT
;
150 g_options
.checkout_opts
.checkout_strategy
= 0;
151 cl_git_pass(git_clone(&g_repo
, cl_git_fixture_url("testrepo.git"), "./foo", &g_options
));
153 cl_git_pass(git_buf_joinpath(&path
, git_repository_workdir(g_repo
), "master.txt"));
154 cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&path
)));
156 git_buf_dispose(&path
);
159 void test_clone_nonetwork__can_checkout_given_branch(void)
161 git_reference
*remote_head
;
163 g_options
.checkout_branch
= "test";
164 cl_git_pass(git_clone(&g_repo
, cl_git_fixture_url("testrepo.git"), "./foo", &g_options
));
166 cl_assert_equal_i(0, git_repository_head_unborn(g_repo
));
168 cl_git_pass(git_repository_head(&g_ref
, g_repo
));
169 cl_assert_equal_s(git_reference_name(g_ref
), "refs/heads/test");
171 cl_assert(git_path_exists("foo/readme.txt"));
173 cl_git_pass(git_reference_lookup(&remote_head
, g_repo
, "refs/remotes/origin/HEAD"));
174 cl_assert_equal_i(GIT_REFERENCE_SYMBOLIC
, git_reference_type(remote_head
));
175 cl_assert_equal_s("refs/remotes/origin/master", git_reference_symbolic_target(remote_head
));
177 git_reference_free(remote_head
);
180 static int clone_cancel_fetch_transfer_progress_cb(
181 const git_indexer_progress
*stats
, void *data
)
183 GIT_UNUSED(stats
); GIT_UNUSED(data
);
187 void test_clone_nonetwork__can_cancel_clone_in_fetch(void)
189 g_options
.checkout_branch
= "test";
191 g_options
.fetch_opts
.callbacks
.transfer_progress
=
192 clone_cancel_fetch_transfer_progress_cb
;
194 cl_git_fail_with(git_clone(
195 &g_repo
, cl_git_fixture_url("testrepo.git"), "./foo", &g_options
),
199 cl_assert(!git_path_exists("foo/readme.txt"));
202 static int clone_cancel_checkout_cb(
203 git_checkout_notify_t why
,
205 const git_diff_file
*b
,
206 const git_diff_file
*t
,
207 const git_diff_file
*w
,
210 const char *at_file
= payload
;
211 GIT_UNUSED(why
); GIT_UNUSED(b
); GIT_UNUSED(t
); GIT_UNUSED(w
);
212 if (!strcmp(path
, at_file
))
217 void test_clone_nonetwork__can_cancel_clone_in_checkout(void)
219 g_options
.checkout_branch
= "test";
221 g_options
.checkout_opts
.notify_flags
= GIT_CHECKOUT_NOTIFY_UPDATED
;
222 g_options
.checkout_opts
.notify_cb
= clone_cancel_checkout_cb
;
223 g_options
.checkout_opts
.notify_payload
= "readme.txt";
225 cl_git_fail_with(git_clone(
226 &g_repo
, cl_git_fixture_url("testrepo.git"), "./foo", &g_options
),
230 cl_assert(!git_path_exists("foo/readme.txt"));
233 void test_clone_nonetwork__can_detached_head(void)
236 git_repository
*cloned
;
237 git_reference
*cloned_head
;
239 cl_git_pass(git_clone(&g_repo
, cl_git_fixture_url("testrepo.git"), "./foo", &g_options
));
241 cl_git_pass(git_revparse_single(&obj
, g_repo
, "master~1"));
242 cl_git_pass(git_repository_set_head_detached(g_repo
, git_object_id(obj
)));
244 cl_git_pass(git_clone(&cloned
, "./foo", "./foo1", &g_options
));
246 cl_assert(git_repository_head_detached(cloned
));
248 cl_git_pass(git_repository_head(&cloned_head
, cloned
));
249 cl_assert_equal_oid(git_object_id(obj
), git_reference_target(cloned_head
));
251 git_object_free(obj
);
252 git_reference_free(cloned_head
);
253 git_repository_free(cloned
);
255 cl_fixture_cleanup("./foo1");
258 void test_clone_nonetwork__clone_tag_to_tree(void)
260 git_repository
*stage
;
261 git_index_entry entry
;
267 git_tree_entry
*tentry
;
268 const char *file_path
= "some/deep/path.txt";
269 const char *file_content
= "some content\n";
270 const char *tag_name
= "refs/tags/tree-tag";
272 stage
= cl_git_sandbox_init("testrepo.git");
273 cl_git_pass(git_repository_odb(&odb
, stage
));
274 cl_git_pass(git_index_new(&index
));
276 memset(&entry
, 0, sizeof(git_index_entry
));
277 entry
.path
= file_path
;
278 entry
.mode
= GIT_FILEMODE_BLOB
;
279 cl_git_pass(git_odb_write(&entry
.id
, odb
, file_content
, strlen(file_content
), GIT_OBJECT_BLOB
));
281 cl_git_pass(git_index_add(index
, &entry
));
282 cl_git_pass(git_index_write_tree_to(&tree_id
, index
, stage
));
283 cl_git_pass(git_reference_create(&tag
, stage
, tag_name
, &tree_id
, 0, NULL
));
284 git_reference_free(tag
);
286 git_index_free(index
);
288 g_options
.local
= GIT_CLONE_NO_LOCAL
;
289 cl_git_pass(git_clone(&g_repo
, cl_git_path_url(git_repository_path(stage
)), "./foo", &g_options
));
290 git_repository_free(stage
);
292 cl_git_pass(git_reference_lookup(&tag
, g_repo
, tag_name
));
293 cl_git_pass(git_tree_lookup(&tree
, g_repo
, git_reference_target(tag
)));
294 git_reference_free(tag
);
296 cl_git_pass(git_tree_entry_bypath(&tentry
, tree
, file_path
));
297 git_tree_entry_free(tentry
);
300 cl_fixture_cleanup("testrepo.git");
303 static void assert_correct_reflog(const char *name
)
306 const git_reflog_entry
*entry
;
307 git_buf expected_message
= GIT_BUF_INIT
;
309 git_buf_printf(&expected_message
,
310 "clone: from %s", cl_git_fixture_url("testrepo.git"));
312 cl_git_pass(git_reflog_read(&log
, g_repo
, name
));
313 cl_assert_equal_i(1, git_reflog_entrycount(log
));
314 entry
= git_reflog_entry_byindex(log
, 0);
315 cl_assert_equal_s(expected_message
.ptr
, git_reflog_entry_message(entry
));
317 git_reflog_free(log
);
319 git_buf_dispose(&expected_message
);
322 void test_clone_nonetwork__clone_updates_reflog_properly(void)
324 cl_git_pass(git_clone(&g_repo
, cl_git_fixture_url("testrepo.git"), "./foo", &g_options
));
325 assert_correct_reflog("HEAD");
326 assert_correct_reflog("refs/heads/master");
329 static void cleanup_repository(void *path
)
332 git_repository_free(g_repo
);
336 cl_fixture_cleanup((const char *)path
);
339 void test_clone_nonetwork__clone_from_empty_sets_upstream(void)
342 git_repository
*repo
;
345 /* Create an empty repo to clone from */
346 cl_set_cleanup(&cleanup_repository
, "./test1");
347 cl_git_pass(git_repository_init(&g_repo
, "./test1", 0));
348 cl_set_cleanup(&cleanup_repository
, "./repowithunborn");
349 cl_git_pass(git_clone(&repo
, "./test1", "./repowithunborn", NULL
));
351 cl_git_pass(git_repository_config_snapshot(&config
, repo
));
353 cl_git_pass(git_config_get_string(&str
, config
, "branch.master.remote"));
354 cl_assert_equal_s("origin", str
);
355 cl_git_pass(git_config_get_string(&str
, config
, "branch.master.merge"));
356 cl_assert_equal_s("refs/heads/master", str
);
358 git_config_free(config
);
359 git_repository_free(repo
);
360 cl_fixture_cleanup("./repowithunborn");