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 GIT_ERROR_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__dispose(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);
70 git_buf_dispose(&buf
);
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 (git_error_last()->klass
!= GIT_ERROR_NOMEMORY
)
115 error
= GIT_EINVALIDSPEC
;
120 git_refspec__dispose(&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) {
135 git_buf_dispose(&var
);
139 static int canonicalize_url(git_buf
*out
, const char *in
)
141 if (in
== NULL
|| strlen(in
) == 0) {
142 git_error_set(GIT_ERROR_INVALID
, "cannot set empty URL");
143 return GIT_EINVALIDSPEC
;
147 /* Given a UNC path like \\server\path, we need to convert this
148 * to //server/path for compatibility with core git.
150 if (in
[0] == '\\' && in
[1] == '\\' &&
151 (git__isalpha(in
[2]) || git__isdigit(in
[2]))) {
153 for (c
= in
; *c
; c
++)
154 git_buf_putc(out
, *c
== '\\' ? '/' : *c
);
156 return git_buf_oom(out
) ? -1 : 0;
160 return git_buf_puts(out
, in
);
163 static int default_fetchspec_for_name(git_buf
*buf
, const char *name
)
165 if (git_buf_printf(buf
, "+refs/heads/*:refs/remotes/%s/*", name
) < 0)
171 static int ensure_remote_doesnot_exist(git_repository
*repo
, const char *name
)
176 error
= git_remote_lookup(&remote
, repo
, name
);
178 if (error
== GIT_ENOTFOUND
)
184 git_remote_free(remote
);
186 git_error_set(GIT_ERROR_CONFIG
, "remote '%s' already exists", name
);
191 int git_remote_create_options_init(git_remote_create_options
*opts
, unsigned int version
)
193 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
194 opts
, version
, git_remote_create_options
, GIT_REMOTE_CREATE_OPTIONS_INIT
);
198 #ifndef GIT_DEPRECATE_HARD
199 int git_remote_create_init_options(git_remote_create_options
*opts
, unsigned int version
)
201 return git_remote_create_options_init(opts
, version
);
205 int git_remote_create_with_opts(git_remote
**out
, const char *url
, const git_remote_create_options
*opts
)
207 git_remote
*remote
= NULL
;
208 git_config
*config_ro
= NULL
, *config_rw
;
209 git_buf canonical_url
= GIT_BUF_INIT
;
210 git_buf var
= GIT_BUF_INIT
;
211 git_buf specbuf
= GIT_BUF_INIT
;
212 const git_remote_create_options dummy_opts
= GIT_REMOTE_CREATE_OPTIONS_INIT
;
221 GIT_ERROR_CHECK_VERSION(opts
, GIT_REMOTE_CREATE_OPTIONS_VERSION
, "git_remote_create_options");
223 if (opts
->name
!= NULL
) {
224 if ((error
= ensure_remote_name_is_valid(opts
->name
)) < 0)
227 if (opts
->repository
&&
228 (error
= ensure_remote_doesnot_exist(opts
->repository
, opts
->name
)) < 0)
232 if (opts
->repository
) {
233 if ((error
= git_repository_config_snapshot(&config_ro
, opts
->repository
)) < 0)
237 remote
= git__calloc(1, sizeof(git_remote
));
238 GIT_ERROR_CHECK_ALLOC(remote
);
240 remote
->repo
= opts
->repository
;
242 if ((error
= git_vector_init(&remote
->refs
, 8, NULL
)) < 0 ||
243 (error
= canonicalize_url(&canonical_url
, url
)) < 0)
246 if (opts
->repository
&& !(opts
->flags
& GIT_REMOTE_CREATE_SKIP_INSTEADOF
)) {
247 remote
->url
= apply_insteadof(config_ro
, canonical_url
.ptr
, GIT_DIRECTION_FETCH
);
249 remote
->url
= git__strdup(canonical_url
.ptr
);
251 GIT_ERROR_CHECK_ALLOC(remote
->url
);
253 if (opts
->name
!= NULL
) {
254 remote
->name
= git__strdup(opts
->name
);
255 GIT_ERROR_CHECK_ALLOC(remote
->name
);
257 if (opts
->repository
&&
258 ((error
= git_buf_printf(&var
, CONFIG_URL_FMT
, opts
->name
)) < 0 ||
259 (error
= git_repository_config__weakptr(&config_rw
, opts
->repository
)) < 0 ||
260 (error
= git_config_set_string(config_rw
, var
.ptr
, canonical_url
.ptr
)) < 0))
264 if (opts
->fetchspec
!= NULL
||
265 (opts
->name
&& !(opts
->flags
& GIT_REMOTE_CREATE_SKIP_DEFAULT_FETCHSPEC
))) {
266 const char *fetch
= NULL
;
267 if (opts
->fetchspec
) {
268 fetch
= opts
->fetchspec
;
270 if ((error
= default_fetchspec_for_name(&specbuf
, opts
->name
)) < 0)
273 fetch
= git_buf_cstr(&specbuf
);
276 if ((error
= add_refspec(remote
, fetch
, true)) < 0)
279 /* only write for named remotes with a repository */
280 if (opts
->repository
&& opts
->name
&&
281 ((error
= write_add_refspec(opts
->repository
, opts
->name
, fetch
, true)) < 0 ||
282 (error
= lookup_remote_prune_config(remote
, config_ro
, opts
->name
)) < 0))
285 /* Move the data over to where the matching functions can find them */
286 if ((error
= dwim_refspecs(&remote
->active_refspecs
, &remote
->refspecs
, &remote
->refs
)) < 0)
290 /* A remote without a name doesn't download tags */
292 remote
->download_tags
= GIT_REMOTE_DOWNLOAD_TAGS_NONE
;
294 remote
->download_tags
= GIT_REMOTE_DOWNLOAD_TAGS_AUTO
;
297 git_buf_dispose(&var
);
304 git_remote_free(remote
);
306 git_config_free(config_ro
);
307 git_buf_dispose(&specbuf
);
308 git_buf_dispose(&canonical_url
);
309 git_buf_dispose(&var
);
313 int git_remote_create(git_remote
**out
, git_repository
*repo
, const char *name
, const char *url
)
315 git_buf buf
= GIT_BUF_INIT
;
317 git_remote_create_options opts
= GIT_REMOTE_CREATE_OPTIONS_INIT
;
319 /* Those 2 tests are duplicated here because of backward-compatibility */
320 if ((error
= ensure_remote_name_is_valid(name
)) < 0)
323 if (canonicalize_url(&buf
, url
) < 0)
328 opts
.repository
= repo
;
331 error
= git_remote_create_with_opts(out
, url
, &opts
);
333 git_buf_dispose(&buf
);
338 int git_remote_create_with_fetchspec(git_remote
**out
, git_repository
*repo
, const char *name
, const char *url
, const char *fetch
)
341 git_remote_create_options opts
= GIT_REMOTE_CREATE_OPTIONS_INIT
;
343 if ((error
= ensure_remote_name_is_valid(name
)) < 0)
346 opts
.repository
= repo
;
348 opts
.fetchspec
= fetch
;
349 opts
.flags
= GIT_REMOTE_CREATE_SKIP_DEFAULT_FETCHSPEC
;
351 return git_remote_create_with_opts(out
, url
, &opts
);
354 int git_remote_create_anonymous(git_remote
**out
, git_repository
*repo
, const char *url
)
356 git_remote_create_options opts
= GIT_REMOTE_CREATE_OPTIONS_INIT
;
358 opts
.repository
= repo
;
360 return git_remote_create_with_opts(out
, url
, &opts
);
363 int git_remote_create_detached(git_remote
**out
, const char *url
)
365 return git_remote_create_with_opts(out
, url
, NULL
);
368 int git_remote_dup(git_remote
**dest
, git_remote
*source
)
373 git_remote
*remote
= git__calloc(1, sizeof(git_remote
));
374 GIT_ERROR_CHECK_ALLOC(remote
);
376 if (source
->name
!= NULL
) {
377 remote
->name
= git__strdup(source
->name
);
378 GIT_ERROR_CHECK_ALLOC(remote
->name
);
381 if (source
->url
!= NULL
) {
382 remote
->url
= git__strdup(source
->url
);
383 GIT_ERROR_CHECK_ALLOC(remote
->url
);
386 if (source
->pushurl
!= NULL
) {
387 remote
->pushurl
= git__strdup(source
->pushurl
);
388 GIT_ERROR_CHECK_ALLOC(remote
->pushurl
);
391 remote
->repo
= source
->repo
;
392 remote
->download_tags
= source
->download_tags
;
393 remote
->prune_refs
= source
->prune_refs
;
395 if (git_vector_init(&remote
->refs
, 32, NULL
) < 0 ||
396 git_vector_init(&remote
->refspecs
, 2, NULL
) < 0 ||
397 git_vector_init(&remote
->active_refspecs
, 2, NULL
) < 0) {
402 git_vector_foreach(&source
->refspecs
, i
, spec
) {
403 if ((error
= add_refspec(remote
, spec
->string
, !spec
->push
)) < 0)
417 struct refspec_cb_data
{
422 static int refspec_cb(const git_config_entry
*entry
, void *payload
)
424 struct refspec_cb_data
*data
= (struct refspec_cb_data
*)payload
;
425 return add_refspec(data
->remote
, entry
->value
, data
->fetch
);
428 static int get_optional_config(
429 bool *found
, git_config
*config
, git_buf
*buf
,
430 git_config_foreach_cb cb
, void *payload
)
433 const char *key
= git_buf_cstr(buf
);
435 if (git_buf_oom(buf
))
439 error
= git_config_get_multivar_foreach(config
, key
, NULL
, cb
, payload
);
441 error
= git_config_get_string(payload
, config
, key
);
446 if (error
== GIT_ENOTFOUND
) {
454 int git_remote_lookup(git_remote
**out
, git_repository
*repo
, const char *name
)
456 git_remote
*remote
= NULL
;
457 git_buf buf
= GIT_BUF_INIT
;
461 struct refspec_cb_data data
= { NULL
};
462 bool optional_setting_found
= false, found
;
464 assert(out
&& repo
&& name
);
466 if ((error
= ensure_remote_name_is_valid(name
)) < 0)
469 if ((error
= git_repository_config_snapshot(&config
, repo
)) < 0)
472 remote
= git__calloc(1, sizeof(git_remote
));
473 GIT_ERROR_CHECK_ALLOC(remote
);
475 remote
->name
= git__strdup(name
);
476 GIT_ERROR_CHECK_ALLOC(remote
->name
);
478 if (git_vector_init(&remote
->refs
, 32, NULL
) < 0 ||
479 git_vector_init(&remote
->refspecs
, 2, NULL
) < 0 ||
480 git_vector_init(&remote
->passive_refspecs
, 2, NULL
) < 0 ||
481 git_vector_init(&remote
->active_refspecs
, 2, NULL
) < 0) {
486 if ((error
= git_buf_printf(&buf
, "remote.%s.url", name
)) < 0)
489 if ((error
= get_optional_config(&found
, config
, &buf
, NULL
, (void *)&val
)) < 0)
492 optional_setting_found
|= found
;
495 remote
->download_tags
= GIT_REMOTE_DOWNLOAD_TAGS_AUTO
;
497 if (found
&& strlen(val
) > 0) {
498 remote
->url
= apply_insteadof(config
, val
, GIT_DIRECTION_FETCH
);
499 GIT_ERROR_CHECK_ALLOC(remote
->url
);
504 git_buf_printf(&buf
, "remote.%s.pushurl", name
);
506 if ((error
= get_optional_config(&found
, config
, &buf
, NULL
, (void *)&val
)) < 0)
509 optional_setting_found
|= found
;
511 if (!optional_setting_found
) {
512 error
= GIT_ENOTFOUND
;
513 git_error_set(GIT_ERROR_CONFIG
, "remote '%s' does not exist", name
);
517 if (found
&& strlen(val
) > 0) {
518 remote
->pushurl
= apply_insteadof(config
, val
, GIT_DIRECTION_PUSH
);
519 GIT_ERROR_CHECK_ALLOC(remote
->pushurl
);
522 data
.remote
= remote
;
526 git_buf_printf(&buf
, "remote.%s.fetch", name
);
528 if ((error
= get_optional_config(NULL
, config
, &buf
, refspec_cb
, &data
)) < 0)
533 git_buf_printf(&buf
, "remote.%s.push", name
);
535 if ((error
= get_optional_config(NULL
, config
, &buf
, refspec_cb
, &data
)) < 0)
538 if ((error
= download_tags_value(remote
, config
)) < 0)
541 if ((error
= lookup_remote_prune_config(remote
, config
, name
)) < 0)
544 /* Move the data over to where the matching functions can find them */
545 if ((error
= dwim_refspecs(&remote
->active_refspecs
, &remote
->refspecs
, &remote
->refs
)) < 0)
551 git_config_free(config
);
552 git_buf_dispose(&buf
);
555 git_remote_free(remote
);
560 static int lookup_remote_prune_config(git_remote
*remote
, git_config
*config
, const char *name
)
562 git_buf buf
= GIT_BUF_INIT
;
565 git_buf_printf(&buf
, "remote.%s.prune", name
);
567 if ((error
= git_config_get_bool(&remote
->prune_refs
, config
, git_buf_cstr(&buf
))) < 0) {
568 if (error
== GIT_ENOTFOUND
) {
571 if ((error
= git_config_get_bool(&remote
->prune_refs
, config
, "fetch.prune")) < 0) {
572 if (error
== GIT_ENOTFOUND
) {
580 git_buf_dispose(&buf
);
584 const char *git_remote_name(const git_remote
*remote
)
590 git_repository
*git_remote_owner(const git_remote
*remote
)
596 const char *git_remote_url(const git_remote
*remote
)
602 static int set_url(git_repository
*repo
, const char *remote
, const char *pattern
, const char *url
)
605 git_buf buf
= GIT_BUF_INIT
, canonical_url
= GIT_BUF_INIT
;
608 assert(repo
&& remote
);
610 if ((error
= ensure_remote_name_is_valid(remote
)) < 0)
613 if ((error
= git_repository_config__weakptr(&cfg
, repo
)) < 0)
616 if ((error
= git_buf_printf(&buf
, pattern
, remote
)) < 0)
620 if ((error
= canonicalize_url(&canonical_url
, url
)) < 0)
623 error
= git_config_set_string(cfg
, buf
.ptr
, url
);
625 error
= git_config_delete_entry(cfg
, buf
.ptr
);
629 git_buf_dispose(&canonical_url
);
630 git_buf_dispose(&buf
);
635 int git_remote_set_url(git_repository
*repo
, const char *remote
, const char *url
)
637 return set_url(repo
, remote
, CONFIG_URL_FMT
, url
);
640 const char *git_remote_pushurl(const git_remote
*remote
)
643 return remote
->pushurl
;
646 int git_remote_set_pushurl(git_repository
*repo
, const char *remote
, const char* url
)
648 return set_url(repo
, remote
, CONFIG_PUSHURL_FMT
, url
);
651 static int resolve_url(git_buf
*resolved_url
, const char *url
, int direction
, const git_remote_callbacks
*callbacks
)
655 if (callbacks
&& callbacks
->resolve_url
) {
656 git_buf_clear(resolved_url
);
657 status
= callbacks
->resolve_url(resolved_url
, url
, direction
, callbacks
->payload
);
658 if (status
!= GIT_PASSTHROUGH
) {
659 git_error_set_after_callback_function(status
, "git_resolve_url_cb");
660 git_buf_sanitize(resolved_url
);
665 return git_buf_sets(resolved_url
, url
);
668 int git_remote__urlfordirection(git_buf
*url_out
, struct git_remote
*remote
, int direction
, const git_remote_callbacks
*callbacks
)
670 const char *url
= NULL
;
673 assert(direction
== GIT_DIRECTION_FETCH
|| direction
== GIT_DIRECTION_PUSH
);
675 if (direction
== GIT_DIRECTION_FETCH
) {
677 } else if (direction
== GIT_DIRECTION_PUSH
) {
678 url
= remote
->pushurl
? remote
->pushurl
: remote
->url
;
682 git_error_set(GIT_ERROR_INVALID
,
683 "malformed remote '%s' - missing %s URL",
684 remote
->name
? remote
->name
: "(anonymous)",
685 direction
== GIT_DIRECTION_FETCH
? "fetch" : "push");
688 return resolve_url(url_out
, url
, direction
, callbacks
);
691 static int remote_transport_set_callbacks(git_transport
*t
, const git_remote_callbacks
*cbs
)
693 if (!t
->set_callbacks
|| !cbs
)
696 return t
->set_callbacks(t
, cbs
->sideband_progress
, NULL
,
697 cbs
->certificate_check
, cbs
->payload
);
700 static int set_transport_custom_headers(git_transport
*t
, const git_strarray
*custom_headers
)
702 if (!t
->set_custom_headers
)
705 return t
->set_custom_headers(t
, custom_headers
);
708 int git_remote__connect(git_remote
*remote
, git_direction direction
, const git_remote_callbacks
*callbacks
, const git_remote_connection_opts
*conn
)
711 git_buf url
= GIT_BUF_INIT
;
712 int flags
= GIT_TRANSPORTFLAGS_NONE
;
714 void *payload
= NULL
;
715 git_credential_acquire_cb credentials
= NULL
;
716 git_transport_cb transport
= NULL
;
721 GIT_ERROR_CHECK_VERSION(callbacks
, GIT_REMOTE_CALLBACKS_VERSION
, "git_remote_callbacks");
722 credentials
= callbacks
->credentials
;
723 transport
= callbacks
->transport
;
724 payload
= callbacks
->payload
;
728 GIT_ERROR_CHECK_VERSION(conn
->proxy
, GIT_PROXY_OPTIONS_VERSION
, "git_proxy_options");
730 t
= remote
->transport
;
732 if ((error
= git_remote__urlfordirection(&url
, remote
, direction
, callbacks
)) < 0)
735 /* If we don't have a transport object yet, and the caller specified a
736 * custom transport factory, use that */
737 if (!t
&& transport
&&
738 (error
= transport(&t
, remote
, payload
)) < 0)
741 /* If we still don't have a transport, then use the global
742 * transport registrations which map URI schemes to transport factories */
743 if (!t
&& (error
= git_transport_new(&t
, remote
, url
.ptr
)) < 0)
746 if ((error
= set_transport_custom_headers(t
, conn
->custom_headers
)) != 0)
749 if ((error
= remote_transport_set_callbacks(t
, callbacks
)) < 0 ||
750 (error
= t
->connect(t
, url
.ptr
, credentials
, payload
, conn
->proxy
, direction
, flags
)) != 0)
753 remote
->transport
= t
;
755 git_buf_dispose(&url
);
763 git_buf_dispose(&url
);
765 if (t
== remote
->transport
)
766 remote
->transport
= NULL
;
771 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
)
773 git_remote_connection_opts conn
;
776 conn
.custom_headers
= custom_headers
;
778 return git_remote__connect(remote
, direction
, callbacks
, &conn
);
781 int git_remote_ls(const git_remote_head
***out
, size_t *size
, git_remote
*remote
)
785 if (!remote
->transport
) {
786 git_error_set(GIT_ERROR_NET
, "this remote has never connected");
790 return remote
->transport
->ls(out
, size
, remote
->transport
);
793 int git_remote__get_http_proxy(git_remote
*remote
, bool use_ssl
, char **proxy_url
)
796 git_config_entry
*ce
= NULL
;
797 git_buf val
= GIT_BUF_INIT
;
802 if (!proxy_url
|| !remote
->repo
)
807 if ((error
= git_repository_config__weakptr(&cfg
, remote
->repo
)) < 0)
810 /* Go through the possible sources for proxy configuration, from most specific
811 * to least specific. */
813 /* remote.<name>.proxy config setting */
814 if (remote
->name
&& remote
->name
[0]) {
815 git_buf buf
= GIT_BUF_INIT
;
817 if ((error
= git_buf_printf(&buf
, "remote.%s.proxy", remote
->name
)) < 0)
820 error
= git_config__lookup_entry(&ce
, cfg
, git_buf_cstr(&buf
), false);
821 git_buf_dispose(&buf
);
826 if (ce
&& ce
->value
) {
827 *proxy_url
= git__strdup(ce
->value
);
832 /* http.proxy config setting */
833 if ((error
= git_config__lookup_entry(&ce
, cfg
, "http.proxy", false)) < 0)
836 if (ce
&& ce
->value
) {
837 *proxy_url
= git__strdup(ce
->value
);
841 /* http_proxy / https_proxy environment variables */
842 error
= git__getenv(&val
, use_ssl
? "https_proxy" : "http_proxy");
844 /* try uppercase environment variables */
845 if (error
== GIT_ENOTFOUND
)
846 error
= git__getenv(&val
, use_ssl
? "HTTPS_PROXY" : "HTTP_PROXY");
849 if (error
== GIT_ENOTFOUND
) {
857 *proxy_url
= git_buf_detach(&val
);
860 GIT_ERROR_CHECK_ALLOC(*proxy_url
);
861 git_config_entry_free(ce
);
866 /* DWIM `refspecs` based on `refs` and append the output to `out` */
867 static int dwim_refspecs(git_vector
*out
, git_vector
*refspecs
, git_vector
*refs
)
872 git_vector_foreach(refspecs
, i
, spec
) {
873 if (git_refspec__dwim_one(out
, spec
, refs
) < 0)
880 static void free_refspecs(git_vector
*vec
)
885 git_vector_foreach(vec
, i
, spec
) {
886 git_refspec__dispose(spec
);
890 git_vector_clear(vec
);
893 static int remote_head_cmp(const void *_a
, const void *_b
)
895 const git_remote_head
*a
= (git_remote_head
*) _a
;
896 const git_remote_head
*b
= (git_remote_head
*) _b
;
898 return git__strcmp_cb(a
->name
, b
->name
);
901 static int ls_to_vector(git_vector
*out
, git_remote
*remote
)
903 git_remote_head
**heads
;
906 if (git_remote_ls((const git_remote_head
***)&heads
, &heads_len
, remote
) < 0)
909 if (git_vector_init(out
, heads_len
, remote_head_cmp
) < 0)
912 for (i
= 0; i
< heads_len
; i
++) {
913 if (git_vector_insert(out
, heads
[i
]) < 0)
920 int git_remote_download(git_remote
*remote
, const git_strarray
*refspecs
, const git_fetch_options
*opts
)
924 git_vector
*to_active
, specs
= GIT_VECTOR_INIT
, refs
= GIT_VECTOR_INIT
;
925 const git_remote_callbacks
*cbs
= NULL
;
926 const git_strarray
*custom_headers
= NULL
;
927 const git_proxy_options
*proxy
= NULL
;
932 git_error_set(GIT_ERROR_INVALID
, "cannot download detached remote");
937 GIT_ERROR_CHECK_VERSION(&opts
->callbacks
, GIT_REMOTE_CALLBACKS_VERSION
, "git_remote_callbacks");
938 cbs
= &opts
->callbacks
;
939 custom_headers
= &opts
->custom_headers
;
940 GIT_ERROR_CHECK_VERSION(&opts
->proxy_opts
, GIT_PROXY_OPTIONS_VERSION
, "git_proxy_options");
941 proxy
= &opts
->proxy_opts
;
944 if (!git_remote_connected(remote
) &&
945 (error
= git_remote_connect(remote
, GIT_DIRECTION_FETCH
, cbs
, proxy
, custom_headers
)) < 0)
948 if (ls_to_vector(&refs
, remote
) < 0)
951 if ((git_vector_init(&specs
, 0, NULL
)) < 0)
954 remote
->passed_refspecs
= 0;
955 if (!refspecs
|| !refspecs
->count
) {
956 to_active
= &remote
->refspecs
;
958 for (i
= 0; i
< refspecs
->count
; i
++) {
959 if ((error
= add_refspec_to(&specs
, refspecs
->strings
[i
], true)) < 0)
964 remote
->passed_refspecs
= 1;
967 free_refspecs(&remote
->passive_refspecs
);
968 if ((error
= dwim_refspecs(&remote
->passive_refspecs
, &remote
->refspecs
, &refs
)) < 0)
971 free_refspecs(&remote
->active_refspecs
);
972 error
= dwim_refspecs(&remote
->active_refspecs
, to_active
, &refs
);
974 git_vector_free(&refs
);
975 free_refspecs(&specs
);
976 git_vector_free(&specs
);
982 git_push_free(remote
->push
);
986 if ((error
= git_fetch_negotiate(remote
, opts
)) < 0)
989 return git_fetch_download_pack(remote
, cbs
);
992 git_vector_free(&refs
);
993 free_refspecs(&specs
);
994 git_vector_free(&specs
);
998 int git_remote_fetch(
1000 const git_strarray
*refspecs
,
1001 const git_fetch_options
*opts
,
1002 const char *reflog_message
)
1004 int error
, update_fetchhead
= 1;
1005 git_remote_autotag_option_t tagopt
= remote
->download_tags
;
1007 git_buf reflog_msg_buf
= GIT_BUF_INIT
;
1008 const git_remote_callbacks
*cbs
= NULL
;
1009 git_remote_connection_opts conn
= GIT_REMOTE_CONNECTION_OPTIONS_INIT
;
1012 GIT_ERROR_CHECK_VERSION(&opts
->callbacks
, GIT_REMOTE_CALLBACKS_VERSION
, "git_remote_callbacks");
1013 cbs
= &opts
->callbacks
;
1014 conn
.custom_headers
= &opts
->custom_headers
;
1015 update_fetchhead
= opts
->update_fetchhead
;
1016 tagopt
= opts
->download_tags
;
1017 GIT_ERROR_CHECK_VERSION(&opts
->proxy_opts
, GIT_PROXY_OPTIONS_VERSION
, "git_proxy_options");
1018 conn
.proxy
= &opts
->proxy_opts
;
1021 /* Connect and download everything */
1022 if ((error
= git_remote__connect(remote
, GIT_DIRECTION_FETCH
, cbs
, &conn
)) != 0)
1025 error
= git_remote_download(remote
, refspecs
, opts
);
1027 /* We don't need to be connected anymore */
1028 git_remote_disconnect(remote
);
1030 /* If the download failed, return the error */
1034 /* Default reflog message */
1036 git_buf_sets(&reflog_msg_buf
, reflog_message
);
1038 git_buf_printf(&reflog_msg_buf
, "fetch %s",
1039 remote
->name
? remote
->name
: remote
->url
);
1042 /* Create "remote/foo" branches for all remote branches */
1043 error
= git_remote_update_tips(remote
, cbs
, update_fetchhead
, tagopt
, git_buf_cstr(&reflog_msg_buf
));
1044 git_buf_dispose(&reflog_msg_buf
);
1048 if (opts
&& opts
->prune
== GIT_FETCH_PRUNE
)
1050 else if (opts
&& opts
->prune
== GIT_FETCH_PRUNE_UNSPECIFIED
&& remote
->prune_refs
)
1052 else if (opts
&& opts
->prune
== GIT_FETCH_NO_PRUNE
)
1055 prune
= remote
->prune_refs
;
1058 error
= git_remote_prune(remote
, cbs
);
1063 static int remote_head_for_fetchspec_src(git_remote_head
**out
, git_vector
*update_heads
, const char *fetchspec_src
)
1066 git_remote_head
*remote_ref
;
1068 assert(update_heads
&& fetchspec_src
);
1072 git_vector_foreach(update_heads
, i
, remote_ref
) {
1073 if (strcmp(remote_ref
->name
, fetchspec_src
) == 0) {
1082 static int ref_to_update(int *update
, git_buf
*remote_name
, git_remote
*remote
, git_refspec
*spec
, const char *ref_name
)
1085 git_repository
*repo
;
1086 git_buf upstream_remote
= GIT_BUF_INIT
;
1087 git_buf upstream_name
= GIT_BUF_INIT
;
1089 repo
= git_remote_owner(remote
);
1091 if ((!git_reference__is_branch(ref_name
)) ||
1092 !git_remote_name(remote
) ||
1093 (error
= git_branch_upstream_remote(&upstream_remote
, repo
, ref_name
) < 0) ||
1094 git__strcmp(git_remote_name(remote
), git_buf_cstr(&upstream_remote
)) ||
1095 (error
= git_branch_upstream_name(&upstream_name
, repo
, ref_name
)) < 0 ||
1096 !git_refspec_dst_matches(spec
, git_buf_cstr(&upstream_name
)) ||
1097 (error
= git_refspec_rtransform(remote_name
, spec
, upstream_name
.ptr
)) < 0) {
1098 /* Not an error if there is no upstream */
1099 if (error
== GIT_ENOTFOUND
) {
1109 git_buf_dispose(&upstream_remote
);
1110 git_buf_dispose(&upstream_name
);
1114 static int remote_head_for_ref(git_remote_head
**out
, git_remote
*remote
, git_refspec
*spec
, git_vector
*update_heads
, git_reference
*ref
)
1116 git_reference
*resolved_ref
= NULL
;
1117 git_buf remote_name
= GIT_BUF_INIT
;
1118 git_config
*config
= NULL
;
1119 const char *ref_name
;
1120 int error
= 0, update
;
1122 assert(out
&& spec
&& ref
);
1126 error
= git_reference_resolve(&resolved_ref
, ref
);
1128 /* If we're in an unborn branch, let's pretend nothing happened */
1129 if (error
== GIT_ENOTFOUND
&& git_reference_type(ref
) == GIT_REFERENCE_SYMBOLIC
) {
1130 ref_name
= git_reference_symbolic_target(ref
);
1133 ref_name
= git_reference_name(resolved_ref
);
1136 if ((error
= ref_to_update(&update
, &remote_name
, remote
, spec
, ref_name
)) < 0)
1140 error
= remote_head_for_fetchspec_src(out
, update_heads
, git_buf_cstr(&remote_name
));
1143 git_buf_dispose(&remote_name
);
1144 git_reference_free(resolved_ref
);
1145 git_config_free(config
);
1149 static int git_remote_write_fetchhead(git_remote
*remote
, git_refspec
*spec
, git_vector
*update_heads
)
1151 git_reference
*head_ref
= NULL
;
1152 git_fetchhead_ref
*fetchhead_ref
;
1153 git_remote_head
*remote_ref
, *merge_remote_ref
;
1154 git_vector fetchhead_refs
;
1155 bool include_all_fetchheads
;
1161 /* no heads, nothing to do */
1162 if (update_heads
->length
== 0)
1165 if (git_vector_init(&fetchhead_refs
, update_heads
->length
, git_fetchhead_ref_cmp
) < 0)
1168 /* Iff refspec is * (but not subdir slash star), include tags */
1169 include_all_fetchheads
= (strcmp(GIT_REFS_HEADS_DIR
"*", git_refspec_src(spec
)) == 0);
1171 /* Determine what to merge: if refspec was a wildcard, just use HEAD */
1172 if (git_refspec_is_wildcard(spec
)) {
1173 if ((error
= git_reference_lookup(&head_ref
, remote
->repo
, GIT_HEAD_FILE
)) < 0 ||
1174 (error
= remote_head_for_ref(&merge_remote_ref
, remote
, spec
, update_heads
, head_ref
)) < 0)
1177 /* If we're fetching a single refspec, that's the only thing that should be in FETCH_HEAD. */
1178 if ((error
= remote_head_for_fetchspec_src(&merge_remote_ref
, update_heads
, git_refspec_src(spec
))) < 0)
1182 /* Create the FETCH_HEAD file */
1183 git_vector_foreach(update_heads
, i
, remote_ref
) {
1184 int merge_this_fetchhead
= (merge_remote_ref
== remote_ref
);
1186 if (!include_all_fetchheads
&&
1187 !git_refspec_src_matches(spec
, remote_ref
->name
) &&
1188 !merge_this_fetchhead
)
1191 if (git_fetchhead_ref_create(&fetchhead_ref
,
1193 merge_this_fetchhead
,
1195 git_remote_url(remote
)) < 0)
1198 if (git_vector_insert(&fetchhead_refs
, fetchhead_ref
) < 0)
1202 git_fetchhead_write(remote
->repo
, &fetchhead_refs
);
1205 for (i
= 0; i
< fetchhead_refs
.length
; ++i
)
1206 git_fetchhead_ref_free(fetchhead_refs
.contents
[i
]);
1208 git_vector_free(&fetchhead_refs
);
1209 git_reference_free(head_ref
);
1215 * Generate a list of candidates for pruning by getting a list of
1216 * references which match the rhs of an active refspec.
1218 static int prune_candidates(git_vector
*candidates
, git_remote
*remote
)
1220 git_strarray arr
= { 0 };
1224 if ((error
= git_reference_list(&arr
, remote
->repo
)) < 0)
1227 for (i
= 0; i
< arr
.count
; i
++) {
1228 const char *refname
= arr
.strings
[i
];
1231 if (!git_remote__matching_dst_refspec(remote
, refname
))
1234 refname_dup
= git__strdup(refname
);
1235 GIT_ERROR_CHECK_ALLOC(refname_dup
);
1237 if ((error
= git_vector_insert(candidates
, refname_dup
)) < 0)
1242 git_strarray_dispose(&arr
);
1246 static int find_head(const void *_a
, const void *_b
)
1248 git_remote_head
*a
= (git_remote_head
*) _a
;
1249 git_remote_head
*b
= (git_remote_head
*) _b
;
1251 return strcmp(a
->name
, b
->name
);
1254 int git_remote_prune(git_remote
*remote
, const git_remote_callbacks
*callbacks
)
1257 git_vector remote_refs
= GIT_VECTOR_INIT
;
1258 git_vector candidates
= GIT_VECTOR_INIT
;
1259 const git_refspec
*spec
;
1260 const char *refname
;
1262 git_oid zero_id
= {{ 0 }};
1265 GIT_ERROR_CHECK_VERSION(callbacks
, GIT_REMOTE_CALLBACKS_VERSION
, "git_remote_callbacks");
1267 if ((error
= ls_to_vector(&remote_refs
, remote
)) < 0)
1270 git_vector_set_cmp(&remote_refs
, find_head
);
1272 if ((error
= prune_candidates(&candidates
, remote
)) < 0)
1276 * Remove those entries from the candidate list for which we
1277 * can find a remote reference in at least one refspec.
1279 git_vector_foreach(&candidates
, i
, refname
) {
1280 git_vector_foreach(&remote
->active_refspecs
, j
, spec
) {
1281 git_buf buf
= GIT_BUF_INIT
;
1284 git_remote_head key
= {0};
1286 if (!git_refspec_dst_matches(spec
, refname
))
1289 if ((error
= git_refspec_rtransform(&buf
, spec
, refname
)) < 0)
1292 key
.name
= (char *) git_buf_cstr(&buf
);
1293 error
= git_vector_bsearch(&pos
, &remote_refs
, &key
);
1294 git_buf_dispose(&buf
);
1296 if (error
< 0 && error
!= GIT_ENOTFOUND
)
1299 if (error
== GIT_ENOTFOUND
)
1302 /* if we did find a source, remove it from the candiates */
1303 if ((error
= git_vector_set((void **) &src_name
, &candidates
, i
, NULL
)) < 0)
1306 git__free(src_name
);
1312 * For those candidates still left in the list, we need to
1313 * remove them. We do not remove symrefs, as those are for
1314 * stuff like origin/HEAD which will never match, but we do
1315 * not want to remove them.
1317 git_vector_foreach(&candidates
, i
, refname
) {
1321 if (refname
== NULL
)
1324 error
= git_reference_lookup(&ref
, remote
->repo
, refname
);
1325 /* as we want it gone, let's not consider this an error */
1326 if (error
== GIT_ENOTFOUND
)
1332 if (git_reference_type(ref
) == GIT_REFERENCE_SYMBOLIC
) {
1333 git_reference_free(ref
);
1337 git_oid_cpy(&id
, git_reference_target(ref
));
1338 error
= git_reference_delete(ref
);
1339 git_reference_free(ref
);
1343 if (callbacks
&& callbacks
->update_tips
)
1344 error
= callbacks
->update_tips(refname
, &id
, &zero_id
, callbacks
->payload
);
1351 git_vector_free(&remote_refs
);
1352 git_vector_free_deep(&candidates
);
1356 static int update_tips_for_spec(
1358 const git_remote_callbacks
*callbacks
,
1359 int update_fetchhead
,
1360 git_remote_autotag_option_t tagopt
,
1363 const char *log_message
)
1365 int error
= 0, autotag
;
1367 git_buf refname
= GIT_BUF_INIT
;
1370 git_remote_head
*head
;
1372 git_refspec tagspec
;
1373 git_vector update_heads
;
1377 if (git_repository_odb__weakptr(&odb
, remote
->repo
) < 0)
1380 if (git_refspec__parse(&tagspec
, GIT_REFSPEC_TAGS
, true) < 0)
1383 /* Make a copy of the transport's refs */
1384 if (git_vector_init(&update_heads
, 16, NULL
) < 0)
1387 for (; i
< refs
->length
; ++i
) {
1388 head
= git_vector_get(refs
, i
);
1390 git_buf_clear(&refname
);
1392 /* Ignore malformed ref names (which also saves us from tag^{} */
1393 if (!git_reference_is_valid_name(head
->name
))
1396 /* If we have a tag, see if the auto-follow rules say to update it */
1397 if (git_refspec_src_matches(&tagspec
, head
->name
)) {
1398 if (tagopt
!= GIT_REMOTE_DOWNLOAD_TAGS_NONE
) {
1400 if (tagopt
== GIT_REMOTE_DOWNLOAD_TAGS_AUTO
)
1403 git_buf_clear(&refname
);
1404 if (git_buf_puts(&refname
, head
->name
) < 0)
1409 /* If we didn't want to auto-follow the tag, check if the refspec matches */
1410 if (!autotag
&& git_refspec_src_matches(spec
, head
->name
)) {
1412 if (git_refspec_transform(&refname
, spec
, head
->name
) < 0)
1416 * no rhs mans store it in FETCH_HEAD, even if we don't
1417 update anything else.
1419 if ((error
= git_vector_insert(&update_heads
, head
)) < 0)
1426 /* If we still don't have a refname, we don't want it */
1427 if (git_buf_len(&refname
) == 0) {
1431 /* In autotag mode, only create tags for objects already in db */
1432 if (autotag
&& !git_odb_exists(odb
, &head
->oid
))
1435 if (!autotag
&& git_vector_insert(&update_heads
, head
) < 0)
1438 error
= git_reference_name_to_id(&old
, remote
->repo
, refname
.ptr
);
1439 if (error
< 0 && error
!= GIT_ENOTFOUND
)
1442 if (error
== GIT_ENOTFOUND
) {
1443 memset(&old
, 0, GIT_OID_RAWSZ
);
1445 if (autotag
&& git_vector_insert(&update_heads
, head
) < 0)
1449 if (!git_oid__cmp(&old
, &head
->oid
))
1452 /* In autotag mode, don't overwrite any locally-existing tags */
1453 error
= git_reference_create(&ref
, remote
->repo
, refname
.ptr
, &head
->oid
, !autotag
,
1456 if (error
== GIT_EEXISTS
)
1462 git_reference_free(ref
);
1464 if (callbacks
&& callbacks
->update_tips
!= NULL
) {
1465 if (callbacks
->update_tips(refname
.ptr
, &old
, &head
->oid
, callbacks
->payload
) < 0)
1470 if (update_fetchhead
&&
1471 (error
= git_remote_write_fetchhead(remote
, spec
, &update_heads
)) < 0)
1474 git_vector_free(&update_heads
);
1475 git_refspec__dispose(&tagspec
);
1476 git_buf_dispose(&refname
);
1480 git_vector_free(&update_heads
);
1481 git_refspec__dispose(&tagspec
);
1482 git_buf_dispose(&refname
);
1488 * Iteration over the three vectors, with a pause whenever we find a match
1490 * On each stop, we store the iteration stat in the inout i,j,k
1491 * parameters, and return the currently matching passive refspec as
1492 * well as the head which we matched.
1494 static int next_head(const git_remote
*remote
, git_vector
*refs
,
1495 git_refspec
**out_spec
, git_remote_head
**out_head
,
1496 size_t *out_i
, size_t *out_j
, size_t *out_k
)
1498 const git_vector
*active
, *passive
;
1499 git_remote_head
*head
;
1500 git_refspec
*spec
, *passive_spec
;
1503 active
= &remote
->active_refspecs
;
1504 passive
= &remote
->passive_refspecs
;
1510 for (; i
< refs
->length
; i
++) {
1511 head
= git_vector_get(refs
, i
);
1513 if (!git_reference_is_valid_name(head
->name
))
1516 for (; j
< active
->length
; j
++) {
1517 spec
= git_vector_get(active
, j
);
1519 if (!git_refspec_src_matches(spec
, head
->name
))
1522 for (; k
< passive
->length
; k
++) {
1523 passive_spec
= git_vector_get(passive
, k
);
1525 if (!git_refspec_src_matches(passive_spec
, head
->name
))
1528 *out_spec
= passive_spec
;
1541 return GIT_ITEROVER
;
1544 static int opportunistic_updates(const git_remote
*remote
, const git_remote_callbacks
*callbacks
,
1545 git_vector
*refs
, const char *msg
)
1549 git_remote_head
*head
;
1551 git_buf refname
= GIT_BUF_INIT
;
1556 while ((error
= next_head(remote
, refs
, &spec
, &head
, &i
, &j
, &k
)) == 0) {
1557 git_oid old
= {{ 0 }};
1559 * If we got here, there is a refspec which was used
1560 * for fetching which matches the source of one of the
1561 * passive refspecs, so we should update that
1562 * remote-tracking branch, but not add it to
1566 git_buf_clear(&refname
);
1567 if ((error
= git_refspec_transform(&refname
, spec
, head
->name
)) < 0)
1570 error
= git_reference_name_to_id(&old
, remote
->repo
, refname
.ptr
);
1571 if (error
< 0 && error
!= GIT_ENOTFOUND
)
1574 if (!git_oid_cmp(&old
, &head
->oid
))
1577 /* If we did find a current reference, make sure we haven't lost a race */
1579 error
= git_reference_create(&ref
, remote
->repo
, refname
.ptr
, &head
->oid
, true, msg
);
1581 error
= git_reference_create_matching(&ref
, remote
->repo
, refname
.ptr
, &head
->oid
, true, &old
, msg
);
1582 git_reference_free(ref
);
1586 if (callbacks
&& callbacks
->update_tips
!= NULL
) {
1587 if (callbacks
->update_tips(refname
.ptr
, &old
, &head
->oid
, callbacks
->payload
) < 0)
1592 if (error
== GIT_ITEROVER
)
1596 git_buf_dispose(&refname
);
1600 static int truncate_fetch_head(const char *gitdir
)
1602 git_buf path
= GIT_BUF_INIT
;
1605 if ((error
= git_buf_joinpath(&path
, gitdir
, GIT_FETCH_HEAD_FILE
)) < 0)
1608 error
= git_futils_truncate(path
.ptr
, GIT_REFS_FILE_MODE
);
1609 git_buf_dispose(&path
);
1614 int git_remote_update_tips(
1616 const git_remote_callbacks
*callbacks
,
1617 int update_fetchhead
,
1618 git_remote_autotag_option_t download_tags
,
1619 const char *reflog_message
)
1621 git_refspec
*spec
, tagspec
;
1622 git_vector refs
= GIT_VECTOR_INIT
;
1623 git_remote_autotag_option_t tagopt
;
1627 /* push has its own logic hidden away in the push object */
1629 return git_push_update_tips(remote
->push
, callbacks
);
1632 if (git_refspec__parse(&tagspec
, GIT_REFSPEC_TAGS
, true) < 0)
1636 if ((error
= ls_to_vector(&refs
, remote
)) < 0)
1639 if (download_tags
== GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED
)
1640 tagopt
= remote
->download_tags
;
1642 tagopt
= download_tags
;
1644 if ((error
= truncate_fetch_head(git_repository_path(remote
->repo
))) < 0)
1647 if (tagopt
== GIT_REMOTE_DOWNLOAD_TAGS_ALL
) {
1648 if ((error
= update_tips_for_spec(remote
, callbacks
, update_fetchhead
, tagopt
, &tagspec
, &refs
, reflog_message
)) < 0)
1652 git_vector_foreach(&remote
->active_refspecs
, i
, spec
) {
1656 if ((error
= update_tips_for_spec(remote
, callbacks
, update_fetchhead
, tagopt
, spec
, &refs
, reflog_message
)) < 0)
1660 /* only try to do opportunisitic updates if the refpec lists differ */
1661 if (remote
->passed_refspecs
)
1662 error
= opportunistic_updates(remote
, callbacks
, &refs
, reflog_message
);
1665 git_vector_free(&refs
);
1666 git_refspec__dispose(&tagspec
);
1670 int git_remote_connected(const git_remote
*remote
)
1674 if (!remote
->transport
|| !remote
->transport
->is_connected
)
1677 /* Ask the transport if it's connected. */
1678 return remote
->transport
->is_connected(remote
->transport
);
1681 int git_remote_stop(git_remote
*remote
)
1685 if (remote
->transport
&& remote
->transport
->cancel
)
1686 remote
->transport
->cancel(remote
->transport
);
1691 int git_remote_disconnect(git_remote
*remote
)
1695 if (git_remote_connected(remote
))
1696 remote
->transport
->close(remote
->transport
);
1701 void git_remote_free(git_remote
*remote
)
1706 if (remote
->transport
!= NULL
) {
1707 git_remote_disconnect(remote
);
1709 remote
->transport
->free(remote
->transport
);
1710 remote
->transport
= NULL
;
1713 git_vector_free(&remote
->refs
);
1715 free_refspecs(&remote
->refspecs
);
1716 git_vector_free(&remote
->refspecs
);
1718 free_refspecs(&remote
->active_refspecs
);
1719 git_vector_free(&remote
->active_refspecs
);
1721 free_refspecs(&remote
->passive_refspecs
);
1722 git_vector_free(&remote
->passive_refspecs
);
1724 git_push_free(remote
->push
);
1725 git__free(remote
->url
);
1726 git__free(remote
->pushurl
);
1727 git__free(remote
->name
);
1731 static int remote_list_cb(const git_config_entry
*entry
, void *payload
)
1733 git_vector
*list
= payload
;
1734 const char *name
= entry
->name
+ strlen("remote.");
1735 size_t namelen
= strlen(name
);
1738 /* we know name matches "remote.<stuff>.(push)?url" */
1740 if (!strcmp(&name
[namelen
- 4], ".url"))
1741 remote_name
= git__strndup(name
, namelen
- 4); /* strip ".url" */
1743 remote_name
= git__strndup(name
, namelen
- 8); /* strip ".pushurl" */
1744 GIT_ERROR_CHECK_ALLOC(remote_name
);
1746 return git_vector_insert(list
, remote_name
);
1749 int git_remote_list(git_strarray
*remotes_list
, git_repository
*repo
)
1753 git_vector list
= GIT_VECTOR_INIT
;
1755 if ((error
= git_repository_config__weakptr(&cfg
, repo
)) < 0)
1758 if ((error
= git_vector_init(&list
, 4, git__strcmp_cb
)) < 0)
1761 error
= git_config_foreach_match(
1762 cfg
, "^remote\\..*\\.(push)?url$", remote_list_cb
, &list
);
1765 git_vector_free_deep(&list
);
1769 git_vector_uniq(&list
, git__free
);
1771 remotes_list
->strings
=
1772 (char **)git_vector_detach(&remotes_list
->count
, NULL
, &list
);
1777 const git_indexer_progress
*git_remote_stats(git_remote
*remote
)
1780 return &remote
->stats
;
1783 git_remote_autotag_option_t
git_remote_autotag(const git_remote
*remote
)
1785 return remote
->download_tags
;
1788 int git_remote_set_autotag(git_repository
*repo
, const char *remote
, git_remote_autotag_option_t value
)
1790 git_buf var
= GIT_BUF_INIT
;
1794 assert(repo
&& remote
);
1796 if ((error
= ensure_remote_name_is_valid(remote
)) < 0)
1799 if ((error
= git_repository_config__weakptr(&config
, repo
)) < 0)
1802 if ((error
= git_buf_printf(&var
, CONFIG_TAGOPT_FMT
, remote
)))
1806 case GIT_REMOTE_DOWNLOAD_TAGS_NONE
:
1807 error
= git_config_set_string(config
, var
.ptr
, "--no-tags");
1809 case GIT_REMOTE_DOWNLOAD_TAGS_ALL
:
1810 error
= git_config_set_string(config
, var
.ptr
, "--tags");
1812 case GIT_REMOTE_DOWNLOAD_TAGS_AUTO
:
1813 error
= git_config_delete_entry(config
, var
.ptr
);
1814 if (error
== GIT_ENOTFOUND
)
1818 git_error_set(GIT_ERROR_INVALID
, "invalid value for the tagopt setting");
1822 git_buf_dispose(&var
);
1826 int git_remote_prune_refs(const git_remote
*remote
)
1828 return remote
->prune_refs
;
1831 static int rename_remote_config_section(
1832 git_repository
*repo
,
1833 const char *old_name
,
1834 const char *new_name
)
1836 git_buf old_section_name
= GIT_BUF_INIT
,
1837 new_section_name
= GIT_BUF_INIT
;
1840 if (git_buf_printf(&old_section_name
, "remote.%s", old_name
) < 0)
1844 (git_buf_printf(&new_section_name
, "remote.%s", new_name
) < 0))
1847 error
= git_config_rename_section(
1849 git_buf_cstr(&old_section_name
),
1850 new_name
? git_buf_cstr(&new_section_name
) : NULL
);
1853 git_buf_dispose(&old_section_name
);
1854 git_buf_dispose(&new_section_name
);
1859 struct update_data
{
1861 const char *old_remote_name
;
1862 const char *new_remote_name
;
1865 static int update_config_entries_cb(
1866 const git_config_entry
*entry
,
1869 struct update_data
*data
= (struct update_data
*)payload
;
1871 if (strcmp(entry
->value
, data
->old_remote_name
))
1874 return git_config_set_string(
1875 data
->config
, entry
->name
, data
->new_remote_name
);
1878 static int update_branch_remote_config_entry(
1879 git_repository
*repo
,
1880 const char *old_name
,
1881 const char *new_name
)
1884 struct update_data data
= { NULL
};
1886 if ((error
= git_repository_config__weakptr(&data
.config
, repo
)) < 0)
1889 data
.old_remote_name
= old_name
;
1890 data
.new_remote_name
= new_name
;
1892 return git_config_foreach_match(
1893 data
.config
, "branch\\..+\\.remote", update_config_entries_cb
, &data
);
1896 static int rename_one_remote_reference(
1897 git_reference
*reference_in
,
1898 const char *old_remote_name
,
1899 const char *new_remote_name
)
1902 git_reference
*ref
= NULL
, *dummy
= NULL
;
1903 git_buf
namespace = GIT_BUF_INIT
, old_namespace
= GIT_BUF_INIT
;
1904 git_buf new_name
= GIT_BUF_INIT
;
1905 git_buf log_message
= GIT_BUF_INIT
;
1909 if ((error
= git_buf_printf(&namespace, GIT_REFS_REMOTES_DIR
"%s/", new_remote_name
)) < 0)
1912 pfx_len
= strlen(GIT_REFS_REMOTES_DIR
) + strlen(old_remote_name
) + 1;
1913 git_buf_puts(&new_name
, namespace.ptr
);
1914 if ((error
= git_buf_puts(&new_name
, git_reference_name(reference_in
) + pfx_len
)) < 0)
1917 if ((error
= git_buf_printf(&log_message
,
1918 "renamed remote %s to %s",
1919 old_remote_name
, new_remote_name
)) < 0)
1922 if ((error
= git_reference_rename(&ref
, reference_in
, git_buf_cstr(&new_name
), 1,
1923 git_buf_cstr(&log_message
))) < 0)
1926 if (git_reference_type(ref
) != GIT_REFERENCE_SYMBOLIC
)
1929 /* Handle refs like origin/HEAD -> origin/master */
1930 target
= git_reference_symbolic_target(ref
);
1931 if ((error
= git_buf_printf(&old_namespace
, GIT_REFS_REMOTES_DIR
"%s/", old_remote_name
)) < 0)
1934 if (git__prefixcmp(target
, old_namespace
.ptr
))
1937 git_buf_clear(&new_name
);
1938 git_buf_puts(&new_name
, namespace.ptr
);
1939 if ((error
= git_buf_puts(&new_name
, target
+ pfx_len
)) < 0)
1942 error
= git_reference_symbolic_set_target(&dummy
, ref
, git_buf_cstr(&new_name
),
1943 git_buf_cstr(&log_message
));
1945 git_reference_free(dummy
);
1948 git_reference_free(reference_in
);
1949 git_reference_free(ref
);
1950 git_buf_dispose(&namespace);
1951 git_buf_dispose(&old_namespace
);
1952 git_buf_dispose(&new_name
);
1953 git_buf_dispose(&log_message
);
1957 static int rename_remote_references(
1958 git_repository
*repo
,
1959 const char *old_name
,
1960 const char *new_name
)
1963 git_buf buf
= GIT_BUF_INIT
;
1965 git_reference_iterator
*iter
;
1967 if ((error
= git_buf_printf(&buf
, GIT_REFS_REMOTES_DIR
"%s/*", old_name
)) < 0)
1970 error
= git_reference_iterator_glob_new(&iter
, repo
, git_buf_cstr(&buf
));
1971 git_buf_dispose(&buf
);
1976 while ((error
= git_reference_next(&ref
, iter
)) == 0) {
1977 if ((error
= rename_one_remote_reference(ref
, old_name
, new_name
)) < 0)
1981 git_reference_iterator_free(iter
);
1983 return (error
== GIT_ITEROVER
) ? 0 : error
;
1986 static int rename_fetch_refspecs(git_vector
*problems
, git_remote
*remote
, const char *new_name
)
1989 git_buf base
= GIT_BUF_INIT
, var
= GIT_BUF_INIT
, val
= GIT_BUF_INIT
;
1990 const git_refspec
*spec
;
1994 if ((error
= git_repository_config__weakptr(&config
, remote
->repo
)) < 0)
1997 if ((error
= git_vector_init(problems
, 1, NULL
)) < 0)
2000 if ((error
= default_fetchspec_for_name(&base
, remote
->name
)) < 0)
2003 git_vector_foreach(&remote
->refspecs
, i
, spec
) {
2007 /* Does the dst part of the refspec follow the expected format? */
2008 if (strcmp(git_buf_cstr(&base
), spec
->string
)) {
2011 dup
= git__strdup(spec
->string
);
2012 GIT_ERROR_CHECK_ALLOC(dup
);
2014 if ((error
= git_vector_insert(problems
, dup
)) < 0)
2020 /* If we do want to move it to the new section */
2022 git_buf_clear(&val
);
2023 git_buf_clear(&var
);
2025 if (default_fetchspec_for_name(&val
, new_name
) < 0 ||
2026 git_buf_printf(&var
, "remote.%s.fetch", new_name
) < 0)
2032 if ((error
= git_config_set_string(
2033 config
, git_buf_cstr(&var
), git_buf_cstr(&val
))) < 0)
2037 git_buf_dispose(&base
);
2038 git_buf_dispose(&var
);
2039 git_buf_dispose(&val
);
2043 git_vector_foreach(problems
, i
, str
)
2046 git_vector_free(problems
);
2052 int git_remote_rename(git_strarray
*out
, git_repository
*repo
, const char *name
, const char *new_name
)
2055 git_vector problem_refspecs
= GIT_VECTOR_INIT
;
2056 git_remote
*remote
= NULL
;
2058 assert(out
&& repo
&& name
&& new_name
);
2060 if ((error
= git_remote_lookup(&remote
, repo
, name
)) < 0)
2063 if ((error
= ensure_remote_name_is_valid(new_name
)) < 0)
2066 if ((error
= ensure_remote_doesnot_exist(repo
, new_name
)) < 0)
2069 if ((error
= rename_remote_config_section(repo
, name
, new_name
)) < 0)
2072 if ((error
= update_branch_remote_config_entry(repo
, name
, new_name
)) < 0)
2075 if ((error
= rename_remote_references(repo
, name
, new_name
)) < 0)
2078 if ((error
= rename_fetch_refspecs(&problem_refspecs
, remote
, new_name
)) < 0)
2081 out
->count
= problem_refspecs
.length
;
2082 out
->strings
= (char **) problem_refspecs
.contents
;
2086 git_vector_free(&problem_refspecs
);
2088 git_remote_free(remote
);
2092 int git_remote_is_valid_name(
2093 const char *remote_name
)
2095 git_buf buf
= GIT_BUF_INIT
;
2096 git_refspec refspec
;
2099 if (!remote_name
|| *remote_name
== '\0')
2102 git_buf_printf(&buf
, "refs/heads/test:refs/remotes/%s/test", remote_name
);
2103 error
= git_refspec__parse(&refspec
, git_buf_cstr(&buf
), true);
2105 git_buf_dispose(&buf
);
2106 git_refspec__dispose(&refspec
);
2112 git_refspec
*git_remote__matching_refspec(git_remote
*remote
, const char *refname
)
2117 git_vector_foreach(&remote
->active_refspecs
, i
, spec
) {
2121 if (git_refspec_src_matches(spec
, refname
))
2128 git_refspec
*git_remote__matching_dst_refspec(git_remote
*remote
, const char *refname
)
2133 git_vector_foreach(&remote
->active_refspecs
, i
, spec
) {
2137 if (git_refspec_dst_matches(spec
, refname
))
2144 int git_remote_add_fetch(git_repository
*repo
, const char *remote
, const char *refspec
)
2146 return write_add_refspec(repo
, remote
, refspec
, true);
2149 int git_remote_add_push(git_repository
*repo
, const char *remote
, const char *refspec
)
2151 return write_add_refspec(repo
, remote
, refspec
, false);
2154 static int copy_refspecs(git_strarray
*array
, const git_remote
*remote
, unsigned int push
)
2157 git_vector refspecs
;
2161 if (git_vector_init(&refspecs
, remote
->refspecs
.length
, NULL
) < 0)
2164 git_vector_foreach(&remote
->refspecs
, i
, spec
) {
2165 if (spec
->push
!= push
)
2168 if ((dup
= git__strdup(spec
->string
)) == NULL
)
2171 if (git_vector_insert(&refspecs
, dup
) < 0) {
2177 array
->strings
= (char **)refspecs
.contents
;
2178 array
->count
= refspecs
.length
;
2183 git_vector_free_deep(&refspecs
);
2188 int git_remote_get_fetch_refspecs(git_strarray
*array
, const git_remote
*remote
)
2190 return copy_refspecs(array
, remote
, false);
2193 int git_remote_get_push_refspecs(git_strarray
*array
, const git_remote
*remote
)
2195 return copy_refspecs(array
, remote
, true);
2198 size_t git_remote_refspec_count(const git_remote
*remote
)
2200 return remote
->refspecs
.length
;
2203 const git_refspec
*git_remote_get_refspec(const git_remote
*remote
, size_t n
)
2205 return git_vector_get(&remote
->refspecs
, n
);
2208 int git_remote_init_callbacks(git_remote_callbacks
*opts
, unsigned int version
)
2210 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
2211 opts
, version
, git_remote_callbacks
, GIT_REMOTE_CALLBACKS_INIT
);
2215 /* asserts a branch.<foo>.remote format */
2216 static const char *name_offset(size_t *len_out
, const char *name
)
2221 prefix_len
= strlen("remote.");
2222 dot
= strchr(name
+ prefix_len
, '.');
2226 *len_out
= dot
- name
- prefix_len
;
2227 return name
+ prefix_len
;
2230 static int remove_branch_config_related_entries(
2231 git_repository
*repo
,
2232 const char *remote_name
)
2236 git_config_entry
*entry
;
2237 git_config_iterator
*iter
;
2238 git_buf buf
= GIT_BUF_INIT
;
2240 if ((error
= git_repository_config__weakptr(&config
, repo
)) < 0)
2243 if ((error
= git_config_iterator_glob_new(&iter
, config
, "branch\\..+\\.remote")) < 0)
2246 /* find any branches with us as upstream and remove that config */
2247 while ((error
= git_config_next(&entry
, iter
)) == 0) {
2251 if (strcmp(remote_name
, entry
->value
))
2254 branch
= name_offset(&branch_len
, entry
->name
);
2256 git_buf_clear(&buf
);
2257 if (git_buf_printf(&buf
, "branch.%.*s.merge", (int)branch_len
, branch
) < 0)
2260 if ((error
= git_config_delete_entry(config
, git_buf_cstr(&buf
))) < 0) {
2261 if (error
!= GIT_ENOTFOUND
)
2266 git_buf_clear(&buf
);
2267 if (git_buf_printf(&buf
, "branch.%.*s.remote", (int)branch_len
, branch
) < 0)
2270 if ((error
= git_config_delete_entry(config
, git_buf_cstr(&buf
))) < 0) {
2271 if (error
!= GIT_ENOTFOUND
)
2277 if (error
== GIT_ITEROVER
)
2280 git_buf_dispose(&buf
);
2281 git_config_iterator_free(iter
);
2285 static int remove_refs(git_repository
*repo
, const git_refspec
*spec
)
2287 git_reference_iterator
*iter
= NULL
;
2294 if ((error
= git_vector_init(&refs
, 8, NULL
)) < 0)
2297 if ((error
= git_reference_iterator_new(&iter
, repo
)) < 0)
2300 while ((error
= git_reference_next_name(&name
, iter
)) == 0) {
2301 if (!git_refspec_dst_matches(spec
, name
))
2304 dup
= git__strdup(name
);
2310 if ((error
= git_vector_insert(&refs
, dup
)) < 0)
2313 if (error
== GIT_ITEROVER
)
2318 git_vector_foreach(&refs
, i
, name
) {
2319 if ((error
= git_reference_remove(repo
, name
)) < 0)
2324 git_reference_iterator_free(iter
);
2325 git_vector_foreach(&refs
, i
, dup
) {
2328 git_vector_free(&refs
);
2332 static int remove_remote_tracking(git_repository
*repo
, const char *remote_name
)
2338 /* we want to use what's on the config, regardless of changes to the instance in memory */
2339 if ((error
= git_remote_lookup(&remote
, repo
, remote_name
)) < 0)
2342 count
= git_remote_refspec_count(remote
);
2343 for (i
= 0; i
< count
; i
++) {
2344 const git_refspec
*refspec
= git_remote_get_refspec(remote
, i
);
2346 /* shouldn't ever actually happen */
2347 if (refspec
== NULL
)
2350 if ((error
= remove_refs(repo
, refspec
)) < 0)
2354 git_remote_free(remote
);
2358 int git_remote_delete(git_repository
*repo
, const char *name
)
2362 assert(repo
&& name
);
2364 if ((error
= remove_branch_config_related_entries(repo
, name
)) < 0 ||
2365 (error
= remove_remote_tracking(repo
, name
)) < 0 ||
2366 (error
= rename_remote_config_section(repo
, name
, NULL
)) < 0)
2372 int git_remote_default_branch(git_buf
*out
, git_remote
*remote
)
2374 const git_remote_head
**heads
;
2375 const git_remote_head
*guess
= NULL
;
2376 const git_oid
*head_id
;
2377 size_t heads_len
, i
;
2378 git_buf local_default
= GIT_BUF_INIT
;
2383 if ((error
= git_remote_ls(&heads
, &heads_len
, remote
)) < 0)
2386 if (heads_len
== 0 || strcmp(heads
[0]->name
, GIT_HEAD_FILE
)) {
2387 error
= GIT_ENOTFOUND
;
2391 git_buf_sanitize(out
);
2393 /* the first one must be HEAD so if that has the symref info, we're done */
2394 if (heads
[0]->symref_target
) {
2395 error
= git_buf_puts(out
, heads
[0]->symref_target
);
2400 * If there's no symref information, we have to look over them
2401 * and guess. We return the first match unless the default
2402 * branch is a candidate. Then we return the default branch.
2405 if ((error
= git_repository_initialbranch(&local_default
, remote
->repo
)) < 0)
2408 head_id
= &heads
[0]->oid
;
2410 for (i
= 1; i
< heads_len
; i
++) {
2411 if (git_oid_cmp(head_id
, &heads
[i
]->oid
))
2414 if (git__prefixcmp(heads
[i
]->name
, GIT_REFS_HEADS_DIR
))
2422 if (!git__strcmp(local_default
.ptr
, heads
[i
]->name
)) {
2429 error
= GIT_ENOTFOUND
;
2433 error
= git_buf_puts(out
, guess
->name
);
2436 git_buf_dispose(&local_default
);
2440 int git_remote_upload(git_remote
*remote
, const git_strarray
*refspecs
, const git_push_options
*opts
)
2446 const git_remote_callbacks
*cbs
= NULL
;
2447 git_remote_connection_opts conn
= GIT_REMOTE_CONNECTION_OPTIONS_INIT
;
2451 if (!remote
->repo
) {
2452 git_error_set(GIT_ERROR_INVALID
, "cannot download detached remote");
2457 cbs
= &opts
->callbacks
;
2458 conn
.custom_headers
= &opts
->custom_headers
;
2459 conn
.proxy
= &opts
->proxy_opts
;
2462 if (!git_remote_connected(remote
) &&
2463 (error
= git_remote__connect(remote
, GIT_DIRECTION_PUSH
, cbs
, &conn
)) < 0)
2466 free_refspecs(&remote
->active_refspecs
);
2467 if ((error
= dwim_refspecs(&remote
->active_refspecs
, &remote
->refspecs
, &remote
->refs
)) < 0)
2471 git_push_free(remote
->push
);
2472 remote
->push
= NULL
;
2475 if ((error
= git_push_new(&remote
->push
, remote
)) < 0)
2478 push
= remote
->push
;
2480 if (opts
&& (error
= git_push_set_options(push
, opts
)) < 0)
2483 if (refspecs
&& refspecs
->count
> 0) {
2484 for (i
= 0; i
< refspecs
->count
; i
++) {
2485 if ((error
= git_push_add_refspec(push
, refspecs
->strings
[i
])) < 0)
2489 git_vector_foreach(&remote
->refspecs
, i
, spec
) {
2492 if ((error
= git_push_add_refspec(push
, spec
->string
)) < 0)
2497 if ((error
= git_push_finish(push
, cbs
)) < 0)
2500 if (cbs
&& cbs
->push_update_reference
&&
2501 (error
= git_push_status_foreach(push
, cbs
->push_update_reference
, cbs
->payload
)) < 0)
2508 int git_remote_push(git_remote
*remote
, const git_strarray
*refspecs
, const git_push_options
*opts
)
2511 const git_remote_callbacks
*cbs
= NULL
;
2512 const git_strarray
*custom_headers
= NULL
;
2513 const git_proxy_options
*proxy
= NULL
;
2517 if (!remote
->repo
) {
2518 git_error_set(GIT_ERROR_INVALID
, "cannot download detached remote");
2523 GIT_ERROR_CHECK_VERSION(&opts
->callbacks
, GIT_REMOTE_CALLBACKS_VERSION
, "git_remote_callbacks");
2524 cbs
= &opts
->callbacks
;
2525 custom_headers
= &opts
->custom_headers
;
2526 GIT_ERROR_CHECK_VERSION(&opts
->proxy_opts
, GIT_PROXY_OPTIONS_VERSION
, "git_proxy_options");
2527 proxy
= &opts
->proxy_opts
;
2532 if ((error
= git_remote_connect(remote
, GIT_DIRECTION_PUSH
, cbs
, proxy
, custom_headers
)) < 0)
2535 if ((error
= git_remote_upload(remote
, refspecs
, opts
)) < 0)
2538 error
= git_remote_update_tips(remote
, cbs
, 0, 0, NULL
);
2540 git_remote_disconnect(remote
);
2544 #define PREFIX "url"
2545 #define SUFFIX_FETCH "insteadof"
2546 #define SUFFIX_PUSH "pushinsteadof"
2548 char *apply_insteadof(git_config
*config
, const char *url
, int direction
)
2550 size_t match_length
, prefix_length
, suffix_length
;
2551 char *replacement
= NULL
;
2554 git_buf result
= GIT_BUF_INIT
;
2555 git_config_entry
*entry
;
2556 git_config_iterator
*iter
;
2560 assert(direction
== GIT_DIRECTION_FETCH
|| direction
== GIT_DIRECTION_PUSH
);
2562 /* Add 1 to prefix/suffix length due to the additional escaped dot */
2563 prefix_length
= strlen(PREFIX
) + 1;
2564 if (direction
== GIT_DIRECTION_FETCH
) {
2565 regexp
= PREFIX
"\\..*\\." SUFFIX_FETCH
;
2566 suffix_length
= strlen(SUFFIX_FETCH
) + 1;
2568 regexp
= PREFIX
"\\..*\\." SUFFIX_PUSH
;
2569 suffix_length
= strlen(SUFFIX_PUSH
) + 1;
2572 if (git_config_iterator_glob_new(&iter
, config
, regexp
) < 0)
2576 while (git_config_next(&entry
, iter
) == 0) {
2577 size_t n
, replacement_length
;
2579 /* Check if entry value is a prefix of URL */
2580 if (git__prefixcmp(url
, entry
->value
))
2582 /* Check if entry value is longer than previous
2584 if ((n
= strlen(entry
->value
)) <= match_length
)
2587 git__free(replacement
);
2590 /* Cut off prefix and suffix of the value */
2591 replacement_length
=
2592 strlen(entry
->name
) - (prefix_length
+ suffix_length
);
2593 replacement
= git__strndup(entry
->name
+ prefix_length
,
2594 replacement_length
);
2597 git_config_iterator_free(iter
);
2599 if (match_length
== 0)
2600 return git__strdup(url
);
2602 git_buf_printf(&result
, "%s%s", replacement
, url
+ match_length
);
2604 git__free(replacement
);