]> git.proxmox.com Git - libgit2.git/blame - src/remote.c
remote: set/unset the autotag setting on save
[libgit2.git] / src / remote.c
CommitLineData
9c82357b 1/*
5e0de328 2 * Copyright (C) 2009-2012 the libgit2 contributors
9c82357b 3 *
bb742ede
VM
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.
9c82357b
CMN
6 */
7
9c82357b
CMN
8#include "git2/config.h"
9#include "git2/types.h"
c07d9c95 10#include "git2/oid.h"
9c82357b
CMN
11
12#include "config.h"
13#include "repository.h"
14#include "remote.h"
e1d88030 15#include "fetch.h"
441f57c2 16#include "refs.h"
ad4b5beb 17#include "pkt.h"
9c82357b 18
8171998f
CMN
19#include <regex.h>
20
eb0bd77a 21static int parse_remote_refspec(git_config *cfg, git_refspec *refspec, const char *var, bool is_fetch)
9c82357b 22{
9c82357b 23 int error;
4376f7f6 24 const char *val;
9c82357b 25
29e948de 26 if ((error = git_config_get_string(&val, cfg, var)) < 0)
9c82357b
CMN
27 return error;
28
eb0bd77a 29 return git_refspec__parse(refspec, val, is_fetch);
9c82357b
CMN
30}
31
24f2f94e
CMN
32static int download_tags_value(git_remote *remote, git_config *cfg)
33{
34 const char *val;
35 git_buf buf = GIT_BUF_INIT;
36 int error;
37
38 if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_UNSET)
39 return 0;
40
41 /* This is the default, let's see if we need to change it */
42 remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO;
43 if (git_buf_printf(&buf, "remote.%s.tagopt", remote->name) < 0)
44 return -1;
45
46 error = git_config_get_string(&val, cfg, git_buf_cstr(&buf));
47 git_buf_free(&buf);
48 if (!error && !strcmp(val, "--no-tags"))
49 remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_NONE;
3230a44f
CMN
50 else if (!error && !strcmp(val, "--tags"))
51 remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL;
24f2f94e
CMN
52
53 if (error == GIT_ENOTFOUND)
54 error = 0;
55
56 return error;
57}
58
baaa8a44 59int git_remote_new(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch)
778e1c73
CMN
60{
61 git_remote *remote;
62
4bef3565
VM
63 /* name is optional */
64 assert(out && repo && url);
617bfdf4 65
778e1c73 66 remote = git__malloc(sizeof(git_remote));
4376f7f6 67 GITERR_CHECK_ALLOC(remote);
778e1c73
CMN
68
69 memset(remote, 0x0, sizeof(git_remote));
70 remote->repo = repo;
250b95b2 71 remote->check_cert = 1;
617bfdf4 72
4376f7f6
CMN
73 if (git_vector_init(&remote->refs, 32, NULL) < 0)
74 return -1;
d88d4311 75
778e1c73 76 remote->url = git__strdup(url);
4376f7f6 77 GITERR_CHECK_ALLOC(remote->url);
778e1c73 78
617bfdf4
CMN
79 if (name != NULL) {
80 remote->name = git__strdup(name);
4376f7f6 81 GITERR_CHECK_ALLOC(remote->name);
617bfdf4
CMN
82 }
83
baaa8a44 84 if (fetch != NULL) {
eb0bd77a 85 if (git_refspec__parse(&remote->fetch, fetch, true) < 0)
baaa8a44
CMN
86 goto on_error;
87 }
88
778e1c73 89 *out = remote;
4376f7f6 90 return 0;
baaa8a44
CMN
91
92on_error:
93 git_remote_free(remote);
94 return -1;
778e1c73
CMN
95}
96
9462c471 97int git_remote_load(git_remote **out, git_repository *repo, const char *name)
9c82357b
CMN
98{
99 git_remote *remote;
f0f3a18a 100 git_buf buf = GIT_BUF_INIT;
9c82357b 101 const char *val;
4376f7f6 102 int error = 0;
9462c471 103 git_config *config;
9c82357b 104
9462c471
VM
105 assert(out && repo && name);
106
4376f7f6
CMN
107 if (git_repository_config__weakptr(&config, repo) < 0)
108 return -1;
4bef3565 109
9c82357b 110 remote = git__malloc(sizeof(git_remote));
4376f7f6 111 GITERR_CHECK_ALLOC(remote);
9c82357b
CMN
112
113 memset(remote, 0x0, sizeof(git_remote));
250b95b2 114 remote->check_cert = 1;
9c82357b 115 remote->name = git__strdup(name);
4376f7f6 116 GITERR_CHECK_ALLOC(remote->name);
9c82357b 117
2fb9d6de 118 if (git_vector_init(&remote->refs, 32, NULL) < 0) {
119 error = -1;
120 goto cleanup;
121 }
d88d4311 122
2fb9d6de 123 if (git_buf_printf(&buf, "remote.%s.url", name) < 0) {
124 error = -1;
125 goto cleanup;
126 }
9c82357b 127
29e948de 128 if ((error = git_config_get_string(&val, config, git_buf_cstr(&buf))) < 0)
9c82357b 129 goto cleanup;
9c82357b 130
9462c471 131 remote->repo = repo;
9c82357b 132 remote->url = git__strdup(val);
4376f7f6 133 GITERR_CHECK_ALLOC(remote->url);
9c82357b 134
3ed4b501
SC
135 git_buf_clear(&buf);
136 if (git_buf_printf(&buf, "remote.%s.pushurl", name) < 0) {
137 error = -1;
138 goto cleanup;
139 }
140
141 error = git_config_get_string(&val, config, git_buf_cstr(&buf));
142 if (error == GIT_ENOTFOUND)
143 error = 0;
144
145 if (error < 0) {
146 error = -1;
147 goto cleanup;
148 }
149
150 if (val) {
151 remote->pushurl = git__strdup(val);
152 GITERR_CHECK_ALLOC(remote->pushurl);
153 }
154
f0f3a18a 155 git_buf_clear(&buf);
2fb9d6de 156 if (git_buf_printf(&buf, "remote.%s.fetch", name) < 0) {
157 error = -1;
158 goto cleanup;
159 }
9c82357b 160
eb0bd77a 161 error = parse_remote_refspec(config, &remote->fetch, git_buf_cstr(&buf), true);
904b67e6 162 if (error == GIT_ENOTFOUND)
4376f7f6 163 error = 0;
9554cd51 164
4376f7f6
CMN
165 if (error < 0) {
166 error = -1;
9c82357b 167 goto cleanup;
2dc31040 168 }
9c82357b 169
f0f3a18a 170 git_buf_clear(&buf);
2fb9d6de 171 if (git_buf_printf(&buf, "remote.%s.push", name) < 0) {
172 error = -1;
173 goto cleanup;
174 }
9c82357b 175
eb0bd77a 176 error = parse_remote_refspec(config, &remote->push, git_buf_cstr(&buf), false);
904b67e6 177 if (error == GIT_ENOTFOUND)
4376f7f6 178 error = 0;
9c82357b 179
4376f7f6
CMN
180 if (error < 0) {
181 error = -1;
9c82357b 182 goto cleanup;
4376f7f6 183 }
9c82357b 184
24f2f94e
CMN
185 if (download_tags_value(remote, config) < 0)
186 goto cleanup;
187
9c82357b
CMN
188 *out = remote;
189
190cleanup:
f0f3a18a 191 git_buf_free(&buf);
9462c471 192
4376f7f6 193 if (error < 0)
9c82357b
CMN
194 git_remote_free(remote);
195
196 return error;
197}
198
89e5ed98
CMN
199int git_remote_save(const git_remote *remote)
200{
218c88a9 201 int error;
89e5ed98 202 git_config *config;
218c88a9 203 const char *tagopt = NULL;
89e5ed98
CMN
204 git_buf buf = GIT_BUF_INIT, value = GIT_BUF_INIT;
205
4376f7f6
CMN
206 if (git_repository_config__weakptr(&config, remote->repo) < 0)
207 return -1;
89e5ed98 208
cb020f0d 209 if (git_buf_printf(&buf, "remote.%s.url", remote->name) < 0)
4376f7f6 210 return -1;
89e5ed98 211
4376f7f6
CMN
212 if (git_config_set_string(config, git_buf_cstr(&buf), remote->url) < 0) {
213 git_buf_free(&buf);
214 return -1;
215 }
89e5ed98 216
413d5563
SC
217 git_buf_clear(&buf);
218 if (git_buf_printf(&buf, "remote.%s.pushurl", remote->name) < 0)
219 return -1;
3ed4b501 220
413d5563 221 if (remote->pushurl) {
3ed4b501
SC
222 if (git_config_set_string(config, git_buf_cstr(&buf), remote->pushurl) < 0) {
223 git_buf_free(&buf);
224 return -1;
225 }
413d5563
SC
226 } else {
227 int error = git_config_delete(config, git_buf_cstr(&buf));
228 if (error == GIT_ENOTFOUND) {
229 error = 0;
230 }
231 if (error < 0) {
232 git_buf_free(&buf);
233 return -1;
234 }
3ed4b501
SC
235 }
236
9c94a356 237 if (remote->fetch.src != NULL && remote->fetch.dst != NULL) {
89e5ed98
CMN
238 git_buf_clear(&buf);
239 git_buf_clear(&value);
4376f7f6 240 git_buf_printf(&buf, "remote.%s.fetch", remote->name);
d05e2c64 241 if (remote->fetch.force)
242 git_buf_putc(&value, '+');
89e5ed98
CMN
243 git_buf_printf(&value, "%s:%s", remote->fetch.src, remote->fetch.dst);
244 if (git_buf_oom(&buf) || git_buf_oom(&value))
4376f7f6 245 return -1;
89e5ed98 246
4376f7f6
CMN
247 if (git_config_set_string(config, git_buf_cstr(&buf), git_buf_cstr(&value)) < 0)
248 goto on_error;
89e5ed98
CMN
249 }
250
9c94a356 251 if (remote->push.src != NULL && remote->push.dst != NULL) {
89e5ed98
CMN
252 git_buf_clear(&buf);
253 git_buf_clear(&value);
4376f7f6 254 git_buf_printf(&buf, "remote.%s.push", remote->name);
d05e2c64 255 if (remote->push.force)
256 git_buf_putc(&value, '+');
89e5ed98
CMN
257 git_buf_printf(&value, "%s:%s", remote->push.src, remote->push.dst);
258 if (git_buf_oom(&buf) || git_buf_oom(&value))
4376f7f6 259 return -1;
89e5ed98 260
4376f7f6
CMN
261 if (git_config_set_string(config, git_buf_cstr(&buf), git_buf_cstr(&value)) < 0)
262 goto on_error;
89e5ed98
CMN
263 }
264
218c88a9
CMN
265 /*
266 * What action to take depends on the old and new values. This
267 * is describes by the table below. tagopt means whether the
268 * is already a value set in the config
269 *
270 * AUTO ALL or NONE
271 * +-----------------------+
272 * tagopt | remove | set |
273 * +---------+-------------|
274 * !tagopt | nothing | set |
275 * +---------+-------------+
276 */
277
278 git_buf_clear(&buf);
279 if (git_buf_printf(&buf, "remote.%s.tagopt", remote->name) < 0)
280 goto on_error;
281
282 error = git_config_get_string(&tagopt, config, git_buf_cstr(&buf));
283 if (error < 0 && error != GIT_ENOTFOUND)
284 goto on_error;
285
286 if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) {
287 if (git_config_set_string(config, git_buf_cstr(&buf), "--tags") < 0)
288 goto on_error;
289 } else if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
290 if (git_config_set_string(config, git_buf_cstr(&buf), "--no-tags") < 0)
291 goto on_error;
292 } else if (tagopt) {
293 if (git_config_delete(config, git_buf_cstr(&buf)) < 0)
294 goto on_error;
295 }
296
89e5ed98
CMN
297 git_buf_free(&buf);
298 git_buf_free(&value);
4376f7f6
CMN
299
300 return 0;
301
302on_error:
303 git_buf_free(&buf);
304 git_buf_free(&value);
305 return -1;
89e5ed98
CMN
306}
307
4bef3565 308const char *git_remote_name(git_remote *remote)
9c82357b 309{
4bef3565 310 assert(remote);
9c82357b
CMN
311 return remote->name;
312}
313
4bef3565 314const char *git_remote_url(git_remote *remote)
9c82357b 315{
4bef3565 316 assert(remote);
9c82357b
CMN
317 return remote->url;
318}
319
76501590
SC
320int git_remote_set_url(git_remote *remote, const char* url)
321{
322 assert(remote);
323 assert(url);
324
325 git__free(remote->url);
326 remote->url = git__strdup(url);
327 GITERR_CHECK_ALLOC(remote->url);
328
329 return 0;
330}
331
332const char *git_remote_pushurl(git_remote *remote)
333{
334 assert(remote);
335 return remote->pushurl;
336}
337
338int git_remote_set_pushurl(git_remote *remote, const char* url)
339{
340 assert(remote);
341
342 git__free(remote->pushurl);
343 if (url) {
344 remote->pushurl = git__strdup(url);
345 GITERR_CHECK_ALLOC(remote->pushurl);
346 } else {
347 remote->pushurl = NULL;
348 }
349 return 0;
350}
351
bcb8c007
CMN
352int git_remote_set_fetchspec(git_remote *remote, const char *spec)
353{
bcb8c007
CMN
354 git_refspec refspec;
355
356 assert(remote && spec);
357
eb0bd77a 358 if (git_refspec__parse(&refspec, spec, true) < 0)
4376f7f6 359 return -1;
bcb8c007 360
eb0bd77a 361 git_refspec__free(&remote->fetch);
bcb8c007
CMN
362 remote->fetch.src = refspec.src;
363 remote->fetch.dst = refspec.dst;
364
4376f7f6 365 return 0;
bcb8c007
CMN
366}
367
4bef3565 368const git_refspec *git_remote_fetchspec(git_remote *remote)
9c82357b 369{
4bef3565 370 assert(remote);
9c82357b
CMN
371 return &remote->fetch;
372}
373
bcb8c007
CMN
374int git_remote_set_pushspec(git_remote *remote, const char *spec)
375{
bcb8c007
CMN
376 git_refspec refspec;
377
378 assert(remote && spec);
379
eb0bd77a 380 if (git_refspec__parse(&refspec, spec, false) < 0)
4376f7f6 381 return -1;
bcb8c007 382
eb0bd77a 383 git_refspec__free(&remote->push);
bcb8c007
CMN
384 remote->push.src = refspec.src;
385 remote->push.dst = refspec.dst;
386
4376f7f6 387 return 0;
bcb8c007
CMN
388}
389
4bef3565 390const git_refspec *git_remote_pushspec(git_remote *remote)
9c82357b 391{
4bef3565 392 assert(remote);
9c82357b
CMN
393 return &remote->push;
394}
395
eff5b499
SC
396const char* git_remote__urlfordirection(git_remote *remote, int direction)
397{
398 assert(remote);
399
400 if (direction == GIT_DIR_FETCH) {
401 return remote->url;
402 }
403
404 if (direction == GIT_DIR_PUSH) {
405 return remote->pushurl ? remote->pushurl : remote->url;
406 }
407
408 return NULL;
409}
410
0ac2726f 411int git_remote_connect(git_remote *remote, int direction)
9ba49bb5 412{
9ba49bb5 413 git_transport *t;
c0c39025 414 const char *url;
9ba49bb5 415
4bef3565
VM
416 assert(remote);
417
c0c39025 418 url = git_remote__urlfordirection(remote, direction);
eff5b499
SC
419 if (url == NULL )
420 return -1;
421
422 if (git_transport_new(&t, url) < 0)
4376f7f6 423 return -1;
9ba49bb5 424
e03e71da
CMN
425 t->progress_cb = remote->callbacks.progress;
426 t->cb_data = remote->callbacks.data;
427
250b95b2 428 t->check_cert = remote->check_cert;
4376f7f6
CMN
429 if (t->connect(t, direction) < 0) {
430 goto on_error;
9ba49bb5
CMN
431 }
432
433 remote->transport = t;
434
4376f7f6 435 return 0;
9ba49bb5 436
4376f7f6
CMN
437on_error:
438 t->free(t);
439 return -1;
9ba49bb5
CMN
440}
441
d88d4311 442int git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void *payload)
9ba49bb5 443{
ad4b5beb
CMN
444 git_vector *refs = &remote->transport->refs;
445 unsigned int i;
446 git_pkt *p = NULL;
447
d88d4311
VM
448 assert(remote);
449
4376f7f6
CMN
450 if (!remote->transport || !remote->transport->connected) {
451 giterr_set(GITERR_NET, "The remote is not connected");
452 return -1;
453 }
d88d4311 454
ad4b5beb
CMN
455 git_vector_foreach(refs, i, p) {
456 git_pkt_ref *pkt = NULL;
457
458 if (p->type != GIT_PKT_REF)
459 continue;
460
461 pkt = (git_pkt_ref *)p;
462
e4607392 463 if (list_cb(&pkt->head, payload))
d8d28e2e 464 return GIT_EUSER;
ad4b5beb
CMN
465 }
466
467 return 0;
9ba49bb5
CMN
468}
469
7a520f5d 470int git_remote_download(git_remote *remote, git_off_t *bytes, git_indexer_stats *stats)
48a65a07 471{
95057b85
CMN
472 int error;
473
7a520f5d 474 assert(remote && bytes && stats);
4bef3565 475
95057b85 476 if ((error = git_fetch_negotiate(remote)) < 0)
4376f7f6 477 return error;
95057b85 478
7a520f5d 479 return git_fetch_download_pack(remote, bytes, stats);
48a65a07
CMN
480}
481
b3aaa7a7 482int git_remote_update_tips(git_remote *remote)
441f57c2 483{
a37ddf7e 484 int error = 0, autotag;
517bda19 485 unsigned int i = 0;
97769280 486 git_buf refname = GIT_BUF_INIT;
f184836b 487 git_oid old;
a37ddf7e
CMN
488 git_pkt *pkt;
489 git_odb *odb;
3f035860 490 git_vector *refs;
441f57c2
CMN
491 git_remote_head *head;
492 git_reference *ref;
3f035860 493 struct git_refspec *spec;
a37ddf7e 494 git_refspec tagspec;
441f57c2 495
4bef3565
VM
496 assert(remote);
497
a37ddf7e 498 refs = &remote->transport->refs;
3f035860
VM
499 spec = &remote->fetch;
500
d88d4311 501 if (refs->length == 0)
e172cf08 502 return 0;
517bda19 503
a37ddf7e
CMN
504 if (git_repository_odb(&odb, remote->repo) < 0)
505 return -1;
506
3230a44f 507 if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
a37ddf7e
CMN
508 return -1;
509
517bda19 510 /* HEAD is only allowed to be the first in the list */
a37ddf7e
CMN
511 pkt = refs->contents[0];
512 head = &((git_pkt_ref *)pkt)->head;
517bda19 513 if (!strcmp(head->name, GIT_HEAD_FILE)) {
4376f7f6
CMN
514 if (git_reference_create_oid(&ref, remote->repo, GIT_FETCH_HEAD_FILE, &head->oid, 1) < 0)
515 return -1;
585a2eb7 516
4376f7f6 517 i = 1;
585a2eb7 518 git_reference_free(ref);
517bda19
CMN
519 }
520
d88d4311 521 for (; i < refs->length; ++i) {
a37ddf7e 522 git_pkt *pkt = refs->contents[i];
9063be1f 523 autotag = 0;
517bda19 524
a37ddf7e
CMN
525 if (pkt->type == GIT_PKT_REF)
526 head = &((git_pkt_ref *)pkt)->head;
527 else
528 continue;
529
530 /* Ignore malformed ref names (which also saves us from tag^{} */
531 if (!git_reference_is_valid_name(head->name))
532 continue;
533
534 if (git_refspec_src_matches(spec, head->name)) {
535 if (git_refspec_transform_r(&refname, spec, head->name) < 0)
536 goto on_error;
537 } else if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
3230a44f
CMN
538
539 if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_ALL)
540 autotag = 1;
a37ddf7e
CMN
541
542 if (!git_refspec_src_matches(&tagspec, head->name))
543 continue;
544
545 git_buf_clear(&refname);
546 if (git_buf_puts(&refname, head->name) < 0)
547 goto on_error;
548 } else {
549 continue;
550 }
551
552 if (autotag && !git_odb_exists(odb, &head->oid))
553 continue;
f184836b
CMN
554
555 error = git_reference_name_to_oid(&old, remote->repo, refname.ptr);
904b67e6 556 if (error < 0 && error != GIT_ENOTFOUND)
f184836b
CMN
557 goto on_error;
558
904b67e6 559 if (error == GIT_ENOTFOUND)
f184836b
CMN
560 memset(&old, 0, GIT_OID_RAWSZ);
561
562 if (!git_oid_cmp(&old, &head->oid))
563 continue;
441f57c2 564
a37ddf7e
CMN
565 /* In autotag mode, don't overwrite any locally-existing tags */
566 error = git_reference_create_oid(&ref, remote->repo, refname.ptr, &head->oid, !autotag);
567 if (error < 0 && error != GIT_EEXISTS)
944d250f 568 goto on_error;
39157563
CMN
569
570 git_reference_free(ref);
f184836b 571
b3aaa7a7
CMN
572 if (remote->callbacks.update_tips != NULL) {
573 if (remote->callbacks.update_tips(refname.ptr, &old, &head->oid, remote->callbacks.data) < 0)
f184836b
CMN
574 goto on_error;
575 }
441f57c2
CMN
576 }
577
a37ddf7e 578 git_refspec__free(&tagspec);
97769280 579 git_buf_free(&refname);
f184836b
CMN
580 return 0;
581
582on_error:
a37ddf7e 583 git_refspec__free(&tagspec);
f184836b
CMN
584 git_buf_free(&refname);
585 return -1;
97769280 586
441f57c2
CMN
587}
588
6ac3b707
CMN
589int git_remote_connected(git_remote *remote)
590{
4bef3565 591 assert(remote);
6ac3b707
CMN
592 return remote->transport == NULL ? 0 : remote->transport->connected;
593}
594
4cf01e9a
CMN
595void git_remote_disconnect(git_remote *remote)
596{
4bef3565
VM
597 assert(remote);
598
42ea35c0 599 if (remote->transport != NULL && remote->transport->connected)
4cf01e9a 600 remote->transport->close(remote->transport);
4cf01e9a
CMN
601}
602
9c82357b
CMN
603void git_remote_free(git_remote *remote)
604{
2aae2188
CMN
605 if (remote == NULL)
606 return;
607
42ea35c0
MS
608 if (remote->transport != NULL) {
609 git_remote_disconnect(remote);
610
611 remote->transport->free(remote->transport);
612 remote->transport = NULL;
613 }
614
615 git_vector_free(&remote->refs);
616
3665ba8e
CMN
617 git_refspec__free(&remote->fetch);
618 git_refspec__free(&remote->push);
3286c408 619 git__free(remote->url);
3ed4b501 620 git__free(remote->pushurl);
3286c408 621 git__free(remote->name);
3286c408 622 git__free(remote);
9c82357b 623}
8171998f
CMN
624
625struct cb_data {
626 git_vector *list;
627 regex_t *preg;
628};
629
854eccbb 630static int remote_list_cb(const char *name, const char *value, void *data_)
8171998f
CMN
631{
632 struct cb_data *data = (struct cb_data *)data_;
633 size_t nmatch = 2;
634 regmatch_t pmatch[2];
854eccbb 635 GIT_UNUSED(value);
8171998f
CMN
636
637 if (!regexec(data->preg, name, nmatch, pmatch, 0)) {
638 char *remote_name = git__strndup(&name[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so);
4376f7f6 639 GITERR_CHECK_ALLOC(remote_name);
8171998f 640
4376f7f6
CMN
641 if (git_vector_insert(data->list, remote_name) < 0)
642 return -1;
8171998f
CMN
643 }
644
4376f7f6 645 return 0;
8171998f
CMN
646}
647
648int git_remote_list(git_strarray *remotes_list, git_repository *repo)
649{
650 git_config *cfg;
651 git_vector list;
652 regex_t preg;
653 struct cb_data data;
654 int error;
655
4376f7f6
CMN
656 if (git_repository_config__weakptr(&cfg, repo) < 0)
657 return -1;
8171998f 658
4376f7f6
CMN
659 if (git_vector_init(&list, 4, NULL) < 0)
660 return -1;
8171998f 661
4376f7f6
CMN
662 if (regcomp(&preg, "^remote\\.(.*)\\.url$", REG_EXTENDED) < 0) {
663 giterr_set(GITERR_OS, "Remote catch regex failed to compile");
664 return -1;
665 }
8171998f
CMN
666
667 data.list = &list;
668 data.preg = &preg;
669 error = git_config_foreach(cfg, remote_list_cb, &data);
670 regfree(&preg);
4376f7f6 671 if (error < 0) {
8171998f
CMN
672 size_t i;
673 char *elem;
674 git_vector_foreach(&list, i, elem) {
2bc8fa02 675 git__free(elem);
8171998f
CMN
676 }
677
678 git_vector_free(&list);
e4607392
RB
679
680 /* cb error is converted to GIT_EUSER by git_config_foreach */
681 if (error == GIT_EUSER)
682 error = -1;
683
8171998f
CMN
684 return error;
685 }
686
687 remotes_list->strings = (char **)list.contents;
688 remotes_list->count = list.length;
689
4376f7f6 690 return 0;
8171998f 691}
a209a025
CMN
692
693int git_remote_add(git_remote **out, git_repository *repo, const char *name, const char *url)
694{
695 git_buf buf = GIT_BUF_INIT;
a209a025 696
d27bf665 697 if (git_buf_printf(&buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0)
baaa8a44 698 return -1;
a209a025 699
baaa8a44 700 if (git_remote_new(out, repo, name, url, git_buf_cstr(&buf)) < 0)
a209a025
CMN
701 goto on_error;
702
703 git_buf_free(&buf);
704
705 if (git_remote_save(*out) < 0)
baaa8a44 706 goto on_error;
a209a025
CMN
707
708 return 0;
709
710on_error:
711 git_buf_free(&buf);
712 git_remote_free(*out);
713 return -1;
714}
250b95b2
CMN
715
716void git_remote_check_cert(git_remote *remote, int check)
717{
718 assert(remote);
719
720 remote->check_cert = check;
721}
b3aaa7a7
CMN
722
723void git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks)
724{
725 assert(remote && callbacks);
726
727 memcpy(&remote->callbacks, callbacks, sizeof(git_remote_callbacks));
e03e71da
CMN
728
729 if (remote->transport) {
730 remote->transport->progress_cb = remote->callbacks.progress;
731 remote->transport->cb_data = remote->callbacks.data;
732 }
b3aaa7a7 733}
f70e466f
CMN
734
735int git_remote_autotag(git_remote *remote)
736{
737 return remote->download_tags;
738}
739
740void git_remote_set_autotag(git_remote *remote, int value)
741{
742 remote->download_tags = value;
743}