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 error
= git_remote_name_is_valid(&valid
, name
);
89 if (!error
&& !valid
) {
92 "'%s' is not a valid remote name.", name
? name
: "(null)");
93 error
= GIT_EINVALIDSPEC
;
99 static int write_add_refspec(git_repository
*repo
, const char *name
, const char *refspec
, bool fetch
)
102 git_buf var
= GIT_BUF_INIT
;
107 if ((error
= git_repository_config__weakptr(&cfg
, repo
)) < 0)
110 fmt
= fetch
? CONFIG_FETCH_FMT
: CONFIG_PUSH_FMT
;
112 if ((error
= ensure_remote_name_is_valid(name
)) < 0)
115 if ((error
= git_refspec__parse(&spec
, refspec
, fetch
)) < 0)
118 git_refspec__dispose(&spec
);
120 if ((error
= git_buf_printf(&var
, fmt
, name
)) < 0)
124 * "$^" is an unmatchable regexp: it will not match anything at all, so
125 * all values will be considered new and we will not replace any
128 if ((error
= git_config_set_multivar(cfg
, var
.ptr
, "$^", refspec
)) < 0) {
133 git_buf_dispose(&var
);
137 static int canonicalize_url(git_buf
*out
, const char *in
)
139 if (in
== NULL
|| strlen(in
) == 0) {
140 git_error_set(GIT_ERROR_INVALID
, "cannot set empty URL");
141 return GIT_EINVALIDSPEC
;
145 /* Given a UNC path like \\server\path, we need to convert this
146 * to //server/path for compatibility with core git.
148 if (in
[0] == '\\' && in
[1] == '\\' &&
149 (git__isalpha(in
[2]) || git__isdigit(in
[2]))) {
151 for (c
= in
; *c
; c
++)
152 git_buf_putc(out
, *c
== '\\' ? '/' : *c
);
154 return git_buf_oom(out
) ? -1 : 0;
158 return git_buf_puts(out
, in
);
161 static int default_fetchspec_for_name(git_buf
*buf
, const char *name
)
163 if (git_buf_printf(buf
, "+refs/heads/*:refs/remotes/%s/*", name
) < 0)
169 static int ensure_remote_doesnot_exist(git_repository
*repo
, const char *name
)
174 error
= git_remote_lookup(&remote
, repo
, name
);
176 if (error
== GIT_ENOTFOUND
)
182 git_remote_free(remote
);
184 git_error_set(GIT_ERROR_CONFIG
, "remote '%s' already exists", name
);
189 int git_remote_create_options_init(git_remote_create_options
*opts
, unsigned int version
)
191 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
192 opts
, version
, git_remote_create_options
, GIT_REMOTE_CREATE_OPTIONS_INIT
);
196 #ifndef GIT_DEPRECATE_HARD
197 int git_remote_create_init_options(git_remote_create_options
*opts
, unsigned int version
)
199 return git_remote_create_options_init(opts
, version
);
203 int git_remote_create_with_opts(git_remote
**out
, const char *url
, const git_remote_create_options
*opts
)
205 git_remote
*remote
= NULL
;
206 git_config
*config_ro
= NULL
, *config_rw
;
207 git_buf canonical_url
= GIT_BUF_INIT
;
208 git_buf var
= GIT_BUF_INIT
;
209 git_buf specbuf
= GIT_BUF_INIT
;
210 const git_remote_create_options dummy_opts
= GIT_REMOTE_CREATE_OPTIONS_INIT
;
220 GIT_ERROR_CHECK_VERSION(opts
, GIT_REMOTE_CREATE_OPTIONS_VERSION
, "git_remote_create_options");
222 if (opts
->name
!= NULL
) {
223 if ((error
= ensure_remote_name_is_valid(opts
->name
)) < 0)
226 if (opts
->repository
&&
227 (error
= ensure_remote_doesnot_exist(opts
->repository
, opts
->name
)) < 0)
231 if (opts
->repository
) {
232 if ((error
= git_repository_config_snapshot(&config_ro
, opts
->repository
)) < 0)
236 remote
= git__calloc(1, sizeof(git_remote
));
237 GIT_ERROR_CHECK_ALLOC(remote
);
239 remote
->repo
= opts
->repository
;
241 if ((error
= git_vector_init(&remote
->refs
, 8, NULL
)) < 0 ||
242 (error
= canonicalize_url(&canonical_url
, url
)) < 0)
245 if (opts
->repository
&& !(opts
->flags
& GIT_REMOTE_CREATE_SKIP_INSTEADOF
)) {
246 remote
->url
= apply_insteadof(config_ro
, canonical_url
.ptr
, GIT_DIRECTION_FETCH
);
248 remote
->url
= git__strdup(canonical_url
.ptr
);
250 GIT_ERROR_CHECK_ALLOC(remote
->url
);
252 if (opts
->name
!= NULL
) {
253 remote
->name
= git__strdup(opts
->name
);
254 GIT_ERROR_CHECK_ALLOC(remote
->name
);
256 if (opts
->repository
&&
257 ((error
= git_buf_printf(&var
, CONFIG_URL_FMT
, opts
->name
)) < 0 ||
258 (error
= git_repository_config__weakptr(&config_rw
, opts
->repository
)) < 0 ||
259 (error
= git_config_set_string(config_rw
, var
.ptr
, canonical_url
.ptr
)) < 0))
263 if (opts
->fetchspec
!= NULL
||
264 (opts
->name
&& !(opts
->flags
& GIT_REMOTE_CREATE_SKIP_DEFAULT_FETCHSPEC
))) {
265 const char *fetch
= NULL
;
266 if (opts
->fetchspec
) {
267 fetch
= opts
->fetchspec
;
269 if ((error
= default_fetchspec_for_name(&specbuf
, opts
->name
)) < 0)
272 fetch
= git_buf_cstr(&specbuf
);
275 if ((error
= add_refspec(remote
, fetch
, true)) < 0)
278 /* only write for named remotes with a repository */
279 if (opts
->repository
&& opts
->name
&&
280 ((error
= write_add_refspec(opts
->repository
, opts
->name
, fetch
, true)) < 0 ||
281 (error
= lookup_remote_prune_config(remote
, config_ro
, opts
->name
)) < 0))
284 /* Move the data over to where the matching functions can find them */
285 if ((error
= dwim_refspecs(&remote
->active_refspecs
, &remote
->refspecs
, &remote
->refs
)) < 0)
289 /* A remote without a name doesn't download tags */
291 remote
->download_tags
= GIT_REMOTE_DOWNLOAD_TAGS_NONE
;
293 remote
->download_tags
= GIT_REMOTE_DOWNLOAD_TAGS_AUTO
;
296 git_buf_dispose(&var
);
303 git_remote_free(remote
);
305 git_config_free(config_ro
);
306 git_buf_dispose(&specbuf
);
307 git_buf_dispose(&canonical_url
);
308 git_buf_dispose(&var
);
312 int git_remote_create(git_remote
**out
, git_repository
*repo
, const char *name
, const char *url
)
314 git_buf buf
= GIT_BUF_INIT
;
316 git_remote_create_options opts
= GIT_REMOTE_CREATE_OPTIONS_INIT
;
318 /* Those 2 tests are duplicated here because of backward-compatibility */
319 if ((error
= ensure_remote_name_is_valid(name
)) < 0)
322 if (canonicalize_url(&buf
, url
) < 0)
327 opts
.repository
= repo
;
330 error
= git_remote_create_with_opts(out
, url
, &opts
);
332 git_buf_dispose(&buf
);
337 int git_remote_create_with_fetchspec(git_remote
**out
, git_repository
*repo
, const char *name
, const char *url
, const char *fetch
)
340 git_remote_create_options opts
= GIT_REMOTE_CREATE_OPTIONS_INIT
;
342 if ((error
= ensure_remote_name_is_valid(name
)) < 0)
345 opts
.repository
= repo
;
347 opts
.fetchspec
= fetch
;
348 opts
.flags
= GIT_REMOTE_CREATE_SKIP_DEFAULT_FETCHSPEC
;
350 return git_remote_create_with_opts(out
, url
, &opts
);
353 int git_remote_create_anonymous(git_remote
**out
, git_repository
*repo
, const char *url
)
355 git_remote_create_options opts
= GIT_REMOTE_CREATE_OPTIONS_INIT
;
357 opts
.repository
= repo
;
359 return git_remote_create_with_opts(out
, url
, &opts
);
362 int git_remote_create_detached(git_remote
**out
, const char *url
)
364 return git_remote_create_with_opts(out
, url
, NULL
);
367 int git_remote_dup(git_remote
**dest
, git_remote
*source
)
372 git_remote
*remote
= git__calloc(1, sizeof(git_remote
));
373 GIT_ERROR_CHECK_ALLOC(remote
);
375 if (source
->name
!= NULL
) {
376 remote
->name
= git__strdup(source
->name
);
377 GIT_ERROR_CHECK_ALLOC(remote
->name
);
380 if (source
->url
!= NULL
) {
381 remote
->url
= git__strdup(source
->url
);
382 GIT_ERROR_CHECK_ALLOC(remote
->url
);
385 if (source
->pushurl
!= NULL
) {
386 remote
->pushurl
= git__strdup(source
->pushurl
);
387 GIT_ERROR_CHECK_ALLOC(remote
->pushurl
);
390 remote
->repo
= source
->repo
;
391 remote
->download_tags
= source
->download_tags
;
392 remote
->prune_refs
= source
->prune_refs
;
394 if (git_vector_init(&remote
->refs
, 32, NULL
) < 0 ||
395 git_vector_init(&remote
->refspecs
, 2, NULL
) < 0 ||
396 git_vector_init(&remote
->active_refspecs
, 2, NULL
) < 0) {
401 git_vector_foreach(&source
->refspecs
, i
, spec
) {
402 if ((error
= add_refspec(remote
, spec
->string
, !spec
->push
)) < 0)
416 struct refspec_cb_data
{
421 static int refspec_cb(const git_config_entry
*entry
, void *payload
)
423 struct refspec_cb_data
*data
= (struct refspec_cb_data
*)payload
;
424 return add_refspec(data
->remote
, entry
->value
, data
->fetch
);
427 static int get_optional_config(
428 bool *found
, git_config
*config
, git_buf
*buf
,
429 git_config_foreach_cb cb
, void *payload
)
432 const char *key
= git_buf_cstr(buf
);
434 if (git_buf_oom(buf
))
438 error
= git_config_get_multivar_foreach(config
, key
, NULL
, cb
, payload
);
440 error
= git_config_get_string(payload
, config
, key
);
445 if (error
== GIT_ENOTFOUND
) {
453 int git_remote_lookup(git_remote
**out
, git_repository
*repo
, const char *name
)
455 git_remote
*remote
= NULL
;
456 git_buf buf
= GIT_BUF_INIT
;
460 struct refspec_cb_data data
= { NULL
};
461 bool optional_setting_found
= false, found
;
464 GIT_ASSERT_ARG(repo
);
465 GIT_ASSERT_ARG(name
);
467 if ((error
= ensure_remote_name_is_valid(name
)) < 0)
470 if ((error
= git_repository_config_snapshot(&config
, repo
)) < 0)
473 remote
= git__calloc(1, sizeof(git_remote
));
474 GIT_ERROR_CHECK_ALLOC(remote
);
476 remote
->name
= git__strdup(name
);
477 GIT_ERROR_CHECK_ALLOC(remote
->name
);
479 if (git_vector_init(&remote
->refs
, 32, NULL
) < 0 ||
480 git_vector_init(&remote
->refspecs
, 2, NULL
) < 0 ||
481 git_vector_init(&remote
->passive_refspecs
, 2, NULL
) < 0 ||
482 git_vector_init(&remote
->active_refspecs
, 2, NULL
) < 0) {
487 if ((error
= git_buf_printf(&buf
, "remote.%s.url", name
)) < 0)
490 if ((error
= get_optional_config(&found
, config
, &buf
, NULL
, (void *)&val
)) < 0)
493 optional_setting_found
|= found
;
496 remote
->download_tags
= GIT_REMOTE_DOWNLOAD_TAGS_AUTO
;
498 if (found
&& strlen(val
) > 0) {
499 remote
->url
= apply_insteadof(config
, val
, GIT_DIRECTION_FETCH
);
500 GIT_ERROR_CHECK_ALLOC(remote
->url
);
505 git_buf_printf(&buf
, "remote.%s.pushurl", name
);
507 if ((error
= get_optional_config(&found
, config
, &buf
, NULL
, (void *)&val
)) < 0)
510 optional_setting_found
|= found
;
512 if (!optional_setting_found
) {
513 error
= GIT_ENOTFOUND
;
514 git_error_set(GIT_ERROR_CONFIG
, "remote '%s' does not exist", name
);
518 if (found
&& strlen(val
) > 0) {
519 remote
->pushurl
= apply_insteadof(config
, val
, GIT_DIRECTION_PUSH
);
520 GIT_ERROR_CHECK_ALLOC(remote
->pushurl
);
523 data
.remote
= remote
;
527 git_buf_printf(&buf
, "remote.%s.fetch", name
);
529 if ((error
= get_optional_config(NULL
, config
, &buf
, refspec_cb
, &data
)) < 0)
534 git_buf_printf(&buf
, "remote.%s.push", name
);
536 if ((error
= get_optional_config(NULL
, config
, &buf
, refspec_cb
, &data
)) < 0)
539 if ((error
= download_tags_value(remote
, config
)) < 0)
542 if ((error
= lookup_remote_prune_config(remote
, config
, name
)) < 0)
545 /* Move the data over to where the matching functions can find them */
546 if ((error
= dwim_refspecs(&remote
->active_refspecs
, &remote
->refspecs
, &remote
->refs
)) < 0)
552 git_config_free(config
);
553 git_buf_dispose(&buf
);
556 git_remote_free(remote
);
561 static int lookup_remote_prune_config(git_remote
*remote
, git_config
*config
, const char *name
)
563 git_buf buf
= GIT_BUF_INIT
;
566 git_buf_printf(&buf
, "remote.%s.prune", name
);
568 if ((error
= git_config_get_bool(&remote
->prune_refs
, config
, git_buf_cstr(&buf
))) < 0) {
569 if (error
== GIT_ENOTFOUND
) {
572 if ((error
= git_config_get_bool(&remote
->prune_refs
, config
, "fetch.prune")) < 0) {
573 if (error
== GIT_ENOTFOUND
) {
581 git_buf_dispose(&buf
);
585 const char *git_remote_name(const git_remote
*remote
)
587 GIT_ASSERT_ARG_WITH_RETVAL(remote
, NULL
);
591 git_repository
*git_remote_owner(const git_remote
*remote
)
593 GIT_ASSERT_ARG_WITH_RETVAL(remote
, NULL
);
597 const char *git_remote_url(const git_remote
*remote
)
599 GIT_ASSERT_ARG_WITH_RETVAL(remote
, NULL
);
603 int git_remote_set_instance_url(git_remote
*remote
, const char *url
)
607 GIT_ASSERT_ARG(remote
);
610 if ((tmp
= git__strdup(url
)) == NULL
)
613 git__free(remote
->url
);
619 static int set_url(git_repository
*repo
, const char *remote
, const char *pattern
, const char *url
)
622 git_buf buf
= GIT_BUF_INIT
, canonical_url
= GIT_BUF_INIT
;
625 GIT_ASSERT_ARG(repo
);
626 GIT_ASSERT_ARG(remote
);
628 if ((error
= ensure_remote_name_is_valid(remote
)) < 0)
631 if ((error
= git_repository_config__weakptr(&cfg
, repo
)) < 0)
634 if ((error
= git_buf_printf(&buf
, pattern
, remote
)) < 0)
638 if ((error
= canonicalize_url(&canonical_url
, url
)) < 0)
641 error
= git_config_set_string(cfg
, buf
.ptr
, url
);
643 error
= git_config_delete_entry(cfg
, buf
.ptr
);
647 git_buf_dispose(&canonical_url
);
648 git_buf_dispose(&buf
);
653 int git_remote_set_url(git_repository
*repo
, const char *remote
, const char *url
)
655 return set_url(repo
, remote
, CONFIG_URL_FMT
, url
);
658 const char *git_remote_pushurl(const git_remote
*remote
)
660 GIT_ASSERT_ARG_WITH_RETVAL(remote
, NULL
);
661 return remote
->pushurl
;
664 int git_remote_set_instance_pushurl(git_remote
*remote
, const char *url
)
668 GIT_ASSERT_ARG(remote
);
671 if ((tmp
= git__strdup(url
)) == NULL
)
674 git__free(remote
->pushurl
);
675 remote
->pushurl
= tmp
;
680 int git_remote_set_pushurl(git_repository
*repo
, const char *remote
, const char *url
)
682 return set_url(repo
, remote
, CONFIG_PUSHURL_FMT
, url
);
685 static int resolve_url(
686 git_buf
*resolved_url
,
689 const git_remote_callbacks
*callbacks
)
691 #ifdef GIT_DEPRECATE_HARD
692 GIT_UNUSED(direction
);
693 GIT_UNUSED(callbacks
);
697 if (callbacks
&& callbacks
->resolve_url
) {
698 git_buf_clear(resolved_url
);
699 status
= callbacks
->resolve_url(resolved_url
, url
, direction
, callbacks
->payload
);
700 if (status
!= GIT_PASSTHROUGH
) {
701 git_error_set_after_callback_function(status
, "git_resolve_url_cb");
703 if ((error
= git_buf_sanitize(resolved_url
)) < 0)
711 return git_buf_sets(resolved_url
, url
);
714 int git_remote__urlfordirection(
716 struct git_remote
*remote
,
718 const git_remote_callbacks
*callbacks
)
720 const char *url
= NULL
;
722 GIT_ASSERT_ARG(remote
);
723 GIT_ASSERT_ARG(direction
== GIT_DIRECTION_FETCH
|| direction
== GIT_DIRECTION_PUSH
);
725 if (callbacks
&& callbacks
->remote_ready
) {
726 int status
= callbacks
->remote_ready(remote
, direction
, callbacks
->payload
);
728 if (status
!= 0 && status
!= GIT_PASSTHROUGH
) {
729 git_error_set_after_callback_function(status
, "git_remote_ready_cb");
734 if (direction
== GIT_DIRECTION_FETCH
)
736 else if (direction
== GIT_DIRECTION_PUSH
)
737 url
= remote
->pushurl
? remote
->pushurl
: remote
->url
;
740 git_error_set(GIT_ERROR_INVALID
,
741 "malformed remote '%s' - missing %s URL",
742 remote
->name
? remote
->name
: "(anonymous)",
743 direction
== GIT_DIRECTION_FETCH
? "fetch" : "push");
747 return resolve_url(url_out
, url
, direction
, callbacks
);
750 static int remote_transport_set_callbacks(git_transport
*t
, const git_remote_callbacks
*cbs
)
752 if (!t
->set_callbacks
|| !cbs
)
755 return t
->set_callbacks(t
, cbs
->sideband_progress
, NULL
,
756 cbs
->certificate_check
, cbs
->payload
);
759 static int set_transport_custom_headers(git_transport
*t
, const git_strarray
*custom_headers
)
761 if (!t
->set_custom_headers
)
764 return t
->set_custom_headers(t
, custom_headers
);
767 int git_remote__connect(git_remote
*remote
, git_direction direction
, const git_remote_callbacks
*callbacks
, const git_remote_connection_opts
*conn
)
770 git_buf url
= GIT_BUF_INIT
;
771 int flags
= GIT_TRANSPORTFLAGS_NONE
;
773 void *payload
= NULL
;
774 git_credential_acquire_cb credentials
= NULL
;
775 git_transport_cb transport
= NULL
;
777 GIT_ASSERT_ARG(remote
);
780 GIT_ERROR_CHECK_VERSION(callbacks
, GIT_REMOTE_CALLBACKS_VERSION
, "git_remote_callbacks");
781 credentials
= callbacks
->credentials
;
782 transport
= callbacks
->transport
;
783 payload
= callbacks
->payload
;
787 GIT_ERROR_CHECK_VERSION(conn
->proxy
, GIT_PROXY_OPTIONS_VERSION
, "git_proxy_options");
789 t
= remote
->transport
;
791 if ((error
= git_remote__urlfordirection(&url
, remote
, direction
, callbacks
)) < 0)
794 /* If we don't have a transport object yet, and the caller specified a
795 * custom transport factory, use that */
796 if (!t
&& transport
&&
797 (error
= transport(&t
, remote
, payload
)) < 0)
800 /* If we still don't have a transport, then use the global
801 * transport registrations which map URI schemes to transport factories */
802 if (!t
&& (error
= git_transport_new(&t
, remote
, url
.ptr
)) < 0)
805 if ((error
= set_transport_custom_headers(t
, conn
->custom_headers
)) != 0)
808 if ((error
= remote_transport_set_callbacks(t
, callbacks
)) < 0 ||
809 (error
= t
->connect(t
, url
.ptr
, credentials
, payload
, conn
->proxy
, direction
, flags
)) != 0)
812 remote
->transport
= t
;
814 git_buf_dispose(&url
);
822 git_buf_dispose(&url
);
824 if (t
== remote
->transport
)
825 remote
->transport
= NULL
;
830 int git_remote_connect(git_remote
*remote
, git_direction direction
, const git_remote_callbacks
*callbacks
, const git_proxy_options
*proxy
, const git_strarray
*custom_headers
)
832 git_remote_connection_opts conn
;
835 conn
.custom_headers
= custom_headers
;
837 return git_remote__connect(remote
, direction
, callbacks
, &conn
);
840 int git_remote_ls(const git_remote_head
***out
, size_t *size
, git_remote
*remote
)
842 GIT_ASSERT_ARG(remote
);
844 if (!remote
->transport
) {
845 git_error_set(GIT_ERROR_NET
, "this remote has never connected");
849 return remote
->transport
->ls(out
, size
, remote
->transport
);
852 static int lookup_config(char **out
, git_config
*cfg
, const char *name
)
854 git_config_entry
*ce
= NULL
;
857 if ((error
= git_config__lookup_entry(&ce
, cfg
, name
, false)) < 0)
860 if (ce
&& ce
->value
) {
861 *out
= git__strdup(ce
->value
);
862 GIT_ERROR_CHECK_ALLOC(*out
);
864 error
= GIT_ENOTFOUND
;
867 git_config_entry_free(ce
);
871 static void url_config_trim(git_net_url
*url
)
873 size_t len
= strlen(url
->path
);
875 if (url
->path
[len
- 1] == '/') {
878 while (len
&& url
->path
[len
- 1] != '/')
882 url
->path
[len
] = '\0';
885 static int http_proxy_config(char **out
, git_remote
*remote
, git_net_url
*url
)
887 git_config
*cfg
= NULL
;
888 git_buf buf
= GIT_BUF_INIT
;
889 git_net_url lookup_url
= GIT_NET_URL_INIT
;
892 if ((error
= git_net_url_dup(&lookup_url
, url
)) < 0)
896 if ((error
= git_repository_config(&cfg
, remote
->repo
)) < 0)
899 if ((error
= git_config_open_default(&cfg
)) < 0)
903 /* remote.<name>.proxy config setting */
904 if (remote
->name
&& remote
->name
[0]) {
907 if ((error
= git_buf_printf(&buf
, "remote.%s.proxy", remote
->name
)) < 0 ||
908 (error
= lookup_config(out
, cfg
, buf
.ptr
)) != GIT_ENOTFOUND
)
915 if ((error
= git_buf_puts(&buf
, "http.")) < 0 ||
916 (error
= git_net_url_fmt(&buf
, &lookup_url
)) < 0 ||
917 (error
= git_buf_puts(&buf
, ".proxy")) < 0 ||
918 (error
= lookup_config(out
, cfg
, buf
.ptr
)) != GIT_ENOTFOUND
)
921 if (! lookup_url
.path
[0])
924 url_config_trim(&lookup_url
);
929 error
= lookup_config(out
, cfg
, "http.proxy");
932 git_config_free(cfg
);
933 git_buf_dispose(&buf
);
934 git_net_url_dispose(&lookup_url
);
938 static int http_proxy_env(char **out
, git_remote
*remote
, git_net_url
*url
)
940 git_buf proxy_env
= GIT_BUF_INIT
, no_proxy_env
= GIT_BUF_INIT
;
941 bool use_ssl
= (strcmp(url
->scheme
, "https") == 0);
946 /* http_proxy / https_proxy environment variables */
947 error
= git__getenv(&proxy_env
, use_ssl
? "https_proxy" : "http_proxy");
949 /* try uppercase environment variables */
950 if (error
== GIT_ENOTFOUND
)
951 error
= git__getenv(&proxy_env
, use_ssl
? "HTTPS_PROXY" : "HTTP_PROXY");
956 /* no_proxy/NO_PROXY environment variables */
957 error
= git__getenv(&no_proxy_env
, "no_proxy");
959 if (error
== GIT_ENOTFOUND
)
960 error
= git__getenv(&no_proxy_env
, "NO_PROXY");
962 if (error
&& error
!= GIT_ENOTFOUND
)
965 if (!git_net_url_matches_pattern_list(url
, no_proxy_env
.ptr
))
966 *out
= git_buf_detach(&proxy_env
);
968 error
= GIT_ENOTFOUND
;
971 git_buf_dispose(&proxy_env
);
972 git_buf_dispose(&no_proxy_env
);
976 int git_remote__http_proxy(char **out
, git_remote
*remote
, git_net_url
*url
)
981 GIT_ASSERT_ARG(remote
);
986 * Go through the possible sources for proxy configuration,
987 * Examine the various git config options first, then
988 * consult environment variables.
990 if ((error
= http_proxy_config(out
, remote
, url
)) != GIT_ENOTFOUND
||
991 (error
= http_proxy_env(out
, remote
, url
)) != GIT_ENOTFOUND
)
997 /* DWIM `refspecs` based on `refs` and append the output to `out` */
998 static int dwim_refspecs(git_vector
*out
, git_vector
*refspecs
, git_vector
*refs
)
1003 git_vector_foreach(refspecs
, i
, spec
) {
1004 if (git_refspec__dwim_one(out
, spec
, refs
) < 0)
1011 static void free_refspecs(git_vector
*vec
)
1016 git_vector_foreach(vec
, i
, spec
) {
1017 git_refspec__dispose(spec
);
1021 git_vector_clear(vec
);
1024 static int remote_head_cmp(const void *_a
, const void *_b
)
1026 const git_remote_head
*a
= (git_remote_head
*) _a
;
1027 const git_remote_head
*b
= (git_remote_head
*) _b
;
1029 return git__strcmp_cb(a
->name
, b
->name
);
1032 static int ls_to_vector(git_vector
*out
, git_remote
*remote
)
1034 git_remote_head
**heads
;
1035 size_t heads_len
, i
;
1037 if (git_remote_ls((const git_remote_head
***)&heads
, &heads_len
, remote
) < 0)
1040 if (git_vector_init(out
, heads_len
, remote_head_cmp
) < 0)
1043 for (i
= 0; i
< heads_len
; i
++) {
1044 if (git_vector_insert(out
, heads
[i
]) < 0)
1051 int git_remote_download(git_remote
*remote
, const git_strarray
*refspecs
, const git_fetch_options
*opts
)
1055 git_vector
*to_active
, specs
= GIT_VECTOR_INIT
, refs
= GIT_VECTOR_INIT
;
1056 const git_remote_callbacks
*cbs
= NULL
;
1057 const git_strarray
*custom_headers
= NULL
;
1058 const git_proxy_options
*proxy
= NULL
;
1060 GIT_ASSERT_ARG(remote
);
1062 if (!remote
->repo
) {
1063 git_error_set(GIT_ERROR_INVALID
, "cannot download detached remote");
1068 GIT_ERROR_CHECK_VERSION(&opts
->callbacks
, GIT_REMOTE_CALLBACKS_VERSION
, "git_remote_callbacks");
1069 cbs
= &opts
->callbacks
;
1070 custom_headers
= &opts
->custom_headers
;
1071 GIT_ERROR_CHECK_VERSION(&opts
->proxy_opts
, GIT_PROXY_OPTIONS_VERSION
, "git_proxy_options");
1072 proxy
= &opts
->proxy_opts
;
1075 if (!git_remote_connected(remote
) &&
1076 (error
= git_remote_connect(remote
, GIT_DIRECTION_FETCH
, cbs
, proxy
, custom_headers
)) < 0)
1079 if (ls_to_vector(&refs
, remote
) < 0)
1082 if ((git_vector_init(&specs
, 0, NULL
)) < 0)
1085 remote
->passed_refspecs
= 0;
1086 if (!refspecs
|| !refspecs
->count
) {
1087 to_active
= &remote
->refspecs
;
1089 for (i
= 0; i
< refspecs
->count
; i
++) {
1090 if ((error
= add_refspec_to(&specs
, refspecs
->strings
[i
], true)) < 0)
1095 remote
->passed_refspecs
= 1;
1098 free_refspecs(&remote
->passive_refspecs
);
1099 if ((error
= dwim_refspecs(&remote
->passive_refspecs
, &remote
->refspecs
, &refs
)) < 0)
1102 free_refspecs(&remote
->active_refspecs
);
1103 error
= dwim_refspecs(&remote
->active_refspecs
, to_active
, &refs
);
1105 git_vector_free(&refs
);
1106 free_refspecs(&specs
);
1107 git_vector_free(&specs
);
1113 git_push_free(remote
->push
);
1114 remote
->push
= NULL
;
1117 if ((error
= git_fetch_negotiate(remote
, opts
)) < 0)
1120 return git_fetch_download_pack(remote
, cbs
);
1123 git_vector_free(&refs
);
1124 free_refspecs(&specs
);
1125 git_vector_free(&specs
);
1129 int git_remote_fetch(
1131 const git_strarray
*refspecs
,
1132 const git_fetch_options
*opts
,
1133 const char *reflog_message
)
1135 int error
, update_fetchhead
= 1;
1136 git_remote_autotag_option_t tagopt
= remote
->download_tags
;
1138 git_buf reflog_msg_buf
= GIT_BUF_INIT
;
1139 const git_remote_callbacks
*cbs
= NULL
;
1140 git_remote_connection_opts conn
= GIT_REMOTE_CONNECTION_OPTIONS_INIT
;
1143 GIT_ERROR_CHECK_VERSION(&opts
->callbacks
, GIT_REMOTE_CALLBACKS_VERSION
, "git_remote_callbacks");
1144 cbs
= &opts
->callbacks
;
1145 conn
.custom_headers
= &opts
->custom_headers
;
1146 update_fetchhead
= opts
->update_fetchhead
;
1147 tagopt
= opts
->download_tags
;
1148 GIT_ERROR_CHECK_VERSION(&opts
->proxy_opts
, GIT_PROXY_OPTIONS_VERSION
, "git_proxy_options");
1149 conn
.proxy
= &opts
->proxy_opts
;
1152 /* Connect and download everything */
1153 if ((error
= git_remote__connect(remote
, GIT_DIRECTION_FETCH
, cbs
, &conn
)) != 0)
1156 error
= git_remote_download(remote
, refspecs
, opts
);
1158 /* We don't need to be connected anymore */
1159 git_remote_disconnect(remote
);
1161 /* If the download failed, return the error */
1165 /* Default reflog message */
1167 git_buf_sets(&reflog_msg_buf
, reflog_message
);
1169 git_buf_printf(&reflog_msg_buf
, "fetch %s",
1170 remote
->name
? remote
->name
: remote
->url
);
1173 /* Create "remote/foo" branches for all remote branches */
1174 error
= git_remote_update_tips(remote
, cbs
, update_fetchhead
, tagopt
, git_buf_cstr(&reflog_msg_buf
));
1175 git_buf_dispose(&reflog_msg_buf
);
1179 if (opts
&& opts
->prune
== GIT_FETCH_PRUNE
)
1181 else if (opts
&& opts
->prune
== GIT_FETCH_PRUNE_UNSPECIFIED
&& remote
->prune_refs
)
1183 else if (opts
&& opts
->prune
== GIT_FETCH_NO_PRUNE
)
1186 prune
= remote
->prune_refs
;
1189 error
= git_remote_prune(remote
, cbs
);
1194 static int remote_head_for_fetchspec_src(git_remote_head
**out
, git_vector
*update_heads
, const char *fetchspec_src
)
1197 git_remote_head
*remote_ref
;
1199 GIT_ASSERT_ARG(update_heads
);
1200 GIT_ASSERT_ARG(fetchspec_src
);
1204 git_vector_foreach(update_heads
, i
, remote_ref
) {
1205 if (strcmp(remote_ref
->name
, fetchspec_src
) == 0) {
1214 static int ref_to_update(int *update
, git_buf
*remote_name
, git_remote
*remote
, git_refspec
*spec
, const char *ref_name
)
1217 git_repository
*repo
;
1218 git_buf upstream_remote
= GIT_BUF_INIT
;
1219 git_buf upstream_name
= GIT_BUF_INIT
;
1221 repo
= git_remote_owner(remote
);
1223 if ((!git_reference__is_branch(ref_name
)) ||
1224 !git_remote_name(remote
) ||
1225 (error
= git_branch_upstream_remote(&upstream_remote
, repo
, ref_name
) < 0) ||
1226 git__strcmp(git_remote_name(remote
), git_buf_cstr(&upstream_remote
)) ||
1227 (error
= git_branch_upstream_name(&upstream_name
, repo
, ref_name
)) < 0 ||
1228 !git_refspec_dst_matches(spec
, git_buf_cstr(&upstream_name
)) ||
1229 (error
= git_refspec_rtransform(remote_name
, spec
, upstream_name
.ptr
)) < 0) {
1230 /* Not an error if there is no upstream */
1231 if (error
== GIT_ENOTFOUND
) {
1241 git_buf_dispose(&upstream_remote
);
1242 git_buf_dispose(&upstream_name
);
1246 static int remote_head_for_ref(git_remote_head
**out
, git_remote
*remote
, git_refspec
*spec
, git_vector
*update_heads
, git_reference
*ref
)
1248 git_reference
*resolved_ref
= NULL
;
1249 git_buf remote_name
= GIT_BUF_INIT
;
1250 git_config
*config
= NULL
;
1251 const char *ref_name
;
1252 int error
= 0, update
;
1254 GIT_ASSERT_ARG(out
);
1255 GIT_ASSERT_ARG(spec
);
1256 GIT_ASSERT_ARG(ref
);
1260 error
= git_reference_resolve(&resolved_ref
, ref
);
1262 /* If we're in an unborn branch, let's pretend nothing happened */
1263 if (error
== GIT_ENOTFOUND
&& git_reference_type(ref
) == GIT_REFERENCE_SYMBOLIC
) {
1264 ref_name
= git_reference_symbolic_target(ref
);
1267 ref_name
= git_reference_name(resolved_ref
);
1271 * The ref name may be unresolvable - perhaps it's pointing to
1272 * something invalid. In this case, there is no remote head for
1280 if ((error
= ref_to_update(&update
, &remote_name
, remote
, spec
, ref_name
)) < 0)
1284 error
= remote_head_for_fetchspec_src(out
, update_heads
, git_buf_cstr(&remote_name
));
1287 git_buf_dispose(&remote_name
);
1288 git_reference_free(resolved_ref
);
1289 git_config_free(config
);
1293 static int git_remote_write_fetchhead(git_remote
*remote
, git_refspec
*spec
, git_vector
*update_heads
)
1295 git_reference
*head_ref
= NULL
;
1296 git_fetchhead_ref
*fetchhead_ref
;
1297 git_remote_head
*remote_ref
, *merge_remote_ref
;
1298 git_vector fetchhead_refs
;
1299 bool include_all_fetchheads
;
1303 GIT_ASSERT_ARG(remote
);
1305 /* no heads, nothing to do */
1306 if (update_heads
->length
== 0)
1309 if (git_vector_init(&fetchhead_refs
, update_heads
->length
, git_fetchhead_ref_cmp
) < 0)
1312 /* Iff refspec is * (but not subdir slash star), include tags */
1313 include_all_fetchheads
= (strcmp(GIT_REFS_HEADS_DIR
"*", git_refspec_src(spec
)) == 0);
1315 /* Determine what to merge: if refspec was a wildcard, just use HEAD */
1316 if (git_refspec_is_wildcard(spec
)) {
1317 if ((error
= git_reference_lookup(&head_ref
, remote
->repo
, GIT_HEAD_FILE
)) < 0 ||
1318 (error
= remote_head_for_ref(&merge_remote_ref
, remote
, spec
, update_heads
, head_ref
)) < 0)
1321 /* If we're fetching a single refspec, that's the only thing that should be in FETCH_HEAD. */
1322 if ((error
= remote_head_for_fetchspec_src(&merge_remote_ref
, update_heads
, git_refspec_src(spec
))) < 0)
1326 /* Create the FETCH_HEAD file */
1327 git_vector_foreach(update_heads
, i
, remote_ref
) {
1328 int merge_this_fetchhead
= (merge_remote_ref
== remote_ref
);
1330 if (!include_all_fetchheads
&&
1331 !git_refspec_src_matches(spec
, remote_ref
->name
) &&
1332 !merge_this_fetchhead
)
1335 if (git_fetchhead_ref_create(&fetchhead_ref
,
1337 merge_this_fetchhead
,
1339 git_remote_url(remote
)) < 0)
1342 if (git_vector_insert(&fetchhead_refs
, fetchhead_ref
) < 0)
1346 git_fetchhead_write(remote
->repo
, &fetchhead_refs
);
1349 for (i
= 0; i
< fetchhead_refs
.length
; ++i
)
1350 git_fetchhead_ref_free(fetchhead_refs
.contents
[i
]);
1352 git_vector_free(&fetchhead_refs
);
1353 git_reference_free(head_ref
);
1359 * Generate a list of candidates for pruning by getting a list of
1360 * references which match the rhs of an active refspec.
1362 static int prune_candidates(git_vector
*candidates
, git_remote
*remote
)
1364 git_strarray arr
= { 0 };
1368 if ((error
= git_reference_list(&arr
, remote
->repo
)) < 0)
1371 for (i
= 0; i
< arr
.count
; i
++) {
1372 const char *refname
= arr
.strings
[i
];
1375 if (!git_remote__matching_dst_refspec(remote
, refname
))
1378 refname_dup
= git__strdup(refname
);
1379 GIT_ERROR_CHECK_ALLOC(refname_dup
);
1381 if ((error
= git_vector_insert(candidates
, refname_dup
)) < 0)
1386 git_strarray_dispose(&arr
);
1390 static int find_head(const void *_a
, const void *_b
)
1392 git_remote_head
*a
= (git_remote_head
*) _a
;
1393 git_remote_head
*b
= (git_remote_head
*) _b
;
1395 return strcmp(a
->name
, b
->name
);
1398 int git_remote_prune(git_remote
*remote
, const git_remote_callbacks
*callbacks
)
1401 git_vector remote_refs
= GIT_VECTOR_INIT
;
1402 git_vector candidates
= GIT_VECTOR_INIT
;
1403 const git_refspec
*spec
;
1404 const char *refname
;
1406 git_oid zero_id
= {{ 0 }};
1409 GIT_ERROR_CHECK_VERSION(callbacks
, GIT_REMOTE_CALLBACKS_VERSION
, "git_remote_callbacks");
1411 if ((error
= ls_to_vector(&remote_refs
, remote
)) < 0)
1414 git_vector_set_cmp(&remote_refs
, find_head
);
1416 if ((error
= prune_candidates(&candidates
, remote
)) < 0)
1420 * Remove those entries from the candidate list for which we
1421 * can find a remote reference in at least one refspec.
1423 git_vector_foreach(&candidates
, i
, refname
) {
1424 git_vector_foreach(&remote
->active_refspecs
, j
, spec
) {
1425 git_buf buf
= GIT_BUF_INIT
;
1428 git_remote_head key
= {0};
1430 if (!git_refspec_dst_matches(spec
, refname
))
1433 if ((error
= git_refspec_rtransform(&buf
, spec
, refname
)) < 0)
1436 key
.name
= (char *) git_buf_cstr(&buf
);
1437 error
= git_vector_bsearch(&pos
, &remote_refs
, &key
);
1438 git_buf_dispose(&buf
);
1440 if (error
< 0 && error
!= GIT_ENOTFOUND
)
1443 if (error
== GIT_ENOTFOUND
)
1446 /* If we did find a source, remove it from the candidates. */
1447 if ((error
= git_vector_set((void **) &src_name
, &candidates
, i
, NULL
)) < 0)
1450 git__free(src_name
);
1456 * For those candidates still left in the list, we need to
1457 * remove them. We do not remove symrefs, as those are for
1458 * stuff like origin/HEAD which will never match, but we do
1459 * not want to remove them.
1461 git_vector_foreach(&candidates
, i
, refname
) {
1465 if (refname
== NULL
)
1468 error
= git_reference_lookup(&ref
, remote
->repo
, refname
);
1469 /* as we want it gone, let's not consider this an error */
1470 if (error
== GIT_ENOTFOUND
)
1476 if (git_reference_type(ref
) == GIT_REFERENCE_SYMBOLIC
) {
1477 git_reference_free(ref
);
1481 git_oid_cpy(&id
, git_reference_target(ref
));
1482 error
= git_reference_delete(ref
);
1483 git_reference_free(ref
);
1487 if (callbacks
&& callbacks
->update_tips
)
1488 error
= callbacks
->update_tips(refname
, &id
, &zero_id
, callbacks
->payload
);
1495 git_vector_free(&remote_refs
);
1496 git_vector_free_deep(&candidates
);
1500 static int update_tips_for_spec(
1502 const git_remote_callbacks
*callbacks
,
1503 int update_fetchhead
,
1504 git_remote_autotag_option_t tagopt
,
1507 const char *log_message
)
1509 int error
= 0, autotag
, valid
;
1511 git_buf refname
= GIT_BUF_INIT
;
1514 git_remote_head
*head
;
1516 git_refspec tagspec
;
1517 git_vector update_heads
;
1519 GIT_ASSERT_ARG(remote
);
1521 if (git_repository_odb__weakptr(&odb
, remote
->repo
) < 0)
1524 if (git_refspec__parse(&tagspec
, GIT_REFSPEC_TAGS
, true) < 0)
1527 /* Make a copy of the transport's refs */
1528 if (git_vector_init(&update_heads
, 16, NULL
) < 0)
1531 for (; i
< refs
->length
; ++i
) {
1532 head
= git_vector_get(refs
, i
);
1534 git_buf_clear(&refname
);
1536 /* Ignore malformed ref names (which also saves us from tag^{} */
1537 if (git_reference_name_is_valid(&valid
, head
->name
) < 0)
1543 /* If we have a tag, see if the auto-follow rules say to update it */
1544 if (git_refspec_src_matches(&tagspec
, head
->name
)) {
1545 if (tagopt
!= GIT_REMOTE_DOWNLOAD_TAGS_NONE
) {
1547 if (tagopt
== GIT_REMOTE_DOWNLOAD_TAGS_AUTO
)
1550 git_buf_clear(&refname
);
1551 if (git_buf_puts(&refname
, head
->name
) < 0)
1556 /* If we didn't want to auto-follow the tag, check if the refspec matches */
1557 if (!autotag
&& git_refspec_src_matches(spec
, head
->name
)) {
1559 if (git_refspec_transform(&refname
, spec
, head
->name
) < 0)
1563 * no rhs mans store it in FETCH_HEAD, even if we don't
1564 update anything else.
1566 if ((error
= git_vector_insert(&update_heads
, head
)) < 0)
1573 /* If we still don't have a refname, we don't want it */
1574 if (git_buf_len(&refname
) == 0) {
1578 /* In autotag mode, only create tags for objects already in db */
1579 if (autotag
&& !git_odb_exists(odb
, &head
->oid
))
1582 if (!autotag
&& git_vector_insert(&update_heads
, head
) < 0)
1585 error
= git_reference_name_to_id(&old
, remote
->repo
, refname
.ptr
);
1586 if (error
< 0 && error
!= GIT_ENOTFOUND
)
1589 if (!(error
|| error
== GIT_ENOTFOUND
)
1591 && !git_graph_descendant_of(remote
->repo
, &head
->oid
, &old
))
1594 if (error
== GIT_ENOTFOUND
) {
1595 memset(&old
, 0, GIT_OID_RAWSZ
);
1597 if (autotag
&& git_vector_insert(&update_heads
, head
) < 0)
1601 if (!git_oid__cmp(&old
, &head
->oid
))
1604 /* In autotag mode, don't overwrite any locally-existing tags */
1605 error
= git_reference_create(&ref
, remote
->repo
, refname
.ptr
, &head
->oid
, !autotag
,
1608 if (error
== GIT_EEXISTS
)
1614 git_reference_free(ref
);
1616 if (callbacks
&& callbacks
->update_tips
!= NULL
) {
1617 if (callbacks
->update_tips(refname
.ptr
, &old
, &head
->oid
, callbacks
->payload
) < 0)
1622 if (update_fetchhead
&&
1623 (error
= git_remote_write_fetchhead(remote
, spec
, &update_heads
)) < 0)
1626 git_vector_free(&update_heads
);
1627 git_refspec__dispose(&tagspec
);
1628 git_buf_dispose(&refname
);
1632 git_vector_free(&update_heads
);
1633 git_refspec__dispose(&tagspec
);
1634 git_buf_dispose(&refname
);
1640 * Iteration over the three vectors, with a pause whenever we find a match
1642 * On each stop, we store the iteration stat in the inout i,j,k
1643 * parameters, and return the currently matching passive refspec as
1644 * well as the head which we matched.
1646 static int next_head(const git_remote
*remote
, git_vector
*refs
,
1647 git_refspec
**out_spec
, git_remote_head
**out_head
,
1648 size_t *out_i
, size_t *out_j
, size_t *out_k
)
1650 const git_vector
*active
, *passive
;
1651 git_remote_head
*head
;
1652 git_refspec
*spec
, *passive_spec
;
1656 active
= &remote
->active_refspecs
;
1657 passive
= &remote
->passive_refspecs
;
1663 for (; i
< refs
->length
; i
++) {
1664 head
= git_vector_get(refs
, i
);
1666 if (git_reference_name_is_valid(&valid
, head
->name
) < 0)
1672 for (; j
< active
->length
; j
++) {
1673 spec
= git_vector_get(active
, j
);
1675 if (!git_refspec_src_matches(spec
, head
->name
))
1678 for (; k
< passive
->length
; k
++) {
1679 passive_spec
= git_vector_get(passive
, k
);
1681 if (!git_refspec_src_matches(passive_spec
, head
->name
))
1684 *out_spec
= passive_spec
;
1697 return GIT_ITEROVER
;
1700 static int opportunistic_updates(const git_remote
*remote
, const git_remote_callbacks
*callbacks
,
1701 git_vector
*refs
, const char *msg
)
1705 git_remote_head
*head
;
1707 git_buf refname
= GIT_BUF_INIT
;
1712 while ((error
= next_head(remote
, refs
, &spec
, &head
, &i
, &j
, &k
)) == 0) {
1713 git_oid old
= {{ 0 }};
1715 * If we got here, there is a refspec which was used
1716 * for fetching which matches the source of one of the
1717 * passive refspecs, so we should update that
1718 * remote-tracking branch, but not add it to
1722 git_buf_clear(&refname
);
1723 if ((error
= git_refspec_transform(&refname
, spec
, head
->name
)) < 0)
1726 error
= git_reference_name_to_id(&old
, remote
->repo
, refname
.ptr
);
1727 if (error
< 0 && error
!= GIT_ENOTFOUND
)
1730 if (!git_oid_cmp(&old
, &head
->oid
))
1733 /* If we did find a current reference, make sure we haven't lost a race */
1735 error
= git_reference_create(&ref
, remote
->repo
, refname
.ptr
, &head
->oid
, true, msg
);
1737 error
= git_reference_create_matching(&ref
, remote
->repo
, refname
.ptr
, &head
->oid
, true, &old
, msg
);
1738 git_reference_free(ref
);
1742 if (callbacks
&& callbacks
->update_tips
!= NULL
) {
1743 if (callbacks
->update_tips(refname
.ptr
, &old
, &head
->oid
, callbacks
->payload
) < 0)
1748 if (error
== GIT_ITEROVER
)
1752 git_buf_dispose(&refname
);
1756 static int truncate_fetch_head(const char *gitdir
)
1758 git_buf path
= GIT_BUF_INIT
;
1761 if ((error
= git_buf_joinpath(&path
, gitdir
, GIT_FETCH_HEAD_FILE
)) < 0)
1764 error
= git_futils_truncate(path
.ptr
, GIT_REFS_FILE_MODE
);
1765 git_buf_dispose(&path
);
1770 int git_remote_update_tips(
1772 const git_remote_callbacks
*callbacks
,
1773 int update_fetchhead
,
1774 git_remote_autotag_option_t download_tags
,
1775 const char *reflog_message
)
1777 git_refspec
*spec
, tagspec
;
1778 git_vector refs
= GIT_VECTOR_INIT
;
1779 git_remote_autotag_option_t tagopt
;
1783 /* push has its own logic hidden away in the push object */
1785 return git_push_update_tips(remote
->push
, callbacks
);
1788 if (git_refspec__parse(&tagspec
, GIT_REFSPEC_TAGS
, true) < 0)
1792 if ((error
= ls_to_vector(&refs
, remote
)) < 0)
1795 if (download_tags
== GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED
)
1796 tagopt
= remote
->download_tags
;
1798 tagopt
= download_tags
;
1800 if ((error
= truncate_fetch_head(git_repository_path(remote
->repo
))) < 0)
1803 if (tagopt
== GIT_REMOTE_DOWNLOAD_TAGS_ALL
) {
1804 if ((error
= update_tips_for_spec(remote
, callbacks
, update_fetchhead
, tagopt
, &tagspec
, &refs
, reflog_message
)) < 0)
1808 git_vector_foreach(&remote
->active_refspecs
, i
, spec
) {
1812 if ((error
= update_tips_for_spec(remote
, callbacks
, update_fetchhead
, tagopt
, spec
, &refs
, reflog_message
)) < 0)
1816 /* Only try to do opportunistic updates if the refpec lists differ. */
1817 if (remote
->passed_refspecs
)
1818 error
= opportunistic_updates(remote
, callbacks
, &refs
, reflog_message
);
1821 git_vector_free(&refs
);
1822 git_refspec__dispose(&tagspec
);
1826 int git_remote_connected(const git_remote
*remote
)
1828 GIT_ASSERT_ARG(remote
);
1830 if (!remote
->transport
|| !remote
->transport
->is_connected
)
1833 /* Ask the transport if it's connected. */
1834 return remote
->transport
->is_connected(remote
->transport
);
1837 int git_remote_stop(git_remote
*remote
)
1839 GIT_ASSERT_ARG(remote
);
1841 if (remote
->transport
&& remote
->transport
->cancel
)
1842 remote
->transport
->cancel(remote
->transport
);
1847 int git_remote_disconnect(git_remote
*remote
)
1849 GIT_ASSERT_ARG(remote
);
1851 if (git_remote_connected(remote
))
1852 remote
->transport
->close(remote
->transport
);
1857 void git_remote_free(git_remote
*remote
)
1862 if (remote
->transport
!= NULL
) {
1863 git_remote_disconnect(remote
);
1865 remote
->transport
->free(remote
->transport
);
1866 remote
->transport
= NULL
;
1869 git_vector_free(&remote
->refs
);
1871 free_refspecs(&remote
->refspecs
);
1872 git_vector_free(&remote
->refspecs
);
1874 free_refspecs(&remote
->active_refspecs
);
1875 git_vector_free(&remote
->active_refspecs
);
1877 free_refspecs(&remote
->passive_refspecs
);
1878 git_vector_free(&remote
->passive_refspecs
);
1880 git_push_free(remote
->push
);
1881 git__free(remote
->url
);
1882 git__free(remote
->pushurl
);
1883 git__free(remote
->name
);
1887 static int remote_list_cb(const git_config_entry
*entry
, void *payload
)
1889 git_vector
*list
= payload
;
1890 const char *name
= entry
->name
+ strlen("remote.");
1891 size_t namelen
= strlen(name
);
1894 /* we know name matches "remote.<stuff>.(push)?url" */
1896 if (!strcmp(&name
[namelen
- 4], ".url"))
1897 remote_name
= git__strndup(name
, namelen
- 4); /* strip ".url" */
1899 remote_name
= git__strndup(name
, namelen
- 8); /* strip ".pushurl" */
1900 GIT_ERROR_CHECK_ALLOC(remote_name
);
1902 return git_vector_insert(list
, remote_name
);
1905 int git_remote_list(git_strarray
*remotes_list
, git_repository
*repo
)
1909 git_vector list
= GIT_VECTOR_INIT
;
1911 if ((error
= git_repository_config__weakptr(&cfg
, repo
)) < 0)
1914 if ((error
= git_vector_init(&list
, 4, git__strcmp_cb
)) < 0)
1917 error
= git_config_foreach_match(
1918 cfg
, "^remote\\..*\\.(push)?url$", remote_list_cb
, &list
);
1921 git_vector_free_deep(&list
);
1925 git_vector_uniq(&list
, git__free
);
1927 remotes_list
->strings
=
1928 (char **)git_vector_detach(&remotes_list
->count
, NULL
, &list
);
1933 const git_indexer_progress
*git_remote_stats(git_remote
*remote
)
1935 GIT_ASSERT_ARG_WITH_RETVAL(remote
, NULL
);
1936 return &remote
->stats
;
1939 git_remote_autotag_option_t
git_remote_autotag(const git_remote
*remote
)
1941 return remote
->download_tags
;
1944 int git_remote_set_autotag(git_repository
*repo
, const char *remote
, git_remote_autotag_option_t value
)
1946 git_buf var
= GIT_BUF_INIT
;
1950 GIT_ASSERT_ARG(repo
&& remote
);
1952 if ((error
= ensure_remote_name_is_valid(remote
)) < 0)
1955 if ((error
= git_repository_config__weakptr(&config
, repo
)) < 0)
1958 if ((error
= git_buf_printf(&var
, CONFIG_TAGOPT_FMT
, remote
)))
1962 case GIT_REMOTE_DOWNLOAD_TAGS_NONE
:
1963 error
= git_config_set_string(config
, var
.ptr
, "--no-tags");
1965 case GIT_REMOTE_DOWNLOAD_TAGS_ALL
:
1966 error
= git_config_set_string(config
, var
.ptr
, "--tags");
1968 case GIT_REMOTE_DOWNLOAD_TAGS_AUTO
:
1969 error
= git_config_delete_entry(config
, var
.ptr
);
1970 if (error
== GIT_ENOTFOUND
)
1974 git_error_set(GIT_ERROR_INVALID
, "invalid value for the tagopt setting");
1978 git_buf_dispose(&var
);
1982 int git_remote_prune_refs(const git_remote
*remote
)
1984 return remote
->prune_refs
;
1987 static int rename_remote_config_section(
1988 git_repository
*repo
,
1989 const char *old_name
,
1990 const char *new_name
)
1992 git_buf old_section_name
= GIT_BUF_INIT
,
1993 new_section_name
= GIT_BUF_INIT
;
1996 if (git_buf_printf(&old_section_name
, "remote.%s", old_name
) < 0)
2000 (git_buf_printf(&new_section_name
, "remote.%s", new_name
) < 0))
2003 error
= git_config_rename_section(
2005 git_buf_cstr(&old_section_name
),
2006 new_name
? git_buf_cstr(&new_section_name
) : NULL
);
2009 git_buf_dispose(&old_section_name
);
2010 git_buf_dispose(&new_section_name
);
2015 struct update_data
{
2017 const char *old_remote_name
;
2018 const char *new_remote_name
;
2021 static int update_config_entries_cb(
2022 const git_config_entry
*entry
,
2025 struct update_data
*data
= (struct update_data
*)payload
;
2027 if (strcmp(entry
->value
, data
->old_remote_name
))
2030 return git_config_set_string(
2031 data
->config
, entry
->name
, data
->new_remote_name
);
2034 static int update_branch_remote_config_entry(
2035 git_repository
*repo
,
2036 const char *old_name
,
2037 const char *new_name
)
2040 struct update_data data
= { NULL
};
2042 if ((error
= git_repository_config__weakptr(&data
.config
, repo
)) < 0)
2045 data
.old_remote_name
= old_name
;
2046 data
.new_remote_name
= new_name
;
2048 return git_config_foreach_match(
2049 data
.config
, "branch\\..+\\.remote", update_config_entries_cb
, &data
);
2052 static int rename_one_remote_reference(
2053 git_reference
*reference_in
,
2054 const char *old_remote_name
,
2055 const char *new_remote_name
)
2058 git_reference
*ref
= NULL
, *dummy
= NULL
;
2059 git_buf
namespace = GIT_BUF_INIT
, old_namespace
= GIT_BUF_INIT
;
2060 git_buf new_name
= GIT_BUF_INIT
;
2061 git_buf log_message
= GIT_BUF_INIT
;
2065 if ((error
= git_buf_printf(&namespace, GIT_REFS_REMOTES_DIR
"%s/", new_remote_name
)) < 0)
2068 pfx_len
= strlen(GIT_REFS_REMOTES_DIR
) + strlen(old_remote_name
) + 1;
2069 git_buf_puts(&new_name
, namespace.ptr
);
2070 if ((error
= git_buf_puts(&new_name
, git_reference_name(reference_in
) + pfx_len
)) < 0)
2073 if ((error
= git_buf_printf(&log_message
,
2074 "renamed remote %s to %s",
2075 old_remote_name
, new_remote_name
)) < 0)
2078 if ((error
= git_reference_rename(&ref
, reference_in
, git_buf_cstr(&new_name
), 1,
2079 git_buf_cstr(&log_message
))) < 0)
2082 if (git_reference_type(ref
) != GIT_REFERENCE_SYMBOLIC
)
2085 /* Handle refs like origin/HEAD -> origin/master */
2086 target
= git_reference_symbolic_target(ref
);
2087 if ((error
= git_buf_printf(&old_namespace
, GIT_REFS_REMOTES_DIR
"%s/", old_remote_name
)) < 0)
2090 if (git__prefixcmp(target
, old_namespace
.ptr
))
2093 git_buf_clear(&new_name
);
2094 git_buf_puts(&new_name
, namespace.ptr
);
2095 if ((error
= git_buf_puts(&new_name
, target
+ pfx_len
)) < 0)
2098 error
= git_reference_symbolic_set_target(&dummy
, ref
, git_buf_cstr(&new_name
),
2099 git_buf_cstr(&log_message
));
2101 git_reference_free(dummy
);
2104 git_reference_free(reference_in
);
2105 git_reference_free(ref
);
2106 git_buf_dispose(&namespace);
2107 git_buf_dispose(&old_namespace
);
2108 git_buf_dispose(&new_name
);
2109 git_buf_dispose(&log_message
);
2113 static int rename_remote_references(
2114 git_repository
*repo
,
2115 const char *old_name
,
2116 const char *new_name
)
2119 git_buf buf
= GIT_BUF_INIT
;
2121 git_reference_iterator
*iter
;
2123 if ((error
= git_buf_printf(&buf
, GIT_REFS_REMOTES_DIR
"%s/*", old_name
)) < 0)
2126 error
= git_reference_iterator_glob_new(&iter
, repo
, git_buf_cstr(&buf
));
2127 git_buf_dispose(&buf
);
2132 while ((error
= git_reference_next(&ref
, iter
)) == 0) {
2133 if ((error
= rename_one_remote_reference(ref
, old_name
, new_name
)) < 0)
2137 git_reference_iterator_free(iter
);
2139 return (error
== GIT_ITEROVER
) ? 0 : error
;
2142 static int rename_fetch_refspecs(git_vector
*problems
, git_remote
*remote
, const char *new_name
)
2145 git_buf base
= GIT_BUF_INIT
, var
= GIT_BUF_INIT
, val
= GIT_BUF_INIT
;
2146 const git_refspec
*spec
;
2150 if ((error
= git_repository_config__weakptr(&config
, remote
->repo
)) < 0)
2153 if ((error
= git_vector_init(problems
, 1, NULL
)) < 0)
2156 if ((error
= default_fetchspec_for_name(&base
, remote
->name
)) < 0)
2159 git_vector_foreach(&remote
->refspecs
, i
, spec
) {
2163 /* Does the dst part of the refspec follow the expected format? */
2164 if (strcmp(git_buf_cstr(&base
), spec
->string
)) {
2167 dup
= git__strdup(spec
->string
);
2168 GIT_ERROR_CHECK_ALLOC(dup
);
2170 if ((error
= git_vector_insert(problems
, dup
)) < 0)
2176 /* If we do want to move it to the new section */
2178 git_buf_clear(&val
);
2179 git_buf_clear(&var
);
2181 if (default_fetchspec_for_name(&val
, new_name
) < 0 ||
2182 git_buf_printf(&var
, "remote.%s.fetch", new_name
) < 0)
2188 if ((error
= git_config_set_string(
2189 config
, git_buf_cstr(&var
), git_buf_cstr(&val
))) < 0)
2193 git_buf_dispose(&base
);
2194 git_buf_dispose(&var
);
2195 git_buf_dispose(&val
);
2199 git_vector_foreach(problems
, i
, str
)
2202 git_vector_free(problems
);
2208 int git_remote_rename(git_strarray
*out
, git_repository
*repo
, const char *name
, const char *new_name
)
2211 git_vector problem_refspecs
= GIT_VECTOR_INIT
;
2212 git_remote
*remote
= NULL
;
2214 GIT_ASSERT_ARG(out
&& repo
&& name
&& new_name
);
2216 if ((error
= git_remote_lookup(&remote
, repo
, name
)) < 0)
2219 if ((error
= ensure_remote_name_is_valid(new_name
)) < 0)
2222 if ((error
= ensure_remote_doesnot_exist(repo
, new_name
)) < 0)
2225 if ((error
= rename_remote_config_section(repo
, name
, new_name
)) < 0)
2228 if ((error
= update_branch_remote_config_entry(repo
, name
, new_name
)) < 0)
2231 if ((error
= rename_remote_references(repo
, name
, new_name
)) < 0)
2234 if ((error
= rename_fetch_refspecs(&problem_refspecs
, remote
, new_name
)) < 0)
2237 out
->count
= problem_refspecs
.length
;
2238 out
->strings
= (char **) problem_refspecs
.contents
;
2242 git_vector_free(&problem_refspecs
);
2244 git_remote_free(remote
);
2248 int git_remote_name_is_valid(int *valid
, const char *remote_name
)
2250 git_buf buf
= GIT_BUF_INIT
;
2251 git_refspec refspec
= {0};
2258 if (!remote_name
|| *remote_name
== '\0')
2261 if ((error
= git_buf_printf(&buf
, "refs/heads/test:refs/remotes/%s/test", remote_name
)) < 0)
2264 error
= git_refspec__parse(&refspec
, git_buf_cstr(&buf
), true);
2268 else if (error
== GIT_EINVALIDSPEC
)
2272 git_buf_dispose(&buf
);
2273 git_refspec__dispose(&refspec
);
2278 git_refspec
*git_remote__matching_refspec(git_remote
*remote
, const char *refname
)
2283 git_vector_foreach(&remote
->active_refspecs
, i
, spec
) {
2287 if (git_refspec_src_matches(spec
, refname
))
2294 git_refspec
*git_remote__matching_dst_refspec(git_remote
*remote
, const char *refname
)
2299 git_vector_foreach(&remote
->active_refspecs
, i
, spec
) {
2303 if (git_refspec_dst_matches(spec
, refname
))
2310 int git_remote_add_fetch(git_repository
*repo
, const char *remote
, const char *refspec
)
2312 return write_add_refspec(repo
, remote
, refspec
, true);
2315 int git_remote_add_push(git_repository
*repo
, const char *remote
, const char *refspec
)
2317 return write_add_refspec(repo
, remote
, refspec
, false);
2320 static int copy_refspecs(git_strarray
*array
, const git_remote
*remote
, unsigned int push
)
2323 git_vector refspecs
;
2327 if (git_vector_init(&refspecs
, remote
->refspecs
.length
, NULL
) < 0)
2330 git_vector_foreach(&remote
->refspecs
, i
, spec
) {
2331 if (spec
->push
!= push
)
2334 if ((dup
= git__strdup(spec
->string
)) == NULL
)
2337 if (git_vector_insert(&refspecs
, dup
) < 0) {
2343 array
->strings
= (char **)refspecs
.contents
;
2344 array
->count
= refspecs
.length
;
2349 git_vector_free_deep(&refspecs
);
2354 int git_remote_get_fetch_refspecs(git_strarray
*array
, const git_remote
*remote
)
2356 return copy_refspecs(array
, remote
, false);
2359 int git_remote_get_push_refspecs(git_strarray
*array
, const git_remote
*remote
)
2361 return copy_refspecs(array
, remote
, true);
2364 size_t git_remote_refspec_count(const git_remote
*remote
)
2366 return remote
->refspecs
.length
;
2369 const git_refspec
*git_remote_get_refspec(const git_remote
*remote
, size_t n
)
2371 return git_vector_get(&remote
->refspecs
, n
);
2374 int git_remote_init_callbacks(git_remote_callbacks
*opts
, unsigned int version
)
2376 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
2377 opts
, version
, git_remote_callbacks
, GIT_REMOTE_CALLBACKS_INIT
);
2381 /* asserts a branch.<foo>.remote format */
2382 static const char *name_offset(size_t *len_out
, const char *name
)
2387 prefix_len
= strlen("remote.");
2388 dot
= strchr(name
+ prefix_len
, '.');
2390 GIT_ASSERT_ARG_WITH_RETVAL(dot
, NULL
);
2392 *len_out
= dot
- name
- prefix_len
;
2393 return name
+ prefix_len
;
2396 static int remove_branch_config_related_entries(
2397 git_repository
*repo
,
2398 const char *remote_name
)
2402 git_config_entry
*entry
;
2403 git_config_iterator
*iter
;
2404 git_buf buf
= GIT_BUF_INIT
;
2406 if ((error
= git_repository_config__weakptr(&config
, repo
)) < 0)
2409 if ((error
= git_config_iterator_glob_new(&iter
, config
, "branch\\..+\\.remote")) < 0)
2412 /* find any branches with us as upstream and remove that config */
2413 while ((error
= git_config_next(&entry
, iter
)) == 0) {
2417 if (strcmp(remote_name
, entry
->value
))
2420 if ((branch
= name_offset(&branch_len
, entry
->name
)) == NULL
) {
2425 git_buf_clear(&buf
);
2426 if ((error
= git_buf_printf(&buf
, "branch.%.*s.merge", (int)branch_len
, branch
)) < 0)
2429 if ((error
= git_config_delete_entry(config
, git_buf_cstr(&buf
))) < 0) {
2430 if (error
!= GIT_ENOTFOUND
)
2435 git_buf_clear(&buf
);
2436 if ((error
= git_buf_printf(&buf
, "branch.%.*s.remote", (int)branch_len
, branch
)) < 0)
2439 if ((error
= git_config_delete_entry(config
, git_buf_cstr(&buf
))) < 0) {
2440 if (error
!= GIT_ENOTFOUND
)
2446 if (error
== GIT_ITEROVER
)
2449 git_buf_dispose(&buf
);
2450 git_config_iterator_free(iter
);
2454 static int remove_refs(git_repository
*repo
, const git_refspec
*spec
)
2456 git_reference_iterator
*iter
= NULL
;
2463 if ((error
= git_vector_init(&refs
, 8, NULL
)) < 0)
2466 if ((error
= git_reference_iterator_new(&iter
, repo
)) < 0)
2469 while ((error
= git_reference_next_name(&name
, iter
)) == 0) {
2470 if (!git_refspec_dst_matches(spec
, name
))
2473 dup
= git__strdup(name
);
2479 if ((error
= git_vector_insert(&refs
, dup
)) < 0)
2482 if (error
== GIT_ITEROVER
)
2487 git_vector_foreach(&refs
, i
, name
) {
2488 if ((error
= git_reference_remove(repo
, name
)) < 0)
2493 git_reference_iterator_free(iter
);
2494 git_vector_foreach(&refs
, i
, dup
) {
2497 git_vector_free(&refs
);
2501 static int remove_remote_tracking(git_repository
*repo
, const char *remote_name
)
2507 /* we want to use what's on the config, regardless of changes to the instance in memory */
2508 if ((error
= git_remote_lookup(&remote
, repo
, remote_name
)) < 0)
2511 count
= git_remote_refspec_count(remote
);
2512 for (i
= 0; i
< count
; i
++) {
2513 const git_refspec
*refspec
= git_remote_get_refspec(remote
, i
);
2515 /* shouldn't ever actually happen */
2516 if (refspec
== NULL
)
2519 if ((error
= remove_refs(repo
, refspec
)) < 0)
2523 git_remote_free(remote
);
2527 int git_remote_delete(git_repository
*repo
, const char *name
)
2531 GIT_ASSERT_ARG(repo
);
2532 GIT_ASSERT_ARG(name
);
2534 if ((error
= remove_branch_config_related_entries(repo
, name
)) < 0 ||
2535 (error
= remove_remote_tracking(repo
, name
)) < 0 ||
2536 (error
= rename_remote_config_section(repo
, name
, NULL
)) < 0)
2542 int git_remote_default_branch(git_buf
*out
, git_remote
*remote
)
2544 const git_remote_head
**heads
;
2545 const git_remote_head
*guess
= NULL
;
2546 const git_oid
*head_id
;
2547 size_t heads_len
, i
;
2548 git_buf local_default
= GIT_BUF_INIT
;
2551 GIT_ASSERT_ARG(out
);
2553 if ((error
= git_remote_ls(&heads
, &heads_len
, remote
)) < 0)
2556 if (heads_len
== 0 || strcmp(heads
[0]->name
, GIT_HEAD_FILE
)) {
2557 error
= GIT_ENOTFOUND
;
2561 if ((error
= git_buf_sanitize(out
)) < 0)
2564 /* the first one must be HEAD so if that has the symref info, we're done */
2565 if (heads
[0]->symref_target
) {
2566 error
= git_buf_puts(out
, heads
[0]->symref_target
);
2571 * If there's no symref information, we have to look over them
2572 * and guess. We return the first match unless the default
2573 * branch is a candidate. Then we return the default branch.
2576 if ((error
= git_repository_initialbranch(&local_default
, remote
->repo
)) < 0)
2579 head_id
= &heads
[0]->oid
;
2581 for (i
= 1; i
< heads_len
; i
++) {
2582 if (git_oid_cmp(head_id
, &heads
[i
]->oid
))
2585 if (git__prefixcmp(heads
[i
]->name
, GIT_REFS_HEADS_DIR
))
2593 if (!git__strcmp(local_default
.ptr
, heads
[i
]->name
)) {
2600 error
= GIT_ENOTFOUND
;
2604 error
= git_buf_puts(out
, guess
->name
);
2607 git_buf_dispose(&local_default
);
2611 int git_remote_upload(git_remote
*remote
, const git_strarray
*refspecs
, const git_push_options
*opts
)
2617 const git_remote_callbacks
*cbs
= NULL
;
2618 git_remote_connection_opts conn
= GIT_REMOTE_CONNECTION_OPTIONS_INIT
;
2620 GIT_ASSERT_ARG(remote
);
2622 if (!remote
->repo
) {
2623 git_error_set(GIT_ERROR_INVALID
, "cannot download detached remote");
2628 cbs
= &opts
->callbacks
;
2629 conn
.custom_headers
= &opts
->custom_headers
;
2630 conn
.proxy
= &opts
->proxy_opts
;
2633 if (!git_remote_connected(remote
) &&
2634 (error
= git_remote__connect(remote
, GIT_DIRECTION_PUSH
, cbs
, &conn
)) < 0)
2637 free_refspecs(&remote
->active_refspecs
);
2638 if ((error
= dwim_refspecs(&remote
->active_refspecs
, &remote
->refspecs
, &remote
->refs
)) < 0)
2642 git_push_free(remote
->push
);
2643 remote
->push
= NULL
;
2646 if ((error
= git_push_new(&remote
->push
, remote
)) < 0)
2649 push
= remote
->push
;
2651 if (opts
&& (error
= git_push_set_options(push
, opts
)) < 0)
2654 if (refspecs
&& refspecs
->count
> 0) {
2655 for (i
= 0; i
< refspecs
->count
; i
++) {
2656 if ((error
= git_push_add_refspec(push
, refspecs
->strings
[i
])) < 0)
2660 git_vector_foreach(&remote
->refspecs
, i
, spec
) {
2663 if ((error
= git_push_add_refspec(push
, spec
->string
)) < 0)
2668 if ((error
= git_push_finish(push
, cbs
)) < 0)
2671 if (cbs
&& cbs
->push_update_reference
&&
2672 (error
= git_push_status_foreach(push
, cbs
->push_update_reference
, cbs
->payload
)) < 0)
2679 int git_remote_push(git_remote
*remote
, const git_strarray
*refspecs
, const git_push_options
*opts
)
2682 const git_remote_callbacks
*cbs
= NULL
;
2683 const git_strarray
*custom_headers
= NULL
;
2684 const git_proxy_options
*proxy
= NULL
;
2686 GIT_ASSERT_ARG(remote
);
2688 if (!remote
->repo
) {
2689 git_error_set(GIT_ERROR_INVALID
, "cannot download detached remote");
2694 GIT_ERROR_CHECK_VERSION(&opts
->callbacks
, GIT_REMOTE_CALLBACKS_VERSION
, "git_remote_callbacks");
2695 cbs
= &opts
->callbacks
;
2696 custom_headers
= &opts
->custom_headers
;
2697 GIT_ERROR_CHECK_VERSION(&opts
->proxy_opts
, GIT_PROXY_OPTIONS_VERSION
, "git_proxy_options");
2698 proxy
= &opts
->proxy_opts
;
2701 if ((error
= git_remote_connect(remote
, GIT_DIRECTION_PUSH
, cbs
, proxy
, custom_headers
)) < 0)
2704 if ((error
= git_remote_upload(remote
, refspecs
, opts
)) < 0)
2707 error
= git_remote_update_tips(remote
, cbs
, 0, 0, NULL
);
2709 git_remote_disconnect(remote
);
2713 #define PREFIX "url"
2714 #define SUFFIX_FETCH "insteadof"
2715 #define SUFFIX_PUSH "pushinsteadof"
2717 char *apply_insteadof(git_config
*config
, const char *url
, int direction
)
2719 size_t match_length
, prefix_length
, suffix_length
;
2720 char *replacement
= NULL
;
2723 git_buf result
= GIT_BUF_INIT
;
2724 git_config_entry
*entry
;
2725 git_config_iterator
*iter
;
2727 GIT_ASSERT_ARG_WITH_RETVAL(config
, NULL
);
2728 GIT_ASSERT_ARG_WITH_RETVAL(url
, NULL
);
2729 GIT_ASSERT_ARG_WITH_RETVAL(direction
== GIT_DIRECTION_FETCH
|| direction
== GIT_DIRECTION_PUSH
, NULL
);
2731 /* Add 1 to prefix/suffix length due to the additional escaped dot */
2732 prefix_length
= strlen(PREFIX
) + 1;
2733 if (direction
== GIT_DIRECTION_FETCH
) {
2734 regexp
= PREFIX
"\\..*\\." SUFFIX_FETCH
;
2735 suffix_length
= strlen(SUFFIX_FETCH
) + 1;
2737 regexp
= PREFIX
"\\..*\\." SUFFIX_PUSH
;
2738 suffix_length
= strlen(SUFFIX_PUSH
) + 1;
2741 if (git_config_iterator_glob_new(&iter
, config
, regexp
) < 0)
2745 while (git_config_next(&entry
, iter
) == 0) {
2746 size_t n
, replacement_length
;
2748 /* Check if entry value is a prefix of URL */
2749 if (git__prefixcmp(url
, entry
->value
))
2751 /* Check if entry value is longer than previous
2753 if ((n
= strlen(entry
->value
)) <= match_length
)
2756 git__free(replacement
);
2759 /* Cut off prefix and suffix of the value */
2760 replacement_length
=
2761 strlen(entry
->name
) - (prefix_length
+ suffix_length
);
2762 replacement
= git__strndup(entry
->name
+ prefix_length
,
2763 replacement_length
);
2766 git_config_iterator_free(iter
);
2768 if (match_length
== 0)
2769 return git__strdup(url
);
2771 git_buf_printf(&result
, "%s%s", replacement
, url
+ match_length
);
2773 git__free(replacement
);
2778 /* Deprecated functions */
2780 #ifndef GIT_DEPRECATE_HARD
2782 int git_remote_is_valid_name(const char *remote_name
)
2786 git_remote_name_is_valid(&valid
, remote_name
);