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