2 * Copyright (C) 2009-2012 the libgit2 contributors
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.
8 #include "git2/config.h"
9 #include "git2/types.h"
13 #include "repository.h"
21 static int refspec_parse(git_refspec
*refspec
, const char *str
)
25 memset(refspec
, 0x0, sizeof(git_refspec
));
32 delim
= strchr(str
, ':');
34 giterr_set(GITERR_NET
, "Invalid refspec, missing ':'");
38 refspec
->src
= git__strndup(str
, delim
- str
);
39 GITERR_CHECK_ALLOC(refspec
->src
);
41 refspec
->dst
= git__strdup(delim
+ 1);
42 GITERR_CHECK_ALLOC(refspec
->dst
);
47 static int parse_remote_refspec(git_config
*cfg
, git_refspec
*refspec
, const char *var
)
52 if ((error
= git_config_get_string(&val
, cfg
, var
)) < 0)
55 return refspec_parse(refspec
, val
);
58 static int download_tags_value(git_remote
*remote
, git_config
*cfg
)
61 git_buf buf
= GIT_BUF_INIT
;
64 if (remote
->download_tags
!= GIT_REMOTE_DOWNLOAD_TAGS_UNSET
)
67 /* This is the default, let's see if we need to change it */
68 remote
->download_tags
= GIT_REMOTE_DOWNLOAD_TAGS_AUTO
;
69 if (git_buf_printf(&buf
, "remote.%s.tagopt", remote
->name
) < 0)
72 error
= git_config_get_string(&val
, cfg
, git_buf_cstr(&buf
));
74 if (!error
&& !strcmp(val
, "--no-tags"))
75 remote
->download_tags
= GIT_REMOTE_DOWNLOAD_TAGS_NONE
;
77 if (error
== GIT_ENOTFOUND
)
83 int git_remote_new(git_remote
**out
, git_repository
*repo
, const char *name
, const char *url
, const char *fetch
)
87 /* name is optional */
88 assert(out
&& repo
&& url
);
90 remote
= git__malloc(sizeof(git_remote
));
91 GITERR_CHECK_ALLOC(remote
);
93 memset(remote
, 0x0, sizeof(git_remote
));
95 remote
->check_cert
= 1;
97 if (git_vector_init(&remote
->refs
, 32, NULL
) < 0)
100 remote
->url
= git__strdup(url
);
101 GITERR_CHECK_ALLOC(remote
->url
);
104 remote
->name
= git__strdup(name
);
105 GITERR_CHECK_ALLOC(remote
->name
);
109 if (refspec_parse(&remote
->fetch
, fetch
) < 0)
117 git_remote_free(remote
);
121 int git_remote_load(git_remote
**out
, git_repository
*repo
, const char *name
)
124 git_buf buf
= GIT_BUF_INIT
;
129 assert(out
&& repo
&& name
);
131 if (git_repository_config__weakptr(&config
, repo
) < 0)
134 remote
= git__malloc(sizeof(git_remote
));
135 GITERR_CHECK_ALLOC(remote
);
137 memset(remote
, 0x0, sizeof(git_remote
));
138 remote
->check_cert
= 1;
139 remote
->name
= git__strdup(name
);
140 GITERR_CHECK_ALLOC(remote
->name
);
142 if (git_vector_init(&remote
->refs
, 32, NULL
) < 0) {
147 if (git_buf_printf(&buf
, "remote.%s.url", name
) < 0) {
152 if ((error
= git_config_get_string(&val
, config
, git_buf_cstr(&buf
))) < 0)
156 remote
->url
= git__strdup(val
);
157 GITERR_CHECK_ALLOC(remote
->url
);
160 if (git_buf_printf(&buf
, "remote.%s.pushurl", name
) < 0) {
165 error
= git_config_get_string(&val
, config
, git_buf_cstr(&buf
));
166 if (error
== GIT_ENOTFOUND
)
175 remote
->pushurl
= git__strdup(val
);
176 GITERR_CHECK_ALLOC(remote
->pushurl
);
180 if (git_buf_printf(&buf
, "remote.%s.fetch", name
) < 0) {
185 error
= parse_remote_refspec(config
, &remote
->fetch
, git_buf_cstr(&buf
));
186 if (error
== GIT_ENOTFOUND
)
195 if (git_buf_printf(&buf
, "remote.%s.push", name
) < 0) {
200 error
= parse_remote_refspec(config
, &remote
->push
, git_buf_cstr(&buf
));
201 if (error
== GIT_ENOTFOUND
)
209 if (download_tags_value(remote
, config
) < 0)
218 git_remote_free(remote
);
223 int git_remote_save(const git_remote
*remote
)
226 git_buf buf
= GIT_BUF_INIT
, value
= GIT_BUF_INIT
;
228 if (git_repository_config__weakptr(&config
, remote
->repo
) < 0)
231 if (git_buf_printf(&buf
, "remote.%s.url", remote
->name
) < 0)
234 if (git_config_set_string(config
, git_buf_cstr(&buf
), remote
->url
) < 0) {
240 if (git_buf_printf(&buf
, "remote.%s.pushurl", remote
->name
) < 0)
243 if (remote
->pushurl
) {
244 if (git_config_set_string(config
, git_buf_cstr(&buf
), remote
->pushurl
) < 0) {
249 int error
= git_config_delete(config
, git_buf_cstr(&buf
));
250 if (error
== GIT_ENOTFOUND
) {
259 if (remote
->fetch
.src
!= NULL
&& remote
->fetch
.dst
!= NULL
) {
261 git_buf_clear(&value
);
262 git_buf_printf(&buf
, "remote.%s.fetch", remote
->name
);
263 if (remote
->fetch
.force
)
264 git_buf_putc(&value
, '+');
265 git_buf_printf(&value
, "%s:%s", remote
->fetch
.src
, remote
->fetch
.dst
);
266 if (git_buf_oom(&buf
) || git_buf_oom(&value
))
269 if (git_config_set_string(config
, git_buf_cstr(&buf
), git_buf_cstr(&value
)) < 0)
273 if (remote
->push
.src
!= NULL
&& remote
->push
.dst
!= NULL
) {
275 git_buf_clear(&value
);
276 git_buf_printf(&buf
, "remote.%s.push", remote
->name
);
277 if (remote
->push
.force
)
278 git_buf_putc(&value
, '+');
279 git_buf_printf(&value
, "%s:%s", remote
->push
.src
, remote
->push
.dst
);
280 if (git_buf_oom(&buf
) || git_buf_oom(&value
))
283 if (git_config_set_string(config
, git_buf_cstr(&buf
), git_buf_cstr(&value
)) < 0)
288 git_buf_free(&value
);
294 git_buf_free(&value
);
298 const char *git_remote_name(git_remote
*remote
)
304 const char *git_remote_url(git_remote
*remote
)
310 int git_remote_set_url(git_remote
*remote
, const char* url
)
315 git__free(remote
->url
);
316 remote
->url
= git__strdup(url
);
317 GITERR_CHECK_ALLOC(remote
->url
);
322 const char *git_remote_pushurl(git_remote
*remote
)
325 return remote
->pushurl
;
328 int git_remote_set_pushurl(git_remote
*remote
, const char* url
)
332 git__free(remote
->pushurl
);
334 remote
->pushurl
= git__strdup(url
);
335 GITERR_CHECK_ALLOC(remote
->pushurl
);
337 remote
->pushurl
= NULL
;
342 int git_remote_set_fetchspec(git_remote
*remote
, const char *spec
)
346 assert(remote
&& spec
);
348 if (refspec_parse(&refspec
, spec
) < 0)
351 git__free(remote
->fetch
.src
);
352 git__free(remote
->fetch
.dst
);
353 remote
->fetch
.src
= refspec
.src
;
354 remote
->fetch
.dst
= refspec
.dst
;
359 const git_refspec
*git_remote_fetchspec(git_remote
*remote
)
362 return &remote
->fetch
;
365 int git_remote_set_pushspec(git_remote
*remote
, const char *spec
)
369 assert(remote
&& spec
);
371 if (refspec_parse(&refspec
, spec
) < 0)
374 git__free(remote
->push
.src
);
375 git__free(remote
->push
.dst
);
376 remote
->push
.src
= refspec
.src
;
377 remote
->push
.dst
= refspec
.dst
;
382 const git_refspec
*git_remote_pushspec(git_remote
*remote
)
385 return &remote
->push
;
388 const char* git_remote__urlfordirection(git_remote
*remote
, int direction
)
392 if (direction
== GIT_DIR_FETCH
) {
396 if (direction
== GIT_DIR_PUSH
) {
397 return remote
->pushurl
? remote
->pushurl
: remote
->url
;
403 int git_remote_connect(git_remote
*remote
, int direction
)
410 url
= git_remote__urlfordirection(remote
, direction
);
414 if (git_transport_new(&t
, url
) < 0)
417 t
->progress_cb
= remote
->callbacks
.progress
;
418 t
->cb_data
= remote
->callbacks
.data
;
420 t
->check_cert
= remote
->check_cert
;
421 if (t
->connect(t
, direction
) < 0) {
425 remote
->transport
= t
;
434 int git_remote_ls(git_remote
*remote
, git_headlist_cb list_cb
, void *payload
)
436 git_vector
*refs
= &remote
->transport
->refs
;
442 if (!remote
->transport
|| !remote
->transport
->connected
) {
443 giterr_set(GITERR_NET
, "The remote is not connected");
447 git_vector_foreach(refs
, i
, p
) {
448 git_pkt_ref
*pkt
= NULL
;
450 if (p
->type
!= GIT_PKT_REF
)
453 pkt
= (git_pkt_ref
*)p
;
455 if (list_cb(&pkt
->head
, payload
))
462 int git_remote_download(git_remote
*remote
, git_off_t
*bytes
, git_indexer_stats
*stats
)
466 assert(remote
&& bytes
&& stats
);
468 if ((error
= git_fetch_negotiate(remote
)) < 0)
471 return git_fetch_download_pack(remote
, bytes
, stats
);
474 int git_remote_update_tips(git_remote
*remote
)
476 int error
= 0, autotag
;
478 git_buf refname
= GIT_BUF_INIT
;
483 git_remote_head
*head
;
485 struct git_refspec
*spec
;
486 char *tagstr
= "refs/tags/*:refs/tags/*";
491 refs
= &remote
->transport
->refs
;
492 spec
= &remote
->fetch
;
494 if (refs
->length
== 0)
497 if (git_repository_odb(&odb
, remote
->repo
) < 0)
500 if (git_refspec__parse(&tagspec
, tagstr
, true) < 0)
503 /* HEAD is only allowed to be the first in the list */
504 pkt
= refs
->contents
[0];
505 head
= &((git_pkt_ref
*)pkt
)->head
;
506 if (!strcmp(head
->name
, GIT_HEAD_FILE
)) {
507 if (git_reference_create_oid(&ref
, remote
->repo
, GIT_FETCH_HEAD_FILE
, &head
->oid
, 1) < 0)
511 git_reference_free(ref
);
514 for (; i
< refs
->length
; ++i
) {
516 git_pkt
*pkt
= refs
->contents
[i
];
518 if (pkt
->type
== GIT_PKT_REF
)
519 head
= &((git_pkt_ref
*)pkt
)->head
;
523 /* Ignore malformed ref names (which also saves us from tag^{} */
524 if (!git_reference_is_valid_name(head
->name
))
527 if (git_refspec_src_matches(spec
, head
->name
)) {
528 if (git_refspec_transform_r(&refname
, spec
, head
->name
) < 0)
530 } else if (remote
->download_tags
!= GIT_REMOTE_DOWNLOAD_TAGS_NONE
) {
533 if (!git_refspec_src_matches(&tagspec
, head
->name
))
536 git_buf_clear(&refname
);
537 if (git_buf_puts(&refname
, head
->name
) < 0)
543 if (autotag
&& !git_odb_exists(odb
, &head
->oid
))
546 error
= git_reference_name_to_oid(&old
, remote
->repo
, refname
.ptr
);
547 if (error
< 0 && error
!= GIT_ENOTFOUND
)
550 if (error
== GIT_ENOTFOUND
)
551 memset(&old
, 0, GIT_OID_RAWSZ
);
553 if (!git_oid_cmp(&old
, &head
->oid
))
556 /* In autotag mode, don't overwrite any locally-existing tags */
557 error
= git_reference_create_oid(&ref
, remote
->repo
, refname
.ptr
, &head
->oid
, !autotag
);
558 if (error
< 0 && error
!= GIT_EEXISTS
)
561 git_reference_free(ref
);
563 if (remote
->callbacks
.update_tips
!= NULL
) {
564 if (remote
->callbacks
.update_tips(refname
.ptr
, &old
, &head
->oid
, remote
->callbacks
.data
) < 0)
569 git_refspec__free(&tagspec
);
570 git_buf_free(&refname
);
574 git_refspec__free(&tagspec
);
575 git_buf_free(&refname
);
580 int git_remote_connected(git_remote
*remote
)
583 return remote
->transport
== NULL
? 0 : remote
->transport
->connected
;
586 void git_remote_disconnect(git_remote
*remote
)
590 if (remote
->transport
!= NULL
&& remote
->transport
->connected
)
591 remote
->transport
->close(remote
->transport
);
594 void git_remote_free(git_remote
*remote
)
599 if (remote
->transport
!= NULL
) {
600 git_remote_disconnect(remote
);
602 remote
->transport
->free(remote
->transport
);
603 remote
->transport
= NULL
;
606 git_vector_free(&remote
->refs
);
608 git_refspec__free(&remote
->fetch
);
609 git_refspec__free(&remote
->push
);
610 git__free(remote
->url
);
611 git__free(remote
->pushurl
);
612 git__free(remote
->name
);
621 static int remote_list_cb(const char *name
, const char *value
, void *data_
)
623 struct cb_data
*data
= (struct cb_data
*)data_
;
625 regmatch_t pmatch
[2];
628 if (!regexec(data
->preg
, name
, nmatch
, pmatch
, 0)) {
629 char *remote_name
= git__strndup(&name
[pmatch
[1].rm_so
], pmatch
[1].rm_eo
- pmatch
[1].rm_so
);
630 GITERR_CHECK_ALLOC(remote_name
);
632 if (git_vector_insert(data
->list
, remote_name
) < 0)
639 int git_remote_list(git_strarray
*remotes_list
, git_repository
*repo
)
647 if (git_repository_config__weakptr(&cfg
, repo
) < 0)
650 if (git_vector_init(&list
, 4, NULL
) < 0)
653 if (regcomp(&preg
, "^remote\\.(.*)\\.url$", REG_EXTENDED
) < 0) {
654 giterr_set(GITERR_OS
, "Remote catch regex failed to compile");
660 error
= git_config_foreach(cfg
, remote_list_cb
, &data
);
665 git_vector_foreach(&list
, i
, elem
) {
669 git_vector_free(&list
);
671 /* cb error is converted to GIT_EUSER by git_config_foreach */
672 if (error
== GIT_EUSER
)
678 remotes_list
->strings
= (char **)list
.contents
;
679 remotes_list
->count
= list
.length
;
684 int git_remote_add(git_remote
**out
, git_repository
*repo
, const char *name
, const char *url
)
686 git_buf buf
= GIT_BUF_INIT
;
688 if (git_buf_printf(&buf
, "+refs/heads/*:refs/remotes/%s/*", name
) < 0)
691 if (git_remote_new(out
, repo
, name
, url
, git_buf_cstr(&buf
)) < 0)
696 if (git_remote_save(*out
) < 0)
703 git_remote_free(*out
);
707 void git_remote_check_cert(git_remote
*remote
, int check
)
711 remote
->check_cert
= check
;
714 void git_remote_set_callbacks(git_remote
*remote
, git_remote_callbacks
*callbacks
)
716 assert(remote
&& callbacks
);
718 memcpy(&remote
->callbacks
, callbacks
, sizeof(git_remote_callbacks
));
720 if (remote
->transport
) {
721 remote
->transport
->progress_cb
= remote
->callbacks
.progress
;
722 remote
->transport
->cb_data
= remote
->callbacks
.data
;
726 int git_remote_autotag(git_remote
*remote
)
728 return remote
->download_tags
;
731 void git_remote_set_autotag(git_remote
*remote
, int value
)
733 remote
->download_tags
= value
;