fetch.c 9.68 KB
Newer Older
1
#include "clar_libgit2.h"
2
#include "futils.h"
3 4 5 6

static git_repository *_repo;
static int counter;

7 8 9 10
static char *_remote_proxy_scheme = NULL;
static char *_remote_proxy_host = NULL;
static char *_remote_proxy_user = NULL;
static char *_remote_proxy_pass = NULL;
11 12
static char *_remote_redirect_initial = NULL;
static char *_remote_redirect_subsequent = NULL;
13

14
void test_online_fetch__initialize(void)
15 16
{
	cl_git_pass(git_repository_init(&_repo, "./fetch", 0));
17

18 19 20 21 22 23
	_remote_proxy_scheme = cl_getenv("GITTEST_REMOTE_PROXY_SCHEME");
	_remote_proxy_host = cl_getenv("GITTEST_REMOTE_PROXY_HOST");
	_remote_proxy_user = cl_getenv("GITTEST_REMOTE_PROXY_USER");
	_remote_proxy_pass = cl_getenv("GITTEST_REMOTE_PROXY_PASS");
	_remote_redirect_initial = cl_getenv("GITTEST_REMOTE_REDIRECT_INITIAL");
	_remote_redirect_subsequent = cl_getenv("GITTEST_REMOTE_REDIRECT_SUBSEQUENT");
24 25
}

26
void test_online_fetch__cleanup(void)
27 28
{
	git_repository_free(_repo);
29 30
	_repo = NULL;

31
	cl_fixture_cleanup("./fetch");
32 33 34 35 36 37 38 39
	cl_fixture_cleanup("./redirected");

	git__free(_remote_proxy_scheme);
	git__free(_remote_proxy_host);
	git__free(_remote_proxy_user);
	git__free(_remote_proxy_pass);
	git__free(_remote_redirect_initial);
	git__free(_remote_redirect_subsequent);
40 41 42 43
}

static int update_tips(const char *refname, const git_oid *a, const git_oid *b, void *data)
{
44
	GIT_UNUSED(refname); GIT_UNUSED(a); GIT_UNUSED(b); GIT_UNUSED(data);
45 46 47 48 49 50

	++counter;

	return 0;
}

51
static int progress(const git_indexer_progress *stats, void *payload)
52
{
53
	size_t *bytes_received = (size_t *)payload;
54
	*bytes_received = stats->received_bytes;
55
	return 0;
56 57
}

nulltoken committed
58
static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n)
59 60
{
	git_remote *remote;
61
	git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
62
	size_t bytes_received = 0;
63

64 65 66
	options.callbacks.transfer_progress = progress;
	options.callbacks.update_tips = update_tips;
	options.callbacks.payload = &bytes_received;
67
	options.download_tags = flag;
68 69
	counter = 0;

Ben Straub committed
70
	cl_git_pass(git_remote_create(&remote, _repo, "test", url));
71
	cl_git_pass(git_remote_fetch(remote, NULL, &options, NULL));
72
	cl_assert_equal_i(counter, n);
73
	cl_assert(bytes_received > 0);
nulltoken committed
74 75

	git_remote_free(remote);
76 77
}

78
void test_online_fetch__default_http(void)
79
{
80
	do_fetch("http://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6);
81 82
}

83 84
void test_online_fetch__default_https(void)
{
85
	do_fetch("https://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6);
86 87
}

88
void test_online_fetch__no_tags_git(void)
89
{
90
	do_fetch("https://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_NONE, 3);
91 92
}

93
void test_online_fetch__no_tags_http(void)
94 95 96
{
	do_fetch("http://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_NONE, 3);
}
nulltoken committed
97

98 99 100
void test_online_fetch__fetch_twice(void)
{
	git_remote *remote;
101
	cl_git_pass(git_remote_create(&remote, _repo, "test", "https://github.com/libgit2/TestGitRepository.git"));
102
	cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL, NULL));
103
	cl_git_pass(git_remote_download(remote, NULL, NULL));
104
    	git_remote_disconnect(remote);
105

106
	git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL, NULL);
107
	cl_git_pass(git_remote_download(remote, NULL, NULL));
108
	git_remote_disconnect(remote);
109

110 111 112
	git_remote_free(remote);
}

113
static int transferProgressCallback(const git_indexer_progress *stats, void *payload)
nulltoken committed
114 115
{
	bool *invoked = (bool *)payload;
nulltoken committed
116 117

	GIT_UNUSED(stats);
nulltoken committed
118
	*invoked = true;
119
	return 0;
nulltoken committed
120 121
}

122
void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date(void)
nulltoken committed
123 124 125
{
	git_repository *_repository;
	bool invoked = false;
126
	git_remote *remote;
127
	git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
128 129
	git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
	opts.bare = true;
nulltoken committed
130

131 132
	cl_git_pass(git_clone(&_repository, "https://github.com/libgit2/TestGitRepository.git",
				"./fetch/lg2", &opts));
nulltoken committed
133 134 135 136
	git_repository_free(_repository);

	cl_git_pass(git_repository_open(&_repository, "./fetch/lg2"));

137
	cl_git_pass(git_remote_lookup(&remote, _repository, "origin"));
138
	cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL, NULL));
nulltoken committed
139 140 141

	cl_assert_equal_i(false, invoked);

142 143 144
	options.callbacks.transfer_progress = &transferProgressCallback;
	options.callbacks.payload = &invoked;
	cl_git_pass(git_remote_download(remote, NULL, &options));
nulltoken committed
145 146 147

	cl_assert_equal_i(false, invoked);

148
	cl_git_pass(git_remote_update_tips(remote, &options.callbacks, 1, options.download_tags, NULL));
nulltoken committed
149 150 151 152 153
	git_remote_disconnect(remote);

	git_remote_free(remote);
	git_repository_free(_repository);
}
154

155
static int cancel_at_half(const git_indexer_progress *stats, void *payload)
156 157 158 159
{
	GIT_UNUSED(payload);

	if (stats->received_objects > (stats->total_objects/2))
160
		return -4321;
161 162 163 164 165 166 167
	return 0;
}

void test_online_fetch__can_cancel(void)
{
	git_remote *remote;
	size_t bytes_received = 0;
168
	git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
169 170 171

	cl_git_pass(git_remote_create(&remote, _repo, "test",
				"http://github.com/libgit2/TestGitRepository.git"));
172

173 174
	options.callbacks.transfer_progress = cancel_at_half;
	options.callbacks.payload = &bytes_received;
175

176
	cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL, NULL));
177
	cl_git_fail_with(git_remote_download(remote, NULL, &options), -4321);
178 179 180
	git_remote_disconnect(remote);
	git_remote_free(remote);
}
181 182 183

void test_online_fetch__ls_disconnected(void)
{
184 185
	const git_remote_head **refs;
	size_t refs_len_before, refs_len_after;
186 187 188 189
	git_remote *remote;

	cl_git_pass(git_remote_create(&remote, _repo, "test",
				"http://github.com/libgit2/TestGitRepository.git"));
190
	cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL, NULL));
191
	cl_git_pass(git_remote_ls(&refs, &refs_len_before, remote));
192
	git_remote_disconnect(remote);
193
	cl_git_pass(git_remote_ls(&refs, &refs_len_after, remote));
194

195
	cl_assert_equal_i(refs_len_before, refs_len_after);
196 197 198

	git_remote_free(remote);
}
199 200 201 202 203 204 205 206 207

void test_online_fetch__remote_symrefs(void)
{
	const git_remote_head **refs;
	size_t refs_len;
	git_remote *remote;

	cl_git_pass(git_remote_create(&remote, _repo, "test",
				"http://github.com/libgit2/TestGitRepository.git"));
208
	cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL, NULL));
209 210 211 212 213 214 215 216
	git_remote_disconnect(remote);
	cl_git_pass(git_remote_ls(&refs, &refs_len, remote));

	cl_assert_equal_s("HEAD", refs[0]->name);
	cl_assert_equal_s("refs/heads/master", refs[0]->symref_target);

	git_remote_free(remote);
}
217 218 219 220 221 222

void test_online_fetch__twice(void)
{
	git_remote *remote;

	cl_git_pass(git_remote_create(&remote, _repo, "test", "http://github.com/libgit2/TestGitRepository.git"));
223 224
	cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL));
	cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL));
225 226 227

	git_remote_free(remote);
}
228 229 230 231

void test_online_fetch__proxy(void)
{
    git_remote *remote;
232
    git_str url = GIT_STR_INIT;
233 234 235 236 237
    git_fetch_options fetch_opts;

    if (!_remote_proxy_host || !_remote_proxy_user || !_remote_proxy_pass)
        cl_skip();

238
    cl_git_pass(git_str_printf(&url, "%s://%s:%s@%s/",
239 240 241 242 243 244 245 246 247 248 249 250
        _remote_proxy_scheme ? _remote_proxy_scheme : "http",
        _remote_proxy_user, _remote_proxy_pass, _remote_proxy_host));

    cl_git_pass(git_fetch_options_init(&fetch_opts, GIT_FETCH_OPTIONS_VERSION));
    fetch_opts.proxy_opts.type = GIT_PROXY_SPECIFIED;
    fetch_opts.proxy_opts.url = url.ptr;

    cl_git_pass(git_remote_create(&remote, _repo, "test", "https://github.com/libgit2/TestGitRepository.git"));
    cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, &fetch_opts.proxy_opts, NULL));
    cl_git_pass(git_remote_fetch(remote, NULL, &fetch_opts, NULL));

    git_remote_free(remote);
251
    git_str_dispose(&url);
252
}
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293

static int do_redirected_fetch(const char *url, const char *name, const char *config)
{
	git_repository *repo;
	git_remote *remote;
	int error;

	cl_git_pass(git_repository_init(&repo, "./redirected", 0));
	cl_fixture_cleanup(name);

	if (config)
		cl_repo_set_string(repo, "http.followRedirects", config);

	cl_git_pass(git_remote_create(&remote, repo, name, url));
	error = git_remote_fetch(remote, NULL, NULL, NULL);

	git_remote_free(remote);
	git_repository_free(repo);

	cl_fixture_cleanup("./redirected");

	return error;
}

void test_online_fetch__redirect_config(void)
{
	if (!_remote_redirect_initial || !_remote_redirect_subsequent)
		cl_skip();

	/* config defaults */
	cl_git_pass(do_redirected_fetch(_remote_redirect_initial, "initial", NULL));
	cl_git_fail(do_redirected_fetch(_remote_redirect_subsequent, "subsequent", NULL));

	/* redirect=initial */
	cl_git_pass(do_redirected_fetch(_remote_redirect_initial, "initial", "initial"));
	cl_git_fail(do_redirected_fetch(_remote_redirect_subsequent, "subsequent", "initial"));

	/* redirect=false */
	cl_git_fail(do_redirected_fetch(_remote_redirect_initial, "initial", "false"));
	cl_git_fail(do_redirected_fetch(_remote_redirect_subsequent, "subsequent", "false"));
}
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323

void test_online_fetch__reachable_commit(void)
{
	git_remote *remote;
	git_strarray refspecs;
	git_object *obj;
	git_oid expected_id;
	git_str fetchhead = GIT_STR_INIT;
	char *refspec = "+2c349335b7f797072cf729c4f3bb0914ecb6dec9:refs/success";

	refspecs.strings = &refspec;
	refspecs.count = 1;

	git_oid_fromstr(&expected_id, "2c349335b7f797072cf729c4f3bb0914ecb6dec9");

	cl_git_pass(git_remote_create(&remote, _repo, "test",
		"https://github.com/libgit2/TestGitRepository"));
	cl_git_pass(git_remote_fetch(remote, &refspecs, NULL, NULL));

	cl_git_pass(git_revparse_single(&obj, _repo, "refs/success"));
	cl_assert_equal_oid(&expected_id, git_object_id(obj));

	cl_git_pass(git_futils_readbuffer(&fetchhead, "./fetch/.git/FETCH_HEAD"));
	cl_assert_equal_s(fetchhead.ptr,
		"2c349335b7f797072cf729c4f3bb0914ecb6dec9\t\t'2c349335b7f797072cf729c4f3bb0914ecb6dec9' of https://github.com/libgit2/TestGitRepository\n");

	git_str_dispose(&fetchhead);
	git_object_free(obj);
	git_remote_free(remote);
}