]> git.proxmox.com Git - libgit2.git/blame - src/remote.c
remote: failing test for rename
[libgit2.git] / src / remote.c
CommitLineData
9c82357b 1/*
359fc2d2 2 * Copyright (C) the libgit2 contributors. All rights reserved.
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"
1ffd0806 11#include "git2/net.h"
9c82357b 12
157cef10 13#include "common.h"
9c82357b
CMN
14#include "config.h"
15#include "repository.h"
16#include "remote.h"
e1d88030 17#include "fetch.h"
441f57c2 18#include "refs.h"
b0f6e45d
ET
19#include "refspec.h"
20#include "fetchhead.h"
9c82357b 21
af613ecd
CMN
22static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs);
23
4330ab26 24static int add_refspec(git_remote *remote, const char *string, bool is_fetch)
9c82357b 25{
4330ab26 26 git_refspec *spec;
9c82357b 27
4330ab26
CMN
28 spec = git__calloc(1, sizeof(git_refspec));
29 GITERR_CHECK_ALLOC(spec);
30
1be680c4
CMN
31 if (git_refspec__parse(spec, string, is_fetch) < 0) {
32 git__free(spec);
33 return -1;
34 }
4330ab26
CMN
35
36 spec->push = !is_fetch;
1be680c4
CMN
37 if (git_vector_insert(&remote->refspecs, spec) < 0) {
38 git_refspec__free(spec);
39 git__free(spec);
40 return -1;
41 }
9c82357b 42
4330ab26 43 return 0;
9c82357b
CMN
44}
45
24f2f94e
CMN
46static int download_tags_value(git_remote *remote, git_config *cfg)
47{
9f77b3f6 48 const git_config_entry *ce;
24f2f94e
CMN
49 git_buf buf = GIT_BUF_INIT;
50 int error;
51
df50512a 52 /* The 0 value is the default (auto), let's see if we need to change it */
24f2f94e
CMN
53 if (git_buf_printf(&buf, "remote.%s.tagopt", remote->name) < 0)
54 return -1;
55
9f77b3f6 56 error = git_config__lookup_entry(&ce, cfg, git_buf_cstr(&buf), false);
24f2f94e 57 git_buf_free(&buf);
24f2f94e 58
9f77b3f6
RB
59 if (!error && ce && ce->value) {
60 if (!strcmp(ce->value, "--no-tags"))
61 remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_NONE;
62 else if (!strcmp(ce->value, "--tags"))
63 remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL;
bf6bebe2 64 }
24f2f94e
CMN
65
66 return error;
67}
68
032ba9e4 69static int ensure_remote_name_is_valid(const char *name)
70{
2bca5b67 71 int error = 0;
032ba9e4 72
2bca5b67 73 if (!git_remote_is_valid_name(name)) {
032ba9e4 74 giterr_set(
75 GITERR_CONFIG,
183aa4f8 76 "'%s' is not a valid remote name.", name ? name : "(null)");
032ba9e4 77 error = GIT_EINVALIDSPEC;
78 }
79
80 return error;
81}
82
80fc7d6b 83static int get_check_cert(int *out, git_repository *repo)
af6dab7e
PK
84{
85 git_config *cfg;
86 const char *val;
80fc7d6b
ET
87 int error = 0;
88
89 assert(out && repo);
af6dab7e 90
80fc7d6b
ET
91 /* By default, we *DO* want to verify the certificate. */
92 *out = 1;
af6dab7e
PK
93
94 /* Go through the possible sources for SSL verification settings, from
95 * most specific to least specific. */
96
97 /* GIT_SSL_NO_VERIFY environment variable */
8f2a3d62 98 if ((val = getenv("GIT_SSL_NO_VERIFY")) != NULL)
80fc7d6b 99 return git_config_parse_bool(out, val);
af6dab7e
PK
100
101 /* http.sslVerify config setting */
80fc7d6b
ET
102 if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
103 return error;
af6dab7e 104
9f77b3f6 105 *out = git_config__get_bool_force(cfg, "http.sslverify", 1);
80fc7d6b 106 return 0;
af6dab7e
PK
107}
108
874dcb25 109static int create_internal(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch)
778e1c73
CMN
110{
111 git_remote *remote;
44f36f6e
BS
112 git_buf fetchbuf = GIT_BUF_INIT;
113 int error = -1;
778e1c73 114
4bef3565 115 /* name is optional */
874dcb25 116 assert(out && repo && url);
617bfdf4 117
59bccf33 118 remote = git__calloc(1, sizeof(git_remote));
4376f7f6 119 GITERR_CHECK_ALLOC(remote);
778e1c73 120
778e1c73 121 remote->repo = repo;
b0f6e45d 122 remote->update_fetchhead = 1;
617bfdf4 123
80fc7d6b
ET
124 if (get_check_cert(&remote->check_cert, repo) < 0)
125 goto on_error;
126
4376f7f6 127 if (git_vector_init(&remote->refs, 32, NULL) < 0)
44f36f6e 128 goto on_error;
d88d4311 129
778e1c73 130 remote->url = git__strdup(url);
4376f7f6 131 GITERR_CHECK_ALLOC(remote->url);
778e1c73 132
617bfdf4
CMN
133 if (name != NULL) {
134 remote->name = git__strdup(name);
4376f7f6 135 GITERR_CHECK_ALLOC(remote->name);
617bfdf4
CMN
136 }
137
baaa8a44 138 if (fetch != NULL) {
4330ab26 139 if (add_refspec(remote, fetch, true) < 0)
baaa8a44
CMN
140 goto on_error;
141 }
142
215af2cc 143 if (!name)
144 /* A remote without a name doesn't download tags */
c648d4a8 145 remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_NONE;
c648d4a8 146
778e1c73 147 *out = remote;
44f36f6e 148 git_buf_free(&fetchbuf);
4376f7f6 149 return 0;
baaa8a44
CMN
150
151on_error:
152 git_remote_free(remote);
44f36f6e
BS
153 git_buf_free(&fetchbuf);
154 return error;
778e1c73
CMN
155}
156
592f466c
BS
157static int ensure_remote_doesnot_exist(git_repository *repo, const char *name)
158{
159 int error;
160 git_remote *remote;
161
162 error = git_remote_load(&remote, repo, name);
163
164 if (error == GIT_ENOTFOUND)
165 return 0;
166
167 if (error < 0)
168 return error;
169
170 git_remote_free(remote);
171
172 giterr_set(
173 GITERR_CONFIG,
174 "Remote '%s' already exists.", name);
175
176 return GIT_EEXISTS;
177}
178
f19304d2 179
874dcb25
BS
180int git_remote_create(git_remote **out, git_repository *repo, const char *name, const char *url)
181{
182 git_buf buf = GIT_BUF_INIT;
c5193e3c 183 git_remote *remote = NULL;
874dcb25
BS
184 int error;
185
186 if ((error = ensure_remote_name_is_valid(name)) < 0)
187 return error;
188
f19304d2 189 if ((error = ensure_remote_doesnot_exist(repo, name)) < 0)
190 return error;
191
874dcb25
BS
192 if (git_buf_printf(&buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0)
193 return -1;
194
c5193e3c 195 if (create_internal(&remote, repo, name, url, git_buf_cstr(&buf)) < 0)
874dcb25
BS
196 goto on_error;
197
198 git_buf_free(&buf);
199
c5193e3c 200 if (git_remote_save(remote) < 0)
874dcb25
BS
201 goto on_error;
202
c5193e3c 203 *out = remote;
204
874dcb25
BS
205 return 0;
206
207on_error:
208 git_buf_free(&buf);
c5193e3c 209 git_remote_free(remote);
874dcb25
BS
210 return -1;
211}
212
40b99d05
VG
213int git_remote_create_with_fetchspec(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch)
214{
40b99d05
VG
215 git_remote *remote = NULL;
216 int error;
217
218 if ((error = ensure_remote_name_is_valid(name)) < 0)
219 return error;
220
221 if ((error = ensure_remote_doesnot_exist(repo, name)) < 0)
222 return error;
874dcb25 223
0fe522d1 224 if (create_internal(&remote, repo, name, url, fetch) < 0)
874dcb25
BS
225 goto on_error;
226
c5193e3c 227 if (git_remote_save(remote) < 0)
874dcb25
BS
228 goto on_error;
229
c5193e3c 230 *out = remote;
231
874dcb25
BS
232 return 0;
233
234on_error:
c5193e3c 235 git_remote_free(remote);
874dcb25
BS
236 return -1;
237}
238
fd536d29 239int git_remote_create_anonymous(git_remote **out, git_repository *repo, const char *url, const char *fetch)
874dcb25
BS
240{
241 int error;
242 git_remote *remote;
243
79000951 244 if ((error = create_internal(&remote, repo, NULL, url, fetch)) < 0)
874dcb25
BS
245 return error;
246
874dcb25
BS
247 *out = remote;
248 return 0;
249}
250
991b2840 251int git_remote_dup(git_remote **dest, git_remote *source)
40ef47dd 252{
991b2840
AS
253 int error = 0;
254 git_strarray refspecs = { 0 };
40ef47dd
AS
255 git_remote *remote = git__calloc(1, sizeof(git_remote));
256 GITERR_CHECK_ALLOC(remote);
257
40ef47dd
AS
258 if (source->name != NULL) {
259 remote->name = git__strdup(source->name);
260 GITERR_CHECK_ALLOC(remote->name);
261 }
262
263 if (source->url != NULL) {
264 remote->url = git__strdup(source->url);
265 GITERR_CHECK_ALLOC(remote->url);
266 }
267
268 if (source->pushurl != NULL) {
269 remote->pushurl = git__strdup(source->pushurl);
270 GITERR_CHECK_ALLOC(remote->pushurl);
271 }
272
273 remote->repo = source->repo;
40ef47dd
AS
274 remote->download_tags = source->download_tags;
275 remote->check_cert = source->check_cert;
276 remote->update_fetchhead = source->update_fetchhead;
277
991b2840
AS
278 if (git_vector_init(&remote->refs, 32, NULL) < 0 ||
279 git_vector_init(&remote->refspecs, 2, NULL) < 0 ||
280 git_vector_init(&remote->active_refspecs, 2, NULL) < 0) {
281 error = -1;
282 goto cleanup;
40ef47dd
AS
283 }
284
991b2840
AS
285 if ((error = git_remote_get_fetch_refspecs(&refspecs, source)) < 0 ||
286 (error = git_remote_set_fetch_refspecs(remote, &refspecs)) < 0)
287 goto cleanup;
288
289 git_strarray_free(&refspecs);
290
291 if ((error = git_remote_get_push_refspecs(&refspecs, source)) < 0 ||
292 (error = git_remote_set_push_refspecs(remote, &refspecs)) < 0)
293 goto cleanup;
294
40ef47dd
AS
295 *dest = remote;
296
991b2840
AS
297cleanup:
298
299 git_strarray_free(&refspecs);
300
301 if (error < 0)
302 git__free(remote);
303
304 return error;
40ef47dd
AS
305}
306
4330ab26
CMN
307struct refspec_cb_data {
308 git_remote *remote;
309 int fetch;
310};
311
312static int refspec_cb(const git_config_entry *entry, void *payload)
313{
96869a4e 314 struct refspec_cb_data *data = (struct refspec_cb_data *)payload;
25e0b157 315 return add_refspec(data->remote, entry->value, data->fetch);
4330ab26
CMN
316}
317
bf6bebe2 318static int get_optional_config(
c9ffa84b 319 bool *found, git_config *config, git_buf *buf,
320 git_config_foreach_cb cb, void *payload)
bf6bebe2
RB
321{
322 int error = 0;
323 const char *key = git_buf_cstr(buf);
324
325 if (git_buf_oom(buf))
326 return -1;
327
328 if (cb != NULL)
4efa3290 329 error = git_config_get_multivar_foreach(config, key, NULL, cb, payload);
bf6bebe2
RB
330 else
331 error = git_config_get_string(payload, config, key);
332
c9ffa84b 333 if (found)
334 *found = !error;
335
bf6bebe2
RB
336 if (error == GIT_ENOTFOUND) {
337 giterr_clear();
338 error = 0;
339 }
340
bf6bebe2
RB
341 return error;
342}
343
9462c471 344int git_remote_load(git_remote **out, git_repository *repo, const char *name)
9c82357b
CMN
345{
346 git_remote *remote;
f0f3a18a 347 git_buf buf = GIT_BUF_INIT;
9c82357b 348 const char *val;
4376f7f6 349 int error = 0;
9462c471 350 git_config *config;
96869a4e 351 struct refspec_cb_data data = { NULL };
c9ffa84b 352 bool optional_setting_found = false, found;
4330ab26 353
9462c471
VM
354 assert(out && repo && name);
355
032ba9e4 356 if ((error = ensure_remote_name_is_valid(name)) < 0)
357 return error;
358
ac99d86b 359 if ((error = git_repository_config_snapshot(&config, repo)) < 0)
29c4cb09 360 return error;
4bef3565 361
9c82357b 362 remote = git__malloc(sizeof(git_remote));
4376f7f6 363 GITERR_CHECK_ALLOC(remote);
9c82357b
CMN
364
365 memset(remote, 0x0, sizeof(git_remote));
b0f6e45d 366 remote->update_fetchhead = 1;
9c82357b 367 remote->name = git__strdup(name);
4376f7f6 368 GITERR_CHECK_ALLOC(remote->name);
9c82357b 369
80fc7d6b
ET
370 if ((error = get_check_cert(&remote->check_cert, repo)) < 0)
371 goto cleanup;
372
25e0b157
RB
373 if (git_vector_init(&remote->refs, 32, NULL) < 0 ||
374 git_vector_init(&remote->refspecs, 2, NULL) < 0 ||
375 git_vector_init(&remote->active_refspecs, 2, NULL) < 0) {
2fb9d6de 376 error = -1;
377 goto cleanup;
378 }
d88d4311 379
25e0b157 380 if ((error = git_buf_printf(&buf, "remote.%s.url", name)) < 0)
2fb9d6de 381 goto cleanup;
9c82357b 382
c9ffa84b 383 if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0)
9c82357b 384 goto cleanup;
bf6bebe2 385
c9ffa84b 386 optional_setting_found |= found;
387
9462c471 388 remote->repo = repo;
c9ffa84b 389
390 if (found && strlen(val) > 0) {
391 remote->url = git__strdup(val);
392 GITERR_CHECK_ALLOC(remote->url);
393 }
9c82357b 394
bf6bebe2 395 val = NULL;
3ed4b501 396 git_buf_clear(&buf);
bf6bebe2 397 git_buf_printf(&buf, "remote.%s.pushurl", name);
3ed4b501 398
c9ffa84b 399 if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0)
3ed4b501 400 goto cleanup;
3ed4b501 401
c9ffa84b 402 optional_setting_found |= found;
403
404 if (!optional_setting_found) {
405 error = GIT_ENOTFOUND;
d723dbed 406 giterr_set(GITERR_CONFIG, "Remote '%s' does not exist.", name);
3ed4b501 407 goto cleanup;
c9ffa84b 408 }
3ed4b501 409
c9ffa84b 410 if (found && strlen(val) > 0) {
3ed4b501
SC
411 remote->pushurl = git__strdup(val);
412 GITERR_CHECK_ALLOC(remote->pushurl);
413 }
414
4330ab26
CMN
415 data.remote = remote;
416 data.fetch = true;
96869a4e 417
f0f3a18a 418 git_buf_clear(&buf);
bf6bebe2
RB
419 git_buf_printf(&buf, "remote.%s.fetch", name);
420
c9ffa84b 421 if ((error = get_optional_config(NULL, config, &buf, refspec_cb, &data)) < 0)
2fb9d6de 422 goto cleanup;
9c82357b 423
4330ab26 424 data.fetch = false;
bf6bebe2
RB
425 git_buf_clear(&buf);
426 git_buf_printf(&buf, "remote.%s.push", name);
9c82357b 427
c9ffa84b 428 if ((error = get_optional_config(NULL, config, &buf, refspec_cb, &data)) < 0)
9c82357b
CMN
429 goto cleanup;
430
24f2f94e
CMN
431 if (download_tags_value(remote, config) < 0)
432 goto cleanup;
433
af613ecd
CMN
434 /* Move the data over to where the matching functions can find them */
435 if (dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs) < 0)
436 goto cleanup;
437
9c82357b
CMN
438 *out = remote;
439
440cleanup:
29c4cb09 441 git_config_free(config);
f0f3a18a 442 git_buf_free(&buf);
9462c471 443
4376f7f6 444 if (error < 0)
9c82357b
CMN
445 git_remote_free(remote);
446
447 return error;
448}
449
4330ab26 450static int update_config_refspec(const git_remote *remote, git_config *config, int direction)
4fe5520a 451{
4330ab26 452 git_buf name = GIT_BUF_INIT;
66566516 453 unsigned int push;
4330ab26
CMN
454 const char *dir;
455 size_t i;
bf6bebe2 456 int error = 0;
3793fa9b 457 const char *cname;
4fe5520a 458
4330ab26
CMN
459 push = direction == GIT_DIRECTION_PUSH;
460 dir = push ? "push" : "fetch";
4fe5520a 461
4330ab26
CMN
462 if (git_buf_printf(&name, "remote.%s.%s", remote->name, dir) < 0)
463 return -1;
3793fa9b 464 cname = git_buf_cstr(&name);
4fe5520a 465
4330ab26 466 /* Clear out the existing config */
bf6bebe2 467 while (!error)
3793fa9b 468 error = git_config_delete_multivar(config, cname, ".*");
4fe5520a 469
4330ab26
CMN
470 if (error != GIT_ENOTFOUND)
471 return error;
472
1be680c4 473 for (i = 0; i < remote->refspecs.length; i++) {
4330ab26 474 git_refspec *spec = git_vector_get(&remote->refspecs, i);
4330ab26
CMN
475
476 if (spec->push != push)
477 continue;
478
376454d0
DRT
479 // "$^" is a unmatcheable regexp: it will not match anything at all, so
480 // all values will be considered new and we will not replace any
481 // present value.
bf6bebe2 482 if ((error = git_config_set_multivar(
376454d0 483 config, cname, "$^", spec->string)) < 0) {
4330ab26
CMN
484 goto cleanup;
485 }
486 }
487
488 giterr_clear();
489 error = 0;
4fe5520a 490
491cleanup:
492 git_buf_free(&name);
4fe5520a 493
494 return error;
495}
496
89e5ed98
CMN
497int git_remote_save(const git_remote *remote)
498{
218c88a9 499 int error;
8286300a 500 git_config *cfg;
218c88a9 501 const char *tagopt = NULL;
4fe5520a 502 git_buf buf = GIT_BUF_INIT;
8286300a 503 const git_config_entry *existing;
89e5ed98 504
e497b16c 505 assert(remote);
506
c07b52df 507 if (!remote->name) {
fd536d29 508 giterr_set(GITERR_INVALID, "Can't save an anonymous remote.");
874dcb25 509 return GIT_EINVALIDSPEC;
a71c27cc
BS
510 }
511
032ba9e4 512 if ((error = ensure_remote_name_is_valid(remote->name)) < 0)
513 return error;
89e5ed98 514
8286300a
RB
515 if ((error = git_repository_config__weakptr(&cfg, remote->repo)) < 0)
516 return error;
89e5ed98 517
8286300a
RB
518 if ((error = git_buf_printf(&buf, "remote.%s.url", remote->name)) < 0)
519 return error;
89e5ed98 520
8286300a
RB
521 /* after this point, buffer is allocated so end with cleanup */
522
523 if ((error = git_config_set_string(
524 cfg, git_buf_cstr(&buf), remote->url)) < 0)
525 goto cleanup;
89e5ed98 526
413d5563 527 git_buf_clear(&buf);
8286300a
RB
528 if ((error = git_buf_printf(&buf, "remote.%s.pushurl", remote->name)) < 0)
529 goto cleanup;
3ed4b501 530
8286300a
RB
531 if ((error = git_config__update_entry(
532 cfg, git_buf_cstr(&buf), remote->pushurl, true, false)) < 0)
533 goto cleanup;
3ed4b501 534
8286300a
RB
535 if ((error = update_config_refspec(remote, cfg, GIT_DIRECTION_FETCH)) < 0)
536 goto cleanup;
89e5ed98 537
8286300a
RB
538 if ((error = update_config_refspec(remote, cfg, GIT_DIRECTION_PUSH)) < 0)
539 goto cleanup;
89e5ed98 540
218c88a9
CMN
541 /*
542 * What action to take depends on the old and new values. This
543 * is describes by the table below. tagopt means whether the
544 * is already a value set in the config
545 *
546 * AUTO ALL or NONE
547 * +-----------------------+
548 * tagopt | remove | set |
549 * +---------+-------------|
550 * !tagopt | nothing | set |
551 * +---------+-------------+
552 */
553
554 git_buf_clear(&buf);
8286300a
RB
555 if ((error = git_buf_printf(&buf, "remote.%s.tagopt", remote->name)) < 0)
556 goto cleanup;
218c88a9 557
8286300a
RB
558 if ((error = git_config__lookup_entry(
559 &existing, cfg, git_buf_cstr(&buf), false)) < 0)
560 goto cleanup;
218c88a9 561
8286300a
RB
562 if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL)
563 tagopt = "--tags";
564 else if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_NONE)
565 tagopt = "--no-tags";
566 else if (existing != NULL)
567 tagopt = NULL;
4376f7f6 568
8286300a
RB
569 error = git_config__update_entry(
570 cfg, git_buf_cstr(&buf), tagopt, true, false);
4376f7f6 571
8286300a 572cleanup:
4376f7f6 573 git_buf_free(&buf);
8286300a 574 return error;
89e5ed98
CMN
575}
576
df705148 577const char *git_remote_name(const git_remote *remote)
9c82357b 578{
4bef3565 579 assert(remote);
9c82357b
CMN
580 return remote->name;
581}
582
85e1eded
ES
583git_repository *git_remote_owner(const git_remote *remote)
584{
585 assert(remote);
586 return remote->repo;
587}
588
df705148 589const char *git_remote_url(const git_remote *remote)
9c82357b 590{
4bef3565 591 assert(remote);
9c82357b
CMN
592 return remote->url;
593}
594
76501590
SC
595int git_remote_set_url(git_remote *remote, const char* url)
596{
597 assert(remote);
598 assert(url);
599
600 git__free(remote->url);
601 remote->url = git__strdup(url);
602 GITERR_CHECK_ALLOC(remote->url);
603
604 return 0;
605}
606
df705148 607const char *git_remote_pushurl(const git_remote *remote)
76501590
SC
608{
609 assert(remote);
610 return remote->pushurl;
611}
612
613int git_remote_set_pushurl(git_remote *remote, const char* url)
614{
615 assert(remote);
616
617 git__free(remote->pushurl);
618 if (url) {
619 remote->pushurl = git__strdup(url);
620 GITERR_CHECK_ALLOC(remote->pushurl);
621 } else {
622 remote->pushurl = NULL;
623 }
624 return 0;
625}
626
eff5b499
SC
627const char* git_remote__urlfordirection(git_remote *remote, int direction)
628{
629 assert(remote);
630
b83c92dd 631 assert(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH);
632
df705148 633 if (direction == GIT_DIRECTION_FETCH) {
eff5b499
SC
634 return remote->url;
635 }
636
df705148 637 if (direction == GIT_DIRECTION_PUSH) {
eff5b499
SC
638 return remote->pushurl ? remote->pushurl : remote->url;
639 }
640
641 return NULL;
642}
643
df705148 644int git_remote_connect(git_remote *remote, git_direction direction)
9ba49bb5 645{
9ba49bb5 646 git_transport *t;
c0c39025 647 const char *url;
41fb1ca0 648 int flags = GIT_TRANSPORTFLAGS_NONE;
80fc7d6b 649 int error;
9ba49bb5 650
4bef3565
VM
651 assert(remote);
652
41fb1ca0
PK
653 t = remote->transport;
654
c0c39025 655 url = git_remote__urlfordirection(remote, direction);
80fc7d6b 656 if (url == NULL) {
44bc0c6a 657 giterr_set(GITERR_INVALID,
658 "Malformed remote '%s' - missing URL", remote->name);
eff5b499 659 return -1;
44bc0c6a 660 }
eff5b499 661
41fb1ca0
PK
662 /* A transport could have been supplied in advance with
663 * git_remote_set_transport */
80fc7d6b
ET
664 if (!t && (error = git_transport_new(&t, remote, url)) < 0)
665 return error;
9ba49bb5 666
41fb1ca0 667 if (t->set_callbacks &&
98020d3a 668 (error = t->set_callbacks(t, remote->callbacks.sideband_progress, NULL, remote->callbacks.payload)) < 0)
41fb1ca0 669 goto on_error;
613d5eb9 670
41fb1ca0
PK
671 if (!remote->check_cert)
672 flags |= GIT_TRANSPORTFLAGS_NO_CHECK_CERT;
e03e71da 673
25e0b157 674 if ((error = t->connect(t, url, remote->callbacks.credentials, remote->callbacks.payload, direction, flags)) != 0)
4376f7f6 675 goto on_error;
9ba49bb5
CMN
676
677 remote->transport = t;
678
4376f7f6 679 return 0;
9ba49bb5 680
4376f7f6
CMN
681on_error:
682 t->free(t);
613d5eb9
PK
683
684 if (t == remote->transport)
685 remote->transport = NULL;
686
80fc7d6b 687 return error;
9ba49bb5
CMN
688}
689
359dce72 690int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote)
9ba49bb5 691{
d88d4311
VM
692 assert(remote);
693
359dce72 694 return remote->transport->ls(out, size, remote->transport);
9ba49bb5
CMN
695}
696
613d5eb9
PK
697int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_url)
698{
699 git_config *cfg;
9f77b3f6
RB
700 const git_config_entry *ce;
701 const char *val = NULL;
80fc7d6b 702 int error;
613d5eb9
PK
703
704 assert(remote);
705
a71c27cc 706 if (!proxy_url || !remote->repo)
613d5eb9
PK
707 return -1;
708
709 *proxy_url = NULL;
710
80fc7d6b
ET
711 if ((error = git_repository_config__weakptr(&cfg, remote->repo)) < 0)
712 return error;
613d5eb9
PK
713
714 /* Go through the possible sources for proxy configuration, from most specific
715 * to least specific. */
716
717 /* remote.<name>.proxy config setting */
9f77b3f6 718 if (remote->name && remote->name[0]) {
613d5eb9
PK
719 git_buf buf = GIT_BUF_INIT;
720
80fc7d6b
ET
721 if ((error = git_buf_printf(&buf, "remote.%s.proxy", remote->name)) < 0)
722 return error;
613d5eb9 723
9f77b3f6
RB
724 error = git_config__lookup_entry(&ce, cfg, git_buf_cstr(&buf), false);
725 git_buf_free(&buf);
613d5eb9 726
9f77b3f6 727 if (error < 0)
80fc7d6b 728 return error;
613d5eb9 729
9f77b3f6
RB
730 if (ce && ce->value) {
731 val = ce->value;
732 goto found;
733 }
613d5eb9
PK
734 }
735
736 /* http.proxy config setting */
9f77b3f6 737 if ((error = git_config__lookup_entry(&ce, cfg, "http.proxy", false)) < 0)
80fc7d6b 738 return error;
9f77b3f6
RB
739 if (ce && ce->value) {
740 val = ce->value;
741 goto found;
742 }
613d5eb9
PK
743
744 /* HTTP_PROXY / HTTPS_PROXY environment variables */
745 val = use_ssl ? getenv("HTTPS_PROXY") : getenv("HTTP_PROXY");
746
9f77b3f6
RB
747found:
748 if (val && val[0]) {
613d5eb9
PK
749 *proxy_url = git__strdup(val);
750 GITERR_CHECK_ALLOC(*proxy_url);
613d5eb9
PK
751 }
752
753 return 0;
754}
755
af613ecd
CMN
756/* DWIM `refspecs` based on `refs` and append the output to `out` */
757static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs)
d8488457 758{
af613ecd 759 size_t i;
d8488457 760 git_refspec *spec;
d8488457
CMN
761
762 git_vector_foreach(refspecs, i, spec) {
af613ecd
CMN
763 if (git_refspec__dwim_one(out, spec, refs) < 0)
764 return -1;
765 }
d8488457 766
af613ecd
CMN
767 return 0;
768}
d8488457 769
af613ecd
CMN
770static void free_refspecs(git_vector *vec)
771{
772 size_t i;
773 git_refspec *spec;
d8488457 774
af613ecd
CMN
775 git_vector_foreach(vec, i, spec) {
776 git_refspec__free(spec);
777 git__free(spec);
d8488457
CMN
778 }
779
af613ecd 780 git_vector_clear(vec);
d8488457
CMN
781}
782
783static int remote_head_cmp(const void *_a, const void *_b)
784{
785 const git_remote_head *a = (git_remote_head *) _a;
786 const git_remote_head *b = (git_remote_head *) _b;
787
788 return git__strcmp_cb(a->name, b->name);
789}
790
877cde76
CMN
791static int ls_to_vector(git_vector *out, git_remote *remote)
792{
793 git_remote_head **heads;
794 size_t heads_len, i;
795
796 if (git_remote_ls((const git_remote_head ***)&heads, &heads_len, remote) < 0)
797 return -1;
798
799 if (git_vector_init(out, heads_len, remote_head_cmp) < 0)
800 return -1;
801
802 for (i = 0; i < heads_len; i++) {
803 if (git_vector_insert(out, heads[i]) < 0)
804 return -1;
805 }
806
807 return 0;
808}
809
d31402a3 810int git_remote_download(git_remote *remote)
48a65a07 811{
95057b85 812 int error;
d8488457 813 git_vector refs;
95057b85 814
1e3b8ed5 815 assert(remote);
4bef3565 816
877cde76 817 if (ls_to_vector(&refs, remote) < 0)
d8488457 818 return -1;
d8488457 819
af613ecd
CMN
820 free_refspecs(&remote->active_refspecs);
821
877cde76
CMN
822 error = dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &refs);
823 git_vector_free(&refs);
824
825 if (error < 0)
25e0b157 826 return error;
d8488457 827
95057b85 828 if ((error = git_fetch_negotiate(remote)) < 0)
4376f7f6 829 return error;
95057b85 830
d31402a3 831 return git_fetch_download_pack(remote);
48a65a07
CMN
832}
833
c3ab1e5a
BS
834int git_remote_fetch(
835 git_remote *remote,
836 const git_signature *signature,
837 const char *reflog_message)
fe3a40a4
CMN
838{
839 int error;
db55bb73 840 git_buf reflog_msg_buf = GIT_BUF_INIT;
fe3a40a4
CMN
841
842 /* Connect and download everything */
25e0b157 843 if ((error = git_remote_connect(remote, GIT_DIRECTION_FETCH)) != 0)
fe3a40a4
CMN
844 return error;
845
06a8f5c3 846 error = git_remote_download(remote);
fe3a40a4
CMN
847
848 /* We don't need to be connected anymore */
849 git_remote_disconnect(remote);
850
06a8f5c3
BL
851 /* If the download failed, return the error */
852 if (error != 0)
853 return error;
854
db55bb73
BS
855 /* Default reflog message */
856 if (reflog_message)
857 git_buf_sets(&reflog_msg_buf, reflog_message);
858 else {
859 git_buf_printf(&reflog_msg_buf, "fetch %s",
860 remote->name ? remote->name : remote->url);
861 }
862
fe3a40a4 863 /* Create "remote/foo" branches for all remote branches */
db55bb73
BS
864 error = git_remote_update_tips(remote, signature, git_buf_cstr(&reflog_msg_buf));
865 git_buf_free(&reflog_msg_buf);
866 return error;
fe3a40a4
CMN
867}
868
b0f6e45d
ET
869static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *update_heads, const char *fetchspec_src)
870{
871 unsigned int i;
872 git_remote_head *remote_ref;
873
874 assert(update_heads && fetchspec_src);
875
876 *out = NULL;
7d4b65f6 877
878 git_vector_foreach(update_heads, i, remote_ref) {
879 if (strcmp(remote_ref->name, fetchspec_src) == 0) {
880 *out = remote_ref;
881 break;
b0f6e45d
ET
882 }
883 }
884
885 return 0;
886}
887
4330ab26 888static int remote_head_for_ref(git_remote_head **out, git_refspec *spec, git_vector *update_heads, git_reference *ref)
b0f6e45d
ET
889{
890 git_reference *resolved_ref = NULL;
b0f6e45d 891 git_buf remote_name = GIT_BUF_INIT;
67d4997a
CMN
892 git_buf upstream_name = GIT_BUF_INIT;
893 git_repository *repo;
894 const char *ref_name;
b0f6e45d
ET
895 int error = 0;
896
4330ab26 897 assert(out && spec && ref);
b0f6e45d
ET
898
899 *out = NULL;
900
67d4997a
CMN
901 repo = git_reference_owner(ref);
902
903 error = git_reference_resolve(&resolved_ref, ref);
904
905 /* If we're in an unborn branch, let's pretend nothing happened */
906 if (error == GIT_ENOTFOUND && git_reference_type(ref) == GIT_REF_SYMBOLIC) {
907 ref_name = git_reference_symbolic_target(ref);
908 error = 0;
909 } else {
910 ref_name = git_reference_name(resolved_ref);
911 }
912
913 if ((!git_reference__is_branch(ref_name)) ||
914 (error = git_branch_upstream_name(&upstream_name, repo, ref_name)) < 0 ||
915 (error = git_refspec_rtransform(&remote_name, spec, upstream_name.ptr)) < 0) {
916 /* Not an error if there is no upstream */
b0f6e45d
ET
917 if (error == GIT_ENOTFOUND)
918 error = 0;
919
920 goto cleanup;
921 }
922
923 error = remote_head_for_fetchspec_src(out, update_heads, git_buf_cstr(&remote_name));
924
925cleanup:
b0f6e45d
ET
926 git_reference_free(resolved_ref);
927 git_buf_free(&remote_name);
67d4997a 928 git_buf_free(&upstream_name);
b0f6e45d
ET
929 return error;
930}
931
4330ab26 932static int git_remote_write_fetchhead(git_remote *remote, git_refspec *spec, git_vector *update_heads)
b0f6e45d 933{
b0f6e45d
ET
934 git_reference *head_ref = NULL;
935 git_fetchhead_ref *fetchhead_ref;
936 git_remote_head *remote_ref, *merge_remote_ref;
937 git_vector fetchhead_refs;
938 bool include_all_fetchheads;
939 unsigned int i = 0;
940 int error = 0;
941
942 assert(remote);
943
404eadb0
CMN
944 /* no heads, nothing to do */
945 if (update_heads->length == 0)
946 return 0;
947
b0f6e45d
ET
948 if (git_vector_init(&fetchhead_refs, update_heads->length, git_fetchhead_ref_cmp) < 0)
949 return -1;
950
951 /* Iff refspec is * (but not subdir slash star), include tags */
952 include_all_fetchheads = (strcmp(GIT_REFS_HEADS_DIR "*", git_refspec_src(spec)) == 0);
953
954 /* Determine what to merge: if refspec was a wildcard, just use HEAD */
955 if (git_refspec_is_wildcard(spec)) {
956 if ((error = git_reference_lookup(&head_ref, remote->repo, GIT_HEAD_FILE)) < 0 ||
4330ab26 957 (error = remote_head_for_ref(&merge_remote_ref, spec, update_heads, head_ref)) < 0)
b0f6e45d
ET
958 goto cleanup;
959 } else {
960 /* If we're fetching a single refspec, that's the only thing that should be in FETCH_HEAD. */
961 if ((error = remote_head_for_fetchspec_src(&merge_remote_ref, update_heads, git_refspec_src(spec))) < 0)
962 goto cleanup;
963 }
964
965 /* Create the FETCH_HEAD file */
7d4b65f6 966 git_vector_foreach(update_heads, i, remote_ref) {
b0f6e45d
ET
967 int merge_this_fetchhead = (merge_remote_ref == remote_ref);
968
969 if (!include_all_fetchheads &&
970 !git_refspec_src_matches(spec, remote_ref->name) &&
971 !merge_this_fetchhead)
972 continue;
973
974 if (git_fetchhead_ref_create(&fetchhead_ref,
975 &remote_ref->oid,
976 merge_this_fetchhead,
977 remote_ref->name,
978 git_remote_url(remote)) < 0)
979 goto cleanup;
980
981 if (git_vector_insert(&fetchhead_refs, fetchhead_ref) < 0)
982 goto cleanup;
983 }
984
985 git_fetchhead_write(remote->repo, &fetchhead_refs);
986
987cleanup:
988 for (i = 0; i < fetchhead_refs.length; ++i)
989 git_fetchhead_ref_free(fetchhead_refs.contents[i]);
990
991 git_vector_free(&fetchhead_refs);
992 git_reference_free(head_ref);
993
994 return error;
995}
996
c3ab1e5a
BS
997static int update_tips_for_spec(
998 git_remote *remote,
999 git_refspec *spec,
1000 git_vector *refs,
1001 const git_signature *signature,
1002 const char *log_message)
441f57c2 1003{
a37ddf7e 1004 int error = 0, autotag;
517bda19 1005 unsigned int i = 0;
97769280 1006 git_buf refname = GIT_BUF_INIT;
f184836b 1007 git_oid old;
a37ddf7e 1008 git_odb *odb;
441f57c2
CMN
1009 git_remote_head *head;
1010 git_reference *ref;
a37ddf7e 1011 git_refspec tagspec;
4330ab26 1012 git_vector update_heads;
441f57c2 1013
4bef3565
VM
1014 assert(remote);
1015
acd17006 1016 if (git_repository_odb__weakptr(&odb, remote->repo) < 0)
a37ddf7e
CMN
1017 return -1;
1018
3230a44f 1019 if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
a37ddf7e
CMN
1020 return -1;
1021
41fb1ca0 1022 /* Make a copy of the transport's refs */
4330ab26 1023 if (git_vector_init(&update_heads, 16, NULL) < 0)
41fb1ca0 1024 return -1;
585a2eb7 1025
4330ab26
CMN
1026 for (; i < refs->length; ++i) {
1027 head = git_vector_get(refs, i);
9063be1f 1028 autotag = 0;
517bda19 1029
a37ddf7e
CMN
1030 /* Ignore malformed ref names (which also saves us from tag^{} */
1031 if (!git_reference_is_valid_name(head->name))
1032 continue;
1033
d8488457 1034 if (git_refspec_src_matches(spec, head->name) && spec->dst) {
bf522e08 1035 if (git_refspec_transform(&refname, spec, head->name) < 0)
a37ddf7e
CMN
1036 goto on_error;
1037 } else if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
3230a44f
CMN
1038
1039 if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_ALL)
1040 autotag = 1;
a37ddf7e
CMN
1041
1042 if (!git_refspec_src_matches(&tagspec, head->name))
1043 continue;
1044
1045 git_buf_clear(&refname);
1046 if (git_buf_puts(&refname, head->name) < 0)
1047 goto on_error;
1048 } else {
1049 continue;
1050 }
1051
1052 if (autotag && !git_odb_exists(odb, &head->oid))
1053 continue;
f184836b 1054
b0f6e45d
ET
1055 if (git_vector_insert(&update_heads, head) < 0)
1056 goto on_error;
1057
2508cc66 1058 error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
904b67e6 1059 if (error < 0 && error != GIT_ENOTFOUND)
f184836b
CMN
1060 goto on_error;
1061
904b67e6 1062 if (error == GIT_ENOTFOUND)
f184836b
CMN
1063 memset(&old, 0, GIT_OID_RAWSZ);
1064
b7f167da 1065 if (!git_oid__cmp(&old, &head->oid))
f184836b 1066 continue;
441f57c2 1067
a37ddf7e 1068 /* In autotag mode, don't overwrite any locally-existing tags */
c3ab1e5a
BS
1069 error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag,
1070 signature, log_message);
a37ddf7e 1071 if (error < 0 && error != GIT_EEXISTS)
944d250f 1072 goto on_error;
39157563
CMN
1073
1074 git_reference_free(ref);
f184836b 1075
b3aaa7a7 1076 if (remote->callbacks.update_tips != NULL) {
df705148 1077 if (remote->callbacks.update_tips(refname.ptr, &old, &head->oid, remote->callbacks.payload) < 0)
f184836b
CMN
1078 goto on_error;
1079 }
441f57c2
CMN
1080 }
1081
b0f6e45d 1082 if (git_remote_update_fetchhead(remote) &&
4330ab26 1083 (error = git_remote_write_fetchhead(remote, spec, &update_heads)) < 0)
b0f6e45d
ET
1084 goto on_error;
1085
b0f6e45d 1086 git_vector_free(&update_heads);
a37ddf7e 1087 git_refspec__free(&tagspec);
97769280 1088 git_buf_free(&refname);
f184836b
CMN
1089 return 0;
1090
1091on_error:
b0f6e45d 1092 git_vector_free(&update_heads);
a37ddf7e 1093 git_refspec__free(&tagspec);
f184836b
CMN
1094 git_buf_free(&refname);
1095 return -1;
97769280 1096
441f57c2
CMN
1097}
1098
c3ab1e5a
BS
1099int git_remote_update_tips(
1100 git_remote *remote,
1101 const git_signature *signature,
1102 const char *reflog_message)
4330ab26 1103{
505b5d0c 1104 git_refspec *spec, tagspec;
4330ab26 1105 git_vector refs;
505b5d0c 1106 int error;
4330ab26
CMN
1107 size_t i;
1108
505b5d0c
CMN
1109 if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
1110 return -1;
1111
877cde76
CMN
1112
1113 if ((error = ls_to_vector(&refs, remote)) < 0)
505b5d0c
CMN
1114 goto out;
1115
1116 if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) {
c3ab1e5a 1117 error = update_tips_for_spec(remote, &tagspec, &refs, signature, reflog_message);
505b5d0c
CMN
1118 goto out;
1119 }
4330ab26 1120
af613ecd 1121 git_vector_foreach(&remote->active_refspecs, i, spec) {
4330ab26
CMN
1122 if (spec->push)
1123 continue;
1124
c3ab1e5a 1125 if ((error = update_tips_for_spec(remote, spec, &refs, signature, reflog_message)) < 0)
505b5d0c 1126 goto out;
4330ab26
CMN
1127 }
1128
505b5d0c 1129out:
877cde76 1130 git_vector_free(&refs);
505b5d0c 1131 git_refspec__free(&tagspec);
505b5d0c 1132 return error;
4330ab26
CMN
1133}
1134
11f6ad5f 1135int git_remote_connected(const git_remote *remote)
6ac3b707 1136{
4bef3565 1137 assert(remote);
41fb1ca0
PK
1138
1139 if (!remote->transport || !remote->transport->is_connected)
1140 return 0;
1141
1142 /* Ask the transport if it's connected. */
613d5eb9 1143 return remote->transport->is_connected(remote->transport);
6ac3b707
CMN
1144}
1145
f0d2ddbb
CMN
1146void git_remote_stop(git_remote *remote)
1147{
613d5eb9
PK
1148 assert(remote);
1149
1150 if (remote->transport && remote->transport->cancel)
41fb1ca0 1151 remote->transport->cancel(remote->transport);
f0d2ddbb
CMN
1152}
1153
4cf01e9a
CMN
1154void git_remote_disconnect(git_remote *remote)
1155{
4bef3565
VM
1156 assert(remote);
1157
41fb1ca0
PK
1158 if (git_remote_connected(remote))
1159 remote->transport->close(remote->transport);
4cf01e9a
CMN
1160}
1161
9c82357b
CMN
1162void git_remote_free(git_remote *remote)
1163{
2aae2188
CMN
1164 if (remote == NULL)
1165 return;
1166
42ea35c0
MS
1167 if (remote->transport != NULL) {
1168 git_remote_disconnect(remote);
1169
1170 remote->transport->free(remote->transport);
1171 remote->transport = NULL;
1172 }
1173
1174 git_vector_free(&remote->refs);
1175
af613ecd 1176 free_refspecs(&remote->refspecs);
4330ab26
CMN
1177 git_vector_free(&remote->refspecs);
1178
af613ecd
CMN
1179 free_refspecs(&remote->active_refspecs);
1180 git_vector_free(&remote->active_refspecs);
1181
3286c408 1182 git__free(remote->url);
3ed4b501 1183 git__free(remote->pushurl);
3286c408 1184 git__free(remote->name);
3286c408 1185 git__free(remote);
9c82357b 1186}
8171998f 1187
106c12f1 1188static int remote_list_cb(const git_config_entry *entry, void *payload)
8171998f 1189{
25e0b157 1190 git_vector *list = payload;
106c12f1
RB
1191 const char *name = entry->name + strlen("remote.");
1192 size_t namelen = strlen(name);
1193 char *remote_name;
8171998f 1194
106c12f1 1195 /* we know name matches "remote.<stuff>.(push)?url" */
8171998f 1196
106c12f1
RB
1197 if (!strcmp(&name[namelen - 4], ".url"))
1198 remote_name = git__strndup(name, namelen - 4); /* strip ".url" */
1199 else
1200 remote_name = git__strndup(name, namelen - 8); /* strip ".pushurl" */
25e0b157 1201 GITERR_CHECK_ALLOC(remote_name);
8171998f 1202
25e0b157 1203 return git_vector_insert(list, remote_name);
8171998f
CMN
1204}
1205
1206int git_remote_list(git_strarray *remotes_list, git_repository *repo)
1207{
8171998f 1208 int error;
96869a4e 1209 git_config *cfg;
25e0b157 1210 git_vector list = GIT_VECTOR_INIT;
8171998f 1211
96869a4e
RB
1212 if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
1213 return error;
8171998f 1214
25e0b157 1215 if ((error = git_vector_init(&list, 4, git__strcmp_cb)) < 0)
96869a4e 1216 return error;
8171998f 1217
106c12f1 1218 error = git_config_foreach_match(
25e0b157 1219 cfg, "^remote\\..*\\.(push)?url$", remote_list_cb, &list);
8171998f 1220
4376f7f6 1221 if (error < 0) {
9cfce273 1222 git_vector_free_deep(&list);
8171998f
CMN
1223 return error;
1224 }
1225
25e0b157 1226 git_vector_uniq(&list, git__free);
aec87f71 1227
25e0b157
RB
1228 remotes_list->strings =
1229 (char **)git_vector_detach(&remotes_list->count, NULL, &list);
8171998f 1230
4376f7f6 1231 return 0;
8171998f 1232}
a209a025 1233
250b95b2
CMN
1234void git_remote_check_cert(git_remote *remote, int check)
1235{
1236 assert(remote);
1237
1238 remote->check_cert = check;
1239}
b3aaa7a7 1240
0e0cf787 1241int git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *callbacks)
b3aaa7a7
CMN
1242{
1243 assert(remote && callbacks);
1244
c7231c45 1245 GITERR_CHECK_VERSION(callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
9267ff58 1246
b3aaa7a7 1247 memcpy(&remote->callbacks, callbacks, sizeof(git_remote_callbacks));
e03e71da 1248
41fb1ca0 1249 if (remote->transport && remote->transport->set_callbacks)
0e0cf787 1250 return remote->transport->set_callbacks(remote->transport,
98020d3a 1251 remote->callbacks.sideband_progress,
41fb1ca0 1252 NULL,
df705148 1253 remote->callbacks.payload);
9267ff58
BS
1254
1255 return 0;
41fb1ca0
PK
1256}
1257
2efd7df6
CMN
1258const git_remote_callbacks *git_remote_get_callbacks(git_remote *remote)
1259{
1260 assert(remote);
1261
1262 return &remote->callbacks;
1263}
1264
41fb1ca0
PK
1265int git_remote_set_transport(git_remote *remote, git_transport *transport)
1266{
1267 assert(remote && transport);
1268
c7231c45 1269 GITERR_CHECK_VERSION(transport, GIT_TRANSPORT_VERSION, "git_transport");
10711769 1270
e03e71da 1271 if (remote->transport) {
41fb1ca0
PK
1272 giterr_set(GITERR_NET, "A transport is already bound to this remote");
1273 return -1;
e03e71da 1274 }
41fb1ca0
PK
1275
1276 remote->transport = transport;
1277 return 0;
b3aaa7a7 1278}
f70e466f 1279
67dad09b 1280const git_transfer_progress* git_remote_stats(git_remote *remote)
d57c47dc
BS
1281{
1282 assert(remote);
1283 return &remote->stats;
1284}
1285
11f6ad5f 1286git_remote_autotag_option_t git_remote_autotag(const git_remote *remote)
f70e466f
CMN
1287{
1288 return remote->download_tags;
1289}
1290
f4a62c30 1291void git_remote_set_autotag(git_remote *remote, git_remote_autotag_option_t value)
f70e466f
CMN
1292{
1293 remote->download_tags = value;
1294}
fcccf304 1295
fcccf304 1296static int rename_remote_config_section(
1297 git_repository *repo,
1298 const char *old_name,
1299 const char *new_name)
1300{
1301 git_buf old_section_name = GIT_BUF_INIT,
1302 new_section_name = GIT_BUF_INIT;
1303 int error = -1;
1304
1305 if (git_buf_printf(&old_section_name, "remote.%s", old_name) < 0)
1306 goto cleanup;
1307
40e48ea4 1308 if (new_name &&
1309 (git_buf_printf(&new_section_name, "remote.%s", new_name) < 0))
1310 goto cleanup;
fcccf304 1311
1312 error = git_config_rename_section(
1313 repo,
1314 git_buf_cstr(&old_section_name),
40e48ea4 1315 new_name ? git_buf_cstr(&new_section_name) : NULL);
fcccf304 1316
1317cleanup:
1318 git_buf_free(&old_section_name);
1319 git_buf_free(&new_section_name);
1320
1321 return error;
1322}
1323
96869a4e 1324struct update_data {
fcccf304 1325 git_config *config;
1326 const char *old_remote_name;
1327 const char *new_remote_name;
1328};
1329
1330static int update_config_entries_cb(
1331 const git_config_entry *entry,
1332 void *payload)
1333{
1334 struct update_data *data = (struct update_data *)payload;
1335
1336 if (strcmp(entry->value, data->old_remote_name))
1337 return 0;
1338
25e0b157
RB
1339 return git_config_set_string(
1340 data->config, entry->name, data->new_remote_name);
fcccf304 1341}
1342
1343static int update_branch_remote_config_entry(
1344 git_repository *repo,
1345 const char *old_name,
1346 const char *new_name)
1347{
96869a4e
RB
1348 int error;
1349 struct update_data data = { NULL };
fcccf304 1350
96869a4e
RB
1351 if ((error = git_repository_config__weakptr(&data.config, repo)) < 0)
1352 return error;
fcccf304 1353
fcccf304 1354 data.old_remote_name = old_name;
1355 data.new_remote_name = new_name;
1356
25e0b157 1357 return git_config_foreach_match(
96869a4e 1358 data.config, "branch\\..+\\.remote", update_config_entries_cb, &data);
fcccf304 1359}
1360
fcccf304 1361static int rename_one_remote_reference(
56960b83 1362 git_reference *reference,
fcccf304 1363 const char *old_remote_name,
1364 const char *new_remote_name)
1365{
96869a4e 1366 int error;
fcccf304 1367 git_buf new_name = GIT_BUF_INIT;
ccf6ce5c 1368 git_buf log_message = GIT_BUF_INIT;
fcccf304 1369
ccf6ce5c
BS
1370 if ((error = git_buf_printf(
1371 &new_name,
1372 GIT_REFS_REMOTES_DIR "%s%s",
1373 new_remote_name,
1374 reference->name + strlen(GIT_REFS_REMOTES_DIR) + strlen(old_remote_name))) < 0)
1375 goto cleanup;
fcccf304 1376
ccf6ce5c
BS
1377 if ((error = git_buf_printf(&log_message,
1378 "renamed remote %s to %s",
1379 old_remote_name, new_remote_name)) < 0)
1380 goto cleanup;
fcccf304 1381
ccf6ce5c
BS
1382 error = git_reference_rename(
1383 NULL, reference, git_buf_cstr(&new_name), 0,
1384 NULL, git_buf_cstr(&log_message));
1385 git_reference_free(reference);
1386
1387cleanup:
fcccf304 1388 git_buf_free(&new_name);
ccf6ce5c 1389 git_buf_free(&log_message);
fcccf304 1390 return error;
1391}
1392
1393static int rename_remote_references(
1394 git_repository *repo,
1395 const char *old_name,
1396 const char *new_name)
1397{
96869a4e 1398 int error;
56960b83 1399 git_reference *ref;
9bd89d96 1400 git_reference_iterator *iter;
fcccf304 1401
96869a4e
RB
1402 if ((error = git_reference_iterator_new(&iter, repo)) < 0)
1403 return error;
fcccf304 1404
56960b83 1405 while ((error = git_reference_next(&ref, iter)) == 0) {
2f77d8f1
RB
1406 if (git__prefixcmp(ref->name, GIT_REFS_REMOTES_DIR)) {
1407 git_reference_free(ref);
9bd89d96 1408 continue;
2f77d8f1 1409 }
9bd89d96 1410
96869a4e
RB
1411 if ((error = rename_one_remote_reference(ref, old_name, new_name)) < 0)
1412 break;
9bd89d96
CMN
1413 }
1414
1415 git_reference_iterator_free(iter);
fcccf304 1416
96869a4e 1417 return (error == GIT_ITEROVER) ? 0 : error;
fcccf304 1418}
1419
1420static int rename_fetch_refspecs(
1421 git_remote *remote,
1422 const char *new_name,
1423 int (*callback)(const char *problematic_refspec, void *payload),
1424 void *payload)
1425{
1426 git_config *config;
4330ab26 1427 git_buf base = GIT_BUF_INIT, var = GIT_BUF_INIT, val = GIT_BUF_INIT;
1be680c4 1428 const git_refspec *spec;
4330ab26 1429 size_t i;
25e0b157 1430 int error = 0;
fcccf304 1431
dab89f9b 1432 if ((error = git_repository_config__weakptr(&config, remote->repo)) < 0)
25e0b157
RB
1433 return error;
1434
1435 if ((error = git_buf_printf(
1436 &base, "+refs/heads/*:refs/remotes/%s/*", remote->name)) < 0)
1437 return error;
dab89f9b 1438
1be680c4 1439 git_vector_foreach(&remote->refspecs, i, spec) {
4330ab26
CMN
1440 if (spec->push)
1441 continue;
fcccf304 1442
fd536d29 1443 /* Every refspec is a problem refspec for an anonymous remote, OR */
dab89f9b
RB
1444 /* Does the dst part of the refspec follow the expected format? */
1445 if (!remote->name ||
1446 strcmp(git_buf_cstr(&base), spec->string)) {
fcccf304 1447
c7b3e1b3 1448 if ((error = callback(spec->string, payload)) != 0) {
26c1cb91 1449 giterr_set_after_callback(error);
25e0b157 1450 break;
c7b3e1b3
RB
1451 }
1452
4330ab26
CMN
1453 continue;
1454 }
fcccf304 1455
4330ab26 1456 /* If we do want to move it to the new section */
fcccf304 1457
dab89f9b
RB
1458 git_buf_clear(&val);
1459 git_buf_clear(&var);
fcccf304 1460
dab89f9b
RB
1461 if (git_buf_printf(
1462 &val, "+refs/heads/*:refs/remotes/%s/*", new_name) < 0 ||
1463 git_buf_printf(&var, "remote.%s.fetch", new_name) < 0)
1464 {
1465 error = -1;
25e0b157 1466 break;
dab89f9b 1467 }
fcccf304 1468
dab89f9b
RB
1469 if ((error = git_config_set_string(
1470 config, git_buf_cstr(&var), git_buf_cstr(&val))) < 0)
25e0b157 1471 break;
4330ab26 1472 }
fcccf304 1473
4330ab26
CMN
1474 git_buf_free(&base);
1475 git_buf_free(&var);
1476 git_buf_free(&val);
fcccf304 1477 return error;
1478}
1479
1480int git_remote_rename(
1481 git_remote *remote,
1482 const char *new_name,
df705148 1483 git_remote_rename_problem_cb callback,
fcccf304 1484 void *payload)
1485{
1486 int error;
1487
1488 assert(remote && new_name);
1489
c07b52df 1490 if (!remote->name) {
fd536d29 1491 giterr_set(GITERR_INVALID, "Can't rename an anonymous remote.");
79000951
BS
1492 return GIT_EINVALIDSPEC;
1493 }
1494
fcccf304 1495 if ((error = ensure_remote_name_is_valid(new_name)) < 0)
1496 return error;
1497
a71c27cc
BS
1498 if (remote->repo) {
1499 if ((error = ensure_remote_doesnot_exist(remote->repo, new_name)) < 0)
fcccf304 1500 return error;
1501
a71c27cc
BS
1502 if (!remote->name) {
1503 if ((error = rename_fetch_refspecs(
1504 remote,
1505 new_name,
1506 callback,
1507 payload)) < 0)
dab89f9b 1508 return error;
fcccf304 1509
a71c27cc 1510 remote->name = git__strdup(new_name);
dab89f9b 1511 GITERR_CHECK_ALLOC(remote->name);
fcccf304 1512
a71c27cc
BS
1513 return git_remote_save(remote);
1514 }
fcccf304 1515
a71c27cc
BS
1516 if ((error = rename_remote_config_section(
1517 remote->repo,
1518 remote->name,
1519 new_name)) < 0)
1520 return error;
fcccf304 1521
a71c27cc
BS
1522 if ((error = update_branch_remote_config_entry(
1523 remote->repo,
1524 remote->name,
1525 new_name)) < 0)
1526 return error;
fcccf304 1527
a71c27cc
BS
1528 if ((error = rename_remote_references(
1529 remote->repo,
1530 remote->name,
1531 new_name)) < 0)
1532 return error;
1533
1534 if ((error = rename_fetch_refspecs(
1535 remote,
1536 new_name,
1537 callback,
1538 payload)) < 0)
dab89f9b 1539 return error;
a71c27cc 1540 }
fcccf304 1541
1542 git__free(remote->name);
dab89f9b 1543
fcccf304 1544 remote->name = git__strdup(new_name);
dab89f9b 1545 GITERR_CHECK_ALLOC(remote->name);
fcccf304 1546
1547 return 0;
1548}
b0f6e45d
ET
1549
1550int git_remote_update_fetchhead(git_remote *remote)
1551{
8f2a3d62 1552 return (remote->update_fetchhead != 0);
b0f6e45d
ET
1553}
1554
1555void git_remote_set_update_fetchhead(git_remote *remote, int value)
1556{
8f2a3d62 1557 remote->update_fetchhead = (value != 0);
b0f6e45d 1558}
2bca5b67 1559
1560int git_remote_is_valid_name(
1561 const char *remote_name)
1562{
1563 git_buf buf = GIT_BUF_INIT;
1564 git_refspec refspec;
1565 int error = -1;
1566
1567 if (!remote_name || *remote_name == '\0')
1568 return 0;
1569
1570 git_buf_printf(&buf, "refs/heads/test:refs/remotes/%s/test", remote_name);
1571 error = git_refspec__parse(&refspec, git_buf_cstr(&buf), true);
1572
1573 git_buf_free(&buf);
1574 git_refspec__free(&refspec);
1575
1576 giterr_clear();
1577 return error == 0;
1578}
4330ab26
CMN
1579
1580git_refspec *git_remote__matching_refspec(git_remote *remote, const char *refname)
1581{
1582 git_refspec *spec;
1583 size_t i;
1584
af613ecd 1585 git_vector_foreach(&remote->active_refspecs, i, spec) {
4330ab26
CMN
1586 if (spec->push)
1587 continue;
1588
1589 if (git_refspec_src_matches(spec, refname))
1590 return spec;
1591 }
1592
1593 return NULL;
1594}
1595
1596git_refspec *git_remote__matching_dst_refspec(git_remote *remote, const char *refname)
1597{
1598 git_refspec *spec;
1599 size_t i;
1600
af613ecd 1601 git_vector_foreach(&remote->active_refspecs, i, spec) {
4330ab26
CMN
1602 if (spec->push)
1603 continue;
1604
1605 if (git_refspec_dst_matches(spec, refname))
1606 return spec;
1607 }
1608
1609 return NULL;
1610}
1611
1612void git_remote_clear_refspecs(git_remote *remote)
1613{
1614 git_refspec *spec;
4330ab26
CMN
1615 size_t i;
1616
1617 git_vector_foreach(&remote->refspecs, i, spec) {
1618 git_refspec__free(spec);
1be680c4 1619 git__free(spec);
4330ab26
CMN
1620 }
1621 git_vector_clear(&remote->refspecs);
4330ab26
CMN
1622}
1623
266af6d8
CMN
1624static int add_and_dwim(git_remote *remote, const char *str, int push)
1625{
1626 git_refspec *spec;
1627 git_vector *vec;
1628
1629 if (add_refspec(remote, str, !push) < 0)
1630 return -1;
1631
1632 vec = &remote->refspecs;
1633 spec = git_vector_get(vec, vec->length - 1);
1634 return git_refspec__dwim_one(&remote->active_refspecs, spec, &remote->refs);
1635}
1636
bc6374ea 1637int git_remote_add_fetch(git_remote *remote, const char *refspec)
4330ab26 1638{
266af6d8 1639 return add_and_dwim(remote, refspec, false);
4330ab26
CMN
1640}
1641
bc6374ea 1642int git_remote_add_push(git_remote *remote, const char *refspec)
4330ab26 1643{
266af6d8
CMN
1644 return add_and_dwim(remote, refspec, true);
1645}
1646
1647static int set_refspecs(git_remote *remote, git_strarray *array, int push)
1648{
1649 git_vector *vec = &remote->refspecs;
1650 git_refspec *spec;
1651 size_t i;
1652
1653 /* Start by removing any refspecs of the same type */
1654 for (i = 0; i < vec->length; i++) {
1655 spec = git_vector_get(vec, i);
1656 if (spec->push != push)
1657 continue;
1658
1659 git_refspec__free(spec);
1660 git__free(spec);
1661 git_vector_remove(vec, i);
1662 i--;
1663 }
1664
1665 /* And now we add the new ones */
1666
1667 for (i = 0; i < array->count; i++) {
1668 if (add_refspec(remote, array->strings[i], !push) < 0)
1669 return -1;
1670 }
1671
1672 free_refspecs(&remote->active_refspecs);
1673 git_vector_clear(&remote->active_refspecs);
1674
1675 return dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs);
1676}
1677
1678int git_remote_set_fetch_refspecs(git_remote *remote, git_strarray *array)
1679{
1680 return set_refspecs(remote, array, false);
1681}
1682
1683int git_remote_set_push_refspecs(git_remote *remote, git_strarray *array)
1684{
1685 return set_refspecs(remote, array, true);
4330ab26 1686}
bc6374ea 1687
11f6ad5f 1688static int copy_refspecs(git_strarray *array, const git_remote *remote, unsigned int push)
bc6374ea
CMN
1689{
1690 size_t i;
1691 git_vector refspecs;
1692 git_refspec *spec;
1693 char *dup;
1694
1695 if (git_vector_init(&refspecs, remote->refspecs.length, NULL) < 0)
1696 return -1;
1697
1698 git_vector_foreach(&remote->refspecs, i, spec) {
1699 if (spec->push != push)
1700 continue;
1701
1be680c4 1702 if ((dup = git__strdup(spec->string)) == NULL)
bc6374ea 1703 goto on_error;
bc6374ea
CMN
1704
1705 if (git_vector_insert(&refspecs, dup) < 0) {
1706 git__free(dup);
1707 goto on_error;
1708 }
1709 }
1710
1711 array->strings = (char **)refspecs.contents;
1712 array->count = refspecs.length;
1713
1714 return 0;
1715
1716on_error:
9cfce273 1717 git_vector_free_deep(&refspecs);
bc6374ea
CMN
1718
1719 return -1;
1720}
1721
11f6ad5f 1722int git_remote_get_fetch_refspecs(git_strarray *array, const git_remote *remote)
bc6374ea
CMN
1723{
1724 return copy_refspecs(array, remote, false);
1725}
1726
11f6ad5f 1727int git_remote_get_push_refspecs(git_strarray *array, const git_remote *remote)
bc6374ea
CMN
1728{
1729 return copy_refspecs(array, remote, true);
1730}
1ffd0806 1731
11f6ad5f 1732size_t git_remote_refspec_count(const git_remote *remote)
1ffd0806
CMN
1733{
1734 return remote->refspecs.length;
1735}
1736
11f6ad5f 1737const git_refspec *git_remote_get_refspec(const git_remote *remote, size_t n)
1ffd0806
CMN
1738{
1739 return git_vector_get(&remote->refspecs, n);
1740}
b9f81997 1741
bc91347b 1742int git_remote_init_callbacks(git_remote_callbacks *opts, unsigned int version)
b9f81997 1743{
bc91347b
RB
1744 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
1745 opts, version, git_remote_callbacks, GIT_REMOTE_CALLBACKS_INIT);
1746 return 0;
b9f81997 1747}
40e48ea4 1748
5cdac19c
CMN
1749/* asserts a branch.<foo>.remote format */
1750static const char *name_offset(size_t *len_out, const char *name)
40e48ea4 1751{
5cdac19c
CMN
1752 size_t prefix_len;
1753 const char *dot;
40e48ea4 1754
5cdac19c
CMN
1755 prefix_len = strlen("remote.");
1756 dot = strchr(name + prefix_len, '.');
40e48ea4 1757
5cdac19c 1758 assert(dot);
40e48ea4 1759
5cdac19c
CMN
1760 *len_out = dot - name - prefix_len;
1761 return name + prefix_len;
40e48ea4 1762}
1763
1764static int remove_branch_config_related_entries(
1765 git_repository *repo,
1766 const char *remote_name)
1767{
1768 int error;
1769 git_config *config;
5cdac19c
CMN
1770 git_config_entry *entry;
1771 git_config_iterator *iter;
1772 git_buf buf = GIT_BUF_INIT;
40e48ea4 1773
1774 if ((error = git_repository_config__weakptr(&config, repo)) < 0)
1775 return error;
1776
5cdac19c 1777 if ((error = git_config_iterator_glob_new(&iter, config, "branch\\..+\\.remote")) < 0)
40e48ea4 1778 return error;
1779
5cdac19c
CMN
1780 /* find any branches with us as upstream and remove that config */
1781 while ((error = git_config_next(&entry, iter)) == 0) {
1782 const char *branch;
1783 size_t branch_len;
40e48ea4 1784
5cdac19c
CMN
1785 if (strcmp(remote_name, entry->value))
1786 continue;
40e48ea4 1787
5cdac19c 1788 branch = name_offset(&branch_len, entry->name);
40e48ea4 1789
5cdac19c
CMN
1790 git_buf_clear(&buf);
1791 if (git_buf_printf(&buf, "branch.%.*s.merge", (int)branch_len, branch) < 0)
1792 break;
1793
1794 if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0)
1795 break;
1796
1797 git_buf_clear(&buf);
1798 if (git_buf_printf(&buf, "branch.%.*s.remote", (int)branch_len, branch) < 0)
1799 break;
1800
1801 if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0)
1802 break;
40e48ea4 1803 }
1804
5cdac19c
CMN
1805 if (error == GIT_ITEROVER)
1806 error = 0;
1807
1808 git_buf_free(&buf);
1809 git_config_iterator_free(iter);
40e48ea4 1810 return error;
1811}
1812
8a9419aa 1813static int remove_refs(git_repository *repo, const git_refspec *spec)
ec8a949a 1814{
8a9419aa
CMN
1815 git_reference_iterator *iter = NULL;
1816 git_vector refs;
ec8a949a 1817 const char *name;
8a9419aa 1818 char *dup;
ec8a949a 1819 int error;
8a9419aa 1820 size_t i;
ec8a949a 1821
8a9419aa 1822 if ((error = git_vector_init(&refs, 8, NULL)) < 0)
ec8a949a
CMN
1823 return error;
1824
8a9419aa
CMN
1825 if ((error = git_reference_iterator_new(&iter, repo)) < 0)
1826 goto cleanup;
1827
ec8a949a 1828 while ((error = git_reference_next_name(&name, iter)) == 0) {
8a9419aa
CMN
1829 if (!git_refspec_dst_matches(spec, name))
1830 continue;
1831
1832 dup = git__strdup(name);
1833 if (!dup) {
1834 error = -1;
1835 goto cleanup;
1836 }
ec8a949a 1837
8a9419aa
CMN
1838 if ((error = git_vector_insert(&refs, dup)) < 0)
1839 goto cleanup;
1840 }
ec8a949a
CMN
1841 if (error == GIT_ITEROVER)
1842 error = 0;
8a9419aa
CMN
1843 if (error < 0)
1844 goto cleanup;
1845
1846 git_vector_foreach(&refs, i, name) {
1847 if ((error = git_reference_remove(repo, name)) < 0)
1848 break;
1849 }
ec8a949a 1850
8a9419aa
CMN
1851cleanup:
1852 git_reference_iterator_free(iter);
1853 git_vector_foreach(&refs, i, dup) {
1854 git__free(dup);
1855 }
1856 git_vector_free(&refs);
ec8a949a
CMN
1857 return error;
1858}
1859
1860static int remove_remote_tracking(git_repository *repo, const char *remote_name)
1861{
1862 git_remote *remote;
1863 int error;
1864 size_t i, count;
1865
1866 /* we want to use what's on the config, regardless of changes to the instance in memory */
1867 if ((error = git_remote_load(&remote, repo, remote_name)) < 0)
1868 return error;
1869
1870 count = git_remote_refspec_count(remote);
1871 for (i = 0; i < count; i++) {
1872 const git_refspec *refspec = git_remote_get_refspec(remote, i);
1873
1874 /* shouldn't ever actually happen */
1875 if (refspec == NULL)
1876 continue;
1877
8a9419aa 1878 if ((error = remove_refs(repo, refspec)) < 0)
ec8a949a
CMN
1879 break;
1880 }
1881
1882 git_remote_free(remote);
1883 return error;
1884}
1885
40e48ea4 1886int git_remote_delete(git_remote *remote)
1887{
1888 int error;
1889 git_repository *repo;
1890
1891 assert(remote);
1892
1893 if (!remote->name) {
1894 giterr_set(GITERR_INVALID, "Can't delete an anonymous remote.");
1895 return -1;
1896 }
1897
1898 repo = git_remote_owner(remote);
1899
40e48ea4 1900 if ((error = remove_branch_config_related_entries(repo,
1901 git_remote_name(remote))) < 0)
1902 return error;
1903
ec8a949a
CMN
1904 if ((error = remove_remote_tracking(repo, git_remote_name(remote))) < 0)
1905 return error;
1906
1907 if ((error = rename_remote_config_section(
1908 repo, git_remote_name(remote), NULL)) < 0)
1909 return error;
1910
40e48ea4 1911 git_remote_free(remote);
1912
1913 return 0;
1914}
d22db24f
CMN
1915
1916int git_remote_default_branch(git_buf *out, git_remote *remote)
1917{
1918 const git_remote_head **heads;
1919 const git_remote_head *guess = NULL;
1920 const git_oid *head_id;
1921 size_t heads_len, i;
1922 int error;
1923
1924 if ((error = git_remote_ls(&heads, &heads_len, remote)) < 0)
1925 return error;
1926
1927 if (heads_len == 0)
1928 return GIT_ENOTFOUND;
1929
1930 git_buf_sanitize(out);
1931 /* the first one must be HEAD so if that has the symref info, we're done */
1932 if (heads[0]->symref_target)
1933 return git_buf_puts(out, heads[0]->symref_target);
1934
1935 /*
1936 * If there's no symref information, we have to look over them
1937 * and guess. We return the first match unless the master
1938 * branch is a candidate. Then we return the master branch.
1939 */
1940 head_id = &heads[0]->oid;
1941
1942 for (i = 1; i < heads_len; i++) {
1943 if (git_oid_cmp(head_id, &heads[i]->oid))
1944 continue;
1945
1946 if (!guess) {
1947 guess = heads[i];
1948 continue;
1949 }
1950
1951 if (!git__strcmp(GIT_REFS_HEADS_MASTER_FILE, heads[i]->name)) {
1952 guess = heads[i];
1953 break;
1954 }
1955 }
1956
1957 if (!guess)
1958 return GIT_ENOTFOUND;
1959
1960 return git_buf_puts(out, guess->name);
1961}