clone.c 7.63 KB
Newer Older
1 2 3
#include "clar_libgit2.h"

#include "git2/clone.h"
4
#include "git2/cred_helpers.h"
5
#include "remote.h"
6 7
#include "fileops.h"
#include "refs.h"
8

9 10
#define LIVE_REPO_URL "http://github.com/libgit2/TestGitRepository"
#define LIVE_EMPTYREPO_URL "http://github.com/libgit2/TestEmptyRepository"
11
#define BB_REPO_URL "https://libgit2@bitbucket.org/libgit2/testgitrepository.git"
12
#define BB_REPO_URL_WITH_PASS "https://libgit2:libgit2@bitbucket.org/libgit2/testgitrepository.git"
13
#define BB_REPO_URL_WITH_WRONG_PASS "https://libgit2:wrong@bitbucket.org/libgit2/testgitrepository.git"
Ben Straub committed
14
#define ASSEMBLA_REPO_URL "https://libgit2:_Libgit2@git.assembla.com/libgit2-test-repos.git"
15 16

static git_repository *g_repo;
17
static git_clone_options g_options;
18

19
void test_online_clone__initialize(void)
20
{
21
	git_checkout_opts dummy_opts = GIT_CHECKOUT_OPTS_INIT;
22
	git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT;
23

24
	g_repo = NULL;
25 26 27

	memset(&g_options, 0, sizeof(git_clone_options));
	g_options.version = GIT_CLONE_OPTIONS_VERSION;
28 29
	g_options.checkout_opts = dummy_opts;
	g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
30
	g_options.remote_callbacks = dummy_callbacks;
31 32
}

33
void test_online_clone__cleanup(void)
34
{
35
	if (g_repo) {
36
		git_repository_free(g_repo);
37 38
		g_repo = NULL;
	}
39
	cl_fixture_cleanup("./foo");
40 41
}

42
void test_online_clone__network_full(void)
43 44 45
{
	git_remote *origin;

46
	cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
47 48
	cl_assert(!git_repository_is_bare(g_repo));
	cl_git_pass(git_remote_load(&origin, g_repo, "origin"));
nulltoken committed
49

50 51
	cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_AUTO, origin->download_tags);

nulltoken committed
52
	git_remote_free(origin);
53 54
}

55
void test_online_clone__network_bare(void)
56 57 58
{
	git_remote *origin;

59
	g_options.bare = true;
60

61
	cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
62 63
	cl_assert(git_repository_is_bare(g_repo));
	cl_git_pass(git_remote_load(&origin, g_repo, "origin"));
nulltoken committed
64 65

	git_remote_free(origin);
66 67
}

68
void test_online_clone__empty_repository(void)
69 70 71
{
	git_reference *head;

72
	cl_git_pass(git_clone(&g_repo, LIVE_EMPTYREPO_URL, "./foo", &g_options));
73 74

	cl_assert_equal_i(true, git_repository_is_empty(g_repo));
75
	cl_assert_equal_i(true, git_repository_head_unborn(g_repo));
76 77 78

	cl_git_pass(git_reference_lookup(&head, g_repo, GIT_HEAD_FILE));
	cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head));
79
	cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head));
80 81 82

	git_reference_free(head);
}
83

84
static void checkout_progress(const char *path, size_t cur, size_t tot, void *payload)
85 86
{
	bool *was_called = (bool*)payload;
Ben Straub committed
87
	GIT_UNUSED(path); GIT_UNUSED(cur); GIT_UNUSED(tot);
88 89 90
	(*was_called) = true;
}

91
static int fetch_progress(const git_transfer_progress *stats, void *payload)
92 93
{
	bool *was_called = (bool*)payload;
Ben Straub committed
94
	GIT_UNUSED(stats);
95
	(*was_called) = true;
96
	return 0;
97 98
}

99
void test_online_clone__can_checkout_a_cloned_repo(void)
100 101
{
	git_buf path = GIT_BUF_INIT;
102
	git_reference *head;
103 104
	bool checkout_progress_cb_was_called = false,
		  fetch_progress_cb_was_called = false;
105

106
	g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
107 108
	g_options.checkout_opts.progress_cb = &checkout_progress;
	g_options.checkout_opts.progress_payload = &checkout_progress_cb_was_called;
109 110
	g_options.remote_callbacks.transfer_progress = &fetch_progress;
	g_options.remote_callbacks.payload = &fetch_progress_cb_was_called;
111

112
	cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
113 114 115

	cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt"));
	cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path)));
116 117 118

	cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD"));
	cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head));
119
	cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head));
nulltoken committed
120

121 122
	cl_assert_equal_i(true, checkout_progress_cb_was_called);
	cl_assert_equal_i(true, fetch_progress_cb_was_called);
123

nulltoken committed
124 125
	git_reference_free(head);
	git_buf_free(&path);
126
}
Ben Straub committed
127

128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
void test_online_clone__clone_into(void)
{
	git_buf path = GIT_BUF_INIT;
	git_remote *remote;
	git_reference *head;
	git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT;
	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;

	bool checkout_progress_cb_was_called = false,
		  fetch_progress_cb_was_called = false;

	checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
	checkout_opts.progress_cb = &checkout_progress;
	checkout_opts.progress_payload = &checkout_progress_cb_was_called;

	cl_git_pass(git_repository_init(&g_repo, "./foo", false));
	cl_git_pass(git_remote_create(&remote, g_repo, "origin", LIVE_REPO_URL));

	callbacks.transfer_progress = &fetch_progress;
	callbacks.payload = &fetch_progress_cb_was_called;
	git_remote_set_callbacks(remote, &callbacks);

	cl_git_pass(git_clone_into(g_repo, remote, &checkout_opts, NULL));

	cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt"));
	cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path)));

	cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD"));
	cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head));
	cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head));

	cl_assert_equal_i(true, checkout_progress_cb_was_called);
	cl_assert_equal_i(true, fetch_progress_cb_was_called);

	git_remote_free(remote);
	git_reference_free(head);
	git_buf_free(&path);
}

Ben Straub committed
167 168 169 170 171 172 173 174
static int update_tips(const char *refname, const git_oid *a, const git_oid *b, void *payload)
{
	int *callcount = (int*)payload;
	GIT_UNUSED(refname); GIT_UNUSED(a); GIT_UNUSED(b);
	*callcount = *callcount + 1;
	return 0;
}

175
void test_online_clone__custom_remote_callbacks(void)
Ben Straub committed
176 177 178
{
	int callcount = 0;

179 180
	g_options.remote_callbacks.update_tips = update_tips;
	g_options.remote_callbacks.payload = &callcount;
Ben Straub committed
181 182 183 184 185

	cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
	cl_assert(callcount > 0);
}

186
void test_online_clone__credentials(void)
Ben Straub committed
187 188 189
{
	/* Remote URL environment variable must be set.  User and password are optional.  */
	const char *remote_url = cl_getenv("GITTEST_REMOTE_URL");
190
	git_cred_userpass_payload user_pass = {
Ben Straub committed
191 192 193 194 195 196
		cl_getenv("GITTEST_REMOTE_USER"),
		cl_getenv("GITTEST_REMOTE_PASS")
	};

	if (!remote_url) return;

197 198
	g_options.remote_callbacks.credentials = git_cred_userpass;
	g_options.remote_callbacks.payload = &user_pass;
Ben Straub committed
199 200

	cl_git_pass(git_clone(&g_repo, remote_url, "./foo", &g_options));
201 202 203 204 205 206 207 208 209 210
	git_repository_free(g_repo); g_repo = NULL;
	cl_fixture_cleanup("./foo");
}

void test_online_clone__bitbucket_style(void)
{
	git_cred_userpass_payload user_pass = {
		"libgit2", "libgit2"
	};

211 212
	g_options.remote_callbacks.credentials = git_cred_userpass;
	g_options.remote_callbacks.payload = &user_pass;
213 214 215 216

	cl_git_pass(git_clone(&g_repo, BB_REPO_URL, "./foo", &g_options));
	git_repository_free(g_repo); g_repo = NULL;
	cl_fixture_cleanup("./foo");
217

218 219
	/* User and pass from URL */
	user_pass.password = "wrong";
220 221 222
	cl_git_pass(git_clone(&g_repo, BB_REPO_URL_WITH_PASS, "./foo", &g_options));
	git_repository_free(g_repo); g_repo = NULL;
	cl_fixture_cleanup("./foo");
223 224 225 226 227 228

	/* Wrong password in URL, fall back to user_pass */
	user_pass.password = "libgit2";
	cl_git_pass(git_clone(&g_repo, BB_REPO_URL_WITH_WRONG_PASS, "./foo", &g_options));
	git_repository_free(g_repo); g_repo = NULL;
	cl_fixture_cleanup("./foo");
Ben Straub committed
229
}
230

Ben Straub committed
231 232 233 234 235
void test_online_clone__assembla_style(void)
{
	cl_git_pass(git_clone(&g_repo, ASSEMBLA_REPO_URL, "./foo", NULL));
}

236 237 238 239 240
static int cancel_at_half(const git_transfer_progress *stats, void *payload)
{
	GIT_UNUSED(payload);

	if (stats->received_objects > (stats->total_objects/2))
241
		return 1;
242 243 244 245 246
	return 0;
}

void test_online_clone__can_cancel(void)
{
247
	g_options.remote_callbacks.transfer_progress = cancel_at_half;
248

249 250
	cl_git_fail_with(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options), GIT_EUSER);
}
251 252 253 254 255 256