]> git.proxmox.com Git - libgit2.git/blame - src/remote.c
Fixed size_t format string warning
[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"
b0f6e45d
ET
17#include "refspec.h"
18#include "fetchhead.h"
9c82357b 19
8171998f
CMN
20#include <regex.h>
21
eb0bd77a 22static int parse_remote_refspec(git_config *cfg, git_refspec *refspec, const char *var, bool is_fetch)
9c82357b 23{
9c82357b 24 int error;
4376f7f6 25 const char *val;
9c82357b 26
29e948de 27 if ((error = git_config_get_string(&val, cfg, var)) < 0)
9c82357b
CMN
28 return error;
29
eb0bd77a 30 return git_refspec__parse(refspec, val, is_fetch);
9c82357b
CMN
31}
32
24f2f94e
CMN
33static int download_tags_value(git_remote *remote, git_config *cfg)
34{
35 const char *val;
36 git_buf buf = GIT_BUF_INIT;
37 int error;
38
39 if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_UNSET)
40 return 0;
41
42 /* This is the default, let's see if we need to change it */
43 remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO;
44 if (git_buf_printf(&buf, "remote.%s.tagopt", remote->name) < 0)
45 return -1;
46
47 error = git_config_get_string(&val, cfg, git_buf_cstr(&buf));
48 git_buf_free(&buf);
49 if (!error && !strcmp(val, "--no-tags"))
50 remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_NONE;
3230a44f
CMN
51 else if (!error && !strcmp(val, "--tags"))
52 remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL;
24f2f94e
CMN
53
54 if (error == GIT_ENOTFOUND)
55 error = 0;
56
57 return error;
58}
59
032ba9e4 60static int ensure_remote_name_is_valid(const char *name)
61{
62 git_buf buf = GIT_BUF_INIT;
63 git_refspec refspec;
64 int error = -1;
65
66 if (!name || *name == '\0')
67 goto cleanup;
68
69 git_buf_printf(&buf, "refs/heads/test:refs/remotes/%s/test", name);
70 error = git_refspec__parse(&refspec, git_buf_cstr(&buf), true);
71
72 git_buf_free(&buf);
73 git_refspec__free(&refspec);
74
75cleanup:
76 if (error) {
77 giterr_set(
78 GITERR_CONFIG,
79 "'%s' is not a valid remote name.", name);
80 error = GIT_EINVALIDSPEC;
81 }
82
83 return error;
84}
85
874dcb25 86static int create_internal(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch)
778e1c73
CMN
87{
88 git_remote *remote;
44f36f6e
BS
89 git_buf fetchbuf = GIT_BUF_INIT;
90 int error = -1;
778e1c73 91
4bef3565 92 /* name is optional */
874dcb25 93 assert(out && repo && url);
617bfdf4 94
59bccf33 95 remote = git__calloc(1, sizeof(git_remote));
4376f7f6 96 GITERR_CHECK_ALLOC(remote);
778e1c73 97
778e1c73 98 remote->repo = repo;
250b95b2 99 remote->check_cert = 1;
b0f6e45d 100 remote->update_fetchhead = 1;
617bfdf4 101
4376f7f6 102 if (git_vector_init(&remote->refs, 32, NULL) < 0)
44f36f6e 103 goto on_error;
d88d4311 104
778e1c73 105 remote->url = git__strdup(url);
4376f7f6 106 GITERR_CHECK_ALLOC(remote->url);
778e1c73 107
617bfdf4
CMN
108 if (name != NULL) {
109 remote->name = git__strdup(name);
4376f7f6 110 GITERR_CHECK_ALLOC(remote->name);
617bfdf4
CMN
111 }
112
baaa8a44 113 if (fetch != NULL) {
eb0bd77a 114 if (git_refspec__parse(&remote->fetch, fetch, true) < 0)
baaa8a44
CMN
115 goto on_error;
116 }
117
c648d4a8
CMN
118 /* A remote without a name doesn't download tags */
119 if (!name) {
120 remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_NONE;
121 }
122
778e1c73 123 *out = remote;
44f36f6e 124 git_buf_free(&fetchbuf);
4376f7f6 125 return 0;
baaa8a44
CMN
126
127on_error:
128 git_remote_free(remote);
44f36f6e
BS
129 git_buf_free(&fetchbuf);
130 return error;
778e1c73
CMN
131}
132
592f466c
BS
133static int ensure_remote_doesnot_exist(git_repository *repo, const char *name)
134{
135 int error;
136 git_remote *remote;
137
138 error = git_remote_load(&remote, repo, name);
139
140 if (error == GIT_ENOTFOUND)
141 return 0;
142
143 if (error < 0)
144 return error;
145
146 git_remote_free(remote);
147
148 giterr_set(
149 GITERR_CONFIG,
150 "Remote '%s' already exists.", name);
151
152 return GIT_EEXISTS;
153}
154
f19304d2 155
874dcb25
BS
156int git_remote_create(git_remote **out, git_repository *repo, const char *name, const char *url)
157{
158 git_buf buf = GIT_BUF_INIT;
159 int error;
160
161 if ((error = ensure_remote_name_is_valid(name)) < 0)
162 return error;
163
f19304d2 164 if ((error = ensure_remote_doesnot_exist(repo, name)) < 0)
165 return error;
166
874dcb25
BS
167 if (git_buf_printf(&buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0)
168 return -1;
169
170 if (create_internal(out, repo, name, url, git_buf_cstr(&buf)) < 0)
171 goto on_error;
172
173 git_buf_free(&buf);
174
175 if (git_remote_save(*out) < 0)
176 goto on_error;
177
178 return 0;
179
180on_error:
181 git_buf_free(&buf);
182 git_remote_free(*out);
183 return -1;
184}
185
0642c143 186int git_remote_create_inmemory(git_remote **out, git_repository *repo, const char *fetch, const char *url)
874dcb25
BS
187{
188 int error;
189 git_remote *remote;
190
79000951 191 if ((error = create_internal(&remote, repo, NULL, url, fetch)) < 0)
874dcb25
BS
192 return error;
193
874dcb25
BS
194 *out = remote;
195 return 0;
196}
197
b914e17d
BS
198int git_remote_set_repository(git_remote *remote, git_repository *repo)
199{
200 assert(repo);
201
202 if (remote->repo) {
203 giterr_set(GITERR_INVALID, "Remotes can't change repositiories.");
204 return GIT_ERROR;
205 }
206
207 remote->repo = repo;
208 return 0;
209}
210
9462c471 211int git_remote_load(git_remote **out, git_repository *repo, const char *name)
9c82357b
CMN
212{
213 git_remote *remote;
f0f3a18a 214 git_buf buf = GIT_BUF_INIT;
9c82357b 215 const char *val;
4376f7f6 216 int error = 0;
9462c471 217 git_config *config;
9c82357b 218
9462c471
VM
219 assert(out && repo && name);
220
032ba9e4 221 if ((error = ensure_remote_name_is_valid(name)) < 0)
222 return error;
223
4376f7f6
CMN
224 if (git_repository_config__weakptr(&config, repo) < 0)
225 return -1;
4bef3565 226
9c82357b 227 remote = git__malloc(sizeof(git_remote));
4376f7f6 228 GITERR_CHECK_ALLOC(remote);
9c82357b
CMN
229
230 memset(remote, 0x0, sizeof(git_remote));
250b95b2 231 remote->check_cert = 1;
b0f6e45d 232 remote->update_fetchhead = 1;
9c82357b 233 remote->name = git__strdup(name);
4376f7f6 234 GITERR_CHECK_ALLOC(remote->name);
9c82357b 235
2fb9d6de 236 if (git_vector_init(&remote->refs, 32, NULL) < 0) {
237 error = -1;
238 goto cleanup;
239 }
d88d4311 240
2fb9d6de 241 if (git_buf_printf(&buf, "remote.%s.url", name) < 0) {
242 error = -1;
243 goto cleanup;
244 }
9c82357b 245
29e948de 246 if ((error = git_config_get_string(&val, config, git_buf_cstr(&buf))) < 0)
9c82357b 247 goto cleanup;
83885891 248
0da81d2b 249 if (strlen(val) == 0) {
c1cd036e 250 giterr_set(GITERR_INVALID, "Malformed remote '%s' - missing URL", name);
83885891
JSS
251 error = -1;
252 goto cleanup;
253 }
9c82357b 254
9462c471 255 remote->repo = repo;
9c82357b 256 remote->url = git__strdup(val);
4376f7f6 257 GITERR_CHECK_ALLOC(remote->url);
9c82357b 258
3ed4b501
SC
259 git_buf_clear(&buf);
260 if (git_buf_printf(&buf, "remote.%s.pushurl", name) < 0) {
261 error = -1;
262 goto cleanup;
263 }
264
265 error = git_config_get_string(&val, config, git_buf_cstr(&buf));
0da81d2b
CMN
266 if (error == GIT_ENOTFOUND) {
267 val = NULL;
3ed4b501 268 error = 0;
0da81d2b 269 }
3ed4b501
SC
270
271 if (error < 0) {
272 error = -1;
273 goto cleanup;
274 }
275
276 if (val) {
277 remote->pushurl = git__strdup(val);
278 GITERR_CHECK_ALLOC(remote->pushurl);
279 }
280
f0f3a18a 281 git_buf_clear(&buf);
2fb9d6de 282 if (git_buf_printf(&buf, "remote.%s.fetch", name) < 0) {
283 error = -1;
284 goto cleanup;
285 }
9c82357b 286
eb0bd77a 287 error = parse_remote_refspec(config, &remote->fetch, git_buf_cstr(&buf), true);
904b67e6 288 if (error == GIT_ENOTFOUND)
4376f7f6 289 error = 0;
9554cd51 290
4376f7f6
CMN
291 if (error < 0) {
292 error = -1;
9c82357b 293 goto cleanup;
2dc31040 294 }
9c82357b 295
f0f3a18a 296 git_buf_clear(&buf);
2fb9d6de 297 if (git_buf_printf(&buf, "remote.%s.push", name) < 0) {
298 error = -1;
299 goto cleanup;
300 }
9c82357b 301
eb0bd77a 302 error = parse_remote_refspec(config, &remote->push, git_buf_cstr(&buf), false);
904b67e6 303 if (error == GIT_ENOTFOUND)
4376f7f6 304 error = 0;
9c82357b 305
4376f7f6
CMN
306 if (error < 0) {
307 error = -1;
9c82357b 308 goto cleanup;
4376f7f6 309 }
9c82357b 310
24f2f94e
CMN
311 if (download_tags_value(remote, config) < 0)
312 goto cleanup;
313
9c82357b
CMN
314 *out = remote;
315
316cleanup:
f0f3a18a 317 git_buf_free(&buf);
9462c471 318
4376f7f6 319 if (error < 0)
9c82357b
CMN
320 git_remote_free(remote);
321
322 return error;
323}
324
4fe5520a 325static int update_config_refspec(
326 git_config *config,
327 const char *remote_name,
328 const git_refspec *refspec,
329 int git_direction)
330{
331 git_buf name = GIT_BUF_INIT, value = GIT_BUF_INIT;
332 int error = -1;
333
334 if (refspec->src == NULL || refspec->dst == NULL)
335 return 0;
336
fb39b3a5 337 if (git_buf_printf(
4fe5520a 338 &name,
339 "remote.%s.%s",
340 remote_name,
df705148 341 git_direction == GIT_DIRECTION_FETCH ? "fetch" : "push") < 0)
fb39b3a5 342 goto cleanup;
4fe5520a 343
fb39b3a5 344 if (git_refspec__serialize(&value, refspec) < 0)
4fe5520a 345 goto cleanup;
346
347 error = git_config_set_string(
348 config,
349 git_buf_cstr(&name),
350 git_buf_cstr(&value));
351
352cleanup:
353 git_buf_free(&name);
354 git_buf_free(&value);
355
356 return error;
357}
358
89e5ed98
CMN
359int git_remote_save(const git_remote *remote)
360{
218c88a9 361 int error;
89e5ed98 362 git_config *config;
218c88a9 363 const char *tagopt = NULL;
4fe5520a 364 git_buf buf = GIT_BUF_INIT;
89e5ed98 365
e497b16c 366 assert(remote);
367
c07b52df 368 if (!remote->name) {
874dcb25
BS
369 giterr_set(GITERR_INVALID, "Can't save an in-memory remote.");
370 return GIT_EINVALIDSPEC;
a71c27cc
BS
371 }
372
032ba9e4 373 if ((error = ensure_remote_name_is_valid(remote->name)) < 0)
374 return error;
89e5ed98 375
4376f7f6
CMN
376 if (git_repository_config__weakptr(&config, remote->repo) < 0)
377 return -1;
89e5ed98 378
cb020f0d 379 if (git_buf_printf(&buf, "remote.%s.url", remote->name) < 0)
4376f7f6 380 return -1;
89e5ed98 381
4376f7f6
CMN
382 if (git_config_set_string(config, git_buf_cstr(&buf), remote->url) < 0) {
383 git_buf_free(&buf);
384 return -1;
385 }
89e5ed98 386
413d5563
SC
387 git_buf_clear(&buf);
388 if (git_buf_printf(&buf, "remote.%s.pushurl", remote->name) < 0)
389 return -1;
3ed4b501 390
413d5563 391 if (remote->pushurl) {
3ed4b501
SC
392 if (git_config_set_string(config, git_buf_cstr(&buf), remote->pushurl) < 0) {
393 git_buf_free(&buf);
394 return -1;
395 }
413d5563 396 } else {
54b2a37a 397 int error = git_config_delete_entry(config, git_buf_cstr(&buf));
413d5563
SC
398 if (error == GIT_ENOTFOUND) {
399 error = 0;
c48e8700 400 giterr_clear();
413d5563
SC
401 }
402 if (error < 0) {
403 git_buf_free(&buf);
404 return -1;
405 }
3ed4b501
SC
406 }
407
4fe5520a 408 if (update_config_refspec(
409 config,
410 remote->name,
411 &remote->fetch,
df705148 412 GIT_DIRECTION_FETCH) < 0)
4376f7f6 413 goto on_error;
89e5ed98 414
4fe5520a 415 if (update_config_refspec(
416 config,
417 remote->name,
418 &remote->push,
df705148 419 GIT_DIRECTION_PUSH) < 0)
4376f7f6 420 goto on_error;
89e5ed98 421
218c88a9
CMN
422 /*
423 * What action to take depends on the old and new values. This
424 * is describes by the table below. tagopt means whether the
425 * is already a value set in the config
426 *
427 * AUTO ALL or NONE
428 * +-----------------------+
429 * tagopt | remove | set |
430 * +---------+-------------|
431 * !tagopt | nothing | set |
432 * +---------+-------------+
433 */
434
435 git_buf_clear(&buf);
436 if (git_buf_printf(&buf, "remote.%s.tagopt", remote->name) < 0)
437 goto on_error;
438
439 error = git_config_get_string(&tagopt, config, git_buf_cstr(&buf));
440 if (error < 0 && error != GIT_ENOTFOUND)
441 goto on_error;
442
443 if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) {
444 if (git_config_set_string(config, git_buf_cstr(&buf), "--tags") < 0)
445 goto on_error;
446 } else if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
447 if (git_config_set_string(config, git_buf_cstr(&buf), "--no-tags") < 0)
448 goto on_error;
449 } else if (tagopt) {
54b2a37a 450 if (git_config_delete_entry(config, git_buf_cstr(&buf)) < 0)
218c88a9
CMN
451 goto on_error;
452 }
453
89e5ed98 454 git_buf_free(&buf);
4376f7f6
CMN
455
456 return 0;
457
458on_error:
459 git_buf_free(&buf);
4376f7f6 460 return -1;
89e5ed98
CMN
461}
462
df705148 463const char *git_remote_name(const git_remote *remote)
9c82357b 464{
4bef3565 465 assert(remote);
9c82357b
CMN
466 return remote->name;
467}
468
df705148 469const char *git_remote_url(const git_remote *remote)
9c82357b 470{
4bef3565 471 assert(remote);
9c82357b
CMN
472 return remote->url;
473}
474
76501590
SC
475int git_remote_set_url(git_remote *remote, const char* url)
476{
477 assert(remote);
478 assert(url);
479
480 git__free(remote->url);
481 remote->url = git__strdup(url);
482 GITERR_CHECK_ALLOC(remote->url);
483
484 return 0;
485}
486
df705148 487const char *git_remote_pushurl(const git_remote *remote)
76501590
SC
488{
489 assert(remote);
490 return remote->pushurl;
491}
492
493int git_remote_set_pushurl(git_remote *remote, const char* url)
494{
495 assert(remote);
496
497 git__free(remote->pushurl);
498 if (url) {
499 remote->pushurl = git__strdup(url);
500 GITERR_CHECK_ALLOC(remote->pushurl);
501 } else {
502 remote->pushurl = NULL;
503 }
504 return 0;
505}
506
bcb8c007
CMN
507int git_remote_set_fetchspec(git_remote *remote, const char *spec)
508{
bcb8c007
CMN
509 git_refspec refspec;
510
511 assert(remote && spec);
512
eb0bd77a 513 if (git_refspec__parse(&refspec, spec, true) < 0)
4376f7f6 514 return -1;
bcb8c007 515
eb0bd77a 516 git_refspec__free(&remote->fetch);
874dcb25 517 memcpy(&remote->fetch, &refspec, sizeof(git_refspec));
bcb8c007 518
4376f7f6 519 return 0;
bcb8c007
CMN
520}
521
df705148 522const git_refspec *git_remote_fetchspec(const git_remote *remote)
9c82357b 523{
4bef3565 524 assert(remote);
9c82357b
CMN
525 return &remote->fetch;
526}
527
bcb8c007
CMN
528int git_remote_set_pushspec(git_remote *remote, const char *spec)
529{
bcb8c007
CMN
530 git_refspec refspec;
531
532 assert(remote && spec);
533
eb0bd77a 534 if (git_refspec__parse(&refspec, spec, false) < 0)
4376f7f6 535 return -1;
bcb8c007 536
eb0bd77a 537 git_refspec__free(&remote->push);
bcb8c007
CMN
538 remote->push.src = refspec.src;
539 remote->push.dst = refspec.dst;
540
4376f7f6 541 return 0;
bcb8c007
CMN
542}
543
df705148 544const git_refspec *git_remote_pushspec(const git_remote *remote)
9c82357b 545{
4bef3565 546 assert(remote);
9c82357b
CMN
547 return &remote->push;
548}
549
eff5b499
SC
550const char* git_remote__urlfordirection(git_remote *remote, int direction)
551{
552 assert(remote);
553
df705148 554 if (direction == GIT_DIRECTION_FETCH) {
eff5b499
SC
555 return remote->url;
556 }
557
df705148 558 if (direction == GIT_DIRECTION_PUSH) {
eff5b499
SC
559 return remote->pushurl ? remote->pushurl : remote->url;
560 }
561
562 return NULL;
563}
564
df705148 565int git_remote_connect(git_remote *remote, git_direction direction)
9ba49bb5 566{
9ba49bb5 567 git_transport *t;
c0c39025 568 const char *url;
41fb1ca0 569 int flags = GIT_TRANSPORTFLAGS_NONE;
9ba49bb5 570
4bef3565
VM
571 assert(remote);
572
41fb1ca0
PK
573 t = remote->transport;
574
c0c39025 575 url = git_remote__urlfordirection(remote, direction);
eff5b499
SC
576 if (url == NULL )
577 return -1;
578
41fb1ca0
PK
579 /* A transport could have been supplied in advance with
580 * git_remote_set_transport */
613d5eb9 581 if (!t && git_transport_new(&t, remote, url) < 0)
4376f7f6 582 return -1;
9ba49bb5 583
41fb1ca0 584 if (t->set_callbacks &&
df705148 585 t->set_callbacks(t, remote->callbacks.progress, NULL, remote->callbacks.payload) < 0)
41fb1ca0 586 goto on_error;
613d5eb9 587
41fb1ca0
PK
588 if (!remote->check_cert)
589 flags |= GIT_TRANSPORTFLAGS_NO_CHECK_CERT;
e03e71da 590
59bccf33 591 if (t->connect(t, url, remote->cred_acquire_cb, remote->cred_acquire_payload, direction, flags) < 0)
4376f7f6 592 goto on_error;
9ba49bb5
CMN
593
594 remote->transport = t;
595
4376f7f6 596 return 0;
9ba49bb5 597
4376f7f6
CMN
598on_error:
599 t->free(t);
613d5eb9
PK
600
601 if (t == remote->transport)
602 remote->transport = NULL;
603
4376f7f6 604 return -1;
9ba49bb5
CMN
605}
606
d88d4311 607int git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void *payload)
9ba49bb5 608{
d88d4311
VM
609 assert(remote);
610
613d5eb9 611 if (!git_remote_connected(remote)) {
4376f7f6
CMN
612 giterr_set(GITERR_NET, "The remote is not connected");
613 return -1;
614 }
d88d4311 615
41fb1ca0 616 return remote->transport->ls(remote->transport, list_cb, payload);
9ba49bb5
CMN
617}
618
613d5eb9
PK
619int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_url)
620{
621 git_config *cfg;
622 const char *val;
623
624 assert(remote);
625
a71c27cc 626 if (!proxy_url || !remote->repo)
613d5eb9
PK
627 return -1;
628
629 *proxy_url = NULL;
630
631 if (git_repository_config__weakptr(&cfg, remote->repo) < 0)
632 return -1;
633
634 /* Go through the possible sources for proxy configuration, from most specific
635 * to least specific. */
636
637 /* remote.<name>.proxy config setting */
638 if (remote->name && 0 != *(remote->name)) {
639 git_buf buf = GIT_BUF_INIT;
640
641 if (git_buf_printf(&buf, "remote.%s.proxy", remote->name) < 0)
642 return -1;
643
644 if (!git_config_get_string(&val, cfg, git_buf_cstr(&buf)) &&
645 val && ('\0' != *val)) {
646 git_buf_free(&buf);
647
648 *proxy_url = git__strdup(val);
649 GITERR_CHECK_ALLOC(*proxy_url);
650 return 0;
651 }
652
653 git_buf_free(&buf);
654 }
655
656 /* http.proxy config setting */
657 if (!git_config_get_string(&val, cfg, "http.proxy") &&
658 val && ('\0' != *val)) {
659 *proxy_url = git__strdup(val);
660 GITERR_CHECK_ALLOC(*proxy_url);
661 return 0;
662 }
663
664 /* HTTP_PROXY / HTTPS_PROXY environment variables */
665 val = use_ssl ? getenv("HTTPS_PROXY") : getenv("HTTP_PROXY");
666
667 if (val && ('\0' != *val)) {
668 *proxy_url = git__strdup(val);
669 GITERR_CHECK_ALLOC(*proxy_url);
670 return 0;
671 }
672
673 return 0;
674}
675
216863c4
BS
676int git_remote_download(
677 git_remote *remote,
7d222e13 678 git_transfer_progress_callback progress_cb,
216863c4 679 void *progress_payload)
48a65a07 680{
95057b85
CMN
681 int error;
682
1e3b8ed5 683 assert(remote);
4bef3565 684
95057b85 685 if ((error = git_fetch_negotiate(remote)) < 0)
4376f7f6 686 return error;
95057b85 687
1e3b8ed5 688 return git_fetch_download_pack(remote, progress_cb, progress_payload);
48a65a07
CMN
689}
690
41fb1ca0
PK
691static int update_tips_callback(git_remote_head *head, void *payload)
692{
693 git_vector *refs = (git_vector *)payload;
694 git_vector_insert(refs, head);
695
7d4b65f6 696 return 0;
41fb1ca0
PK
697}
698
b0f6e45d
ET
699static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *update_heads, const char *fetchspec_src)
700{
701 unsigned int i;
702 git_remote_head *remote_ref;
703
704 assert(update_heads && fetchspec_src);
705
706 *out = NULL;
7d4b65f6 707
708 git_vector_foreach(update_heads, i, remote_ref) {
709 if (strcmp(remote_ref->name, fetchspec_src) == 0) {
710 *out = remote_ref;
711 break;
b0f6e45d
ET
712 }
713 }
714
715 return 0;
716}
717
718static int remote_head_for_ref(git_remote_head **out, git_remote *remote, git_vector *update_heads, git_reference *ref)
719{
720 git_reference *resolved_ref = NULL;
721 git_reference *tracking_ref = NULL;
722 git_buf remote_name = GIT_BUF_INIT;
723 int error = 0;
724
725 assert(out && remote && ref);
726
727 *out = NULL;
728
729 if ((error = git_reference_resolve(&resolved_ref, ref)) < 0 ||
730 (!git_reference_is_branch(resolved_ref)) ||
731 (error = git_branch_tracking(&tracking_ref, resolved_ref)) < 0 ||
732 (error = git_refspec_transform_l(&remote_name, &remote->fetch, git_reference_name(tracking_ref))) < 0) {
733 /* Not an error if HEAD is orphaned or no tracking branch */
734 if (error == GIT_ENOTFOUND)
735 error = 0;
736
737 goto cleanup;
738 }
739
740 error = remote_head_for_fetchspec_src(out, update_heads, git_buf_cstr(&remote_name));
741
742cleanup:
743 git_reference_free(tracking_ref);
744 git_reference_free(resolved_ref);
745 git_buf_free(&remote_name);
746 return error;
747}
748
749static int git_remote_write_fetchhead(git_remote *remote, git_vector *update_heads)
750{
751 struct git_refspec *spec;
752 git_reference *head_ref = NULL;
753 git_fetchhead_ref *fetchhead_ref;
754 git_remote_head *remote_ref, *merge_remote_ref;
755 git_vector fetchhead_refs;
756 bool include_all_fetchheads;
757 unsigned int i = 0;
758 int error = 0;
759
760 assert(remote);
761
762 spec = &remote->fetch;
763
764 if (git_vector_init(&fetchhead_refs, update_heads->length, git_fetchhead_ref_cmp) < 0)
765 return -1;
766
767 /* Iff refspec is * (but not subdir slash star), include tags */
768 include_all_fetchheads = (strcmp(GIT_REFS_HEADS_DIR "*", git_refspec_src(spec)) == 0);
769
770 /* Determine what to merge: if refspec was a wildcard, just use HEAD */
771 if (git_refspec_is_wildcard(spec)) {
772 if ((error = git_reference_lookup(&head_ref, remote->repo, GIT_HEAD_FILE)) < 0 ||
773 (error = remote_head_for_ref(&merge_remote_ref, remote, update_heads, head_ref)) < 0)
774 goto cleanup;
775 } else {
776 /* If we're fetching a single refspec, that's the only thing that should be in FETCH_HEAD. */
777 if ((error = remote_head_for_fetchspec_src(&merge_remote_ref, update_heads, git_refspec_src(spec))) < 0)
778 goto cleanup;
779 }
780
781 /* Create the FETCH_HEAD file */
7d4b65f6 782 git_vector_foreach(update_heads, i, remote_ref) {
b0f6e45d
ET
783 int merge_this_fetchhead = (merge_remote_ref == remote_ref);
784
785 if (!include_all_fetchheads &&
786 !git_refspec_src_matches(spec, remote_ref->name) &&
787 !merge_this_fetchhead)
788 continue;
789
790 if (git_fetchhead_ref_create(&fetchhead_ref,
791 &remote_ref->oid,
792 merge_this_fetchhead,
793 remote_ref->name,
794 git_remote_url(remote)) < 0)
795 goto cleanup;
796
797 if (git_vector_insert(&fetchhead_refs, fetchhead_ref) < 0)
798 goto cleanup;
799 }
800
801 git_fetchhead_write(remote->repo, &fetchhead_refs);
802
803cleanup:
804 for (i = 0; i < fetchhead_refs.length; ++i)
805 git_fetchhead_ref_free(fetchhead_refs.contents[i]);
806
807 git_vector_free(&fetchhead_refs);
808 git_reference_free(head_ref);
809
810 return error;
811}
812
b3aaa7a7 813int git_remote_update_tips(git_remote *remote)
441f57c2 814{
a37ddf7e 815 int error = 0, autotag;
517bda19 816 unsigned int i = 0;
97769280 817 git_buf refname = GIT_BUF_INIT;
f184836b 818 git_oid old;
a37ddf7e 819 git_odb *odb;
441f57c2
CMN
820 git_remote_head *head;
821 git_reference *ref;
3f035860 822 struct git_refspec *spec;
a37ddf7e 823 git_refspec tagspec;
b0f6e45d 824 git_vector refs, update_heads;
441f57c2 825
4bef3565
VM
826 assert(remote);
827
3f035860 828 spec = &remote->fetch;
41fb1ca0 829
acd17006 830 if (git_repository_odb__weakptr(&odb, remote->repo) < 0)
a37ddf7e
CMN
831 return -1;
832
3230a44f 833 if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
a37ddf7e
CMN
834 return -1;
835
41fb1ca0 836 /* Make a copy of the transport's refs */
b0f6e45d 837 if (git_vector_init(&refs, 16, NULL) < 0 ||
7d4b65f6 838 git_vector_init(&update_heads, 16, NULL) < 0)
41fb1ca0 839 return -1;
585a2eb7 840
613d5eb9 841 if (git_remote_ls(remote, update_tips_callback, &refs) < 0)
41fb1ca0
PK
842 goto on_error;
843
844 /* Let's go find HEAD, if it exists. Check only the first ref in the vector. */
845 if (refs.length > 0) {
846 head = (git_remote_head *)refs.contents[0];
847
848 if (!strcmp(head->name, GIT_HEAD_FILE)) {
2508cc66 849 if (git_reference_create(&ref, remote->repo, GIT_FETCH_HEAD_FILE, &head->oid, 1) < 0)
41fb1ca0
PK
850 goto on_error;
851
852 i = 1;
853 git_reference_free(ref);
854 }
517bda19
CMN
855 }
856
41fb1ca0
PK
857 for (; i < refs.length; ++i) {
858 head = (git_remote_head *)refs.contents[i];
9063be1f 859 autotag = 0;
517bda19 860
a37ddf7e
CMN
861 /* Ignore malformed ref names (which also saves us from tag^{} */
862 if (!git_reference_is_valid_name(head->name))
863 continue;
864
865 if (git_refspec_src_matches(spec, head->name)) {
866 if (git_refspec_transform_r(&refname, spec, head->name) < 0)
867 goto on_error;
868 } else if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
3230a44f
CMN
869
870 if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_ALL)
871 autotag = 1;
a37ddf7e
CMN
872
873 if (!git_refspec_src_matches(&tagspec, head->name))
874 continue;
875
876 git_buf_clear(&refname);
877 if (git_buf_puts(&refname, head->name) < 0)
878 goto on_error;
879 } else {
880 continue;
881 }
882
883 if (autotag && !git_odb_exists(odb, &head->oid))
884 continue;
f184836b 885
b0f6e45d
ET
886 if (git_vector_insert(&update_heads, head) < 0)
887 goto on_error;
888
2508cc66 889 error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
904b67e6 890 if (error < 0 && error != GIT_ENOTFOUND)
f184836b
CMN
891 goto on_error;
892
904b67e6 893 if (error == GIT_ENOTFOUND)
f184836b
CMN
894 memset(&old, 0, GIT_OID_RAWSZ);
895
896 if (!git_oid_cmp(&old, &head->oid))
897 continue;
441f57c2 898
a37ddf7e 899 /* In autotag mode, don't overwrite any locally-existing tags */
2508cc66 900 error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag);
a37ddf7e 901 if (error < 0 && error != GIT_EEXISTS)
944d250f 902 goto on_error;
39157563
CMN
903
904 git_reference_free(ref);
f184836b 905
b3aaa7a7 906 if (remote->callbacks.update_tips != NULL) {
df705148 907 if (remote->callbacks.update_tips(refname.ptr, &old, &head->oid, remote->callbacks.payload) < 0)
f184836b
CMN
908 goto on_error;
909 }
441f57c2
CMN
910 }
911
b0f6e45d
ET
912 if (git_remote_update_fetchhead(remote) &&
913 (error = git_remote_write_fetchhead(remote, &update_heads)) < 0)
914 goto on_error;
915
41fb1ca0 916 git_vector_free(&refs);
b0f6e45d 917 git_vector_free(&update_heads);
a37ddf7e 918 git_refspec__free(&tagspec);
97769280 919 git_buf_free(&refname);
f184836b
CMN
920 return 0;
921
922on_error:
41fb1ca0 923 git_vector_free(&refs);
b0f6e45d 924 git_vector_free(&update_heads);
a37ddf7e 925 git_refspec__free(&tagspec);
f184836b
CMN
926 git_buf_free(&refname);
927 return -1;
97769280 928
441f57c2
CMN
929}
930
6ac3b707
CMN
931int git_remote_connected(git_remote *remote)
932{
4bef3565 933 assert(remote);
41fb1ca0
PK
934
935 if (!remote->transport || !remote->transport->is_connected)
936 return 0;
937
938 /* Ask the transport if it's connected. */
613d5eb9 939 return remote->transport->is_connected(remote->transport);
6ac3b707
CMN
940}
941
f0d2ddbb
CMN
942void git_remote_stop(git_remote *remote)
943{
613d5eb9
PK
944 assert(remote);
945
946 if (remote->transport && remote->transport->cancel)
41fb1ca0 947 remote->transport->cancel(remote->transport);
f0d2ddbb
CMN
948}
949
4cf01e9a
CMN
950void git_remote_disconnect(git_remote *remote)
951{
4bef3565
VM
952 assert(remote);
953
41fb1ca0
PK
954 if (git_remote_connected(remote))
955 remote->transport->close(remote->transport);
4cf01e9a
CMN
956}
957
9c82357b
CMN
958void git_remote_free(git_remote *remote)
959{
2aae2188
CMN
960 if (remote == NULL)
961 return;
962
42ea35c0
MS
963 if (remote->transport != NULL) {
964 git_remote_disconnect(remote);
965
966 remote->transport->free(remote->transport);
967 remote->transport = NULL;
968 }
969
970 git_vector_free(&remote->refs);
971
3665ba8e
CMN
972 git_refspec__free(&remote->fetch);
973 git_refspec__free(&remote->push);
3286c408 974 git__free(remote->url);
3ed4b501 975 git__free(remote->pushurl);
3286c408 976 git__free(remote->name);
3286c408 977 git__free(remote);
9c82357b 978}
8171998f
CMN
979
980struct cb_data {
981 git_vector *list;
982 regex_t *preg;
983};
984
a1abe66a 985static int remote_list_cb(const git_config_entry *entry, void *data_)
8171998f
CMN
986{
987 struct cb_data *data = (struct cb_data *)data_;
988 size_t nmatch = 2;
989 regmatch_t pmatch[2];
a1abe66a 990 const char *name = entry->name;
8171998f
CMN
991
992 if (!regexec(data->preg, name, nmatch, pmatch, 0)) {
993 char *remote_name = git__strndup(&name[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so);
4376f7f6 994 GITERR_CHECK_ALLOC(remote_name);
8171998f 995
4376f7f6
CMN
996 if (git_vector_insert(data->list, remote_name) < 0)
997 return -1;
8171998f
CMN
998 }
999
4376f7f6 1000 return 0;
8171998f
CMN
1001}
1002
1003int git_remote_list(git_strarray *remotes_list, git_repository *repo)
1004{
1005 git_config *cfg;
1006 git_vector list;
1007 regex_t preg;
1008 struct cb_data data;
1009 int error;
1010
4376f7f6
CMN
1011 if (git_repository_config__weakptr(&cfg, repo) < 0)
1012 return -1;
8171998f 1013
4376f7f6
CMN
1014 if (git_vector_init(&list, 4, NULL) < 0)
1015 return -1;
8171998f 1016
4376f7f6
CMN
1017 if (regcomp(&preg, "^remote\\.(.*)\\.url$", REG_EXTENDED) < 0) {
1018 giterr_set(GITERR_OS, "Remote catch regex failed to compile");
1019 return -1;
1020 }
8171998f
CMN
1021
1022 data.list = &list;
1023 data.preg = &preg;
1024 error = git_config_foreach(cfg, remote_list_cb, &data);
1025 regfree(&preg);
4376f7f6 1026 if (error < 0) {
8171998f
CMN
1027 size_t i;
1028 char *elem;
1029 git_vector_foreach(&list, i, elem) {
2bc8fa02 1030 git__free(elem);
8171998f
CMN
1031 }
1032
1033 git_vector_free(&list);
e4607392
RB
1034
1035 /* cb error is converted to GIT_EUSER by git_config_foreach */
1036 if (error == GIT_EUSER)
1037 error = -1;
1038
8171998f
CMN
1039 return error;
1040 }
1041
1042 remotes_list->strings = (char **)list.contents;
1043 remotes_list->count = list.length;
1044
4376f7f6 1045 return 0;
8171998f 1046}
a209a025 1047
250b95b2
CMN
1048void git_remote_check_cert(git_remote *remote, int check)
1049{
1050 assert(remote);
1051
1052 remote->check_cert = check;
1053}
b3aaa7a7 1054
9267ff58 1055int git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks)
b3aaa7a7
CMN
1056{
1057 assert(remote && callbacks);
1058
c7231c45 1059 GITERR_CHECK_VERSION(callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
9267ff58 1060
b3aaa7a7 1061 memcpy(&remote->callbacks, callbacks, sizeof(git_remote_callbacks));
e03e71da 1062
41fb1ca0
PK
1063 if (remote->transport && remote->transport->set_callbacks)
1064 remote->transport->set_callbacks(remote->transport,
1065 remote->callbacks.progress,
1066 NULL,
df705148 1067 remote->callbacks.payload);
9267ff58
BS
1068
1069 return 0;
41fb1ca0
PK
1070}
1071
091361f5
PK
1072void git_remote_set_cred_acquire_cb(
1073 git_remote *remote,
59bccf33
BS
1074 git_cred_acquire_cb cred_acquire_cb,
1075 void *payload)
091361f5
PK
1076{
1077 assert(remote);
1078
1079 remote->cred_acquire_cb = cred_acquire_cb;
59bccf33 1080 remote->cred_acquire_payload = payload;
091361f5
PK
1081}
1082
41fb1ca0
PK
1083int git_remote_set_transport(git_remote *remote, git_transport *transport)
1084{
1085 assert(remote && transport);
1086
c7231c45 1087 GITERR_CHECK_VERSION(transport, GIT_TRANSPORT_VERSION, "git_transport");
10711769 1088
e03e71da 1089 if (remote->transport) {
41fb1ca0
PK
1090 giterr_set(GITERR_NET, "A transport is already bound to this remote");
1091 return -1;
e03e71da 1092 }
41fb1ca0
PK
1093
1094 remote->transport = transport;
1095 return 0;
b3aaa7a7 1096}
f70e466f 1097
67dad09b 1098const git_transfer_progress* git_remote_stats(git_remote *remote)
d57c47dc
BS
1099{
1100 assert(remote);
1101 return &remote->stats;
1102}
1103
f4a62c30 1104git_remote_autotag_option_t git_remote_autotag(git_remote *remote)
f70e466f
CMN
1105{
1106 return remote->download_tags;
1107}
1108
f4a62c30 1109void git_remote_set_autotag(git_remote *remote, git_remote_autotag_option_t value)
f70e466f
CMN
1110{
1111 remote->download_tags = value;
1112}
fcccf304 1113
fcccf304 1114static int rename_remote_config_section(
1115 git_repository *repo,
1116 const char *old_name,
1117 const char *new_name)
1118{
1119 git_buf old_section_name = GIT_BUF_INIT,
1120 new_section_name = GIT_BUF_INIT;
1121 int error = -1;
1122
1123 if (git_buf_printf(&old_section_name, "remote.%s", old_name) < 0)
1124 goto cleanup;
1125
1126 if (git_buf_printf(&new_section_name, "remote.%s", new_name) < 0)
1127 goto cleanup;
1128
1129 error = git_config_rename_section(
1130 repo,
1131 git_buf_cstr(&old_section_name),
1132 git_buf_cstr(&new_section_name));
1133
1134cleanup:
1135 git_buf_free(&old_section_name);
1136 git_buf_free(&new_section_name);
1137
1138 return error;
1139}
1140
1141struct update_data
1142{
1143 git_config *config;
1144 const char *old_remote_name;
1145 const char *new_remote_name;
1146};
1147
1148static int update_config_entries_cb(
1149 const git_config_entry *entry,
1150 void *payload)
1151{
1152 struct update_data *data = (struct update_data *)payload;
1153
1154 if (strcmp(entry->value, data->old_remote_name))
1155 return 0;
1156
1157 return git_config_set_string(
1158 data->config,
1159 entry->name,
1160 data->new_remote_name);
1161}
1162
1163static int update_branch_remote_config_entry(
1164 git_repository *repo,
1165 const char *old_name,
1166 const char *new_name)
1167{
1168 git_config *config;
1169 struct update_data data;
1170
1171 if (git_repository_config__weakptr(&config, repo) < 0)
1172 return -1;
1173
1174 data.config = config;
1175 data.old_remote_name = old_name;
1176 data.new_remote_name = new_name;
1177
1178 return git_config_foreach_match(
1179 config,
1180 "branch\\..+\\.remote",
1181 update_config_entries_cb, &data);
1182}
1183
1184static int rename_cb(const char *ref, void *data)
1185{
1186 if (git__prefixcmp(ref, GIT_REFS_REMOTES_DIR))
1187 return 0;
1188
1189 return git_vector_insert((git_vector *)data, git__strdup(ref));
1190}
1191
1192static int rename_one_remote_reference(
1193 git_repository *repo,
1194 const char *reference_name,
1195 const char *old_remote_name,
1196 const char *new_remote_name)
1197{
6cfbbf7e 1198 int error = -1;
fcccf304 1199 git_buf new_name = GIT_BUF_INIT;
1200 git_reference *reference = NULL;
1201
1202 if (git_buf_printf(
1203 &new_name,
1204 GIT_REFS_REMOTES_DIR "%s%s",
1205 new_remote_name,
1206 reference_name + strlen(GIT_REFS_REMOTES_DIR) + strlen(old_remote_name)) < 0)
1207 return -1;
1208
1209 if (git_reference_lookup(&reference, repo, reference_name) < 0)
1210 goto cleanup;
1211
1212 error = git_reference_rename(reference, git_buf_cstr(&new_name), 0);
1213
1214cleanup:
1215 git_reference_free(reference);
1216 git_buf_free(&new_name);
1217 return error;
1218}
1219
1220static int rename_remote_references(
1221 git_repository *repo,
1222 const char *old_name,
1223 const char *new_name)
1224{
1225 git_vector refnames;
1226 int error = -1;
1227 unsigned int i;
1228 char *name;
1229
1230 if (git_vector_init(&refnames, 8, NULL) < 0)
1231 goto cleanup;
1232
1233 if (git_reference_foreach(
1234 repo,
1235 GIT_REF_LISTALL,
1236 rename_cb,
1237 &refnames) < 0)
1238 goto cleanup;
1239
1240 git_vector_foreach(&refnames, i, name) {
1241 if ((error = rename_one_remote_reference(repo, name, old_name, new_name)) < 0)
1242 goto cleanup;
1243 }
1244
1245 error = 0;
1246cleanup:
1247 git_vector_foreach(&refnames, i, name) {
1248 git__free(name);
1249 }
1250
1251 git_vector_free(&refnames);
1252 return error;
1253}
1254
1255static int rename_fetch_refspecs(
1256 git_remote *remote,
1257 const char *new_name,
1258 int (*callback)(const char *problematic_refspec, void *payload),
1259 void *payload)
1260{
1261 git_config *config;
1262 const git_refspec *fetch_refspec;
1263 git_buf dst_prefix = GIT_BUF_INIT, serialized = GIT_BUF_INIT;
1264 const char* pos;
1265 int error = -1;
1266
1267 fetch_refspec = git_remote_fetchspec(remote);
1268
1269 /* Is there a refspec to deal with? */
1270 if (fetch_refspec->src == NULL &&
1271 fetch_refspec->dst == NULL)
1272 return 0;
1273
1274 if (git_refspec__serialize(&serialized, fetch_refspec) < 0)
1275 goto cleanup;
1276
1277 /* Is it an in-memory remote? */
1278 if (remote->name == '\0') {
1279 error = (callback(git_buf_cstr(&serialized), payload) < 0) ? GIT_EUSER : 0;
1280 goto cleanup;
1281 }
1282
1283 if (git_buf_printf(&dst_prefix, ":refs/remotes/%s/", remote->name) < 0)
1284 goto cleanup;
1285
1286 pos = strstr(git_buf_cstr(&serialized), git_buf_cstr(&dst_prefix));
1287
1288 /* Does the dst part of the refspec follow the extected standard format? */
1289 if (!pos) {
1290 error = (callback(git_buf_cstr(&serialized), payload) < 0) ? GIT_EUSER : 0;
1291 goto cleanup;
1292 }
1293
1294 if (git_buf_splice(
1295 &serialized,
1296 pos - git_buf_cstr(&serialized) + strlen(":refs/remotes/"),
1297 strlen(remote->name), new_name,
1298 strlen(new_name)) < 0)
1299 goto cleanup;
1300
1301 git_refspec__free(&remote->fetch);
1302
1303 if (git_refspec__parse(&remote->fetch, git_buf_cstr(&serialized), true) < 0)
1304 goto cleanup;
1305
1306 if (git_repository_config__weakptr(&config, remote->repo) < 0)
1307 goto cleanup;
1308
df705148 1309 error = update_config_refspec(config, new_name, &remote->fetch, GIT_DIRECTION_FETCH);
fcccf304 1310
1311cleanup:
1312 git_buf_free(&serialized);
1313 git_buf_free(&dst_prefix);
1314 return error;
1315}
1316
1317int git_remote_rename(
1318 git_remote *remote,
1319 const char *new_name,
df705148 1320 git_remote_rename_problem_cb callback,
fcccf304 1321 void *payload)
1322{
1323 int error;
1324
1325 assert(remote && new_name);
1326
c07b52df 1327 if (!remote->name) {
79000951
BS
1328 giterr_set(GITERR_INVALID, "Can't rename an in-memory remote.");
1329 return GIT_EINVALIDSPEC;
1330 }
1331
fcccf304 1332 if ((error = ensure_remote_name_is_valid(new_name)) < 0)
1333 return error;
1334
a71c27cc
BS
1335 if (remote->repo) {
1336 if ((error = ensure_remote_doesnot_exist(remote->repo, new_name)) < 0)
fcccf304 1337 return error;
1338
a71c27cc
BS
1339 if (!remote->name) {
1340 if ((error = rename_fetch_refspecs(
1341 remote,
1342 new_name,
1343 callback,
1344 payload)) < 0)
1345 return error;
fcccf304 1346
a71c27cc 1347 remote->name = git__strdup(new_name);
fcccf304 1348
c07b52df 1349 if (!remote->name) return 0;
a71c27cc
BS
1350 return git_remote_save(remote);
1351 }
fcccf304 1352
a71c27cc
BS
1353 if ((error = rename_remote_config_section(
1354 remote->repo,
1355 remote->name,
1356 new_name)) < 0)
1357 return error;
fcccf304 1358
a71c27cc
BS
1359 if ((error = update_branch_remote_config_entry(
1360 remote->repo,
1361 remote->name,
1362 new_name)) < 0)
1363 return error;
fcccf304 1364
a71c27cc
BS
1365 if ((error = rename_remote_references(
1366 remote->repo,
1367 remote->name,
1368 new_name)) < 0)
1369 return error;
1370
1371 if ((error = rename_fetch_refspecs(
1372 remote,
1373 new_name,
1374 callback,
1375 payload)) < 0)
1376 return error;
1377 }
fcccf304 1378
1379 git__free(remote->name);
1380 remote->name = git__strdup(new_name);
1381
1382 return 0;
1383}
b0f6e45d
ET
1384
1385int git_remote_update_fetchhead(git_remote *remote)
1386{
1387 return remote->update_fetchhead;
1388}
1389
1390void git_remote_set_update_fetchhead(git_remote *remote, int value)
1391{
1392 remote->update_fetchhead = value;
1393}