]> git.proxmox.com Git - libgit2.git/blob - src/remote.c
Tabify everything
[libgit2.git] / src / remote.c
1 /*
2 * Copyright (C) 2009-2011 the libgit2 contributors
3 *
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.
6 */
7
8 #include "git2/remote.h"
9 #include "git2/config.h"
10 #include "git2/types.h"
11
12 #include "config.h"
13 #include "repository.h"
14 #include "remote.h"
15 #include "fetch.h"
16 #include "refs.h"
17
18 static int refspec_parse(git_refspec *refspec, const char *str)
19 {
20 char *delim;
21
22 memset(refspec, 0x0, sizeof(git_refspec));
23
24 if (*str == '+') {
25 refspec->force = 1;
26 str++;
27 }
28
29 delim = strchr(str, ':');
30 if (delim == NULL)
31 return git__throw(GIT_EOBJCORRUPTED, "Failed to parse refspec. No ':'");
32
33 refspec->src = git__strndup(str, delim - str);
34 if (refspec->src == NULL)
35 return GIT_ENOMEM;
36
37 refspec->dst = git__strdup(delim + 1);
38 if (refspec->dst == NULL) {
39 free(refspec->src);
40 refspec->src = NULL;
41 return GIT_ENOMEM;
42 }
43
44 return GIT_SUCCESS;
45 }
46
47 static int parse_remote_refspec(git_config *cfg, git_refspec *refspec, const char *var)
48 {
49 const char *val;
50 int error;
51
52 error = git_config_get_string(cfg, var, &val);
53 if (error < GIT_SUCCESS)
54 return error;
55
56 return refspec_parse(refspec, val);
57 }
58
59 int git_remote_new(git_remote **out, git_repository *repo, const char *url)
60 {
61 git_remote *remote;
62
63 remote = git__malloc(sizeof(git_remote));
64 if (remote == NULL)
65 return GIT_ENOMEM;
66
67 memset(remote, 0x0, sizeof(git_remote));
68 remote->repo = repo;
69 remote->url = git__strdup(url);
70 if (remote->url == NULL) {
71 free(remote);
72 return GIT_ENOMEM;
73 }
74
75 *out = remote;
76 return GIT_SUCCESS;
77 }
78
79 int git_remote_get(git_remote **out, git_config *cfg, const char *name)
80 {
81 git_remote *remote;
82 char *buf = NULL;
83 const char *val;
84 int ret, error, buf_len;
85
86 remote = git__malloc(sizeof(git_remote));
87 if (remote == NULL)
88 return GIT_ENOMEM;
89
90 memset(remote, 0x0, sizeof(git_remote));
91 remote->name = git__strdup(name);
92 if (remote->name == NULL) {
93 error = GIT_ENOMEM;
94 goto cleanup;
95 }
96
97 /* "fetch" is the longest var name we're interested in */
98 buf_len = strlen("remote.") + strlen(".fetch") + strlen(name) + 1;
99 buf = git__malloc(buf_len);
100 if (buf == NULL) {
101 error = GIT_ENOMEM;
102 goto cleanup;
103 }
104
105 ret = p_snprintf(buf, buf_len, "%s.%s.%s", "remote", name, "url");
106 if (ret < 0) {
107 error = git__throw(GIT_EOSERR, "Failed to build config var name");
108 goto cleanup;
109 }
110
111 error = git_config_get_string(cfg, buf, &val);
112 if (error < GIT_SUCCESS) {
113 error = git__rethrow(error, "Remote's url doesn't exist");
114 goto cleanup;
115 }
116
117 remote->repo = cfg->repo;
118 remote->url = git__strdup(val);
119 if (remote->url == NULL) {
120 error = GIT_ENOMEM;
121 goto cleanup;
122 }
123
124 ret = p_snprintf(buf, buf_len, "%s.%s.%s", "remote", name, "fetch");
125 if (ret < 0) {
126 error = git__throw(GIT_EOSERR, "Failed to build config var name");
127 goto cleanup;
128 }
129
130 error = parse_remote_refspec(cfg, &remote->fetch, buf);
131 if (error < GIT_SUCCESS) {
132 error = git__rethrow(error, "Failed to get fetch refspec");
133 goto cleanup;
134 }
135
136 ret = p_snprintf(buf, buf_len, "%s.%s.%s", "remote", name, "push");
137 if (ret < 0) {
138 error = git__throw(GIT_EOSERR, "Failed to build config var name");
139 goto cleanup;
140 }
141
142 error = parse_remote_refspec(cfg, &remote->push, buf);
143 /* Not finding push is fine */
144 if (error == GIT_ENOTFOUND)
145 error = GIT_SUCCESS;
146
147 if (error < GIT_SUCCESS)
148 goto cleanup;
149
150 *out = remote;
151
152 cleanup:
153 free(buf);
154 if (error < GIT_SUCCESS)
155 git_remote_free(remote);
156
157 return error;
158 }
159
160 const char *git_remote_name(struct git_remote *remote)
161 {
162 return remote->name;
163 }
164
165 const char *git_remote_url(struct git_remote *remote)
166 {
167 return remote->url;
168 }
169
170 const git_refspec *git_remote_fetchspec(struct git_remote *remote)
171 {
172 return &remote->fetch;
173 }
174
175 const git_refspec *git_remote_pushspec(struct git_remote *remote)
176 {
177 return &remote->push;
178 }
179
180 int git_remote_connect(git_remote *remote, int direction)
181 {
182 int error;
183 git_transport *t;
184
185 error = git_transport_new(&t, remote->url);
186 if (error < GIT_SUCCESS)
187 return git__rethrow(error, "Failed to create transport");
188
189 error = t->connect(t, direction);
190 if (error < GIT_SUCCESS) {
191 error = git__rethrow(error, "Failed to connect the transport");
192 goto cleanup;
193 }
194
195 remote->transport = t;
196
197 cleanup:
198 if (error < GIT_SUCCESS)
199 t->free(t);
200
201 return error;
202 }
203
204 int git_remote_ls(git_remote *remote, git_headarray *refs)
205 {
206 return remote->transport->ls(remote->transport, refs);
207 }
208
209 int git_remote_negotiate(git_remote *remote)
210 {
211 return git_fetch_negotiate(remote);
212 }
213
214 int git_remote_download(char **filename, git_remote *remote)
215 {
216 return git_fetch_download_pack(filename, remote);
217 }
218
219 git_headarray *git_remote_tips(git_remote *remote)
220 {
221 return &remote->refs;
222 }
223
224 int git_remote_update_tips(struct git_remote *remote)
225 {
226 int error = GIT_SUCCESS;
227 unsigned int i;
228 char refname[GIT_PATH_MAX];
229 git_headarray *refs = &remote->refs;
230 git_remote_head *head;
231 git_reference *ref;
232 struct git_refspec *spec = &remote->fetch;
233
234 memset(refname, 0x0, sizeof(refname));
235
236 for (i = 0; i < refs->len; ++i) {
237 head = refs->heads[i];
238 error = git_refspec_transform(refname, sizeof(refname), spec, head->name);
239 if (error < GIT_SUCCESS)
240 return error;
241
242 error = git_reference_create_oid(&ref, remote->repo, refname, &head->oid, 1);
243 if (error < GIT_SUCCESS)
244 return error;
245 }
246
247 return GIT_SUCCESS;
248 }
249
250 void git_remote_free(git_remote *remote)
251 {
252 free(remote->fetch.src);
253 free(remote->fetch.dst);
254 free(remote->push.src);
255 free(remote->push.dst);
256 free(remote->url);
257 free(remote->name);
258 if (remote->transport != NULL) {
259 if (remote->transport->connected)
260 remote->transport->close(remote->transport);
261
262 remote->transport->free(remote->transport);
263 }
264 free(remote);
265 }