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