]>
git.proxmox.com Git - libgit2.git/blob - src/remote.c
2 * Copyright (C) 2009-2011 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/remote.h"
9 #include "git2/config.h"
10 #include "git2/types.h"
13 #include "repository.h"
18 static int refspec_parse(git_refspec
*refspec
, const char *str
)
22 memset(refspec
, 0x0, sizeof(git_refspec
));
29 delim
= strchr(str
, ':');
31 return git__throw(GIT_EOBJCORRUPTED
, "Failed to parse refspec. No ':'");
33 refspec
->src
= git__strndup(str
, delim
- str
);
34 if (refspec
->src
== NULL
)
37 refspec
->dst
= git__strdup(delim
+ 1);
38 if (refspec
->dst
== NULL
) {
39 git__free(refspec
->src
);
47 static int parse_remote_refspec(git_config
*cfg
, git_refspec
*refspec
, const char *var
)
52 error
= git_config_get_string(cfg
, var
, &val
);
53 if (error
< GIT_SUCCESS
)
56 return refspec_parse(refspec
, val
);
59 int git_remote_new(git_remote
**out
, git_repository
*repo
, const char *url
, const char *name
)
63 /* name is optional */
64 assert(out
&& repo
&& url
);
66 remote
= git__malloc(sizeof(git_remote
));
70 memset(remote
, 0x0, sizeof(git_remote
));
73 if (git_vector_init(&remote
->refs
, 32, NULL
) < 0) {
74 git_remote_free(remote
);
78 remote
->url
= git__strdup(url
);
79 if (remote
->url
== NULL
) {
80 git_remote_free(remote
);
85 remote
->name
= git__strdup(name
);
86 if (remote
->name
== NULL
) {
87 git_remote_free(remote
);
96 int git_remote_load(git_remote
**out
, git_repository
*repo
, const char *name
)
101 int ret
, error
, buf_len
;
104 assert(out
&& repo
&& name
);
106 error
= git_repository_config__weakptr(&config
, repo
);
107 if (error
< GIT_SUCCESS
)
110 remote
= git__malloc(sizeof(git_remote
));
114 memset(remote
, 0x0, sizeof(git_remote
));
115 remote
->name
= git__strdup(name
);
116 if (remote
->name
== NULL
) {
121 if (git_vector_init(&remote
->refs
, 32, NULL
) < 0) {
126 /* "fetch" is the longest var name we're interested in */
127 buf_len
= strlen("remote.") + strlen(".fetch") + strlen(name
) + 1;
128 buf
= git__malloc(buf_len
);
134 ret
= p_snprintf(buf
, buf_len
, "%s.%s.%s", "remote", name
, "url");
136 error
= git__throw(GIT_EOSERR
, "Failed to build config var name");
140 error
= git_config_get_string(config
, buf
, &val
);
141 if (error
< GIT_SUCCESS
) {
142 error
= git__rethrow(error
, "Remote's url doesn't exist");
147 remote
->url
= git__strdup(val
);
148 if (remote
->url
== NULL
) {
153 ret
= p_snprintf(buf
, buf_len
, "%s.%s.%s", "remote", name
, "fetch");
155 error
= git__throw(GIT_EOSERR
, "Failed to build config var name");
159 error
= parse_remote_refspec(config
, &remote
->fetch
, buf
);
160 if (error
< GIT_SUCCESS
) {
161 error
= git__rethrow(error
, "Failed to get fetch refspec");
165 ret
= p_snprintf(buf
, buf_len
, "%s.%s.%s", "remote", name
, "push");
167 error
= git__throw(GIT_EOSERR
, "Failed to build config var name");
171 error
= parse_remote_refspec(config
, &remote
->push
, buf
);
172 /* Not finding push is fine */
173 if (error
== GIT_ENOTFOUND
)
176 if (error
< GIT_SUCCESS
)
184 if (error
< GIT_SUCCESS
)
185 git_remote_free(remote
);
190 const char *git_remote_name(git_remote
*remote
)
196 const char *git_remote_url(git_remote
*remote
)
202 const git_refspec
*git_remote_fetchspec(git_remote
*remote
)
205 return &remote
->fetch
;
208 const git_refspec
*git_remote_pushspec(git_remote
*remote
)
211 return &remote
->push
;
214 int git_remote_connect(git_remote
*remote
, int direction
)
221 error
= git_transport_new(&t
, remote
->url
);
222 if (error
< GIT_SUCCESS
)
223 return git__rethrow(error
, "Failed to create transport");
225 error
= t
->connect(t
, direction
);
226 if (error
< GIT_SUCCESS
) {
227 error
= git__rethrow(error
, "Failed to connect the transport");
231 remote
->transport
= t
;
234 if (error
< GIT_SUCCESS
)
240 int git_remote_ls(git_remote
*remote
, git_headlist_cb list_cb
, void *payload
)
244 if (!remote
->transport
|| !remote
->transport
->connected
)
245 return git__throw(GIT_ERROR
, "The remote is not connected");
247 return remote
->transport
->ls(remote
->transport
, list_cb
, payload
);
250 int git_remote_download(char **filename
, git_remote
*remote
)
254 assert(filename
&& remote
);
256 if ((error
= git_fetch_negotiate(remote
)) < 0)
257 return git__rethrow(error
, "Error negotiating");
259 return git_fetch_download_pack(filename
, remote
);
262 int git_remote_update_tips(git_remote
*remote
)
264 int error
= GIT_SUCCESS
;
266 git_buf refname
= GIT_BUF_INIT
;
267 git_vector
*refs
= &remote
->refs
;
268 git_remote_head
*head
;
270 struct git_refspec
*spec
= &remote
->fetch
;
274 if (refs
->length
== 0)
277 /* HEAD is only allowed to be the first in the list */
278 head
= refs
->contents
[0];
279 if (!strcmp(head
->name
, GIT_HEAD_FILE
)) {
280 error
= git_reference_create_oid(&ref
, remote
->repo
, GIT_FETCH_HEAD_FILE
, &head
->oid
, 1);
282 if (error
< GIT_SUCCESS
)
283 return git__rethrow(error
, "Failed to update FETCH_HEAD");
285 git_reference_free(ref
);
288 for (; i
< refs
->length
; ++i
) {
289 head
= refs
->contents
[i
];
291 error
= git_refspec_transform_r(&refname
, spec
, head
->name
);
292 if (error
< GIT_SUCCESS
)
295 error
= git_reference_create_oid(&ref
, remote
->repo
, refname
.ptr
, &head
->oid
, 1);
296 if (error
< GIT_SUCCESS
)
299 git_reference_free(ref
);
302 git_buf_free(&refname
);
307 int git_remote_connected(git_remote
*remote
)
310 return remote
->transport
== NULL
? 0 : remote
->transport
->connected
;
313 void git_remote_disconnect(git_remote
*remote
)
317 if (remote
->transport
!= NULL
) {
318 if (remote
->transport
->connected
)
319 remote
->transport
->close(remote
->transport
);
321 remote
->transport
->free(remote
->transport
);
322 remote
->transport
= NULL
;
326 void git_remote_free(git_remote
*remote
)
331 git__free(remote
->fetch
.src
);
332 git__free(remote
->fetch
.dst
);
333 git__free(remote
->push
.src
);
334 git__free(remote
->push
.dst
);
335 git__free(remote
->url
);
336 git__free(remote
->name
);
337 git_vector_free(&remote
->refs
);
338 git_remote_disconnect(remote
);