2 * Copyright (C) the libgit2 contributors. All rights reserved.
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.
10 #include "git2/config.h"
11 #include "git2/types.h"
16 #include "repository.h"
20 #include "fetchhead.h"
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"
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
);
33 static int add_refspec_to(git_vector
*vector
, const char *string
, bool is_fetch
)
37 spec
= git__calloc(1, sizeof(git_refspec
));
38 GITERR_CHECK_ALLOC(spec
);
40 if (git_refspec__parse(spec
, string
, is_fetch
) < 0) {
45 spec
->push
= !is_fetch
;
46 if (git_vector_insert(vector
, spec
) < 0) {
47 git_refspec__free(spec
);
55 static int add_refspec(git_remote
*remote
, const char *string
, bool is_fetch
)
57 return add_refspec_to(&remote
->refspecs
, string
, is_fetch
);
60 static int download_tags_value(git_remote
*remote
, git_config
*cfg
)
63 git_buf buf
= GIT_BUF_INIT
;
66 if (git_buf_printf(&buf
, "remote.%s.tagopt", remote
->name
) < 0)
69 error
= git_config__lookup_entry(&ce
, cfg
, git_buf_cstr(&buf
), false);
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
;
79 git_config_entry_free(ce
);
83 static int ensure_remote_name_is_valid(const char *name
)
87 if (!git_remote_is_valid_name(name
)) {
90 "'%s' is not a valid remote name.", name
? name
: "(null)");
91 error
= GIT_EINVALIDSPEC
;
97 static int write_add_refspec(git_repository
*repo
, const char *name
, const char *refspec
, bool fetch
)
100 git_buf var
= GIT_BUF_INIT
;
105 if ((error
= git_repository_config__weakptr(&cfg
, repo
)) < 0)
108 fmt
= fetch
? CONFIG_FETCH_FMT
: CONFIG_PUSH_FMT
;
110 if ((error
= ensure_remote_name_is_valid(name
)) < 0)
113 if ((error
= git_refspec__parse(&spec
, refspec
, fetch
)) < 0) {
114 if (giterr_last()->klass
!= GITERR_NOMEMORY
)
115 error
= GIT_EINVALIDSPEC
;
120 git_refspec__free(&spec
);
122 if ((error
= git_buf_printf(&var
, fmt
, name
)) < 0)
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
130 if ((error
= git_config_set_multivar(cfg
, var
.ptr
, "$^", refspec
)) < 0) {
140 /* We could export this as a helper */
141 static int get_check_cert(int *out
, git_repository
*repo
)
149 /* By default, we *DO* want to verify the certificate. */
152 /* Go through the possible sources for SSL verification settings, from
153 * most specific to least specific. */
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
);
159 /* http.sslVerify config setting */
160 if ((error
= git_repository_config__weakptr(&cfg
, repo
)) < 0)
163 *out
= git_config__get_bool_force(cfg
, "http.sslverify", 1);
168 static int canonicalize_url(git_buf
*out
, const char *in
)
170 if (in
== NULL
|| strlen(in
) == 0) {
171 giterr_set(GITERR_INVALID
, "cannot set empty URL");
172 return GIT_EINVALIDSPEC
;
176 /* Given a UNC path like \\server\path, we need to convert this
177 * to //server/path for compatibility with core git.
179 if (in
[0] == '\\' && in
[1] == '\\' &&
180 (git__isalpha(in
[2]) || git__isdigit(in
[2]))) {
182 for (c
= in
; *c
; c
++)
183 git_buf_putc(out
, *c
== '\\' ? '/' : *c
);
185 return git_buf_oom(out
) ? -1 : 0;
189 return git_buf_puts(out
, in
);
192 static int create_internal(git_remote
**out
, git_repository
*repo
, const char *name
, const char *url
, const char *fetch
)
195 git_config
*config_ro
= NULL
, *config_rw
;
196 git_buf canonical_url
= GIT_BUF_INIT
;
197 git_buf var
= GIT_BUF_INIT
;
200 /* repo, name, and fetch are optional */
203 if (repo
&& (error
= git_repository_config_snapshot(&config_ro
, repo
)) < 0)
206 remote
= git__calloc(1, sizeof(git_remote
));
207 GITERR_CHECK_ALLOC(remote
);
211 if ((error
= git_vector_init(&remote
->refs
, 32, NULL
)) < 0 ||
212 (error
= canonicalize_url(&canonical_url
, url
)) < 0)
216 remote
->url
= apply_insteadof(config_ro
, canonical_url
.ptr
, GIT_DIRECTION_FETCH
);
218 remote
->url
= git__strdup(canonical_url
.ptr
);
220 GITERR_CHECK_ALLOC(remote
->url
);
223 remote
->name
= git__strdup(name
);
224 GITERR_CHECK_ALLOC(remote
->name
);
226 if ((error
= git_buf_printf(&var
, CONFIG_URL_FMT
, name
)) < 0)
230 ((error
= git_repository_config__weakptr(&config_rw
, repo
)) < 0 ||
231 (error
= git_config_set_string(config_rw
, var
.ptr
, canonical_url
.ptr
)) < 0))
236 if ((error
= add_refspec(remote
, fetch
, true)) < 0)
239 /* only write for non-anonymous remotes */
240 if (name
&& (error
= write_add_refspec(repo
, name
, fetch
, true)) < 0)
243 if (repo
&& (error
= lookup_remote_prune_config(remote
, config_ro
, name
)) < 0)
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)
251 /* A remote without a name doesn't download tags */
253 remote
->download_tags
= GIT_REMOTE_DOWNLOAD_TAGS_NONE
;
255 remote
->download_tags
= GIT_REMOTE_DOWNLOAD_TAGS_AUTO
;
265 git_remote_free(remote
);
267 git_config_free(config_ro
);
268 git_buf_free(&canonical_url
);
273 static int ensure_remote_doesnot_exist(git_repository
*repo
, const char *name
)
278 error
= git_remote_lookup(&remote
, repo
, name
);
280 if (error
== GIT_ENOTFOUND
)
286 git_remote_free(remote
);
290 "remote '%s' already exists", name
);
296 int git_remote_create(git_remote
**out
, git_repository
*repo
, const char *name
, const char *url
)
298 git_buf buf
= GIT_BUF_INIT
;
301 if (git_buf_printf(&buf
, "+refs/heads/*:refs/remotes/%s/*", name
) < 0)
304 error
= git_remote_create_with_fetchspec(out
, repo
, name
, url
, git_buf_cstr(&buf
));
310 int git_remote_create_with_fetchspec(git_remote
**out
, git_repository
*repo
, const char *name
, const char *url
, const char *fetch
)
312 git_remote
*remote
= NULL
;
315 if ((error
= ensure_remote_name_is_valid(name
)) < 0)
318 if ((error
= ensure_remote_doesnot_exist(repo
, name
)) < 0)
321 if (create_internal(&remote
, repo
, name
, url
, fetch
) < 0)
329 git_remote_free(remote
);
333 int git_remote_create_anonymous(git_remote
**out
, git_repository
*repo
, const char *url
)
335 return create_internal(out
, repo
, NULL
, url
, NULL
);
338 int git_remote_create_detached(git_remote
**out
, const char *url
)
340 return create_internal(out
, NULL
, NULL
, url
, NULL
);
343 int git_remote_dup(git_remote
**dest
, git_remote
*source
)
348 git_remote
*remote
= git__calloc(1, sizeof(git_remote
));
349 GITERR_CHECK_ALLOC(remote
);
351 if (source
->name
!= NULL
) {
352 remote
->name
= git__strdup(source
->name
);
353 GITERR_CHECK_ALLOC(remote
->name
);
356 if (source
->url
!= NULL
) {
357 remote
->url
= git__strdup(source
->url
);
358 GITERR_CHECK_ALLOC(remote
->url
);
361 if (source
->pushurl
!= NULL
) {
362 remote
->pushurl
= git__strdup(source
->pushurl
);
363 GITERR_CHECK_ALLOC(remote
->pushurl
);
366 remote
->repo
= source
->repo
;
367 remote
->download_tags
= source
->download_tags
;
368 remote
->prune_refs
= source
->prune_refs
;
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) {
377 git_vector_foreach(&source
->refspecs
, i
, spec
) {
378 if ((error
= add_refspec(remote
, spec
->string
, !spec
->push
)) < 0)
392 struct refspec_cb_data
{
397 static int refspec_cb(const git_config_entry
*entry
, void *payload
)
399 struct refspec_cb_data
*data
= (struct refspec_cb_data
*)payload
;
400 return add_refspec(data
->remote
, entry
->value
, data
->fetch
);
403 static int get_optional_config(
404 bool *found
, git_config
*config
, git_buf
*buf
,
405 git_config_foreach_cb cb
, void *payload
)
408 const char *key
= git_buf_cstr(buf
);
410 if (git_buf_oom(buf
))
414 error
= git_config_get_multivar_foreach(config
, key
, NULL
, cb
, payload
);
416 error
= git_config_get_string(payload
, config
, key
);
421 if (error
== GIT_ENOTFOUND
) {
429 int git_remote_lookup(git_remote
**out
, git_repository
*repo
, const char *name
)
432 git_buf buf
= GIT_BUF_INIT
;
436 struct refspec_cb_data data
= { NULL
};
437 bool optional_setting_found
= false, found
;
439 assert(out
&& repo
&& name
);
441 if ((error
= ensure_remote_name_is_valid(name
)) < 0)
444 if ((error
= git_repository_config_snapshot(&config
, repo
)) < 0)
447 remote
= git__calloc(1, sizeof(git_remote
));
448 GITERR_CHECK_ALLOC(remote
);
450 remote
->name
= git__strdup(name
);
451 GITERR_CHECK_ALLOC(remote
->name
);
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) {
461 if ((error
= git_buf_printf(&buf
, "remote.%s.url", name
)) < 0)
464 if ((error
= get_optional_config(&found
, config
, &buf
, NULL
, (void *)&val
)) < 0)
467 optional_setting_found
|= found
;
470 remote
->download_tags
= GIT_REMOTE_DOWNLOAD_TAGS_AUTO
;
472 if (found
&& strlen(val
) > 0) {
473 remote
->url
= apply_insteadof(config
, val
, GIT_DIRECTION_FETCH
);
474 GITERR_CHECK_ALLOC(remote
->url
);
479 git_buf_printf(&buf
, "remote.%s.pushurl", name
);
481 if ((error
= get_optional_config(&found
, config
, &buf
, NULL
, (void *)&val
)) < 0)
484 optional_setting_found
|= found
;
486 if (!optional_setting_found
) {
487 error
= GIT_ENOTFOUND
;
488 giterr_set(GITERR_CONFIG
, "remote '%s' does not exist", name
);
492 if (found
&& strlen(val
) > 0) {
493 remote
->pushurl
= apply_insteadof(config
, val
, GIT_DIRECTION_PUSH
);
494 GITERR_CHECK_ALLOC(remote
->pushurl
);
497 data
.remote
= remote
;
501 git_buf_printf(&buf
, "remote.%s.fetch", name
);
503 if ((error
= get_optional_config(NULL
, config
, &buf
, refspec_cb
, &data
)) < 0)
508 git_buf_printf(&buf
, "remote.%s.push", name
);
510 if ((error
= get_optional_config(NULL
, config
, &buf
, refspec_cb
, &data
)) < 0)
513 if (download_tags_value(remote
, config
) < 0)
516 if ((error
= lookup_remote_prune_config(remote
, config
, name
)) < 0)
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)
526 git_config_free(config
);
530 git_remote_free(remote
);
535 static int lookup_remote_prune_config(git_remote
*remote
, git_config
*config
, const char *name
)
537 git_buf buf
= GIT_BUF_INIT
;
540 git_buf_printf(&buf
, "remote.%s.prune", name
);
542 if ((error
= git_config_get_bool(&remote
->prune_refs
, config
, git_buf_cstr(&buf
))) < 0) {
543 if (error
== GIT_ENOTFOUND
) {
546 if ((error
= git_config_get_bool(&remote
->prune_refs
, config
, "fetch.prune")) < 0) {
547 if (error
== GIT_ENOTFOUND
) {
559 const char *git_remote_name(const git_remote
*remote
)
565 git_repository
*git_remote_owner(const git_remote
*remote
)
571 const char *git_remote_url(const git_remote
*remote
)
577 static int set_url(git_repository
*repo
, const char *remote
, const char *pattern
, const char *url
)
580 git_buf buf
= GIT_BUF_INIT
, canonical_url
= GIT_BUF_INIT
;
583 assert(repo
&& remote
);
585 if ((error
= ensure_remote_name_is_valid(remote
)) < 0)
588 if ((error
= git_repository_config__weakptr(&cfg
, repo
)) < 0)
591 if ((error
= git_buf_printf(&buf
, pattern
, remote
)) < 0)
595 if ((error
= canonicalize_url(&canonical_url
, url
)) < 0)
598 error
= git_config_set_string(cfg
, buf
.ptr
, url
);
600 error
= git_config_delete_entry(cfg
, buf
.ptr
);
604 git_buf_free(&canonical_url
);
610 int git_remote_set_url(git_repository
*repo
, const char *remote
, const char *url
)
612 return set_url(repo
, remote
, CONFIG_URL_FMT
, url
);
615 const char *git_remote_pushurl(const git_remote
*remote
)
618 return remote
->pushurl
;
621 int git_remote_set_pushurl(git_repository
*repo
, const char *remote
, const char* url
)
623 return set_url(repo
, remote
, CONFIG_PUSHURL_FMT
, url
);
626 const char* git_remote__urlfordirection(git_remote
*remote
, int direction
)
630 assert(direction
== GIT_DIRECTION_FETCH
|| direction
== GIT_DIRECTION_PUSH
);
632 if (direction
== GIT_DIRECTION_FETCH
) {
636 if (direction
== GIT_DIRECTION_PUSH
) {
637 return remote
->pushurl
? remote
->pushurl
: remote
->url
;
643 int set_transport_callbacks(git_transport
*t
, const git_remote_callbacks
*cbs
)
645 if (!t
->set_callbacks
|| !cbs
)
648 return t
->set_callbacks(t
, cbs
->sideband_progress
, NULL
,
649 cbs
->certificate_check
, cbs
->payload
);
652 static int set_transport_custom_headers(git_transport
*t
, const git_strarray
*custom_headers
)
654 if (!t
->set_custom_headers
)
657 return t
->set_custom_headers(t
, custom_headers
);
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
)
664 int flags
= GIT_TRANSPORTFLAGS_NONE
;
666 void *payload
= NULL
;
667 git_cred_acquire_cb credentials
= NULL
;
668 git_transport_cb transport
= NULL
;
673 GITERR_CHECK_VERSION(callbacks
, GIT_REMOTE_CALLBACKS_VERSION
, "git_remote_callbacks");
674 credentials
= callbacks
->credentials
;
675 transport
= callbacks
->transport
;
676 payload
= callbacks
->payload
;
680 GITERR_CHECK_VERSION(proxy
, GIT_PROXY_OPTIONS_VERSION
, "git_proxy_options");
682 t
= remote
->transport
;
684 url
= git_remote__urlfordirection(remote
, direction
);
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");
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)
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)
704 if ((error
= set_transport_custom_headers(t
, custom_headers
)) != 0)
707 if ((error
= set_transport_callbacks(t
, callbacks
)) < 0 ||
708 (error
= t
->connect(t
, url
, credentials
, payload
, proxy
, direction
, flags
)) != 0)
711 remote
->transport
= t
;
718 if (t
== remote
->transport
)
719 remote
->transport
= NULL
;
724 int git_remote_ls(const git_remote_head
***out
, size_t *size
, git_remote
*remote
)
728 if (!remote
->transport
) {
729 giterr_set(GITERR_NET
, "this remote has never connected");
733 return remote
->transport
->ls(out
, size
, remote
->transport
);
736 int git_remote__get_http_proxy(git_remote
*remote
, bool use_ssl
, char **proxy_url
)
739 git_config_entry
*ce
= NULL
;
740 git_buf val
= GIT_BUF_INIT
;
745 if (!proxy_url
|| !remote
->repo
)
750 if ((error
= git_repository_config__weakptr(&cfg
, remote
->repo
)) < 0)
753 /* Go through the possible sources for proxy configuration, from most specific
754 * to least specific. */
756 /* remote.<name>.proxy config setting */
757 if (remote
->name
&& remote
->name
[0]) {
758 git_buf buf
= GIT_BUF_INIT
;
760 if ((error
= git_buf_printf(&buf
, "remote.%s.proxy", remote
->name
)) < 0)
763 error
= git_config__lookup_entry(&ce
, cfg
, git_buf_cstr(&buf
), false);
769 if (ce
&& ce
->value
) {
770 *proxy_url
= git__strdup(ce
->value
);
775 /* http.proxy config setting */
776 if ((error
= git_config__lookup_entry(&ce
, cfg
, "http.proxy", false)) < 0)
779 if (ce
&& ce
->value
) {
780 *proxy_url
= git__strdup(ce
->value
);
784 /* http_proxy / https_proxy environment variables */
785 error
= git__getenv(&val
, use_ssl
? "https_proxy" : "http_proxy");
787 /* try uppercase environment variables */
788 if (error
== GIT_ENOTFOUND
)
789 error
= git__getenv(&val
, use_ssl
? "HTTPS_PROXY" : "HTTP_PROXY");
792 if (error
== GIT_ENOTFOUND
) {
800 *proxy_url
= git_buf_detach(&val
);
803 GITERR_CHECK_ALLOC(*proxy_url
);
804 git_config_entry_free(ce
);
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
)
815 git_vector_foreach(refspecs
, i
, spec
) {
816 if (git_refspec__dwim_one(out
, spec
, refs
) < 0)
823 static void free_refspecs(git_vector
*vec
)
828 git_vector_foreach(vec
, i
, spec
) {
829 git_refspec__free(spec
);
833 git_vector_clear(vec
);
836 static int remote_head_cmp(const void *_a
, const void *_b
)
838 const git_remote_head
*a
= (git_remote_head
*) _a
;
839 const git_remote_head
*b
= (git_remote_head
*) _b
;
841 return git__strcmp_cb(a
->name
, b
->name
);
844 static int ls_to_vector(git_vector
*out
, git_remote
*remote
)
846 git_remote_head
**heads
;
849 if (git_remote_ls((const git_remote_head
***)&heads
, &heads_len
, remote
) < 0)
852 if (git_vector_init(out
, heads_len
, remote_head_cmp
) < 0)
855 for (i
= 0; i
< heads_len
; i
++) {
856 if (git_vector_insert(out
, heads
[i
]) < 0)
863 int git_remote_download(git_remote
*remote
, const git_strarray
*refspecs
, const git_fetch_options
*opts
)
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
;
875 giterr_set(GITERR_INVALID
, "cannot download detached remote");
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
;
887 if (!git_remote_connected(remote
) &&
888 (error
= git_remote_connect(remote
, GIT_DIRECTION_FETCH
, cbs
, proxy
, custom_headers
)) < 0)
891 if (ls_to_vector(&refs
, remote
) < 0)
894 if ((git_vector_init(&specs
, 0, NULL
)) < 0)
897 remote
->passed_refspecs
= 0;
898 if (!refspecs
|| !refspecs
->count
) {
899 to_active
= &remote
->refspecs
;
901 for (i
= 0; i
< refspecs
->count
; i
++) {
902 if ((error
= add_refspec_to(&specs
, refspecs
->strings
[i
], true)) < 0)
907 remote
->passed_refspecs
= 1;
910 free_refspecs(&remote
->passive_refspecs
);
911 if ((error
= dwim_refspecs(&remote
->passive_refspecs
, &remote
->refspecs
, &refs
)) < 0)
914 free_refspecs(&remote
->active_refspecs
);
915 error
= dwim_refspecs(&remote
->active_refspecs
, to_active
, &refs
);
917 git_vector_free(&refs
);
918 free_refspecs(&specs
);
919 git_vector_free(&specs
);
925 git_push_free(remote
->push
);
929 if ((error
= git_fetch_negotiate(remote
, opts
)) < 0)
932 return git_fetch_download_pack(remote
, cbs
);
935 git_vector_free(&refs
);
936 free_refspecs(&specs
);
937 git_vector_free(&specs
);
941 int git_remote_fetch(
943 const git_strarray
*refspecs
,
944 const git_fetch_options
*opts
,
945 const char *reflog_message
)
947 int error
, update_fetchhead
= 1;
948 git_remote_autotag_option_t tagopt
= remote
->download_tags
;
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
;
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
;
965 /* Connect and download everything */
966 if ((error
= git_remote_connect(remote
, GIT_DIRECTION_FETCH
, cbs
, proxy
, custom_headers
)) != 0)
969 error
= git_remote_download(remote
, refspecs
, opts
);
971 /* We don't need to be connected anymore */
972 git_remote_disconnect(remote
);
974 /* If the download failed, return the error */
978 /* Default reflog message */
980 git_buf_sets(&reflog_msg_buf
, reflog_message
);
982 git_buf_printf(&reflog_msg_buf
, "fetch %s",
983 remote
->name
? remote
->name
: remote
->url
);
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
);
992 if (opts
&& opts
->prune
== GIT_FETCH_PRUNE
)
994 else if (opts
&& opts
->prune
== GIT_FETCH_PRUNE_UNSPECIFIED
&& remote
->prune_refs
)
996 else if (opts
&& opts
->prune
== GIT_FETCH_NO_PRUNE
)
999 prune
= remote
->prune_refs
;
1002 error
= git_remote_prune(remote
, cbs
);
1007 static int remote_head_for_fetchspec_src(git_remote_head
**out
, git_vector
*update_heads
, const char *fetchspec_src
)
1010 git_remote_head
*remote_ref
;
1012 assert(update_heads
&& fetchspec_src
);
1016 git_vector_foreach(update_heads
, i
, remote_ref
) {
1017 if (strcmp(remote_ref
->name
, fetchspec_src
) == 0) {
1026 static int ref_to_update(int *update
, git_buf
*remote_name
, git_remote
*remote
, git_refspec
*spec
, const char *ref_name
)
1029 git_repository
*repo
;
1030 git_buf upstream_remote
= GIT_BUF_INIT
;
1031 git_buf upstream_name
= GIT_BUF_INIT
;
1033 repo
= git_remote_owner(remote
);
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
) {
1053 git_buf_free(&upstream_remote
);
1054 git_buf_free(&upstream_name
);
1058 static int remote_head_for_ref(git_remote_head
**out
, git_remote
*remote
, git_refspec
*spec
, git_vector
*update_heads
, git_reference
*ref
)
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
;
1066 assert(out
&& spec
&& ref
);
1070 error
= git_reference_resolve(&resolved_ref
, ref
);
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
);
1077 ref_name
= git_reference_name(resolved_ref
);
1080 if ((error
= ref_to_update(&update
, &remote_name
, remote
, spec
, ref_name
)) < 0)
1084 error
= remote_head_for_fetchspec_src(out
, update_heads
, git_buf_cstr(&remote_name
));
1087 git_buf_free(&remote_name
);
1088 git_reference_free(resolved_ref
);
1089 git_config_free(config
);
1093 static int git_remote_write_fetchhead(git_remote
*remote
, git_refspec
*spec
, git_vector
*update_heads
)
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
;
1105 /* no heads, nothing to do */
1106 if (update_heads
->length
== 0)
1109 if (git_vector_init(&fetchhead_refs
, update_heads
->length
, git_fetchhead_ref_cmp
) < 0)
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);
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)
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)
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
);
1130 if (!include_all_fetchheads
&&
1131 !git_refspec_src_matches(spec
, remote_ref
->name
) &&
1132 !merge_this_fetchhead
)
1135 if (git_fetchhead_ref_create(&fetchhead_ref
,
1137 merge_this_fetchhead
,
1139 git_remote_url(remote
)) < 0)
1142 if (git_vector_insert(&fetchhead_refs
, fetchhead_ref
) < 0)
1146 git_fetchhead_write(remote
->repo
, &fetchhead_refs
);
1149 for (i
= 0; i
< fetchhead_refs
.length
; ++i
)
1150 git_fetchhead_ref_free(fetchhead_refs
.contents
[i
]);
1152 git_vector_free(&fetchhead_refs
);
1153 git_reference_free(head_ref
);
1159 * Generate a list of candidates for pruning by getting a list of
1160 * references which match the rhs of an active refspec.
1162 static int prune_candidates(git_vector
*candidates
, git_remote
*remote
)
1164 git_strarray arr
= { 0 };
1168 if ((error
= git_reference_list(&arr
, remote
->repo
)) < 0)
1171 for (i
= 0; i
< arr
.count
; i
++) {
1172 const char *refname
= arr
.strings
[i
];
1175 if (!git_remote__matching_dst_refspec(remote
, refname
))
1178 refname_dup
= git__strdup(refname
);
1179 GITERR_CHECK_ALLOC(refname_dup
);
1181 if ((error
= git_vector_insert(candidates
, refname_dup
)) < 0)
1186 git_strarray_free(&arr
);
1190 static int find_head(const void *_a
, const void *_b
)
1192 git_remote_head
*a
= (git_remote_head
*) _a
;
1193 git_remote_head
*b
= (git_remote_head
*) _b
;
1195 return strcmp(a
->name
, b
->name
);
1198 int git_remote_prune(git_remote
*remote
, const git_remote_callbacks
*callbacks
)
1201 git_vector remote_refs
= GIT_VECTOR_INIT
;
1202 git_vector candidates
= GIT_VECTOR_INIT
;
1203 const git_refspec
*spec
;
1204 const char *refname
;
1206 git_oid zero_id
= {{ 0 }};
1209 GITERR_CHECK_VERSION(callbacks
, GIT_REMOTE_CALLBACKS_VERSION
, "git_remote_callbacks");
1211 if ((error
= ls_to_vector(&remote_refs
, remote
)) < 0)
1214 git_vector_set_cmp(&remote_refs
, find_head
);
1216 if ((error
= prune_candidates(&candidates
, remote
)) < 0)
1220 * Remove those entries from the candidate list for which we
1221 * can find a remote reference in at least one refspec.
1223 git_vector_foreach(&candidates
, i
, refname
) {
1224 git_vector_foreach(&remote
->active_refspecs
, j
, spec
) {
1225 git_buf buf
= GIT_BUF_INIT
;
1228 git_remote_head key
= {0};
1230 if (!git_refspec_dst_matches(spec
, refname
))
1233 if ((error
= git_refspec_rtransform(&buf
, spec
, refname
)) < 0)
1236 key
.name
= (char *) git_buf_cstr(&buf
);
1237 error
= git_vector_search(&pos
, &remote_refs
, &key
);
1240 if (error
< 0 && error
!= GIT_ENOTFOUND
)
1243 if (error
== GIT_ENOTFOUND
)
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)
1250 git__free(src_name
);
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.
1261 git_vector_foreach(&candidates
, i
, refname
) {
1265 if (refname
== NULL
)
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
)
1276 if (git_reference_type(ref
) == GIT_REF_SYMBOLIC
) {
1277 git_reference_free(ref
);
1281 git_oid_cpy(&id
, git_reference_target(ref
));
1282 error
= git_reference_delete(ref
);
1283 git_reference_free(ref
);
1287 if (callbacks
&& callbacks
->update_tips
)
1288 error
= callbacks
->update_tips(refname
, &id
, &zero_id
, callbacks
->payload
);
1295 git_vector_free(&remote_refs
);
1296 git_vector_free_deep(&candidates
);
1300 static int update_tips_for_spec(
1302 const git_remote_callbacks
*callbacks
,
1303 int update_fetchhead
,
1304 git_remote_autotag_option_t tagopt
,
1307 const char *log_message
)
1309 int error
= 0, autotag
;
1311 git_buf refname
= GIT_BUF_INIT
;
1314 git_remote_head
*head
;
1316 git_refspec tagspec
;
1317 git_vector update_heads
;
1321 if (git_repository_odb__weakptr(&odb
, remote
->repo
) < 0)
1324 if (git_refspec__parse(&tagspec
, GIT_REFSPEC_TAGS
, true) < 0)
1327 /* Make a copy of the transport's refs */
1328 if (git_vector_init(&update_heads
, 16, NULL
) < 0)
1331 for (; i
< refs
->length
; ++i
) {
1332 head
= git_vector_get(refs
, i
);
1334 git_buf_clear(&refname
);
1336 /* Ignore malformed ref names (which also saves us from tag^{} */
1337 if (!git_reference_is_valid_name(head
->name
))
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
) {
1344 if (tagopt
== GIT_REMOTE_DOWNLOAD_TAGS_AUTO
)
1347 git_buf_clear(&refname
);
1348 if (git_buf_puts(&refname
, head
->name
) < 0)
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
)) {
1356 if (git_refspec_transform(&refname
, spec
, head
->name
) < 0)
1360 * no rhs mans store it in FETCH_HEAD, even if we don't
1361 update anything else.
1363 if ((error
= git_vector_insert(&update_heads
, head
)) < 0)
1370 /* If we still don't have a refname, we don't want it */
1371 if (git_buf_len(&refname
) == 0) {
1375 /* In autotag mode, only create tags for objects already in db */
1376 if (autotag
&& !git_odb_exists(odb
, &head
->oid
))
1379 if (!autotag
&& git_vector_insert(&update_heads
, head
) < 0)
1382 error
= git_reference_name_to_id(&old
, remote
->repo
, refname
.ptr
);
1383 if (error
< 0 && error
!= GIT_ENOTFOUND
)
1386 if (error
== GIT_ENOTFOUND
) {
1387 memset(&old
, 0, GIT_OID_RAWSZ
);
1389 if (autotag
&& git_vector_insert(&update_heads
, head
) < 0)
1393 if (!git_oid__cmp(&old
, &head
->oid
))
1396 /* In autotag mode, don't overwrite any locally-existing tags */
1397 error
= git_reference_create(&ref
, remote
->repo
, refname
.ptr
, &head
->oid
, !autotag
,
1400 if (error
== GIT_EEXISTS
)
1406 git_reference_free(ref
);
1408 if (callbacks
&& callbacks
->update_tips
!= NULL
) {
1409 if (callbacks
->update_tips(refname
.ptr
, &old
, &head
->oid
, callbacks
->payload
) < 0)
1414 if (update_fetchhead
&&
1415 (error
= git_remote_write_fetchhead(remote
, spec
, &update_heads
)) < 0)
1418 git_vector_free(&update_heads
);
1419 git_refspec__free(&tagspec
);
1420 git_buf_free(&refname
);
1424 git_vector_free(&update_heads
);
1425 git_refspec__free(&tagspec
);
1426 git_buf_free(&refname
);
1432 * Iteration over the three vectors, with a pause whenever we find a match
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.
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
)
1442 const git_vector
*active
, *passive
;
1443 git_remote_head
*head
;
1444 git_refspec
*spec
, *passive_spec
;
1447 active
= &remote
->active_refspecs
;
1448 passive
= &remote
->passive_refspecs
;
1454 for (; i
< refs
->length
; i
++) {
1455 head
= git_vector_get(refs
, i
);
1457 if (!git_reference_is_valid_name(head
->name
))
1460 for (; j
< active
->length
; j
++) {
1461 spec
= git_vector_get(active
, j
);
1463 if (!git_refspec_src_matches(spec
, head
->name
))
1466 for (; k
< passive
->length
; k
++) {
1467 passive_spec
= git_vector_get(passive
, k
);
1469 if (!git_refspec_src_matches(passive_spec
, head
->name
))
1472 *out_spec
= passive_spec
;
1485 return GIT_ITEROVER
;
1488 static int opportunistic_updates(const git_remote
*remote
, const git_remote_callbacks
*callbacks
,
1489 git_vector
*refs
, const char *msg
)
1493 git_remote_head
*head
;
1495 git_buf refname
= GIT_BUF_INIT
;
1500 while ((error
= next_head(remote
, refs
, &spec
, &head
, &i
, &j
, &k
)) == 0) {
1501 git_oid old
= {{ 0 }};
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
1510 git_buf_clear(&refname
);
1511 if ((error
= git_refspec_transform(&refname
, spec
, head
->name
)) < 0)
1514 error
= git_reference_name_to_id(&old
, remote
->repo
, refname
.ptr
);
1515 if (error
< 0 && error
!= GIT_ENOTFOUND
)
1518 if (!git_oid_cmp(&old
, &head
->oid
))
1521 /* If we did find a current reference, make sure we haven't lost a race */
1523 error
= git_reference_create(&ref
, remote
->repo
, refname
.ptr
, &head
->oid
, true, msg
);
1525 error
= git_reference_create_matching(&ref
, remote
->repo
, refname
.ptr
, &head
->oid
, true, &old
, msg
);
1526 git_reference_free(ref
);
1530 if (callbacks
&& callbacks
->update_tips
!= NULL
) {
1531 if (callbacks
->update_tips(refname
.ptr
, &old
, &head
->oid
, callbacks
->payload
) < 0)
1536 if (error
== GIT_ITEROVER
)
1540 git_buf_free(&refname
);
1544 static int truncate_fetch_head(const char *gitdir
)
1546 git_buf path
= GIT_BUF_INIT
;
1549 if ((error
= git_buf_joinpath(&path
, gitdir
, GIT_FETCH_HEAD_FILE
)) < 0)
1552 error
= git_futils_truncate(path
.ptr
, GIT_REFS_FILE_MODE
);
1553 git_buf_free(&path
);
1558 int git_remote_update_tips(
1560 const git_remote_callbacks
*callbacks
,
1561 int update_fetchhead
,
1562 git_remote_autotag_option_t download_tags
,
1563 const char *reflog_message
)
1565 git_refspec
*spec
, tagspec
;
1566 git_vector refs
= GIT_VECTOR_INIT
;
1567 git_remote_autotag_option_t tagopt
;
1571 /* push has its own logic hidden away in the push object */
1573 return git_push_update_tips(remote
->push
, callbacks
);
1576 if (git_refspec__parse(&tagspec
, GIT_REFSPEC_TAGS
, true) < 0)
1580 if ((error
= ls_to_vector(&refs
, remote
)) < 0)
1583 if (download_tags
== GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED
)
1584 tagopt
= remote
->download_tags
;
1586 tagopt
= download_tags
;
1588 if ((error
= truncate_fetch_head(git_repository_path(remote
->repo
))) < 0)
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)
1596 git_vector_foreach(&remote
->active_refspecs
, i
, spec
) {
1600 if ((error
= update_tips_for_spec(remote
, callbacks
, update_fetchhead
, tagopt
, spec
, &refs
, reflog_message
)) < 0)
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
);
1609 git_vector_free(&refs
);
1610 git_refspec__free(&tagspec
);
1614 int git_remote_connected(const git_remote
*remote
)
1618 if (!remote
->transport
|| !remote
->transport
->is_connected
)
1621 /* Ask the transport if it's connected. */
1622 return remote
->transport
->is_connected(remote
->transport
);
1625 void git_remote_stop(git_remote
*remote
)
1629 if (remote
->transport
&& remote
->transport
->cancel
)
1630 remote
->transport
->cancel(remote
->transport
);
1633 void git_remote_disconnect(git_remote
*remote
)
1637 if (git_remote_connected(remote
))
1638 remote
->transport
->close(remote
->transport
);
1641 void git_remote_free(git_remote
*remote
)
1646 if (remote
->transport
!= NULL
) {
1647 git_remote_disconnect(remote
);
1649 remote
->transport
->free(remote
->transport
);
1650 remote
->transport
= NULL
;
1653 git_vector_free(&remote
->refs
);
1655 free_refspecs(&remote
->refspecs
);
1656 git_vector_free(&remote
->refspecs
);
1658 free_refspecs(&remote
->active_refspecs
);
1659 git_vector_free(&remote
->active_refspecs
);
1661 free_refspecs(&remote
->passive_refspecs
);
1662 git_vector_free(&remote
->passive_refspecs
);
1664 git_push_free(remote
->push
);
1665 git__free(remote
->url
);
1666 git__free(remote
->pushurl
);
1667 git__free(remote
->name
);
1671 static int remote_list_cb(const git_config_entry
*entry
, void *payload
)
1673 git_vector
*list
= payload
;
1674 const char *name
= entry
->name
+ strlen("remote.");
1675 size_t namelen
= strlen(name
);
1678 /* we know name matches "remote.<stuff>.(push)?url" */
1680 if (!strcmp(&name
[namelen
- 4], ".url"))
1681 remote_name
= git__strndup(name
, namelen
- 4); /* strip ".url" */
1683 remote_name
= git__strndup(name
, namelen
- 8); /* strip ".pushurl" */
1684 GITERR_CHECK_ALLOC(remote_name
);
1686 return git_vector_insert(list
, remote_name
);
1689 int git_remote_list(git_strarray
*remotes_list
, git_repository
*repo
)
1693 git_vector list
= GIT_VECTOR_INIT
;
1695 if ((error
= git_repository_config__weakptr(&cfg
, repo
)) < 0)
1698 if ((error
= git_vector_init(&list
, 4, git__strcmp_cb
)) < 0)
1701 error
= git_config_foreach_match(
1702 cfg
, "^remote\\..*\\.(push)?url$", remote_list_cb
, &list
);
1705 git_vector_free_deep(&list
);
1709 git_vector_uniq(&list
, git__free
);
1711 remotes_list
->strings
=
1712 (char **)git_vector_detach(&remotes_list
->count
, NULL
, &list
);
1717 const git_transfer_progress
* git_remote_stats(git_remote
*remote
)
1720 return &remote
->stats
;
1723 git_remote_autotag_option_t
git_remote_autotag(const git_remote
*remote
)
1725 return remote
->download_tags
;
1728 int git_remote_set_autotag(git_repository
*repo
, const char *remote
, git_remote_autotag_option_t value
)
1730 git_buf var
= GIT_BUF_INIT
;
1734 assert(repo
&& remote
);
1736 if ((error
= ensure_remote_name_is_valid(remote
)) < 0)
1739 if ((error
= git_repository_config__weakptr(&config
, repo
)) < 0)
1742 if ((error
= git_buf_printf(&var
, CONFIG_TAGOPT_FMT
, remote
)))
1746 case GIT_REMOTE_DOWNLOAD_TAGS_NONE
:
1747 error
= git_config_set_string(config
, var
.ptr
, "--no-tags");
1749 case GIT_REMOTE_DOWNLOAD_TAGS_ALL
:
1750 error
= git_config_set_string(config
, var
.ptr
, "--tags");
1752 case GIT_REMOTE_DOWNLOAD_TAGS_AUTO
:
1753 error
= git_config_delete_entry(config
, var
.ptr
);
1754 if (error
== GIT_ENOTFOUND
)
1758 giterr_set(GITERR_INVALID
, "invalid value for the tagopt setting");
1766 int git_remote_prune_refs(const git_remote
*remote
)
1768 return remote
->prune_refs
;
1771 static int rename_remote_config_section(
1772 git_repository
*repo
,
1773 const char *old_name
,
1774 const char *new_name
)
1776 git_buf old_section_name
= GIT_BUF_INIT
,
1777 new_section_name
= GIT_BUF_INIT
;
1780 if (git_buf_printf(&old_section_name
, "remote.%s", old_name
) < 0)
1784 (git_buf_printf(&new_section_name
, "remote.%s", new_name
) < 0))
1787 error
= git_config_rename_section(
1789 git_buf_cstr(&old_section_name
),
1790 new_name
? git_buf_cstr(&new_section_name
) : NULL
);
1793 git_buf_free(&old_section_name
);
1794 git_buf_free(&new_section_name
);
1799 struct update_data
{
1801 const char *old_remote_name
;
1802 const char *new_remote_name
;
1805 static int update_config_entries_cb(
1806 const git_config_entry
*entry
,
1809 struct update_data
*data
= (struct update_data
*)payload
;
1811 if (strcmp(entry
->value
, data
->old_remote_name
))
1814 return git_config_set_string(
1815 data
->config
, entry
->name
, data
->new_remote_name
);
1818 static int update_branch_remote_config_entry(
1819 git_repository
*repo
,
1820 const char *old_name
,
1821 const char *new_name
)
1824 struct update_data data
= { NULL
};
1826 if ((error
= git_repository_config__weakptr(&data
.config
, repo
)) < 0)
1829 data
.old_remote_name
= old_name
;
1830 data
.new_remote_name
= new_name
;
1832 return git_config_foreach_match(
1833 data
.config
, "branch\\..+\\.remote", update_config_entries_cb
, &data
);
1836 static int rename_one_remote_reference(
1837 git_reference
*reference_in
,
1838 const char *old_remote_name
,
1839 const char *new_remote_name
)
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
;
1849 if ((error
= git_buf_printf(&namespace, GIT_REFS_REMOTES_DIR
"%s/", new_remote_name
)) < 0)
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)
1857 if ((error
= git_buf_printf(&log_message
,
1858 "renamed remote %s to %s",
1859 old_remote_name
, new_remote_name
)) < 0)
1862 if ((error
= git_reference_rename(&ref
, reference_in
, git_buf_cstr(&new_name
), 1,
1863 git_buf_cstr(&log_message
))) < 0)
1866 if (git_reference_type(ref
) != GIT_REF_SYMBOLIC
)
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)
1874 if (git__prefixcmp(target
, old_namespace
.ptr
))
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)
1882 error
= git_reference_symbolic_set_target(&dummy
, ref
, git_buf_cstr(&new_name
),
1883 git_buf_cstr(&log_message
));
1885 git_reference_free(dummy
);
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
);
1897 static int rename_remote_references(
1898 git_repository
*repo
,
1899 const char *old_name
,
1900 const char *new_name
)
1903 git_buf buf
= GIT_BUF_INIT
;
1905 git_reference_iterator
*iter
;
1907 if ((error
= git_buf_printf(&buf
, GIT_REFS_REMOTES_DIR
"%s/*", old_name
)) < 0)
1910 error
= git_reference_iterator_glob_new(&iter
, repo
, git_buf_cstr(&buf
));
1916 while ((error
= git_reference_next(&ref
, iter
)) == 0) {
1917 if ((error
= rename_one_remote_reference(ref
, old_name
, new_name
)) < 0)
1921 git_reference_iterator_free(iter
);
1923 return (error
== GIT_ITEROVER
) ? 0 : error
;
1926 static int rename_fetch_refspecs(git_vector
*problems
, git_remote
*remote
, const char *new_name
)
1929 git_buf base
= GIT_BUF_INIT
, var
= GIT_BUF_INIT
, val
= GIT_BUF_INIT
;
1930 const git_refspec
*spec
;
1934 if ((error
= git_repository_config__weakptr(&config
, remote
->repo
)) < 0)
1937 if ((error
= git_vector_init(problems
, 1, NULL
)) < 0)
1940 if ((error
= git_buf_printf(
1941 &base
, "+refs/heads/*:refs/remotes/%s/*", remote
->name
)) < 0)
1944 git_vector_foreach(&remote
->refspecs
, i
, spec
) {
1948 /* Does the dst part of the refspec follow the expected format? */
1949 if (strcmp(git_buf_cstr(&base
), spec
->string
)) {
1952 dup
= git__strdup(spec
->string
);
1953 GITERR_CHECK_ALLOC(dup
);
1955 if ((error
= git_vector_insert(problems
, dup
)) < 0)
1961 /* If we do want to move it to the new section */
1963 git_buf_clear(&val
);
1964 git_buf_clear(&var
);
1967 &val
, "+refs/heads/*:refs/remotes/%s/*", new_name
) < 0 ||
1968 git_buf_printf(&var
, "remote.%s.fetch", new_name
) < 0)
1974 if ((error
= git_config_set_string(
1975 config
, git_buf_cstr(&var
), git_buf_cstr(&val
))) < 0)
1979 git_buf_free(&base
);
1985 git_vector_foreach(problems
, i
, str
)
1988 git_vector_free(problems
);
1994 int git_remote_rename(git_strarray
*out
, git_repository
*repo
, const char *name
, const char *new_name
)
1997 git_vector problem_refspecs
= GIT_VECTOR_INIT
;
1998 git_remote
*remote
= NULL
;
2000 assert(out
&& repo
&& name
&& new_name
);
2002 if ((error
= git_remote_lookup(&remote
, repo
, name
)) < 0)
2005 if ((error
= ensure_remote_name_is_valid(new_name
)) < 0)
2008 if ((error
= ensure_remote_doesnot_exist(repo
, new_name
)) < 0)
2011 if ((error
= rename_remote_config_section(repo
, name
, new_name
)) < 0)
2014 if ((error
= update_branch_remote_config_entry(repo
, name
, new_name
)) < 0)
2017 if ((error
= rename_remote_references(repo
, name
, new_name
)) < 0)
2020 if ((error
= rename_fetch_refspecs(&problem_refspecs
, remote
, new_name
)) < 0)
2023 out
->count
= problem_refspecs
.length
;
2024 out
->strings
= (char **) problem_refspecs
.contents
;
2028 git_vector_free(&problem_refspecs
);
2030 git_remote_free(remote
);
2034 int git_remote_is_valid_name(
2035 const char *remote_name
)
2037 git_buf buf
= GIT_BUF_INIT
;
2038 git_refspec refspec
;
2041 if (!remote_name
|| *remote_name
== '\0')
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);
2048 git_refspec__free(&refspec
);
2054 git_refspec
*git_remote__matching_refspec(git_remote
*remote
, const char *refname
)
2059 git_vector_foreach(&remote
->active_refspecs
, i
, spec
) {
2063 if (git_refspec_src_matches(spec
, refname
))
2070 git_refspec
*git_remote__matching_dst_refspec(git_remote
*remote
, const char *refname
)
2075 git_vector_foreach(&remote
->active_refspecs
, i
, spec
) {
2079 if (git_refspec_dst_matches(spec
, refname
))
2086 int git_remote_add_fetch(git_repository
*repo
, const char *remote
, const char *refspec
)
2088 return write_add_refspec(repo
, remote
, refspec
, true);
2091 int git_remote_add_push(git_repository
*repo
, const char *remote
, const char *refspec
)
2093 return write_add_refspec(repo
, remote
, refspec
, false);
2096 static int copy_refspecs(git_strarray
*array
, const git_remote
*remote
, unsigned int push
)
2099 git_vector refspecs
;
2103 if (git_vector_init(&refspecs
, remote
->refspecs
.length
, NULL
) < 0)
2106 git_vector_foreach(&remote
->refspecs
, i
, spec
) {
2107 if (spec
->push
!= push
)
2110 if ((dup
= git__strdup(spec
->string
)) == NULL
)
2113 if (git_vector_insert(&refspecs
, dup
) < 0) {
2119 array
->strings
= (char **)refspecs
.contents
;
2120 array
->count
= refspecs
.length
;
2125 git_vector_free_deep(&refspecs
);
2130 int git_remote_get_fetch_refspecs(git_strarray
*array
, const git_remote
*remote
)
2132 return copy_refspecs(array
, remote
, false);
2135 int git_remote_get_push_refspecs(git_strarray
*array
, const git_remote
*remote
)
2137 return copy_refspecs(array
, remote
, true);
2140 size_t git_remote_refspec_count(const git_remote
*remote
)
2142 return remote
->refspecs
.length
;
2145 const git_refspec
*git_remote_get_refspec(const git_remote
*remote
, size_t n
)
2147 return git_vector_get(&remote
->refspecs
, n
);
2150 int git_remote_init_callbacks(git_remote_callbacks
*opts
, unsigned int version
)
2152 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
2153 opts
, version
, git_remote_callbacks
, GIT_REMOTE_CALLBACKS_INIT
);
2157 /* asserts a branch.<foo>.remote format */
2158 static const char *name_offset(size_t *len_out
, const char *name
)
2163 prefix_len
= strlen("remote.");
2164 dot
= strchr(name
+ prefix_len
, '.');
2168 *len_out
= dot
- name
- prefix_len
;
2169 return name
+ prefix_len
;
2172 static int remove_branch_config_related_entries(
2173 git_repository
*repo
,
2174 const char *remote_name
)
2178 git_config_entry
*entry
;
2179 git_config_iterator
*iter
;
2180 git_buf buf
= GIT_BUF_INIT
;
2182 if ((error
= git_repository_config__weakptr(&config
, repo
)) < 0)
2185 if ((error
= git_config_iterator_glob_new(&iter
, config
, "branch\\..+\\.remote")) < 0)
2188 /* find any branches with us as upstream and remove that config */
2189 while ((error
= git_config_next(&entry
, iter
)) == 0) {
2193 if (strcmp(remote_name
, entry
->value
))
2196 branch
= name_offset(&branch_len
, entry
->name
);
2198 git_buf_clear(&buf
);
2199 if (git_buf_printf(&buf
, "branch.%.*s.merge", (int)branch_len
, branch
) < 0)
2202 if ((error
= git_config_delete_entry(config
, git_buf_cstr(&buf
))) < 0) {
2203 if (error
!= GIT_ENOTFOUND
)
2208 git_buf_clear(&buf
);
2209 if (git_buf_printf(&buf
, "branch.%.*s.remote", (int)branch_len
, branch
) < 0)
2212 if ((error
= git_config_delete_entry(config
, git_buf_cstr(&buf
))) < 0) {
2213 if (error
!= GIT_ENOTFOUND
)
2219 if (error
== GIT_ITEROVER
)
2223 git_config_iterator_free(iter
);
2227 static int remove_refs(git_repository
*repo
, const git_refspec
*spec
)
2229 git_reference_iterator
*iter
= NULL
;
2236 if ((error
= git_vector_init(&refs
, 8, NULL
)) < 0)
2239 if ((error
= git_reference_iterator_new(&iter
, repo
)) < 0)
2242 while ((error
= git_reference_next_name(&name
, iter
)) == 0) {
2243 if (!git_refspec_dst_matches(spec
, name
))
2246 dup
= git__strdup(name
);
2252 if ((error
= git_vector_insert(&refs
, dup
)) < 0)
2255 if (error
== GIT_ITEROVER
)
2260 git_vector_foreach(&refs
, i
, name
) {
2261 if ((error
= git_reference_remove(repo
, name
)) < 0)
2266 git_reference_iterator_free(iter
);
2267 git_vector_foreach(&refs
, i
, dup
) {
2270 git_vector_free(&refs
);
2274 static int remove_remote_tracking(git_repository
*repo
, const char *remote_name
)
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)
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
);
2288 /* shouldn't ever actually happen */
2289 if (refspec
== NULL
)
2292 if ((error
= remove_refs(repo
, refspec
)) < 0)
2296 git_remote_free(remote
);
2300 int git_remote_delete(git_repository
*repo
, const char *name
)
2304 assert(repo
&& name
);
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)
2314 int git_remote_default_branch(git_buf
*out
, git_remote
*remote
)
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
;
2324 if ((error
= git_remote_ls(&heads
, &heads_len
, remote
)) < 0)
2328 return GIT_ENOTFOUND
;
2330 if (strcmp(heads
[0]->name
, GIT_HEAD_FILE
))
2331 return GIT_ENOTFOUND
;
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
);
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.
2343 head_id
= &heads
[0]->oid
;
2345 for (i
= 1; i
< heads_len
; i
++) {
2346 if (git_oid_cmp(head_id
, &heads
[i
]->oid
))
2349 if (git__prefixcmp(heads
[i
]->name
, GIT_REFS_HEADS_DIR
))
2357 if (!git__strcmp(GIT_REFS_HEADS_MASTER_FILE
, heads
[i
]->name
)) {
2364 return GIT_ENOTFOUND
;
2366 return git_buf_puts(out
, guess
->name
);
2369 int git_remote_upload(git_remote
*remote
, const git_strarray
*refspecs
, const git_push_options
*opts
)
2375 const git_remote_callbacks
*cbs
= NULL
;
2376 const git_strarray
*custom_headers
= NULL
;
2377 const git_proxy_options
*proxy
= NULL
;
2381 if (!remote
->repo
) {
2382 giterr_set(GITERR_INVALID
, "cannot download detached remote");
2387 cbs
= &opts
->callbacks
;
2388 custom_headers
= &opts
->custom_headers
;
2389 proxy
= &opts
->proxy_opts
;
2392 if (!git_remote_connected(remote
) &&
2393 (error
= git_remote_connect(remote
, GIT_DIRECTION_PUSH
, cbs
, proxy
, custom_headers
)) < 0)
2396 free_refspecs(&remote
->active_refspecs
);
2397 if ((error
= dwim_refspecs(&remote
->active_refspecs
, &remote
->refspecs
, &remote
->refs
)) < 0)
2401 git_push_free(remote
->push
);
2402 remote
->push
= NULL
;
2405 if ((error
= git_push_new(&remote
->push
, remote
)) < 0)
2408 push
= remote
->push
;
2410 if (opts
&& (error
= git_push_set_options(push
, opts
)) < 0)
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)
2419 git_vector_foreach(&remote
->refspecs
, i
, spec
) {
2422 if ((error
= git_push_add_refspec(push
, spec
->string
)) < 0)
2427 if ((error
= git_push_finish(push
, cbs
)) < 0)
2430 if (cbs
&& cbs
->push_update_reference
&&
2431 (error
= git_push_status_foreach(push
, cbs
->push_update_reference
, cbs
->payload
)) < 0)
2438 int git_remote_push(git_remote
*remote
, const git_strarray
*refspecs
, const git_push_options
*opts
)
2441 const git_remote_callbacks
*cbs
= NULL
;
2442 const git_strarray
*custom_headers
= NULL
;
2443 const git_proxy_options
*proxy
= NULL
;
2447 if (!remote
->repo
) {
2448 giterr_set(GITERR_INVALID
, "cannot download detached remote");
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
;
2462 if ((error
= git_remote_connect(remote
, GIT_DIRECTION_PUSH
, cbs
, proxy
, custom_headers
)) < 0)
2465 if ((error
= git_remote_upload(remote
, refspecs
, opts
)) < 0)
2468 error
= git_remote_update_tips(remote
, cbs
, 0, 0, NULL
);
2470 git_remote_disconnect(remote
);
2474 #define PREFIX "url"
2475 #define SUFFIX_FETCH "insteadof"
2476 #define SUFFIX_PUSH "pushinsteadof"
2478 char *apply_insteadof(git_config
*config
, const char *url
, int direction
)
2480 size_t match_length
, prefix_length
, suffix_length
;
2481 char *replacement
= NULL
;
2484 git_buf result
= GIT_BUF_INIT
;
2485 git_config_entry
*entry
;
2486 git_config_iterator
*iter
;
2490 assert(direction
== GIT_DIRECTION_FETCH
|| direction
== GIT_DIRECTION_PUSH
);
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;
2498 regexp
= PREFIX
"\\..*\\." SUFFIX_PUSH
;
2499 suffix_length
= strlen(SUFFIX_PUSH
) + 1;
2502 if (git_config_iterator_glob_new(&iter
, config
, regexp
) < 0)
2506 while (git_config_next(&entry
, iter
) == 0) {
2507 size_t n
, replacement_length
;
2509 /* Check if entry value is a prefix of URL */
2510 if (git__prefixcmp(url
, entry
->value
))
2512 /* Check if entry value is longer than previous
2514 if ((n
= strlen(entry
->value
)) <= match_length
)
2517 git__free(replacement
);
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
);
2527 git_config_iterator_free(iter
);
2529 if (match_length
== 0)
2530 return git__strdup(url
);
2532 git_buf_printf(&result
, "%s%s", replacement
, url
+ match_length
);
2534 git__free(replacement
);