1 /*
2  * Copyright (C) the libgit2 contributors. All rights reserved.
3  *
4  * This file is part of libgit2, distributed under the GNU GPL v2 with
5  * a Linking Exception. For full terms see the included COPYING file.
6  */
7 
8 #include "remote.h"
9 
10 #include "git2/config.h"
11 #include "git2/types.h"
12 #include "git2/oid.h"
13 #include "git2/net.h"
14 
15 #include "config.h"
16 #include "repository.h"
17 #include "fetch.h"
18 #include "refs.h"
19 #include "refspec.h"
20 #include "fetchhead.h"
21 #include "push.h"
22 
23 #define CONFIG_URL_FMT "remote.%s.url"
24 #define CONFIG_PUSHURL_FMT "remote.%s.pushurl"
25 #define CONFIG_FETCH_FMT "remote.%s.fetch"
26 #define CONFIG_PUSH_FMT "remote.%s.push"
27 #define CONFIG_TAGOPT_FMT "remote.%s.tagopt"
28 
29 static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs);
30 static int lookup_remote_prune_config(git_remote *remote, git_config *config, const char *name);
31 char *apply_insteadof(git_config *config, const char *url, int direction);
32 
add_refspec_to(git_vector * vector,const char * string,bool is_fetch)33 static int add_refspec_to(git_vector *vector, const char *string, bool is_fetch)
34 {
35 	git_refspec *spec;
36 
37 	spec = git__calloc(1, sizeof(git_refspec));
38 	GIT_ERROR_CHECK_ALLOC(spec);
39 
40 	if (git_refspec__parse(spec, string, is_fetch) < 0) {
41 		git__free(spec);
42 		return -1;
43 	}
44 
45 	spec->push = !is_fetch;
46 	if (git_vector_insert(vector, spec) < 0) {
47 		git_refspec__dispose(spec);
48 		git__free(spec);
49 		return -1;
50 	}
51 
52 	return 0;
53 }
54 
add_refspec(git_remote * remote,const char * string,bool is_fetch)55 static int add_refspec(git_remote *remote, const char *string, bool is_fetch)
56 {
57 	return add_refspec_to(&remote->refspecs, string, is_fetch);
58 }
59 
download_tags_value(git_remote * remote,git_config * cfg)60 static int download_tags_value(git_remote *remote, git_config *cfg)
61 {
62 	git_config_entry *ce;
63 	git_buf buf = GIT_BUF_INIT;
64 	int error;
65 
66 	if (git_buf_printf(&buf, "remote.%s.tagopt", remote->name) < 0)
67 		return -1;
68 
69 	error = git_config__lookup_entry(&ce, cfg, git_buf_cstr(&buf), false);
70 	git_buf_dispose(&buf);
71 
72 	if (!error && ce && ce->value) {
73 		if (!strcmp(ce->value, "--no-tags"))
74 			remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_NONE;
75 		else if (!strcmp(ce->value, "--tags"))
76 			remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL;
77 	}
78 
79 	git_config_entry_free(ce);
80 	return error;
81 }
82 
ensure_remote_name_is_valid(const char * name)83 static int ensure_remote_name_is_valid(const char *name)
84 {
85 	int valid, error;
86 
87 	error = git_remote_name_is_valid(&valid, name);
88 
89 	if (!error && !valid) {
90 		git_error_set(
91 			GIT_ERROR_CONFIG,
92 			"'%s' is not a valid remote name.", name ? name : "(null)");
93 		error = GIT_EINVALIDSPEC;
94 	}
95 
96 	return error;
97 }
98 
write_add_refspec(git_repository * repo,const char * name,const char * refspec,bool fetch)99 static int write_add_refspec(git_repository *repo, const char *name, const char *refspec, bool fetch)
100 {
101 	git_config *cfg;
102 	git_buf var = GIT_BUF_INIT;
103 	git_refspec spec;
104 	const char *fmt;
105 	int error;
106 
107 	if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
108 	    return error;
109 
110 	fmt = fetch ? CONFIG_FETCH_FMT : CONFIG_PUSH_FMT;
111 
112 	if ((error = ensure_remote_name_is_valid(name)) < 0)
113 		return error;
114 
115 	if ((error = git_refspec__parse(&spec, refspec, fetch)) < 0)
116 		return error;
117 
118 	git_refspec__dispose(&spec);
119 
120 	if ((error = git_buf_printf(&var, fmt, name)) < 0)
121 		return error;
122 
123 	/*
124 	 * "$^" is an unmatchable regexp: it will not match anything at all, so
125 	 * all values will be considered new and we will not replace any
126 	 * present value.
127 	 */
128 	if ((error = git_config_set_multivar(cfg, var.ptr, "$^", refspec)) < 0) {
129 		goto cleanup;
130 	}
131 
132 cleanup:
133 	git_buf_dispose(&var);
134 	return 0;
135 }
136 
canonicalize_url(git_buf * out,const char * in)137 static int canonicalize_url(git_buf *out, const char *in)
138 {
139 	if (in == NULL || strlen(in) == 0) {
140 		git_error_set(GIT_ERROR_INVALID, "cannot set empty URL");
141 		return GIT_EINVALIDSPEC;
142 	}
143 
144 #ifdef GIT_WIN32
145 	/* Given a UNC path like \\server\path, we need to convert this
146 	 * to //server/path for compatibility with core git.
147 	 */
148 	if (in[0] == '\\' && in[1] == '\\' &&
149 		(git__isalpha(in[2]) || git__isdigit(in[2]))) {
150 		const char *c;
151 		for (c = in; *c; c++)
152 			git_buf_putc(out, *c == '\\' ? '/' : *c);
153 
154 		return git_buf_oom(out) ? -1 : 0;
155 	}
156 #endif
157 
158 	return git_buf_puts(out, in);
159 }
160 
default_fetchspec_for_name(git_buf * buf,const char * name)161 static int default_fetchspec_for_name(git_buf *buf, const char *name)
162 {
163 	if (git_buf_printf(buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0)
164 		return -1;
165 
166 	return 0;
167 }
168 
ensure_remote_doesnot_exist(git_repository * repo,const char * name)169 static int ensure_remote_doesnot_exist(git_repository *repo, const char *name)
170 {
171 	int error;
172 	git_remote *remote;
173 
174 	error = git_remote_lookup(&remote, repo, name);
175 
176 	if (error == GIT_ENOTFOUND)
177 		return 0;
178 
179 	if (error < 0)
180 		return error;
181 
182 	git_remote_free(remote);
183 
184 	git_error_set(GIT_ERROR_CONFIG, "remote '%s' already exists", name);
185 
186 	return GIT_EEXISTS;
187 }
188 
git_remote_create_options_init(git_remote_create_options * opts,unsigned int version)189 int git_remote_create_options_init(git_remote_create_options *opts, unsigned int version)
190 {
191 	GIT_INIT_STRUCTURE_FROM_TEMPLATE(
192 		opts, version, git_remote_create_options, GIT_REMOTE_CREATE_OPTIONS_INIT);
193 	return 0;
194 }
195 
196 #ifndef GIT_DEPRECATE_HARD
git_remote_create_init_options(git_remote_create_options * opts,unsigned int version)197 int git_remote_create_init_options(git_remote_create_options *opts, unsigned int version)
198 {
199 	return git_remote_create_options_init(opts, version);
200 }
201 #endif
202 
git_remote_create_with_opts(git_remote ** out,const char * url,const git_remote_create_options * opts)203 int git_remote_create_with_opts(git_remote **out, const char *url, const git_remote_create_options *opts)
204 {
205 	git_remote *remote = NULL;
206 	git_config *config_ro = NULL, *config_rw;
207 	git_buf canonical_url = GIT_BUF_INIT;
208 	git_buf var = GIT_BUF_INIT;
209 	git_buf specbuf = GIT_BUF_INIT;
210 	const git_remote_create_options dummy_opts = GIT_REMOTE_CREATE_OPTIONS_INIT;
211 	int error = -1;
212 
213 	GIT_ASSERT_ARG(out);
214 	GIT_ASSERT_ARG(url);
215 
216 	if (!opts) {
217 		opts = &dummy_opts;
218 	}
219 
220 	GIT_ERROR_CHECK_VERSION(opts, GIT_REMOTE_CREATE_OPTIONS_VERSION, "git_remote_create_options");
221 
222 	if (opts->name != NULL) {
223 		if ((error = ensure_remote_name_is_valid(opts->name)) < 0)
224 			return error;
225 
226 		if (opts->repository &&
227 		    (error = ensure_remote_doesnot_exist(opts->repository, opts->name)) < 0)
228 			return error;
229 	}
230 
231 	if (opts->repository) {
232 		if ((error = git_repository_config_snapshot(&config_ro, opts->repository)) < 0)
233 			goto on_error;
234 	}
235 
236 	remote = git__calloc(1, sizeof(git_remote));
237 	GIT_ERROR_CHECK_ALLOC(remote);
238 
239 	remote->repo = opts->repository;
240 
241 	if ((error = git_vector_init(&remote->refs, 8, NULL)) < 0 ||
242 		(error = canonicalize_url(&canonical_url, url)) < 0)
243 		goto on_error;
244 
245 	if (opts->repository && !(opts->flags & GIT_REMOTE_CREATE_SKIP_INSTEADOF)) {
246 		remote->url = apply_insteadof(config_ro, canonical_url.ptr, GIT_DIRECTION_FETCH);
247 	} else {
248 		remote->url = git__strdup(canonical_url.ptr);
249 	}
250 	GIT_ERROR_CHECK_ALLOC(remote->url);
251 
252 	if (opts->name != NULL) {
253 		remote->name = git__strdup(opts->name);
254 		GIT_ERROR_CHECK_ALLOC(remote->name);
255 
256 		if (opts->repository &&
257 		    ((error = git_buf_printf(&var, CONFIG_URL_FMT, opts->name)) < 0 ||
258 		    (error = git_repository_config__weakptr(&config_rw, opts->repository)) < 0 ||
259 		    (error = git_config_set_string(config_rw, var.ptr, canonical_url.ptr)) < 0))
260 			goto on_error;
261 	}
262 
263 	if (opts->fetchspec != NULL ||
264 	    (opts->name && !(opts->flags & GIT_REMOTE_CREATE_SKIP_DEFAULT_FETCHSPEC))) {
265 		const char *fetch = NULL;
266 		if (opts->fetchspec) {
267 			fetch = opts->fetchspec;
268 		} else {
269 			if ((error = default_fetchspec_for_name(&specbuf, opts->name)) < 0)
270 				goto on_error;
271 
272 			fetch = git_buf_cstr(&specbuf);
273 		}
274 
275 		if ((error = add_refspec(remote, fetch, true)) < 0)
276 			goto on_error;
277 
278 		/* only write for named remotes with a repository */
279 		if (opts->repository && opts->name &&
280 		    ((error = write_add_refspec(opts->repository, opts->name, fetch, true)) < 0 ||
281 		    (error = lookup_remote_prune_config(remote, config_ro, opts->name)) < 0))
282 			goto on_error;
283 
284 		/* Move the data over to where the matching functions can find them */
285 		if ((error = dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs)) < 0)
286 			goto on_error;
287 	}
288 
289 	/* A remote without a name doesn't download tags */
290 	if (!opts->name)
291 		remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_NONE;
292 	else
293 		remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO;
294 
295 
296 	git_buf_dispose(&var);
297 
298 	*out = remote;
299 	error = 0;
300 
301 on_error:
302 	if (error)
303 		git_remote_free(remote);
304 
305 	git_config_free(config_ro);
306 	git_buf_dispose(&specbuf);
307 	git_buf_dispose(&canonical_url);
308 	git_buf_dispose(&var);
309 	return error;
310 }
311 
git_remote_create(git_remote ** out,git_repository * repo,const char * name,const char * url)312 int git_remote_create(git_remote **out, git_repository *repo, const char *name, const char *url)
313 {
314 	git_buf buf = GIT_BUF_INIT;
315 	int error;
316 	git_remote_create_options opts = GIT_REMOTE_CREATE_OPTIONS_INIT;
317 
318 	/* Those 2 tests are duplicated here because of backward-compatibility */
319 	if ((error = ensure_remote_name_is_valid(name)) < 0)
320 		return error;
321 
322 	if (canonicalize_url(&buf, url) < 0)
323 		return GIT_ERROR;
324 
325 	git_buf_clear(&buf);
326 
327 	opts.repository = repo;
328 	opts.name = name;
329 
330 	error = git_remote_create_with_opts(out, url, &opts);
331 
332 	git_buf_dispose(&buf);
333 
334 	return error;
335 }
336 
git_remote_create_with_fetchspec(git_remote ** out,git_repository * repo,const char * name,const char * url,const char * fetch)337 int git_remote_create_with_fetchspec(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch)
338 {
339 	int error;
340 	git_remote_create_options opts = GIT_REMOTE_CREATE_OPTIONS_INIT;
341 
342 	if ((error = ensure_remote_name_is_valid(name)) < 0)
343 		return error;
344 
345 	opts.repository = repo;
346 	opts.name = name;
347 	opts.fetchspec = fetch;
348 	opts.flags = GIT_REMOTE_CREATE_SKIP_DEFAULT_FETCHSPEC;
349 
350 	return git_remote_create_with_opts(out, url, &opts);
351 }
352 
git_remote_create_anonymous(git_remote ** out,git_repository * repo,const char * url)353 int git_remote_create_anonymous(git_remote **out, git_repository *repo, const char *url)
354 {
355 	git_remote_create_options opts = GIT_REMOTE_CREATE_OPTIONS_INIT;
356 
357 	opts.repository = repo;
358 
359 	return git_remote_create_with_opts(out, url, &opts);
360 }
361 
git_remote_create_detached(git_remote ** out,const char * url)362 int git_remote_create_detached(git_remote **out, const char *url)
363 {
364 	return git_remote_create_with_opts(out, url, NULL);
365 }
366 
git_remote_dup(git_remote ** dest,git_remote * source)367 int git_remote_dup(git_remote **dest, git_remote *source)
368 {
369 	size_t i;
370 	int error = 0;
371 	git_refspec *spec;
372 	git_remote *remote = git__calloc(1, sizeof(git_remote));
373 	GIT_ERROR_CHECK_ALLOC(remote);
374 
375 	if (source->name != NULL) {
376 		remote->name = git__strdup(source->name);
377 		GIT_ERROR_CHECK_ALLOC(remote->name);
378 	}
379 
380 	if (source->url != NULL) {
381 		remote->url = git__strdup(source->url);
382 		GIT_ERROR_CHECK_ALLOC(remote->url);
383 	}
384 
385 	if (source->pushurl != NULL) {
386 		remote->pushurl = git__strdup(source->pushurl);
387 		GIT_ERROR_CHECK_ALLOC(remote->pushurl);
388 	}
389 
390 	remote->repo = source->repo;
391 	remote->download_tags = source->download_tags;
392 	remote->prune_refs = source->prune_refs;
393 
394 	if (git_vector_init(&remote->refs, 32, NULL) < 0 ||
395 	    git_vector_init(&remote->refspecs, 2, NULL) < 0 ||
396 	    git_vector_init(&remote->active_refspecs, 2, NULL) < 0) {
397 		error = -1;
398 		goto cleanup;
399 	}
400 
401 	git_vector_foreach(&source->refspecs, i, spec) {
402 		if ((error = add_refspec(remote, spec->string, !spec->push)) < 0)
403 			goto cleanup;
404 	}
405 
406 	*dest = remote;
407 
408 cleanup:
409 
410 	if (error < 0)
411 		git__free(remote);
412 
413 	return error;
414 }
415 
416 struct refspec_cb_data {
417 	git_remote *remote;
418 	int fetch;
419 };
420 
refspec_cb(const git_config_entry * entry,void * payload)421 static int refspec_cb(const git_config_entry *entry, void *payload)
422 {
423 	struct refspec_cb_data *data = (struct refspec_cb_data *)payload;
424 	return add_refspec(data->remote, entry->value, data->fetch);
425 }
426 
get_optional_config(bool * found,git_config * config,git_buf * buf,git_config_foreach_cb cb,void * payload)427 static int get_optional_config(
428 	bool *found, git_config *config, git_buf *buf,
429 	git_config_foreach_cb cb, void *payload)
430 {
431 	int error = 0;
432 	const char *key = git_buf_cstr(buf);
433 
434 	if (git_buf_oom(buf))
435 		return -1;
436 
437 	if (cb != NULL)
438 		error = git_config_get_multivar_foreach(config, key, NULL, cb, payload);
439 	else
440 		error = git_config_get_string(payload, config, key);
441 
442 	if (found)
443 		*found = !error;
444 
445 	if (error == GIT_ENOTFOUND) {
446 		git_error_clear();
447 		error = 0;
448 	}
449 
450 	return error;
451 }
452 
git_remote_lookup(git_remote ** out,git_repository * repo,const char * name)453 int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
454 {
455 	git_remote *remote = NULL;
456 	git_buf buf = GIT_BUF_INIT;
457 	const char *val;
458 	int error = 0;
459 	git_config *config;
460 	struct refspec_cb_data data = { NULL };
461 	bool optional_setting_found = false, found;
462 
463 	GIT_ASSERT_ARG(out);
464 	GIT_ASSERT_ARG(repo);
465 	GIT_ASSERT_ARG(name);
466 
467 	if ((error = ensure_remote_name_is_valid(name)) < 0)
468 		return error;
469 
470 	if ((error = git_repository_config_snapshot(&config, repo)) < 0)
471 		return error;
472 
473 	remote = git__calloc(1, sizeof(git_remote));
474 	GIT_ERROR_CHECK_ALLOC(remote);
475 
476 	remote->name = git__strdup(name);
477 	GIT_ERROR_CHECK_ALLOC(remote->name);
478 
479 	if (git_vector_init(&remote->refs, 32, NULL) < 0 ||
480 	    git_vector_init(&remote->refspecs, 2, NULL) < 0 ||
481 	    git_vector_init(&remote->passive_refspecs, 2, NULL) < 0 ||
482 	    git_vector_init(&remote->active_refspecs, 2, NULL) < 0) {
483 		error = -1;
484 		goto cleanup;
485 	}
486 
487 	if ((error = git_buf_printf(&buf, "remote.%s.url", name)) < 0)
488 		goto cleanup;
489 
490 	if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0)
491 		goto cleanup;
492 
493 	optional_setting_found |= found;
494 
495 	remote->repo = repo;
496 	remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO;
497 
498 	if (found && strlen(val) > 0) {
499 		remote->url = apply_insteadof(config, val, GIT_DIRECTION_FETCH);
500 		GIT_ERROR_CHECK_ALLOC(remote->url);
501 	}
502 
503 	val = NULL;
504 	git_buf_clear(&buf);
505 	git_buf_printf(&buf, "remote.%s.pushurl", name);
506 
507 	if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0)
508 		goto cleanup;
509 
510 	optional_setting_found |= found;
511 
512 	if (!optional_setting_found) {
513 		error = GIT_ENOTFOUND;
514 		git_error_set(GIT_ERROR_CONFIG, "remote '%s' does not exist", name);
515 		goto cleanup;
516 	}
517 
518 	if (found && strlen(val) > 0) {
519 		remote->pushurl = apply_insteadof(config, val, GIT_DIRECTION_PUSH);
520 		GIT_ERROR_CHECK_ALLOC(remote->pushurl);
521 	}
522 
523 	data.remote = remote;
524 	data.fetch = true;
525 
526 	git_buf_clear(&buf);
527 	git_buf_printf(&buf, "remote.%s.fetch", name);
528 
529 	if ((error = get_optional_config(NULL, config, &buf, refspec_cb, &data)) < 0)
530 		goto cleanup;
531 
532 	data.fetch = false;
533 	git_buf_clear(&buf);
534 	git_buf_printf(&buf, "remote.%s.push", name);
535 
536 	if ((error = get_optional_config(NULL, config, &buf, refspec_cb, &data)) < 0)
537 		goto cleanup;
538 
539 	if ((error = download_tags_value(remote, config)) < 0)
540 		goto cleanup;
541 
542 	if ((error = lookup_remote_prune_config(remote, config, name)) < 0)
543 		goto cleanup;
544 
545 	/* Move the data over to where the matching functions can find them */
546 	if ((error = dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs)) < 0)
547 		goto cleanup;
548 
549 	*out = remote;
550 
551 cleanup:
552 	git_config_free(config);
553 	git_buf_dispose(&buf);
554 
555 	if (error < 0)
556 		git_remote_free(remote);
557 
558 	return error;
559 }
560 
lookup_remote_prune_config(git_remote * remote,git_config * config,const char * name)561 static int lookup_remote_prune_config(git_remote *remote, git_config *config, const char *name)
562 {
563 	git_buf buf = GIT_BUF_INIT;
564 	int error = 0;
565 
566 	git_buf_printf(&buf, "remote.%s.prune", name);
567 
568 	if ((error = git_config_get_bool(&remote->prune_refs, config, git_buf_cstr(&buf))) < 0) {
569 		if (error == GIT_ENOTFOUND) {
570 			git_error_clear();
571 
572 			if ((error = git_config_get_bool(&remote->prune_refs, config, "fetch.prune")) < 0) {
573 				if (error == GIT_ENOTFOUND) {
574 					git_error_clear();
575 					error = 0;
576 				}
577 			}
578 		}
579 	}
580 
581 	git_buf_dispose(&buf);
582 	return error;
583 }
584 
git_remote_name(const git_remote * remote)585 const char *git_remote_name(const git_remote *remote)
586 {
587 	GIT_ASSERT_ARG_WITH_RETVAL(remote, NULL);
588 	return remote->name;
589 }
590 
git_remote_owner(const git_remote * remote)591 git_repository *git_remote_owner(const git_remote *remote)
592 {
593 	GIT_ASSERT_ARG_WITH_RETVAL(remote, NULL);
594 	return remote->repo;
595 }
596 
git_remote_url(const git_remote * remote)597 const char *git_remote_url(const git_remote *remote)
598 {
599 	GIT_ASSERT_ARG_WITH_RETVAL(remote, NULL);
600 	return remote->url;
601 }
602 
git_remote_set_instance_url(git_remote * remote,const char * url)603 int git_remote_set_instance_url(git_remote *remote, const char *url)
604 {
605 	char *tmp;
606 
607 	GIT_ASSERT_ARG(remote);
608 	GIT_ASSERT_ARG(url);
609 
610 	if ((tmp = git__strdup(url)) == NULL)
611 		return -1;
612 
613 	git__free(remote->url);
614 	remote->url = tmp;
615 
616 	return 0;
617 }
618 
set_url(git_repository * repo,const char * remote,const char * pattern,const char * url)619 static int set_url(git_repository *repo, const char *remote, const char *pattern, const char *url)
620 {
621 	git_config *cfg;
622 	git_buf buf = GIT_BUF_INIT, canonical_url = GIT_BUF_INIT;
623 	int error;
624 
625 	GIT_ASSERT_ARG(repo);
626 	GIT_ASSERT_ARG(remote);
627 
628 	if ((error = ensure_remote_name_is_valid(remote)) < 0)
629 		return error;
630 
631 	if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
632 		return error;
633 
634 	if ((error = git_buf_printf(&buf, pattern, remote)) < 0)
635 		return error;
636 
637 	if (url) {
638 		if ((error = canonicalize_url(&canonical_url, url)) < 0)
639 			goto cleanup;
640 
641 		error = git_config_set_string(cfg, buf.ptr, url);
642 	} else {
643 		error = git_config_delete_entry(cfg, buf.ptr);
644 	}
645 
646 cleanup:
647 	git_buf_dispose(&canonical_url);
648 	git_buf_dispose(&buf);
649 
650 	return error;
651 }
652 
git_remote_set_url(git_repository * repo,const char * remote,const char * url)653 int git_remote_set_url(git_repository *repo, const char *remote, const char *url)
654 {
655 	return set_url(repo, remote, CONFIG_URL_FMT, url);
656 }
657 
git_remote_pushurl(const git_remote * remote)658 const char *git_remote_pushurl(const git_remote *remote)
659 {
660 	GIT_ASSERT_ARG_WITH_RETVAL(remote, NULL);
661 	return remote->pushurl;
662 }
663 
git_remote_set_instance_pushurl(git_remote * remote,const char * url)664 int git_remote_set_instance_pushurl(git_remote *remote, const char *url)
665 {
666 	char *tmp;
667 
668 	GIT_ASSERT_ARG(remote);
669 	GIT_ASSERT_ARG(url);
670 
671 	if ((tmp = git__strdup(url)) == NULL)
672 		return -1;
673 
674 	git__free(remote->pushurl);
675 	remote->pushurl = tmp;
676 
677 	return 0;
678 }
679 
git_remote_set_pushurl(git_repository * repo,const char * remote,const char * url)680 int git_remote_set_pushurl(git_repository *repo, const char *remote, const char *url)
681 {
682 	return set_url(repo, remote, CONFIG_PUSHURL_FMT, url);
683 }
684 
resolve_url(git_buf * resolved_url,const char * url,int direction,const git_remote_callbacks * callbacks)685 static int resolve_url(
686 	git_buf *resolved_url,
687 	const char *url,
688 	int direction,
689 	const git_remote_callbacks *callbacks)
690 {
691 #ifdef GIT_DEPRECATE_HARD
692 	GIT_UNUSED(direction);
693 	GIT_UNUSED(callbacks);
694 #else
695 	int status, error;
696 
697 	if (callbacks && callbacks->resolve_url) {
698 		git_buf_clear(resolved_url);
699 		status = callbacks->resolve_url(resolved_url, url, direction, callbacks->payload);
700 		if (status != GIT_PASSTHROUGH) {
701 			git_error_set_after_callback_function(status, "git_resolve_url_cb");
702 
703 			if ((error = git_buf_sanitize(resolved_url)) < 0)
704 				return error;
705 
706 			return status;
707 		}
708 	}
709 #endif
710 
711 	return git_buf_sets(resolved_url, url);
712 }
713 
git_remote__urlfordirection(git_buf * url_out,struct git_remote * remote,int direction,const git_remote_callbacks * callbacks)714 int git_remote__urlfordirection(
715 	git_buf *url_out,
716 	struct git_remote *remote,
717 	int direction,
718 	const git_remote_callbacks *callbacks)
719 {
720 	const char *url = NULL;
721 
722 	GIT_ASSERT_ARG(remote);
723 	GIT_ASSERT_ARG(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH);
724 
725 	if (callbacks && callbacks->remote_ready) {
726 		int status = callbacks->remote_ready(remote, direction, callbacks->payload);
727 
728 		if (status != 0 && status != GIT_PASSTHROUGH) {
729 			git_error_set_after_callback_function(status, "git_remote_ready_cb");
730 			return status;
731 		}
732 	}
733 
734 	if (direction == GIT_DIRECTION_FETCH)
735 		url = remote->url;
736 	else if (direction == GIT_DIRECTION_PUSH)
737 		url = remote->pushurl ? remote->pushurl : remote->url;
738 
739 	if (!url) {
740 		git_error_set(GIT_ERROR_INVALID,
741 			"malformed remote '%s' - missing %s URL",
742 			remote->name ? remote->name : "(anonymous)",
743 			direction == GIT_DIRECTION_FETCH ? "fetch" : "push");
744 		return GIT_EINVALID;
745 	}
746 
747 	return resolve_url(url_out, url, direction, callbacks);
748 }
749 
remote_transport_set_callbacks(git_transport * t,const git_remote_callbacks * cbs)750 static int remote_transport_set_callbacks(git_transport *t, const git_remote_callbacks *cbs)
751 {
752 	if (!t->set_callbacks || !cbs)
753 		return 0;
754 
755 	return t->set_callbacks(t, cbs->sideband_progress, NULL,
756 				cbs->certificate_check, cbs->payload);
757 }
758 
set_transport_custom_headers(git_transport * t,const git_strarray * custom_headers)759 static int set_transport_custom_headers(git_transport *t, const git_strarray *custom_headers)
760 {
761 	if (!t->set_custom_headers)
762 		return 0;
763 
764 	return t->set_custom_headers(t, custom_headers);
765 }
766 
git_remote__connect(git_remote * remote,git_direction direction,const git_remote_callbacks * callbacks,const git_remote_connection_opts * conn)767 int git_remote__connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_remote_connection_opts *conn)
768 {
769 	git_transport *t;
770 	git_buf url = GIT_BUF_INIT;
771 	int flags = GIT_TRANSPORTFLAGS_NONE;
772 	int error;
773 	void *payload = NULL;
774 	git_credential_acquire_cb credentials = NULL;
775 	git_transport_cb transport = NULL;
776 
777 	GIT_ASSERT_ARG(remote);
778 
779 	if (callbacks) {
780 		GIT_ERROR_CHECK_VERSION(callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
781 		credentials = callbacks->credentials;
782 		transport   = callbacks->transport;
783 		payload     = callbacks->payload;
784 	}
785 
786 	if (conn->proxy)
787 		GIT_ERROR_CHECK_VERSION(conn->proxy, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
788 
789 	t = remote->transport;
790 
791 	if ((error = git_remote__urlfordirection(&url, remote, direction, callbacks)) < 0)
792 		goto on_error;
793 
794 	/* If we don't have a transport object yet, and the caller specified a
795 	 * custom transport factory, use that */
796 	if (!t && transport &&
797 		(error = transport(&t, remote, payload)) < 0)
798 		goto on_error;
799 
800 	/* If we still don't have a transport, then use the global
801 	 * transport registrations which map URI schemes to transport factories */
802 	if (!t && (error = git_transport_new(&t, remote, url.ptr)) < 0)
803 		goto on_error;
804 
805 	if ((error = set_transport_custom_headers(t, conn->custom_headers)) != 0)
806 		goto on_error;
807 
808 	if ((error = remote_transport_set_callbacks(t, callbacks)) < 0 ||
809 	    (error = t->connect(t, url.ptr, credentials, payload, conn->proxy, direction, flags)) != 0)
810 		goto on_error;
811 
812 	remote->transport = t;
813 
814 	git_buf_dispose(&url);
815 
816 	return 0;
817 
818 on_error:
819 	if (t)
820 		t->free(t);
821 
822 	git_buf_dispose(&url);
823 
824 	if (t == remote->transport)
825 		remote->transport = NULL;
826 
827 	return error;
828 }
829 
git_remote_connect(git_remote * remote,git_direction direction,const git_remote_callbacks * callbacks,const git_proxy_options * proxy,const git_strarray * custom_headers)830 int git_remote_connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_proxy_options *proxy, const git_strarray *custom_headers)
831 {
832 	git_remote_connection_opts conn;
833 
834 	conn.proxy = proxy;
835 	conn.custom_headers = custom_headers;
836 
837 	return git_remote__connect(remote, direction, callbacks, &conn);
838 }
839 
git_remote_ls(const git_remote_head *** out,size_t * size,git_remote * remote)840 int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote)
841 {
842 	GIT_ASSERT_ARG(remote);
843 
844 	if (!remote->transport) {
845 		git_error_set(GIT_ERROR_NET, "this remote has never connected");
846 		return -1;
847 	}
848 
849 	return remote->transport->ls(out, size, remote->transport);
850 }
851 
lookup_config(char ** out,git_config * cfg,const char * name)852 static int lookup_config(char **out, git_config *cfg, const char *name)
853 {
854 	git_config_entry *ce = NULL;
855 	int error;
856 
857 	if ((error = git_config__lookup_entry(&ce, cfg, name, false)) < 0)
858 		return error;
859 
860 	if (ce && ce->value) {
861 		*out = git__strdup(ce->value);
862 		GIT_ERROR_CHECK_ALLOC(*out);
863 	} else {
864 		error = GIT_ENOTFOUND;
865 	}
866 
867 	git_config_entry_free(ce);
868 	return error;
869 }
870 
url_config_trim(git_net_url * url)871 static void url_config_trim(git_net_url *url)
872 {
873 	size_t len = strlen(url->path);
874 
875 	if (url->path[len - 1] == '/') {
876 		len--;
877 	} else {
878 		while (len && url->path[len - 1] != '/')
879 			len--;
880 	}
881 
882 	url->path[len] = '\0';
883 }
884 
http_proxy_config(char ** out,git_remote * remote,git_net_url * url)885 static int http_proxy_config(char **out, git_remote *remote, git_net_url *url)
886 {
887 	git_config *cfg = NULL;
888 	git_buf buf = GIT_BUF_INIT;
889 	git_net_url lookup_url = GIT_NET_URL_INIT;
890 	int error;
891 
892 	if ((error = git_net_url_dup(&lookup_url, url)) < 0)
893 		goto done;
894 
895 	if (remote->repo) {
896 		if ((error = git_repository_config(&cfg, remote->repo)) < 0)
897 			goto done;
898 	} else {
899 		if ((error = git_config_open_default(&cfg)) < 0)
900 			goto done;
901 	}
902 
903 	/* remote.<name>.proxy config setting */
904 	if (remote->name && remote->name[0]) {
905 		git_buf_clear(&buf);
906 
907 		if ((error = git_buf_printf(&buf, "remote.%s.proxy", remote->name)) < 0 ||
908 		    (error = lookup_config(out, cfg, buf.ptr)) != GIT_ENOTFOUND)
909 			goto done;
910 	}
911 
912 	while (true) {
913 		git_buf_clear(&buf);
914 
915 		if ((error = git_buf_puts(&buf, "http.")) < 0 ||
916 		    (error = git_net_url_fmt(&buf, &lookup_url)) < 0 ||
917 		    (error = git_buf_puts(&buf, ".proxy")) < 0 ||
918 		    (error = lookup_config(out, cfg, buf.ptr)) != GIT_ENOTFOUND)
919 			goto done;
920 
921 		if (! lookup_url.path[0])
922 			break;
923 
924 		url_config_trim(&lookup_url);
925 	}
926 
927 	git_buf_clear(&buf);
928 
929 	error = lookup_config(out, cfg, "http.proxy");
930 
931 done:
932 	git_config_free(cfg);
933 	git_buf_dispose(&buf);
934 	git_net_url_dispose(&lookup_url);
935 	return error;
936 }
937 
http_proxy_env(char ** out,git_remote * remote,git_net_url * url)938 static int http_proxy_env(char **out, git_remote *remote, git_net_url *url)
939 {
940 	git_buf proxy_env = GIT_BUF_INIT, no_proxy_env = GIT_BUF_INIT;
941 	bool use_ssl = (strcmp(url->scheme, "https") == 0);
942 	int error;
943 
944 	GIT_UNUSED(remote);
945 
946 	/* http_proxy / https_proxy environment variables */
947 	error = git__getenv(&proxy_env, use_ssl ? "https_proxy" : "http_proxy");
948 
949 	/* try uppercase environment variables */
950 	if (error == GIT_ENOTFOUND)
951 		error = git__getenv(&proxy_env, use_ssl ? "HTTPS_PROXY" : "HTTP_PROXY");
952 
953 	if (error)
954 		goto done;
955 
956 	/* no_proxy/NO_PROXY environment variables */
957 	error = git__getenv(&no_proxy_env, "no_proxy");
958 
959 	if (error == GIT_ENOTFOUND)
960 		error = git__getenv(&no_proxy_env, "NO_PROXY");
961 
962 	if (error && error != GIT_ENOTFOUND)
963 		goto done;
964 
965 	if (!git_net_url_matches_pattern_list(url, no_proxy_env.ptr))
966 		*out = git_buf_detach(&proxy_env);
967 	else
968 		error = GIT_ENOTFOUND;
969 
970 done:
971 	git_buf_dispose(&proxy_env);
972 	git_buf_dispose(&no_proxy_env);
973 	return error;
974 }
975 
git_remote__http_proxy(char ** out,git_remote * remote,git_net_url * url)976 int git_remote__http_proxy(char **out, git_remote *remote, git_net_url *url)
977 {
978 	int error;
979 
980 	GIT_ASSERT_ARG(out);
981 	GIT_ASSERT_ARG(remote);
982 
983 	*out = NULL;
984 
985 	/*
986 	 * Go through the possible sources for proxy configuration,
987 	 * Examine the various git config options first, then
988 	 * consult environment variables.
989 	 */
990 	if ((error = http_proxy_config(out, remote, url)) != GIT_ENOTFOUND ||
991 	    (error = http_proxy_env(out, remote, url)) != GIT_ENOTFOUND)
992 		return error;
993 
994 	return 0;
995 }
996 
997 /* DWIM `refspecs` based on `refs` and append the output to `out` */
dwim_refspecs(git_vector * out,git_vector * refspecs,git_vector * refs)998 static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs)
999 {
1000 	size_t i;
1001 	git_refspec *spec;
1002 
1003 	git_vector_foreach(refspecs, i, spec) {
1004 		if (git_refspec__dwim_one(out, spec, refs) < 0)
1005 			return -1;
1006 	}
1007 
1008 	return 0;
1009 }
1010 
free_refspecs(git_vector * vec)1011 static void free_refspecs(git_vector *vec)
1012 {
1013 	size_t i;
1014 	git_refspec *spec;
1015 
1016 	git_vector_foreach(vec, i, spec) {
1017 		git_refspec__dispose(spec);
1018 		git__free(spec);
1019 	}
1020 
1021 	git_vector_clear(vec);
1022 }
1023 
remote_head_cmp(const void * _a,const void * _b)1024 static int remote_head_cmp(const void *_a, const void *_b)
1025 {
1026 	const git_remote_head *a = (git_remote_head *) _a;
1027 	const git_remote_head *b = (git_remote_head *) _b;
1028 
1029 	return git__strcmp_cb(a->name, b->name);
1030 }
1031 
ls_to_vector(git_vector * out,git_remote * remote)1032 static int ls_to_vector(git_vector *out, git_remote *remote)
1033 {
1034 	git_remote_head **heads;
1035 	size_t heads_len, i;
1036 
1037 	if (git_remote_ls((const git_remote_head ***)&heads, &heads_len, remote) < 0)
1038 		return -1;
1039 
1040 	if (git_vector_init(out, heads_len, remote_head_cmp) < 0)
1041 		return -1;
1042 
1043 	for (i = 0; i < heads_len; i++) {
1044 		if (git_vector_insert(out, heads[i]) < 0)
1045 			return -1;
1046 	}
1047 
1048 	return 0;
1049 }
1050 
git_remote_download(git_remote * remote,const git_strarray * refspecs,const git_fetch_options * opts)1051 int git_remote_download(git_remote *remote, const git_strarray *refspecs, const git_fetch_options *opts)
1052 {
1053 	int error = -1;
1054 	size_t i;
1055 	git_vector *to_active, specs = GIT_VECTOR_INIT, refs = GIT_VECTOR_INIT;
1056 	const git_remote_callbacks *cbs = NULL;
1057 	const git_strarray *custom_headers = NULL;
1058 	const git_proxy_options *proxy = NULL;
1059 
1060 	GIT_ASSERT_ARG(remote);
1061 
1062 	if (!remote->repo) {
1063 		git_error_set(GIT_ERROR_INVALID, "cannot download detached remote");
1064 		return -1;
1065 	}
1066 
1067 	if (opts) {
1068 		GIT_ERROR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
1069 		cbs = &opts->callbacks;
1070 		custom_headers = &opts->custom_headers;
1071 		GIT_ERROR_CHECK_VERSION(&opts->proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
1072 		proxy = &opts->proxy_opts;
1073 	}
1074 
1075 	if (!git_remote_connected(remote) &&
1076 	    (error = git_remote_connect(remote, GIT_DIRECTION_FETCH, cbs, proxy, custom_headers)) < 0)
1077 		goto on_error;
1078 
1079 	if (ls_to_vector(&refs, remote) < 0)
1080 		return -1;
1081 
1082 	if ((git_vector_init(&specs, 0, NULL)) < 0)
1083 		goto on_error;
1084 
1085 	remote->passed_refspecs = 0;
1086 	if (!refspecs || !refspecs->count) {
1087 		to_active = &remote->refspecs;
1088 	} else {
1089 		for (i = 0; i < refspecs->count; i++) {
1090 			if ((error = add_refspec_to(&specs, refspecs->strings[i], true)) < 0)
1091 				goto on_error;
1092 		}
1093 
1094 		to_active = &specs;
1095 		remote->passed_refspecs = 1;
1096 	}
1097 
1098 	free_refspecs(&remote->passive_refspecs);
1099 	if ((error = dwim_refspecs(&remote->passive_refspecs, &remote->refspecs, &refs)) < 0)
1100 		goto on_error;
1101 
1102 	free_refspecs(&remote->active_refspecs);
1103 	error = dwim_refspecs(&remote->active_refspecs, to_active, &refs);
1104 
1105 	git_vector_free(&refs);
1106 	free_refspecs(&specs);
1107 	git_vector_free(&specs);
1108 
1109 	if (error < 0)
1110 		return error;
1111 
1112 	if (remote->push) {
1113 		git_push_free(remote->push);
1114 		remote->push = NULL;
1115 	}
1116 
1117 	if ((error = git_fetch_negotiate(remote, opts)) < 0)
1118 		return error;
1119 
1120 	return git_fetch_download_pack(remote, cbs);
1121 
1122 on_error:
1123 	git_vector_free(&refs);
1124 	free_refspecs(&specs);
1125 	git_vector_free(&specs);
1126 	return error;
1127 }
1128 
git_remote_fetch(git_remote * remote,const git_strarray * refspecs,const git_fetch_options * opts,const char * reflog_message)1129 int git_remote_fetch(
1130 		git_remote *remote,
1131 		const git_strarray *refspecs,
1132 		const git_fetch_options *opts,
1133 		const char *reflog_message)
1134 {
1135 	int error, update_fetchhead = 1;
1136 	git_remote_autotag_option_t tagopt = remote->download_tags;
1137 	bool prune = false;
1138 	git_buf reflog_msg_buf = GIT_BUF_INIT;
1139 	const git_remote_callbacks *cbs = NULL;
1140 	git_remote_connection_opts conn = GIT_REMOTE_CONNECTION_OPTIONS_INIT;
1141 
1142 	if (opts) {
1143 		GIT_ERROR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
1144 		cbs = &opts->callbacks;
1145 		conn.custom_headers = &opts->custom_headers;
1146 		update_fetchhead = opts->update_fetchhead;
1147 		tagopt = opts->download_tags;
1148 		GIT_ERROR_CHECK_VERSION(&opts->proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
1149 		conn.proxy = &opts->proxy_opts;
1150 	}
1151 
1152 	/* Connect and download everything */
1153 	if ((error = git_remote__connect(remote, GIT_DIRECTION_FETCH, cbs, &conn)) != 0)
1154 		return error;
1155 
1156 	error = git_remote_download(remote, refspecs, opts);
1157 
1158 	/* We don't need to be connected anymore */
1159 	git_remote_disconnect(remote);
1160 
1161 	/* If the download failed, return the error */
1162 	if (error != 0)
1163 		return error;
1164 
1165 	/* Default reflog message */
1166 	if (reflog_message)
1167 		git_buf_sets(&reflog_msg_buf, reflog_message);
1168 	else {
1169 		git_buf_printf(&reflog_msg_buf, "fetch %s",
1170 				remote->name ? remote->name : remote->url);
1171 	}
1172 
1173 	/* Create "remote/foo" branches for all remote branches */
1174 	error = git_remote_update_tips(remote, cbs, update_fetchhead, tagopt, git_buf_cstr(&reflog_msg_buf));
1175 	git_buf_dispose(&reflog_msg_buf);
1176 	if (error < 0)
1177 		return error;
1178 
1179 	if (opts && opts->prune == GIT_FETCH_PRUNE)
1180 		prune = true;
1181 	else if (opts && opts->prune == GIT_FETCH_PRUNE_UNSPECIFIED && remote->prune_refs)
1182 		prune = true;
1183 	else if (opts && opts->prune == GIT_FETCH_NO_PRUNE)
1184 		prune = false;
1185 	else
1186 		prune = remote->prune_refs;
1187 
1188 	if (prune)
1189 		error = git_remote_prune(remote, cbs);
1190 
1191 	return error;
1192 }
1193 
remote_head_for_fetchspec_src(git_remote_head ** out,git_vector * update_heads,const char * fetchspec_src)1194 static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *update_heads, const char *fetchspec_src)
1195 {
1196 	unsigned int i;
1197 	git_remote_head *remote_ref;
1198 
1199 	GIT_ASSERT_ARG(update_heads);
1200 	GIT_ASSERT_ARG(fetchspec_src);
1201 
1202 	*out = NULL;
1203 
1204 	git_vector_foreach(update_heads, i, remote_ref) {
1205 		if (strcmp(remote_ref->name, fetchspec_src) == 0) {
1206 			*out = remote_ref;
1207 			break;
1208 		}
1209 	}
1210 
1211 	return 0;
1212 }
1213 
ref_to_update(int * update,git_buf * remote_name,git_remote * remote,git_refspec * spec,const char * ref_name)1214 static int ref_to_update(int *update, git_buf *remote_name, git_remote *remote, git_refspec *spec, const char *ref_name)
1215 {
1216 	int error = 0;
1217 	git_repository *repo;
1218 	git_buf upstream_remote = GIT_BUF_INIT;
1219 	git_buf upstream_name = GIT_BUF_INIT;
1220 
1221 	repo = git_remote_owner(remote);
1222 
1223 	if ((!git_reference__is_branch(ref_name)) ||
1224 	    !git_remote_name(remote) ||
1225 	    (error = git_branch_upstream_remote(&upstream_remote, repo, ref_name) < 0) ||
1226 	    git__strcmp(git_remote_name(remote), git_buf_cstr(&upstream_remote)) ||
1227 	    (error = git_branch_upstream_name(&upstream_name, repo, ref_name)) < 0 ||
1228 	    !git_refspec_dst_matches(spec, git_buf_cstr(&upstream_name)) ||
1229 	    (error = git_refspec_rtransform(remote_name, spec, upstream_name.ptr)) < 0) {
1230 		/* Not an error if there is no upstream */
1231 		if (error == GIT_ENOTFOUND) {
1232 			git_error_clear();
1233 			error = 0;
1234 		}
1235 
1236 		*update = 0;
1237 	} else {
1238 		*update = 1;
1239 	}
1240 
1241 	git_buf_dispose(&upstream_remote);
1242 	git_buf_dispose(&upstream_name);
1243 	return error;
1244 }
1245 
remote_head_for_ref(git_remote_head ** out,git_remote * remote,git_refspec * spec,git_vector * update_heads,git_reference * ref)1246 static int remote_head_for_ref(git_remote_head **out, git_remote *remote, git_refspec *spec, git_vector *update_heads, git_reference *ref)
1247 {
1248 	git_reference *resolved_ref = NULL;
1249 	git_buf remote_name = GIT_BUF_INIT;
1250 	git_config *config = NULL;
1251 	const char *ref_name;
1252 	int error = 0, update;
1253 
1254 	GIT_ASSERT_ARG(out);
1255 	GIT_ASSERT_ARG(spec);
1256 	GIT_ASSERT_ARG(ref);
1257 
1258 	*out = NULL;
1259 
1260 	error = git_reference_resolve(&resolved_ref, ref);
1261 
1262 	/* If we're in an unborn branch, let's pretend nothing happened */
1263 	if (error == GIT_ENOTFOUND && git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC) {
1264 		ref_name = git_reference_symbolic_target(ref);
1265 		error = 0;
1266 	} else {
1267 		ref_name = git_reference_name(resolved_ref);
1268 	}
1269 
1270 	/*
1271 	 * The ref name may be unresolvable - perhaps it's pointing to
1272 	 * something invalid.  In this case, there is no remote head for
1273 	 * this ref.
1274 	 */
1275 	if (!ref_name) {
1276 		error = 0;
1277 		goto cleanup;
1278 	}
1279 
1280 	if ((error = ref_to_update(&update, &remote_name, remote, spec, ref_name)) < 0)
1281 		goto cleanup;
1282 
1283 	if (update)
1284 		error = remote_head_for_fetchspec_src(out, update_heads, git_buf_cstr(&remote_name));
1285 
1286 cleanup:
1287 	git_buf_dispose(&remote_name);
1288 	git_reference_free(resolved_ref);
1289 	git_config_free(config);
1290 	return error;
1291 }
1292 
git_remote_write_fetchhead(git_remote * remote,git_refspec * spec,git_vector * update_heads)1293 static int git_remote_write_fetchhead(git_remote *remote, git_refspec *spec, git_vector *update_heads)
1294 {
1295 	git_reference *head_ref = NULL;
1296 	git_fetchhead_ref *fetchhead_ref;
1297 	git_remote_head *remote_ref, *merge_remote_ref;
1298 	git_vector fetchhead_refs;
1299 	bool include_all_fetchheads;
1300 	unsigned int i = 0;
1301 	int error = 0;
1302 
1303 	GIT_ASSERT_ARG(remote);
1304 
1305 	/* no heads, nothing to do */
1306 	if (update_heads->length == 0)
1307 		return 0;
1308 
1309 	if (git_vector_init(&fetchhead_refs, update_heads->length, git_fetchhead_ref_cmp) < 0)
1310 		return -1;
1311 
1312 	/* Iff refspec is * (but not subdir slash star), include tags */
1313 	include_all_fetchheads = (strcmp(GIT_REFS_HEADS_DIR "*", git_refspec_src(spec)) == 0);
1314 
1315 	/* Determine what to merge: if refspec was a wildcard, just use HEAD */
1316 	if (git_refspec_is_wildcard(spec)) {
1317 		if ((error = git_reference_lookup(&head_ref, remote->repo, GIT_HEAD_FILE)) < 0 ||
1318 			(error = remote_head_for_ref(&merge_remote_ref, remote, spec, update_heads, head_ref)) < 0)
1319 				goto cleanup;
1320 	} else {
1321 		/* If we're fetching a single refspec, that's the only thing that should be in FETCH_HEAD. */
1322 		if ((error = remote_head_for_fetchspec_src(&merge_remote_ref, update_heads, git_refspec_src(spec))) < 0)
1323 			goto cleanup;
1324 	}
1325 
1326 	/* Create the FETCH_HEAD file */
1327 	git_vector_foreach(update_heads, i, remote_ref) {
1328 		int merge_this_fetchhead = (merge_remote_ref == remote_ref);
1329 
1330 		if (!include_all_fetchheads &&
1331 			!git_refspec_src_matches(spec, remote_ref->name) &&
1332 			!merge_this_fetchhead)
1333 			continue;
1334 
1335 		if (git_fetchhead_ref_create(&fetchhead_ref,
1336 			&remote_ref->oid,
1337 			merge_this_fetchhead,
1338 			remote_ref->name,
1339 			git_remote_url(remote)) < 0)
1340 			goto cleanup;
1341 
1342 		if (git_vector_insert(&fetchhead_refs, fetchhead_ref) < 0)
1343 			goto cleanup;
1344 	}
1345 
1346 	git_fetchhead_write(remote->repo, &fetchhead_refs);
1347 
1348 cleanup:
1349 	for (i = 0; i < fetchhead_refs.length; ++i)
1350 		git_fetchhead_ref_free(fetchhead_refs.contents[i]);
1351 
1352 	git_vector_free(&fetchhead_refs);
1353 	git_reference_free(head_ref);
1354 
1355 	return error;
1356 }
1357 
1358 /**
1359  * Generate a list of candidates for pruning by getting a list of
1360  * references which match the rhs of an active refspec.
1361  */
prune_candidates(git_vector * candidates,git_remote * remote)1362 static int prune_candidates(git_vector *candidates, git_remote *remote)
1363 {
1364 	git_strarray arr = { 0 };
1365 	size_t i;
1366 	int error;
1367 
1368 	if ((error = git_reference_list(&arr, remote->repo)) < 0)
1369 		return error;
1370 
1371 	for (i = 0; i < arr.count; i++) {
1372 		const char *refname = arr.strings[i];
1373 		char *refname_dup;
1374 
1375 		if (!git_remote__matching_dst_refspec(remote, refname))
1376 			continue;
1377 
1378 		refname_dup = git__strdup(refname);
1379 		GIT_ERROR_CHECK_ALLOC(refname_dup);
1380 
1381 		if ((error = git_vector_insert(candidates, refname_dup)) < 0)
1382 			goto out;
1383 	}
1384 
1385 out:
1386 	git_strarray_dispose(&arr);
1387 	return error;
1388 }
1389 
find_head(const void * _a,const void * _b)1390 static int find_head(const void *_a, const void *_b)
1391 {
1392 	git_remote_head *a = (git_remote_head *) _a;
1393 	git_remote_head *b = (git_remote_head *) _b;
1394 
1395 	return strcmp(a->name, b->name);
1396 }
1397 
git_remote_prune(git_remote * remote,const git_remote_callbacks * callbacks)1398 int git_remote_prune(git_remote *remote, const git_remote_callbacks *callbacks)
1399 {
1400 	size_t i, j;
1401 	git_vector remote_refs = GIT_VECTOR_INIT;
1402 	git_vector candidates = GIT_VECTOR_INIT;
1403 	const git_refspec *spec;
1404 	const char *refname;
1405 	int error;
1406 	git_oid zero_id = {{ 0 }};
1407 
1408 	if (callbacks)
1409 		GIT_ERROR_CHECK_VERSION(callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
1410 
1411 	if ((error = ls_to_vector(&remote_refs, remote)) < 0)
1412 		goto cleanup;
1413 
1414 	git_vector_set_cmp(&remote_refs, find_head);
1415 
1416 	if ((error = prune_candidates(&candidates, remote)) < 0)
1417 		goto cleanup;
1418 
1419 	/*
1420 	 * Remove those entries from the candidate list for which we
1421 	 * can find a remote reference in at least one refspec.
1422 	 */
1423 	git_vector_foreach(&candidates, i, refname) {
1424 		git_vector_foreach(&remote->active_refspecs, j, spec) {
1425 			git_buf buf = GIT_BUF_INIT;
1426 			size_t pos;
1427 			char *src_name;
1428 			git_remote_head key = {0};
1429 
1430 			if (!git_refspec_dst_matches(spec, refname))
1431 				continue;
1432 
1433 			if ((error = git_refspec_rtransform(&buf, spec, refname)) < 0)
1434 				goto cleanup;
1435 
1436 			key.name = (char *) git_buf_cstr(&buf);
1437 			error = git_vector_bsearch(&pos, &remote_refs, &key);
1438 			git_buf_dispose(&buf);
1439 
1440 			if (error < 0 && error != GIT_ENOTFOUND)
1441 				goto cleanup;
1442 
1443 			if (error == GIT_ENOTFOUND)
1444 				continue;
1445 
1446 			/* If we did find a source, remove it from the candidates. */
1447 			if ((error = git_vector_set((void **) &src_name, &candidates, i, NULL)) < 0)
1448 				goto cleanup;
1449 
1450 			git__free(src_name);
1451 			break;
1452 		}
1453 	}
1454 
1455 	/*
1456 	 * For those candidates still left in the list, we need to
1457 	 * remove them. We do not remove symrefs, as those are for
1458 	 * stuff like origin/HEAD which will never match, but we do
1459 	 * not want to remove them.
1460 	 */
1461 	git_vector_foreach(&candidates, i, refname) {
1462 		git_reference *ref;
1463 		git_oid id;
1464 
1465 		if (refname == NULL)
1466 			continue;
1467 
1468 		error = git_reference_lookup(&ref, remote->repo, refname);
1469 		/* as we want it gone, let's not consider this an error */
1470 		if (error == GIT_ENOTFOUND)
1471 			continue;
1472 
1473 		if (error < 0)
1474 			goto cleanup;
1475 
1476 		if (git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC) {
1477 			git_reference_free(ref);
1478 			continue;
1479 		}
1480 
1481 		git_oid_cpy(&id, git_reference_target(ref));
1482 		error = git_reference_delete(ref);
1483 		git_reference_free(ref);
1484 		if (error < 0)
1485 			goto cleanup;
1486 
1487 		if (callbacks && callbacks->update_tips)
1488 			error = callbacks->update_tips(refname, &id, &zero_id, callbacks->payload);
1489 
1490 		if (error < 0)
1491 			goto cleanup;
1492 	}
1493 
1494 cleanup:
1495 	git_vector_free(&remote_refs);
1496 	git_vector_free_deep(&candidates);
1497 	return error;
1498 }
1499 
update_tips_for_spec(git_remote * remote,const git_remote_callbacks * callbacks,int update_fetchhead,git_remote_autotag_option_t tagopt,git_refspec * spec,git_vector * refs,const char * log_message)1500 static int update_tips_for_spec(
1501 		git_remote *remote,
1502 		const git_remote_callbacks *callbacks,
1503 		int update_fetchhead,
1504 		git_remote_autotag_option_t tagopt,
1505 		git_refspec *spec,
1506 		git_vector *refs,
1507 		const char *log_message)
1508 {
1509 	int error = 0, autotag, valid;
1510 	unsigned int i = 0;
1511 	git_buf refname = GIT_BUF_INIT;
1512 	git_oid old;
1513 	git_odb *odb;
1514 	git_remote_head *head;
1515 	git_reference *ref;
1516 	git_refspec tagspec;
1517 	git_vector update_heads;
1518 
1519 	GIT_ASSERT_ARG(remote);
1520 
1521 	if (git_repository_odb__weakptr(&odb, remote->repo) < 0)
1522 		return -1;
1523 
1524 	if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
1525 		return -1;
1526 
1527 	/* Make a copy of the transport's refs */
1528 	if (git_vector_init(&update_heads, 16, NULL) < 0)
1529 		return -1;
1530 
1531 	for (; i < refs->length; ++i) {
1532 		head = git_vector_get(refs, i);
1533 		autotag = 0;
1534 		git_buf_clear(&refname);
1535 
1536 		/* Ignore malformed ref names (which also saves us from tag^{} */
1537 		if (git_reference_name_is_valid(&valid, head->name) < 0)
1538 			goto on_error;
1539 
1540 		if (!valid)
1541 			continue;
1542 
1543 		/* If we have a tag, see if the auto-follow rules say to update it */
1544 		if (git_refspec_src_matches(&tagspec, head->name)) {
1545 			if (tagopt != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
1546 
1547 				if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_AUTO)
1548 					autotag = 1;
1549 
1550 				git_buf_clear(&refname);
1551 				if (git_buf_puts(&refname, head->name) < 0)
1552 					goto on_error;
1553 			}
1554 		}
1555 
1556 		/* If we didn't want to auto-follow the tag, check if the refspec matches */
1557 		if (!autotag && git_refspec_src_matches(spec, head->name)) {
1558 			if (spec->dst) {
1559 				if (git_refspec_transform(&refname, spec, head->name) < 0)
1560 					goto on_error;
1561 			} else {
1562 				/*
1563 				 * no rhs mans store it in FETCH_HEAD, even if we don't
1564 				 update anything else.
1565 				 */
1566 				if ((error = git_vector_insert(&update_heads, head)) < 0)
1567 					goto on_error;
1568 
1569 				continue;
1570 			}
1571 		}
1572 
1573 		/* If we still don't have a refname, we don't want it */
1574 		if (git_buf_len(&refname) == 0) {
1575 			continue;
1576 		}
1577 
1578 		/* In autotag mode, only create tags for objects already in db */
1579 		if (autotag && !git_odb_exists(odb, &head->oid))
1580 			continue;
1581 
1582 		if (!autotag && git_vector_insert(&update_heads, head) < 0)
1583 			goto on_error;
1584 
1585 		error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
1586 		if (error < 0 && error != GIT_ENOTFOUND)
1587 			goto on_error;
1588 
1589 		if (!(error || error == GIT_ENOTFOUND)
1590 				&& !spec->force
1591 				&& !git_graph_descendant_of(remote->repo, &head->oid, &old))
1592 			continue;
1593 
1594 		if (error == GIT_ENOTFOUND) {
1595 			memset(&old, 0, GIT_OID_RAWSZ);
1596 
1597 			if (autotag && git_vector_insert(&update_heads, head) < 0)
1598 				goto on_error;
1599 		}
1600 
1601 		if (!git_oid__cmp(&old, &head->oid))
1602 			continue;
1603 
1604 		/* In autotag mode, don't overwrite any locally-existing tags */
1605 		error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag,
1606 				log_message);
1607 
1608 		if (error == GIT_EEXISTS)
1609 			continue;
1610 
1611 		if (error < 0)
1612 			goto on_error;
1613 
1614 		git_reference_free(ref);
1615 
1616 		if (callbacks && callbacks->update_tips != NULL) {
1617 			if (callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload) < 0)
1618 				goto on_error;
1619 		}
1620 	}
1621 
1622 	if (update_fetchhead &&
1623 	    (error = git_remote_write_fetchhead(remote, spec, &update_heads)) < 0)
1624 		goto on_error;
1625 
1626 	git_vector_free(&update_heads);
1627 	git_refspec__dispose(&tagspec);
1628 	git_buf_dispose(&refname);
1629 	return 0;
1630 
1631 on_error:
1632 	git_vector_free(&update_heads);
1633 	git_refspec__dispose(&tagspec);
1634 	git_buf_dispose(&refname);
1635 	return -1;
1636 
1637 }
1638 
1639 /**
1640  * Iteration over the three vectors, with a pause whenever we find a match
1641  *
1642  * On each stop, we store the iteration stat in the inout i,j,k
1643  * parameters, and return the currently matching passive refspec as
1644  * well as the head which we matched.
1645  */
next_head(const git_remote * remote,git_vector * refs,git_refspec ** out_spec,git_remote_head ** out_head,size_t * out_i,size_t * out_j,size_t * out_k)1646 static int next_head(const git_remote *remote, git_vector *refs,
1647 		     git_refspec **out_spec, git_remote_head **out_head,
1648 		     size_t *out_i, size_t *out_j, size_t *out_k)
1649 {
1650 	const git_vector *active, *passive;
1651 	git_remote_head *head;
1652 	git_refspec *spec, *passive_spec;
1653 	size_t i, j, k;
1654 	int valid;
1655 
1656 	active = &remote->active_refspecs;
1657 	passive = &remote->passive_refspecs;
1658 
1659 	i = *out_i;
1660 	j = *out_j;
1661 	k = *out_k;
1662 
1663 	for (; i < refs->length; i++) {
1664 		head = git_vector_get(refs, i);
1665 
1666 		if (git_reference_name_is_valid(&valid, head->name) < 0)
1667 			return -1;
1668 
1669 		if (!valid)
1670 			continue;
1671 
1672 		for (; j < active->length; j++) {
1673 			spec = git_vector_get(active, j);
1674 
1675 			if (!git_refspec_src_matches(spec, head->name))
1676 				continue;
1677 
1678 			for (; k < passive->length; k++) {
1679 				passive_spec = git_vector_get(passive, k);
1680 
1681 				if (!git_refspec_src_matches(passive_spec, head->name))
1682 				    continue;
1683 
1684 				*out_spec = passive_spec;
1685 				*out_head = head;
1686 				*out_i = i;
1687 				*out_j = j;
1688 				*out_k = k + 1;
1689 				return 0;
1690 
1691 			}
1692 			k = 0;
1693 		}
1694 		j = 0;
1695 	}
1696 
1697 	return GIT_ITEROVER;
1698 }
1699 
opportunistic_updates(const git_remote * remote,const git_remote_callbacks * callbacks,git_vector * refs,const char * msg)1700 static int opportunistic_updates(const git_remote *remote, const git_remote_callbacks *callbacks,
1701 				 git_vector *refs, const char *msg)
1702 {
1703 	size_t i, j, k;
1704 	git_refspec *spec;
1705 	git_remote_head *head;
1706 	git_reference *ref;
1707 	git_buf refname = GIT_BUF_INIT;
1708 	int error = 0;
1709 
1710 	i = j = k = 0;
1711 
1712 	while ((error = next_head(remote, refs, &spec, &head, &i, &j, &k)) == 0) {
1713 		git_oid old = {{ 0 }};
1714 		/*
1715 		 * If we got here, there is a refspec which was used
1716 		 * for fetching which matches the source of one of the
1717 		 * passive refspecs, so we should update that
1718 		 * remote-tracking branch, but not add it to
1719 		 * FETCH_HEAD
1720 		 */
1721 
1722 		git_buf_clear(&refname);
1723 		if ((error = git_refspec_transform(&refname, spec, head->name)) < 0)
1724 			goto cleanup;
1725 
1726 		error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
1727 		if (error < 0 && error != GIT_ENOTFOUND)
1728 			goto cleanup;
1729 
1730 		if (!git_oid_cmp(&old, &head->oid))
1731 			continue;
1732 
1733 		/* If we did find a current reference, make sure we haven't lost a race */
1734 		if (error)
1735 			error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, true, msg);
1736 		else
1737 			error = git_reference_create_matching(&ref, remote->repo, refname.ptr, &head->oid, true, &old, msg);
1738 		git_reference_free(ref);
1739 		if (error < 0)
1740 			goto cleanup;
1741 
1742 		if (callbacks && callbacks->update_tips != NULL) {
1743 			if (callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload) < 0)
1744 				goto cleanup;
1745 		}
1746 	}
1747 
1748 	if (error == GIT_ITEROVER)
1749 		error = 0;
1750 
1751 cleanup:
1752 	git_buf_dispose(&refname);
1753 	return error;
1754 }
1755 
truncate_fetch_head(const char * gitdir)1756 static int truncate_fetch_head(const char *gitdir)
1757 {
1758 	git_buf path = GIT_BUF_INIT;
1759 	int error;
1760 
1761 	if ((error = git_buf_joinpath(&path, gitdir, GIT_FETCH_HEAD_FILE)) < 0)
1762 		return error;
1763 
1764 	error = git_futils_truncate(path.ptr, GIT_REFS_FILE_MODE);
1765 	git_buf_dispose(&path);
1766 
1767 	return error;
1768 }
1769 
git_remote_update_tips(git_remote * remote,const git_remote_callbacks * callbacks,int update_fetchhead,git_remote_autotag_option_t download_tags,const char * reflog_message)1770 int git_remote_update_tips(
1771 		git_remote *remote,
1772 		const git_remote_callbacks *callbacks,
1773 		int update_fetchhead,
1774 		git_remote_autotag_option_t download_tags,
1775 		const char *reflog_message)
1776 {
1777 	git_refspec *spec, tagspec;
1778 	git_vector refs = GIT_VECTOR_INIT;
1779 	git_remote_autotag_option_t tagopt;
1780 	int error;
1781 	size_t i;
1782 
1783 	/* push has its own logic hidden away in the push object */
1784 	if (remote->push) {
1785 		return git_push_update_tips(remote->push, callbacks);
1786 	}
1787 
1788 	if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
1789 		return -1;
1790 
1791 
1792 	if ((error = ls_to_vector(&refs, remote)) < 0)
1793 		goto out;
1794 
1795 	if (download_tags == GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED)
1796 		tagopt = remote->download_tags;
1797 	else
1798 		tagopt = download_tags;
1799 
1800 	if ((error = truncate_fetch_head(git_repository_path(remote->repo))) < 0)
1801 		goto out;
1802 
1803 	if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_ALL) {
1804 		if ((error = update_tips_for_spec(remote, callbacks, update_fetchhead, tagopt, &tagspec, &refs, reflog_message)) < 0)
1805 			goto out;
1806 	}
1807 
1808 	git_vector_foreach(&remote->active_refspecs, i, spec) {
1809 		if (spec->push)
1810 			continue;
1811 
1812 		if ((error = update_tips_for_spec(remote, callbacks, update_fetchhead, tagopt, spec, &refs, reflog_message)) < 0)
1813 			goto out;
1814 	}
1815 
1816 	/* Only try to do opportunistic updates if the refpec lists differ. */
1817 	if (remote->passed_refspecs)
1818 		error = opportunistic_updates(remote, callbacks, &refs, reflog_message);
1819 
1820 out:
1821 	git_vector_free(&refs);
1822 	git_refspec__dispose(&tagspec);
1823 	return error;
1824 }
1825 
git_remote_connected(const git_remote * remote)1826 int git_remote_connected(const git_remote *remote)
1827 {
1828 	GIT_ASSERT_ARG(remote);
1829 
1830 	if (!remote->transport || !remote->transport->is_connected)
1831 		return 0;
1832 
1833 	/* Ask the transport if it's connected. */
1834 	return remote->transport->is_connected(remote->transport);
1835 }
1836 
git_remote_stop(git_remote * remote)1837 int git_remote_stop(git_remote *remote)
1838 {
1839 	GIT_ASSERT_ARG(remote);
1840 
1841 	if (remote->transport && remote->transport->cancel)
1842 		remote->transport->cancel(remote->transport);
1843 
1844 	return 0;
1845 }
1846 
git_remote_disconnect(git_remote * remote)1847 int git_remote_disconnect(git_remote *remote)
1848 {
1849 	GIT_ASSERT_ARG(remote);
1850 
1851 	if (git_remote_connected(remote))
1852 		remote->transport->close(remote->transport);
1853 
1854 	return 0;
1855 }
1856 
git_remote_free(git_remote * remote)1857 void git_remote_free(git_remote *remote)
1858 {
1859 	if (remote == NULL)
1860 		return;
1861 
1862 	if (remote->transport != NULL) {
1863 		git_remote_disconnect(remote);
1864 
1865 		remote->transport->free(remote->transport);
1866 		remote->transport = NULL;
1867 	}
1868 
1869 	git_vector_free(&remote->refs);
1870 
1871 	free_refspecs(&remote->refspecs);
1872 	git_vector_free(&remote->refspecs);
1873 
1874 	free_refspecs(&remote->active_refspecs);
1875 	git_vector_free(&remote->active_refspecs);
1876 
1877 	free_refspecs(&remote->passive_refspecs);
1878 	git_vector_free(&remote->passive_refspecs);
1879 
1880 	git_push_free(remote->push);
1881 	git__free(remote->url);
1882 	git__free(remote->pushurl);
1883 	git__free(remote->name);
1884 	git__free(remote);
1885 }
1886 
remote_list_cb(const git_config_entry * entry,void * payload)1887 static int remote_list_cb(const git_config_entry *entry, void *payload)
1888 {
1889 	git_vector *list = payload;
1890 	const char *name = entry->name + strlen("remote.");
1891 	size_t namelen = strlen(name);
1892 	char *remote_name;
1893 
1894 	/* we know name matches "remote.<stuff>.(push)?url" */
1895 
1896 	if (!strcmp(&name[namelen - 4], ".url"))
1897 		remote_name = git__strndup(name, namelen - 4); /* strip ".url" */
1898 	else
1899 		remote_name = git__strndup(name, namelen - 8); /* strip ".pushurl" */
1900 	GIT_ERROR_CHECK_ALLOC(remote_name);
1901 
1902 	return git_vector_insert(list, remote_name);
1903 }
1904 
git_remote_list(git_strarray * remotes_list,git_repository * repo)1905 int git_remote_list(git_strarray *remotes_list, git_repository *repo)
1906 {
1907 	int error;
1908 	git_config *cfg;
1909 	git_vector list = GIT_VECTOR_INIT;
1910 
1911 	if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
1912 		return error;
1913 
1914 	if ((error = git_vector_init(&list, 4, git__strcmp_cb)) < 0)
1915 		return error;
1916 
1917 	error = git_config_foreach_match(
1918 		cfg, "^remote\\..*\\.(push)?url$", remote_list_cb, &list);
1919 
1920 	if (error < 0) {
1921 		git_vector_free_deep(&list);
1922 		return error;
1923 	}
1924 
1925 	git_vector_uniq(&list, git__free);
1926 
1927 	remotes_list->strings =
1928 		(char **)git_vector_detach(&remotes_list->count, NULL, &list);
1929 
1930 	return 0;
1931 }
1932 
git_remote_stats(git_remote * remote)1933 const git_indexer_progress *git_remote_stats(git_remote *remote)
1934 {
1935 	GIT_ASSERT_ARG_WITH_RETVAL(remote, NULL);
1936 	return &remote->stats;
1937 }
1938 
git_remote_autotag(const git_remote * remote)1939 git_remote_autotag_option_t git_remote_autotag(const git_remote *remote)
1940 {
1941 	return remote->download_tags;
1942 }
1943 
git_remote_set_autotag(git_repository * repo,const char * remote,git_remote_autotag_option_t value)1944 int git_remote_set_autotag(git_repository *repo, const char *remote, git_remote_autotag_option_t value)
1945 {
1946 	git_buf var = GIT_BUF_INIT;
1947 	git_config *config;
1948 	int error;
1949 
1950 	GIT_ASSERT_ARG(repo && remote);
1951 
1952 	if ((error = ensure_remote_name_is_valid(remote)) < 0)
1953 		return error;
1954 
1955 	if ((error = git_repository_config__weakptr(&config, repo)) < 0)
1956 		return error;
1957 
1958 	if ((error = git_buf_printf(&var, CONFIG_TAGOPT_FMT, remote)))
1959 		return error;
1960 
1961 	switch (value) {
1962 	case GIT_REMOTE_DOWNLOAD_TAGS_NONE:
1963 		error = git_config_set_string(config, var.ptr, "--no-tags");
1964 		break;
1965 	case GIT_REMOTE_DOWNLOAD_TAGS_ALL:
1966 		error = git_config_set_string(config, var.ptr, "--tags");
1967 		break;
1968 	case GIT_REMOTE_DOWNLOAD_TAGS_AUTO:
1969 		error = git_config_delete_entry(config, var.ptr);
1970 		if (error == GIT_ENOTFOUND)
1971 			error = 0;
1972 		break;
1973 	default:
1974 		git_error_set(GIT_ERROR_INVALID, "invalid value for the tagopt setting");
1975 		error = -1;
1976 	}
1977 
1978 	git_buf_dispose(&var);
1979 	return error;
1980 }
1981 
git_remote_prune_refs(const git_remote * remote)1982 int git_remote_prune_refs(const git_remote *remote)
1983 {
1984 	return remote->prune_refs;
1985 }
1986 
rename_remote_config_section(git_repository * repo,const char * old_name,const char * new_name)1987 static int rename_remote_config_section(
1988 	git_repository *repo,
1989 	const char *old_name,
1990 	const char *new_name)
1991 {
1992 	git_buf old_section_name = GIT_BUF_INIT,
1993 		new_section_name = GIT_BUF_INIT;
1994 	int error = -1;
1995 
1996 	if (git_buf_printf(&old_section_name, "remote.%s", old_name) < 0)
1997 		goto cleanup;
1998 
1999 	if (new_name &&
2000 		(git_buf_printf(&new_section_name, "remote.%s", new_name) < 0))
2001 			goto cleanup;
2002 
2003 	error = git_config_rename_section(
2004 		repo,
2005 		git_buf_cstr(&old_section_name),
2006 		new_name ? git_buf_cstr(&new_section_name) : NULL);
2007 
2008 cleanup:
2009 	git_buf_dispose(&old_section_name);
2010 	git_buf_dispose(&new_section_name);
2011 
2012 	return error;
2013 }
2014 
2015 struct update_data {
2016 	git_config *config;
2017 	const char *old_remote_name;
2018 	const char *new_remote_name;
2019 };
2020 
update_config_entries_cb(const git_config_entry * entry,void * payload)2021 static int update_config_entries_cb(
2022 	const git_config_entry *entry,
2023 	void *payload)
2024 {
2025 	struct update_data *data = (struct update_data *)payload;
2026 
2027 	if (strcmp(entry->value, data->old_remote_name))
2028 		return 0;
2029 
2030 	return git_config_set_string(
2031 		data->config, entry->name, data->new_remote_name);
2032 }
2033 
update_branch_remote_config_entry(git_repository * repo,const char * old_name,const char * new_name)2034 static int update_branch_remote_config_entry(
2035 	git_repository *repo,
2036 	const char *old_name,
2037 	const char *new_name)
2038 {
2039 	int error;
2040 	struct update_data data = { NULL };
2041 
2042 	if ((error = git_repository_config__weakptr(&data.config, repo)) < 0)
2043 		return error;
2044 
2045 	data.old_remote_name = old_name;
2046 	data.new_remote_name = new_name;
2047 
2048 	return git_config_foreach_match(
2049 		data.config, "branch\\..+\\.remote", update_config_entries_cb, &data);
2050 }
2051 
rename_one_remote_reference(git_reference * reference_in,const char * old_remote_name,const char * new_remote_name)2052 static int rename_one_remote_reference(
2053 	git_reference *reference_in,
2054 	const char *old_remote_name,
2055 	const char *new_remote_name)
2056 {
2057 	int error;
2058 	git_reference *ref = NULL, *dummy = NULL;
2059 	git_buf namespace = GIT_BUF_INIT, old_namespace = GIT_BUF_INIT;
2060 	git_buf new_name = GIT_BUF_INIT;
2061 	git_buf log_message = GIT_BUF_INIT;
2062 	size_t pfx_len;
2063 	const char *target;
2064 
2065 	if ((error = git_buf_printf(&namespace, GIT_REFS_REMOTES_DIR "%s/", new_remote_name)) < 0)
2066 		return error;
2067 
2068 	pfx_len = strlen(GIT_REFS_REMOTES_DIR) + strlen(old_remote_name) + 1;
2069 	git_buf_puts(&new_name, namespace.ptr);
2070 	if ((error = git_buf_puts(&new_name, git_reference_name(reference_in) + pfx_len)) < 0)
2071 		goto cleanup;
2072 
2073 	if ((error = git_buf_printf(&log_message,
2074 					"renamed remote %s to %s",
2075 					old_remote_name, new_remote_name)) < 0)
2076 		goto cleanup;
2077 
2078 	if ((error = git_reference_rename(&ref, reference_in, git_buf_cstr(&new_name), 1,
2079 					  git_buf_cstr(&log_message))) < 0)
2080 		goto cleanup;
2081 
2082 	if (git_reference_type(ref) != GIT_REFERENCE_SYMBOLIC)
2083 		goto cleanup;
2084 
2085 	/* Handle refs like origin/HEAD -> origin/master */
2086 	target = git_reference_symbolic_target(ref);
2087 	if ((error = git_buf_printf(&old_namespace, GIT_REFS_REMOTES_DIR "%s/", old_remote_name)) < 0)
2088 		goto cleanup;
2089 
2090 	if (git__prefixcmp(target, old_namespace.ptr))
2091 		goto cleanup;
2092 
2093 	git_buf_clear(&new_name);
2094 	git_buf_puts(&new_name, namespace.ptr);
2095 	if ((error = git_buf_puts(&new_name, target + pfx_len)) < 0)
2096 		goto cleanup;
2097 
2098 	error = git_reference_symbolic_set_target(&dummy, ref, git_buf_cstr(&new_name),
2099 						  git_buf_cstr(&log_message));
2100 
2101 	git_reference_free(dummy);
2102 
2103 cleanup:
2104 	git_reference_free(reference_in);
2105 	git_reference_free(ref);
2106 	git_buf_dispose(&namespace);
2107 	git_buf_dispose(&old_namespace);
2108 	git_buf_dispose(&new_name);
2109 	git_buf_dispose(&log_message);
2110 	return error;
2111 }
2112 
rename_remote_references(git_repository * repo,const char * old_name,const char * new_name)2113 static int rename_remote_references(
2114 	git_repository *repo,
2115 	const char *old_name,
2116 	const char *new_name)
2117 {
2118 	int error;
2119 	git_buf buf = GIT_BUF_INIT;
2120 	git_reference *ref;
2121 	git_reference_iterator *iter;
2122 
2123 	if ((error = git_buf_printf(&buf, GIT_REFS_REMOTES_DIR "%s/*", old_name)) < 0)
2124 		return error;
2125 
2126 	error = git_reference_iterator_glob_new(&iter, repo, git_buf_cstr(&buf));
2127 	git_buf_dispose(&buf);
2128 
2129 	if (error < 0)
2130 		return error;
2131 
2132 	while ((error = git_reference_next(&ref, iter)) == 0) {
2133 		if ((error = rename_one_remote_reference(ref, old_name, new_name)) < 0)
2134 			break;
2135 	}
2136 
2137 	git_reference_iterator_free(iter);
2138 
2139 	return (error == GIT_ITEROVER) ? 0 : error;
2140 }
2141 
rename_fetch_refspecs(git_vector * problems,git_remote * remote,const char * new_name)2142 static int rename_fetch_refspecs(git_vector *problems, git_remote *remote, const char *new_name)
2143 {
2144 	git_config *config;
2145 	git_buf base = GIT_BUF_INIT, var = GIT_BUF_INIT, val = GIT_BUF_INIT;
2146 	const git_refspec *spec;
2147 	size_t i;
2148 	int error = 0;
2149 
2150 	if ((error = git_repository_config__weakptr(&config, remote->repo)) < 0)
2151 		return error;
2152 
2153 	if ((error = git_vector_init(problems, 1, NULL)) < 0)
2154 		return error;
2155 
2156 	if ((error = default_fetchspec_for_name(&base, remote->name)) < 0)
2157 		return error;
2158 
2159 	git_vector_foreach(&remote->refspecs, i, spec) {
2160 		if (spec->push)
2161 			continue;
2162 
2163 		/* Does the dst part of the refspec follow the expected format? */
2164 		if (strcmp(git_buf_cstr(&base), spec->string)) {
2165 			char *dup;
2166 
2167 			dup = git__strdup(spec->string);
2168 			GIT_ERROR_CHECK_ALLOC(dup);
2169 
2170 			if ((error = git_vector_insert(problems, dup)) < 0)
2171 				break;
2172 
2173 			continue;
2174 		}
2175 
2176 		/* If we do want to move it to the new section */
2177 
2178 		git_buf_clear(&val);
2179 		git_buf_clear(&var);
2180 
2181 		if (default_fetchspec_for_name(&val, new_name) < 0 ||
2182 			git_buf_printf(&var, "remote.%s.fetch", new_name) < 0)
2183 		{
2184 			error = -1;
2185 			break;
2186 		}
2187 
2188 		if ((error = git_config_set_string(
2189 				config, git_buf_cstr(&var), git_buf_cstr(&val))) < 0)
2190 			break;
2191 	}
2192 
2193 	git_buf_dispose(&base);
2194 	git_buf_dispose(&var);
2195 	git_buf_dispose(&val);
2196 
2197 	if (error < 0) {
2198 		char *str;
2199 		git_vector_foreach(problems, i, str)
2200 			git__free(str);
2201 
2202 		git_vector_free(problems);
2203 	}
2204 
2205 	return error;
2206 }
2207 
git_remote_rename(git_strarray * out,git_repository * repo,const char * name,const char * new_name)2208 int git_remote_rename(git_strarray *out, git_repository *repo, const char *name, const char *new_name)
2209 {
2210 	int error;
2211 	git_vector problem_refspecs = GIT_VECTOR_INIT;
2212 	git_remote *remote = NULL;
2213 
2214 	GIT_ASSERT_ARG(out && repo && name && new_name);
2215 
2216 	if ((error = git_remote_lookup(&remote, repo, name)) < 0)
2217 		return error;
2218 
2219 	if ((error = ensure_remote_name_is_valid(new_name)) < 0)
2220 		goto cleanup;
2221 
2222 	if ((error = ensure_remote_doesnot_exist(repo, new_name)) < 0)
2223 		goto cleanup;
2224 
2225 	if ((error = rename_remote_config_section(repo, name, new_name)) < 0)
2226 		goto cleanup;
2227 
2228 	if ((error = update_branch_remote_config_entry(repo, name, new_name)) < 0)
2229 		goto cleanup;
2230 
2231 	if ((error = rename_remote_references(repo, name, new_name)) < 0)
2232 		goto cleanup;
2233 
2234 	if ((error = rename_fetch_refspecs(&problem_refspecs, remote, new_name)) < 0)
2235 		goto cleanup;
2236 
2237 	out->count = problem_refspecs.length;
2238 	out->strings = (char **) problem_refspecs.contents;
2239 
2240 cleanup:
2241 	if (error < 0)
2242 		git_vector_free(&problem_refspecs);
2243 
2244 	git_remote_free(remote);
2245 	return error;
2246 }
2247 
git_remote_name_is_valid(int * valid,const char * remote_name)2248 int git_remote_name_is_valid(int *valid, const char *remote_name)
2249 {
2250 	git_buf buf = GIT_BUF_INIT;
2251 	git_refspec refspec = {0};
2252 	int error;
2253 
2254 	GIT_ASSERT(valid);
2255 
2256 	*valid = 0;
2257 
2258 	if (!remote_name || *remote_name == '\0')
2259 		return 0;
2260 
2261 	if ((error = git_buf_printf(&buf, "refs/heads/test:refs/remotes/%s/test", remote_name)) < 0)
2262 		goto done;
2263 
2264 	error = git_refspec__parse(&refspec, git_buf_cstr(&buf), true);
2265 
2266 	if (!error)
2267 		*valid = 1;
2268 	else if (error == GIT_EINVALIDSPEC)
2269 		error = 0;
2270 
2271 done:
2272 	git_buf_dispose(&buf);
2273 	git_refspec__dispose(&refspec);
2274 
2275 	return error;
2276 }
2277 
git_remote__matching_refspec(git_remote * remote,const char * refname)2278 git_refspec *git_remote__matching_refspec(git_remote *remote, const char *refname)
2279 {
2280 	git_refspec *spec;
2281 	size_t i;
2282 
2283 	git_vector_foreach(&remote->active_refspecs, i, spec) {
2284 		if (spec->push)
2285 			continue;
2286 
2287 		if (git_refspec_src_matches(spec, refname))
2288 			return spec;
2289 	}
2290 
2291 	return NULL;
2292 }
2293 
git_remote__matching_dst_refspec(git_remote * remote,const char * refname)2294 git_refspec *git_remote__matching_dst_refspec(git_remote *remote, const char *refname)
2295 {
2296 	git_refspec *spec;
2297 	size_t i;
2298 
2299 	git_vector_foreach(&remote->active_refspecs, i, spec) {
2300 		if (spec->push)
2301 			continue;
2302 
2303 		if (git_refspec_dst_matches(spec, refname))
2304 			return spec;
2305 	}
2306 
2307 	return NULL;
2308 }
2309 
git_remote_add_fetch(git_repository * repo,const char * remote,const char * refspec)2310 int git_remote_add_fetch(git_repository *repo, const char *remote, const char *refspec)
2311 {
2312 	return write_add_refspec(repo, remote, refspec, true);
2313 }
2314 
git_remote_add_push(git_repository * repo,const char * remote,const char * refspec)2315 int git_remote_add_push(git_repository *repo, const char *remote, const char *refspec)
2316 {
2317 	return write_add_refspec(repo, remote, refspec, false);
2318 }
2319 
copy_refspecs(git_strarray * array,const git_remote * remote,unsigned int push)2320 static int copy_refspecs(git_strarray *array, const git_remote *remote, unsigned int push)
2321 {
2322 	size_t i;
2323 	git_vector refspecs;
2324 	git_refspec *spec;
2325 	char *dup;
2326 
2327 	if (git_vector_init(&refspecs, remote->refspecs.length, NULL) < 0)
2328 		return -1;
2329 
2330 	git_vector_foreach(&remote->refspecs, i, spec) {
2331 		if (spec->push != push)
2332 			continue;
2333 
2334 		if ((dup = git__strdup(spec->string)) == NULL)
2335 			goto on_error;
2336 
2337 		if (git_vector_insert(&refspecs, dup) < 0) {
2338 			git__free(dup);
2339 			goto on_error;
2340 		}
2341 	}
2342 
2343 	array->strings = (char **)refspecs.contents;
2344 	array->count = refspecs.length;
2345 
2346 	return 0;
2347 
2348 on_error:
2349 	git_vector_free_deep(&refspecs);
2350 
2351 	return -1;
2352 }
2353 
git_remote_get_fetch_refspecs(git_strarray * array,const git_remote * remote)2354 int git_remote_get_fetch_refspecs(git_strarray *array, const git_remote *remote)
2355 {
2356 	return copy_refspecs(array, remote, false);
2357 }
2358 
git_remote_get_push_refspecs(git_strarray * array,const git_remote * remote)2359 int git_remote_get_push_refspecs(git_strarray *array, const git_remote *remote)
2360 {
2361 	return copy_refspecs(array, remote, true);
2362 }
2363 
git_remote_refspec_count(const git_remote * remote)2364 size_t git_remote_refspec_count(const git_remote *remote)
2365 {
2366 	return remote->refspecs.length;
2367 }
2368 
git_remote_get_refspec(const git_remote * remote,size_t n)2369 const git_refspec *git_remote_get_refspec(const git_remote *remote, size_t n)
2370 {
2371 	return git_vector_get(&remote->refspecs, n);
2372 }
2373 
git_remote_init_callbacks(git_remote_callbacks * opts,unsigned int version)2374 int git_remote_init_callbacks(git_remote_callbacks *opts, unsigned int version)
2375 {
2376 	GIT_INIT_STRUCTURE_FROM_TEMPLATE(
2377 		opts, version, git_remote_callbacks, GIT_REMOTE_CALLBACKS_INIT);
2378 	return 0;
2379 }
2380 
2381 /* asserts a branch.<foo>.remote format */
name_offset(size_t * len_out,const char * name)2382 static const char *name_offset(size_t *len_out, const char *name)
2383 {
2384 	size_t prefix_len;
2385 	const char *dot;
2386 
2387 	prefix_len = strlen("remote.");
2388 	dot = strchr(name + prefix_len, '.');
2389 
2390 	GIT_ASSERT_ARG_WITH_RETVAL(dot, NULL);
2391 
2392 	*len_out = dot - name - prefix_len;
2393 	return name + prefix_len;
2394 }
2395 
remove_branch_config_related_entries(git_repository * repo,const char * remote_name)2396 static int remove_branch_config_related_entries(
2397 	git_repository *repo,
2398 	const char *remote_name)
2399 {
2400 	int error;
2401 	git_config *config;
2402 	git_config_entry *entry;
2403 	git_config_iterator *iter;
2404 	git_buf buf = GIT_BUF_INIT;
2405 
2406 	if ((error = git_repository_config__weakptr(&config, repo)) < 0)
2407 		return error;
2408 
2409 	if ((error = git_config_iterator_glob_new(&iter, config, "branch\\..+\\.remote")) < 0)
2410 		return error;
2411 
2412 	/* find any branches with us as upstream and remove that config */
2413 	while ((error = git_config_next(&entry, iter)) == 0) {
2414 		const char *branch;
2415 		size_t branch_len;
2416 
2417 		if (strcmp(remote_name, entry->value))
2418 			continue;
2419 
2420 		if ((branch = name_offset(&branch_len, entry->name)) == NULL) {
2421 			error = -1;
2422 			break;
2423 		}
2424 
2425 		git_buf_clear(&buf);
2426 		if ((error = git_buf_printf(&buf, "branch.%.*s.merge", (int)branch_len, branch)) < 0)
2427 			break;
2428 
2429 		if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0) {
2430 			if (error != GIT_ENOTFOUND)
2431 				break;
2432 			git_error_clear();
2433 		}
2434 
2435 		git_buf_clear(&buf);
2436 		if ((error = git_buf_printf(&buf, "branch.%.*s.remote", (int)branch_len, branch)) < 0)
2437 			break;
2438 
2439 		if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0) {
2440 			if (error != GIT_ENOTFOUND)
2441 				break;
2442 			git_error_clear();
2443 		}
2444 	}
2445 
2446 	if (error == GIT_ITEROVER)
2447 		error = 0;
2448 
2449 	git_buf_dispose(&buf);
2450 	git_config_iterator_free(iter);
2451 	return error;
2452 }
2453 
remove_refs(git_repository * repo,const git_refspec * spec)2454 static int remove_refs(git_repository *repo, const git_refspec *spec)
2455 {
2456 	git_reference_iterator *iter = NULL;
2457 	git_vector refs;
2458 	const char *name;
2459 	char *dup;
2460 	int error;
2461 	size_t i;
2462 
2463 	if ((error = git_vector_init(&refs, 8, NULL)) < 0)
2464 		return error;
2465 
2466 	if ((error = git_reference_iterator_new(&iter, repo)) < 0)
2467 		goto cleanup;
2468 
2469 	while ((error = git_reference_next_name(&name, iter)) == 0) {
2470 		if (!git_refspec_dst_matches(spec, name))
2471 			continue;
2472 
2473 		dup = git__strdup(name);
2474 		if (!dup) {
2475 			error = -1;
2476 			goto cleanup;
2477 		}
2478 
2479 		if ((error = git_vector_insert(&refs, dup)) < 0)
2480 			goto cleanup;
2481 	}
2482 	if (error == GIT_ITEROVER)
2483 		error = 0;
2484 	if (error < 0)
2485 		goto cleanup;
2486 
2487 	git_vector_foreach(&refs, i, name) {
2488 		if ((error = git_reference_remove(repo, name)) < 0)
2489 			break;
2490 	}
2491 
2492 cleanup:
2493 	git_reference_iterator_free(iter);
2494 	git_vector_foreach(&refs, i, dup) {
2495 		git__free(dup);
2496 	}
2497 	git_vector_free(&refs);
2498 	return error;
2499 }
2500 
remove_remote_tracking(git_repository * repo,const char * remote_name)2501 static int remove_remote_tracking(git_repository *repo, const char *remote_name)
2502 {
2503 	git_remote *remote;
2504 	int error;
2505 	size_t i, count;
2506 
2507 	/* we want to use what's on the config, regardless of changes to the instance in memory */
2508 	if ((error = git_remote_lookup(&remote, repo, remote_name)) < 0)
2509 		return error;
2510 
2511 	count = git_remote_refspec_count(remote);
2512 	for (i = 0; i < count; i++) {
2513 		const git_refspec *refspec = git_remote_get_refspec(remote, i);
2514 
2515 		/* shouldn't ever actually happen */
2516 		if (refspec == NULL)
2517 			continue;
2518 
2519 		if ((error = remove_refs(repo, refspec)) < 0)
2520 			break;
2521 	}
2522 
2523 	git_remote_free(remote);
2524 	return error;
2525 }
2526 
git_remote_delete(git_repository * repo,const char * name)2527 int git_remote_delete(git_repository *repo, const char *name)
2528 {
2529 	int error;
2530 
2531 	GIT_ASSERT_ARG(repo);
2532 	GIT_ASSERT_ARG(name);
2533 
2534 	if ((error = remove_branch_config_related_entries(repo, name)) < 0 ||
2535 	    (error = remove_remote_tracking(repo, name)) < 0 ||
2536 	    (error = rename_remote_config_section(repo, name, NULL)) < 0)
2537 		return error;
2538 
2539 	return 0;
2540 }
2541 
git_remote_default_branch(git_buf * out,git_remote * remote)2542 int git_remote_default_branch(git_buf *out, git_remote *remote)
2543 {
2544 	const git_remote_head **heads;
2545 	const git_remote_head *guess = NULL;
2546 	const git_oid *head_id;
2547 	size_t heads_len, i;
2548 	git_buf local_default = GIT_BUF_INIT;
2549 	int error;
2550 
2551 	GIT_ASSERT_ARG(out);
2552 
2553 	if ((error = git_remote_ls(&heads, &heads_len, remote)) < 0)
2554 		goto done;
2555 
2556 	if (heads_len == 0 || strcmp(heads[0]->name, GIT_HEAD_FILE)) {
2557 		error = GIT_ENOTFOUND;
2558 		goto done;
2559 	}
2560 
2561 	if ((error = git_buf_sanitize(out)) < 0)
2562 		return error;
2563 
2564 	/* the first one must be HEAD so if that has the symref info, we're done */
2565 	if (heads[0]->symref_target) {
2566 		error = git_buf_puts(out, heads[0]->symref_target);
2567 		goto done;
2568 	}
2569 
2570 	/*
2571 	 * If there's no symref information, we have to look over them
2572 	 * and guess. We return the first match unless the default
2573 	 * branch is a candidate. Then we return the default branch.
2574 	 */
2575 
2576 	if ((error = git_repository_initialbranch(&local_default, remote->repo)) < 0)
2577 		goto done;
2578 
2579 	head_id = &heads[0]->oid;
2580 
2581 	for (i = 1; i < heads_len; i++) {
2582 		if (git_oid_cmp(head_id, &heads[i]->oid))
2583 			continue;
2584 
2585 		if (git__prefixcmp(heads[i]->name, GIT_REFS_HEADS_DIR))
2586 			continue;
2587 
2588 		if (!guess) {
2589 			guess = heads[i];
2590 			continue;
2591 		}
2592 
2593 		if (!git__strcmp(local_default.ptr, heads[i]->name)) {
2594 			guess = heads[i];
2595 			break;
2596 		}
2597 	}
2598 
2599 	if (!guess) {
2600 		error = GIT_ENOTFOUND;
2601 		goto done;
2602 	}
2603 
2604 	error = git_buf_puts(out, guess->name);
2605 
2606 done:
2607 	git_buf_dispose(&local_default);
2608 	return error;
2609 }
2610 
git_remote_upload(git_remote * remote,const git_strarray * refspecs,const git_push_options * opts)2611 int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts)
2612 {
2613 	size_t i;
2614 	int error;
2615 	git_push *push;
2616 	git_refspec *spec;
2617 	const git_remote_callbacks *cbs = NULL;
2618 	git_remote_connection_opts conn = GIT_REMOTE_CONNECTION_OPTIONS_INIT;
2619 
2620 	GIT_ASSERT_ARG(remote);
2621 
2622 	if (!remote->repo) {
2623 		git_error_set(GIT_ERROR_INVALID, "cannot download detached remote");
2624 		return -1;
2625 	}
2626 
2627 	if (opts) {
2628 		cbs = &opts->callbacks;
2629 		conn.custom_headers = &opts->custom_headers;
2630 		conn.proxy = &opts->proxy_opts;
2631 	}
2632 
2633 	if (!git_remote_connected(remote) &&
2634 	    (error = git_remote__connect(remote, GIT_DIRECTION_PUSH, cbs, &conn)) < 0)
2635 		goto cleanup;
2636 
2637 	free_refspecs(&remote->active_refspecs);
2638 	if ((error = dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs)) < 0)
2639 		goto cleanup;
2640 
2641 	if (remote->push) {
2642 		git_push_free(remote->push);
2643 		remote->push = NULL;
2644 	}
2645 
2646 	if ((error = git_push_new(&remote->push, remote)) < 0)
2647 		return error;
2648 
2649 	push = remote->push;
2650 
2651 	if (opts && (error = git_push_set_options(push, opts)) < 0)
2652 		goto cleanup;
2653 
2654 	if (refspecs && refspecs->count > 0) {
2655 		for (i = 0; i < refspecs->count; i++) {
2656 			if ((error = git_push_add_refspec(push, refspecs->strings[i])) < 0)
2657 				goto cleanup;
2658 		}
2659 	} else {
2660 		git_vector_foreach(&remote->refspecs, i, spec) {
2661 			if (!spec->push)
2662 				continue;
2663 			if ((error = git_push_add_refspec(push, spec->string)) < 0)
2664 				goto cleanup;
2665 		}
2666 	}
2667 
2668 	if ((error = git_push_finish(push, cbs)) < 0)
2669 		goto cleanup;
2670 
2671 	if (cbs && cbs->push_update_reference &&
2672 	    (error = git_push_status_foreach(push, cbs->push_update_reference, cbs->payload)) < 0)
2673 		goto cleanup;
2674 
2675 cleanup:
2676 	return error;
2677 }
2678 
git_remote_push(git_remote * remote,const git_strarray * refspecs,const git_push_options * opts)2679 int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts)
2680 {
2681 	int error;
2682 	const git_remote_callbacks *cbs = NULL;
2683 	const git_strarray *custom_headers = NULL;
2684 	const git_proxy_options *proxy = NULL;
2685 
2686 	GIT_ASSERT_ARG(remote);
2687 
2688 	if (!remote->repo) {
2689 		git_error_set(GIT_ERROR_INVALID, "cannot download detached remote");
2690 		return -1;
2691 	}
2692 
2693 	if (opts) {
2694 		GIT_ERROR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
2695 		cbs = &opts->callbacks;
2696 		custom_headers = &opts->custom_headers;
2697 		GIT_ERROR_CHECK_VERSION(&opts->proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
2698 		proxy = &opts->proxy_opts;
2699 	}
2700 
2701 	if ((error = git_remote_connect(remote, GIT_DIRECTION_PUSH, cbs, proxy, custom_headers)) < 0)
2702 		return error;
2703 
2704 	if ((error = git_remote_upload(remote, refspecs, opts)) < 0)
2705 		return error;
2706 
2707 	error = git_remote_update_tips(remote, cbs, 0, 0, NULL);
2708 
2709 	git_remote_disconnect(remote);
2710 	return error;
2711 }
2712 
2713 #define PREFIX "url"
2714 #define SUFFIX_FETCH "insteadof"
2715 #define SUFFIX_PUSH "pushinsteadof"
2716 
apply_insteadof(git_config * config,const char * url,int direction)2717 char *apply_insteadof(git_config *config, const char *url, int direction)
2718 {
2719 	size_t match_length, prefix_length, suffix_length;
2720 	char *replacement = NULL;
2721 	const char *regexp;
2722 
2723 	git_buf result = GIT_BUF_INIT;
2724 	git_config_entry *entry;
2725 	git_config_iterator *iter;
2726 
2727 	GIT_ASSERT_ARG_WITH_RETVAL(config, NULL);
2728 	GIT_ASSERT_ARG_WITH_RETVAL(url, NULL);
2729 	GIT_ASSERT_ARG_WITH_RETVAL(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH, NULL);
2730 
2731 	/* Add 1 to prefix/suffix length due to the additional escaped dot */
2732 	prefix_length = strlen(PREFIX) + 1;
2733 	if (direction == GIT_DIRECTION_FETCH) {
2734 		regexp = PREFIX "\\..*\\." SUFFIX_FETCH;
2735 		suffix_length = strlen(SUFFIX_FETCH) + 1;
2736 	} else {
2737 		regexp = PREFIX "\\..*\\." SUFFIX_PUSH;
2738 		suffix_length = strlen(SUFFIX_PUSH) + 1;
2739 	}
2740 
2741 	if (git_config_iterator_glob_new(&iter, config, regexp) < 0)
2742 		return NULL;
2743 
2744 	match_length = 0;
2745 	while (git_config_next(&entry, iter) == 0) {
2746 		size_t n, replacement_length;
2747 
2748 		/* Check if entry value is a prefix of URL */
2749 		if (git__prefixcmp(url, entry->value))
2750 			continue;
2751 		/* Check if entry value is longer than previous
2752 		 * prefixes */
2753 		if ((n = strlen(entry->value)) <= match_length)
2754 			continue;
2755 
2756 		git__free(replacement);
2757 		match_length = n;
2758 
2759 		/* Cut off prefix and suffix of the value */
2760 		replacement_length =
2761 		    strlen(entry->name) - (prefix_length + suffix_length);
2762 		replacement = git__strndup(entry->name + prefix_length,
2763 				replacement_length);
2764 	}
2765 
2766 	git_config_iterator_free(iter);
2767 
2768 	if (match_length == 0)
2769 		return git__strdup(url);
2770 
2771 	git_buf_printf(&result, "%s%s", replacement, url + match_length);
2772 
2773 	git__free(replacement);
2774 
2775 	return result.ptr;
2776 }
2777 
2778 /* Deprecated functions */
2779 
2780 #ifndef GIT_DEPRECATE_HARD
2781 
git_remote_is_valid_name(const char * remote_name)2782 int git_remote_is_valid_name(const char *remote_name)
2783 {
2784 	int valid = 0;
2785 
2786 	git_remote_name_is_valid(&valid, remote_name);
2787 	return valid;
2788 }
2789 
2790 #endif
2791