File Coverage

deps/libgit2/src/branch.c
Criterion Covered Total %
statement 139 350 39.7
branch 46 206 22.3
condition n/a
subroutine n/a
pod n/a
total 185 556 33.2


line stmt bran cond sub pod time code
1             /*
2             * Copyright (C) the libgit2 contributors. All rights reserved.
3             *
4             * This file is part of libgit2, distributed under the GNU GPL v2 with
5             * a Linking Exception. For full terms see the included COPYING file.
6             */
7              
8             #include "branch.h"
9              
10             #include "commit.h"
11             #include "tag.h"
12             #include "config.h"
13             #include "refspec.h"
14             #include "refs.h"
15             #include "remote.h"
16             #include "annotated_commit.h"
17             #include "worktree.h"
18              
19             #include "git2/branch.h"
20              
21 15           static int retrieve_branch_reference(
22             git_reference **branch_reference_out,
23             git_repository *repo,
24             const char *branch_name,
25             bool is_remote)
26             {
27 15           git_reference *branch = NULL;
28 15           int error = 0;
29             char *prefix;
30 15           git_buf ref_name = GIT_BUF_INIT;
31              
32 15 100         prefix = is_remote ? GIT_REFS_REMOTES_DIR : GIT_REFS_HEADS_DIR;
33              
34 15 50         if ((error = git_buf_joinpath(&ref_name, prefix, branch_name)) < 0)
35             /* OOM */;
36 15 100         else if ((error = git_reference_lookup(&branch, repo, ref_name.ptr)) < 0)
37 2 100         git_error_set(
38             GIT_ERROR_REFERENCE, "cannot locate %s branch '%s'",
39             is_remote ? "remote-tracking" : "local", branch_name);
40              
41 15           *branch_reference_out = branch; /* will be NULL on error */
42              
43 15           git_buf_dispose(&ref_name);
44 15           return error;
45             }
46              
47 0           static int not_a_local_branch(const char *reference_name)
48             {
49 0           git_error_set(
50             GIT_ERROR_INVALID,
51             "reference '%s' is not a local branch.", reference_name);
52 0           return -1;
53             }
54              
55 16           static int create_branch(
56             git_reference **ref_out,
57             git_repository *repository,
58             const char *branch_name,
59             const git_commit *commit,
60             const char *from,
61             int force)
62             {
63 16           int is_unmovable_head = 0;
64 16           git_reference *branch = NULL;
65 16           git_buf canonical_branch_name = GIT_BUF_INIT,
66 16           log_message = GIT_BUF_INIT;
67 16           int error = -1;
68 16           int bare = git_repository_is_bare(repository);
69              
70 16 50         assert(branch_name && commit && ref_out);
    50          
    50          
71 16 50         assert(git_object_owner((const git_object *)commit) == repository);
72              
73 16 50         if (!git__strcmp(branch_name, "HEAD")) {
74 0           git_error_set(GIT_ERROR_REFERENCE, "'HEAD' is not a valid branch name");
75 0           error = -1;
76 0           goto cleanup;
77             }
78              
79 16 50         if (force && !bare && git_branch_lookup(&branch, repository, branch_name, GIT_BRANCH_LOCAL) == 0) {
    0          
    0          
80 0           error = git_branch_is_head(branch);
81 0           git_reference_free(branch);
82 0           branch = NULL;
83              
84 0 0         if (error < 0)
85 0           goto cleanup;
86              
87 0           is_unmovable_head = error;
88             }
89              
90 16 50         if (is_unmovable_head && force) {
    0          
91 0           git_error_set(GIT_ERROR_REFERENCE, "cannot force update branch '%s' as it is "
92             "the current HEAD of the repository.", branch_name);
93 0           error = -1;
94 0           goto cleanup;
95             }
96              
97 16 50         if (git_buf_joinpath(&canonical_branch_name, GIT_REFS_HEADS_DIR, branch_name) < 0)
98 0           goto cleanup;
99              
100 16 50         if (git_buf_printf(&log_message, "branch: Created from %s", from) < 0)
101 0           goto cleanup;
102              
103 16           error = git_reference_create(&branch, repository,
104             git_buf_cstr(&canonical_branch_name), git_commit_id(commit), force,
105             git_buf_cstr(&log_message));
106              
107 16 50         if (!error)
108 16           *ref_out = branch;
109              
110             cleanup:
111 16           git_buf_dispose(&canonical_branch_name);
112 16           git_buf_dispose(&log_message);
113 16           return error;
114             }
115              
116 16           int git_branch_create(
117             git_reference **ref_out,
118             git_repository *repository,
119             const char *branch_name,
120             const git_commit *commit,
121             int force)
122             {
123 16           return create_branch(ref_out, repository, branch_name, commit, git_oid_tostr_s(git_commit_id(commit)), force);
124             }
125              
126 0           int git_branch_create_from_annotated(
127             git_reference **ref_out,
128             git_repository *repository,
129             const char *branch_name,
130             const git_annotated_commit *commit,
131             int force)
132             {
133 0           return create_branch(ref_out,
134 0           repository, branch_name, commit->commit, commit->description, force);
135             }
136              
137 17           static int branch_equals(git_repository *repo, const char *path, void *payload)
138             {
139 17           git_reference *branch = (git_reference *) payload;
140 17           git_reference *head = NULL;
141 17           int equal = 0;
142              
143 34           if (git_reference__read_head(&head, repo, path) < 0 ||
144 17           git_reference_type(head) != GIT_REFERENCE_SYMBOLIC)
145             goto done;
146              
147 17           equal = !git__strcmp(head->target.symbolic, branch->name);
148              
149             done:
150 17           git_reference_free(head);
151 17           return equal;
152             }
153              
154 17           int git_branch_is_checked_out(const git_reference *branch)
155             {
156             git_repository *repo;
157 17           int flags = 0;
158              
159 17 50         assert(branch);
160              
161 17 50         if (!git_reference_is_branch(branch))
162 0           return 0;
163              
164 17           repo = git_reference_owner(branch);
165              
166 17 50         if (git_repository_is_bare(repo))
167 0           flags |= GIT_REPOSITORY_FOREACH_HEAD_SKIP_REPO;
168              
169 17           return git_repository_foreach_head(repo, branch_equals, flags, (void *) branch) == 1;
170             }
171              
172 0           int git_branch_delete(git_reference *branch)
173             {
174             int is_head;
175 0           git_buf config_section = GIT_BUF_INIT;
176 0           int error = -1;
177              
178 0 0         assert(branch);
179              
180 0 0         if (!git_reference_is_branch(branch) && !git_reference_is_remote(branch)) {
    0          
181 0           git_error_set(GIT_ERROR_INVALID, "reference '%s' is not a valid branch.",
182             git_reference_name(branch));
183 0           return GIT_ENOTFOUND;
184             }
185              
186 0 0         if ((is_head = git_branch_is_head(branch)) < 0)
187 0           return is_head;
188              
189 0 0         if (is_head) {
190 0           git_error_set(GIT_ERROR_REFERENCE, "cannot delete branch '%s' as it is "
191             "the current HEAD of the repository.", git_reference_name(branch));
192 0           return -1;
193             }
194              
195 0 0         if (git_reference_is_branch(branch) && git_branch_is_checked_out(branch)) {
    0          
196 0           git_error_set(GIT_ERROR_REFERENCE, "Cannot delete branch '%s' as it is "
197             "the current HEAD of a linked repository.", git_reference_name(branch));
198 0           return -1;
199             }
200              
201 0 0         if (git_buf_join(&config_section, '.', "branch",
202 0           git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR)) < 0)
203 0           goto on_error;
204              
205 0 0         if (git_config_rename_section(
206             git_reference_owner(branch), git_buf_cstr(&config_section), NULL) < 0)
207 0           goto on_error;
208              
209 0           error = git_reference_delete(branch);
210              
211             on_error:
212 0           git_buf_dispose(&config_section);
213 0           return error;
214             }
215              
216             typedef struct {
217             git_reference_iterator *iter;
218             unsigned int flags;
219             } branch_iter;
220              
221 6           int git_branch_next(git_reference **out, git_branch_t *out_type, git_branch_iterator *_iter)
222             {
223 6           branch_iter *iter = (branch_iter *) _iter;
224             git_reference *ref;
225             int error;
226              
227 8 100         while ((error = git_reference_next(&ref, iter->iter)) == 0) {
228 12           if ((iter->flags & GIT_BRANCH_LOCAL) &&
229 6           !git__prefixcmp(ref->name, GIT_REFS_HEADS_DIR)) {
230 4           *out = ref;
231 4           *out_type = GIT_BRANCH_LOCAL;
232              
233 4           return 0;
234 3           } else if ((iter->flags & GIT_BRANCH_REMOTE) &&
235 1           !git__prefixcmp(ref->name, GIT_REFS_REMOTES_DIR)) {
236 0           *out = ref;
237 0           *out_type = GIT_BRANCH_REMOTE;
238              
239 0           return 0;
240             } else {
241 2           git_reference_free(ref);
242             }
243             }
244              
245 6           return error;
246             }
247              
248 2           int git_branch_iterator_new(
249             git_branch_iterator **out,
250             git_repository *repo,
251             git_branch_t list_flags)
252             {
253             branch_iter *iter;
254              
255 2           iter = git__calloc(1, sizeof(branch_iter));
256 2 50         GIT_ERROR_CHECK_ALLOC(iter);
257              
258 2           iter->flags = list_flags;
259              
260 2 50         if (git_reference_iterator_new(&iter->iter, repo) < 0) {
261 0           git__free(iter);
262 0           return -1;
263             }
264              
265 2           *out = (git_branch_iterator *) iter;
266              
267 2           return 0;
268             }
269              
270 2           void git_branch_iterator_free(git_branch_iterator *_iter)
271             {
272 2           branch_iter *iter = (branch_iter *) _iter;
273              
274 2 50         if (iter == NULL)
275 0           return;
276              
277 2           git_reference_iterator_free(iter->iter);
278 2           git__free(iter);
279             }
280              
281 1           int git_branch_move(
282             git_reference **out,
283             git_reference *branch,
284             const char *new_branch_name,
285             int force)
286             {
287 1           git_buf new_reference_name = GIT_BUF_INIT,
288 1           old_config_section = GIT_BUF_INIT,
289 1           new_config_section = GIT_BUF_INIT,
290 1           log_message = GIT_BUF_INIT;
291             int error;
292              
293 1 50         assert(branch && new_branch_name);
    50          
294              
295 1 50         if (!git_reference_is_branch(branch))
296 0           return not_a_local_branch(git_reference_name(branch));
297              
298 1 50         if ((error = git_buf_joinpath(&new_reference_name, GIT_REFS_HEADS_DIR, new_branch_name)) < 0)
299 0           goto done;
300              
301 1 50         if ((error = git_buf_printf(&log_message, "branch: renamed %s to %s",
302             git_reference_name(branch), git_buf_cstr(&new_reference_name))) < 0)
303 0           goto done;
304              
305             /* first update ref then config so failure won't trash config */
306              
307 1           error = git_reference_rename(
308             out, branch, git_buf_cstr(&new_reference_name), force,
309             git_buf_cstr(&log_message));
310 1 50         if (error < 0)
311 0           goto done;
312              
313 1           git_buf_join(&old_config_section, '.', "branch",
314 1           git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR));
315 1           git_buf_join(&new_config_section, '.', "branch", new_branch_name);
316              
317 1           error = git_config_rename_section(
318             git_reference_owner(branch),
319             git_buf_cstr(&old_config_section),
320             git_buf_cstr(&new_config_section));
321              
322             done:
323 1           git_buf_dispose(&new_reference_name);
324 1           git_buf_dispose(&old_config_section);
325 1           git_buf_dispose(&new_config_section);
326 1           git_buf_dispose(&log_message);
327              
328 1           return error;
329             }
330              
331 15           int git_branch_lookup(
332             git_reference **ref_out,
333             git_repository *repo,
334             const char *branch_name,
335             git_branch_t branch_type)
336             {
337 15           int error = -1;
338 15 50         assert(ref_out && repo && branch_name);
    50          
    50          
339              
340 15           switch (branch_type) {
341             case GIT_BRANCH_LOCAL:
342             case GIT_BRANCH_REMOTE:
343 15           error = retrieve_branch_reference(ref_out, repo, branch_name, branch_type == GIT_BRANCH_REMOTE);
344 15           break;
345             case GIT_BRANCH_ALL:
346 0           error = retrieve_branch_reference(ref_out, repo, branch_name, false);
347 0 0         if (error == GIT_ENOTFOUND)
348 0           error = retrieve_branch_reference(ref_out, repo, branch_name, true);
349 0           break;
350             default:
351 0           assert(false);
352             }
353 15           return error;
354             }
355              
356 0           int git_branch_name(
357             const char **out,
358             const git_reference *ref)
359             {
360             const char *branch_name;
361              
362 0 0         assert(out && ref);
    0          
363              
364 0           branch_name = ref->name;
365              
366 0 0         if (git_reference_is_branch(ref)) {
367 0           branch_name += strlen(GIT_REFS_HEADS_DIR);
368 0 0         } else if (git_reference_is_remote(ref)) {
369 0           branch_name += strlen(GIT_REFS_REMOTES_DIR);
370             } else {
371 0           git_error_set(GIT_ERROR_INVALID,
372 0           "reference '%s' is neither a local nor a remote branch.", ref->name);
373 0           return -1;
374             }
375 0           *out = branch_name;
376 0           return 0;
377             }
378              
379 4           static int retrieve_upstream_configuration(
380             git_buf *out,
381             const git_config *config,
382             const char *canonical_branch_name,
383             const char *format)
384             {
385 4           git_buf buf = GIT_BUF_INIT;
386             int error;
387              
388 4 50         if (git_buf_printf(&buf, format,
389             canonical_branch_name + strlen(GIT_REFS_HEADS_DIR)) < 0)
390 0           return -1;
391              
392 4           error = git_config_get_string_buf(out, config, git_buf_cstr(&buf));
393 4           git_buf_dispose(&buf);
394 4           return error;
395             }
396              
397 4           int git_branch_upstream_name(
398             git_buf *out,
399             git_repository *repo,
400             const char *refname)
401             {
402 4           git_buf remote_name = GIT_BUF_INIT;
403 4           git_buf merge_name = GIT_BUF_INIT;
404 4           git_buf buf = GIT_BUF_INIT;
405 4           int error = -1;
406 4           git_remote *remote = NULL;
407             const git_refspec *refspec;
408             git_config *config;
409              
410 4 50         assert(out && refname);
    50          
411              
412 4           git_buf_sanitize(out);
413              
414 4 50         if (!git_reference__is_branch(refname))
415 0           return not_a_local_branch(refname);
416              
417 4 50         if ((error = git_repository_config_snapshot(&config, repo)) < 0)
418 0           return error;
419              
420 4 50         if ((error = retrieve_upstream_configuration(
421             &remote_name, config, refname, "branch.%s.remote")) < 0)
422 4           goto cleanup;
423              
424 0 0         if ((error = retrieve_upstream_configuration(
425             &merge_name, config, refname, "branch.%s.merge")) < 0)
426 0           goto cleanup;
427              
428 0 0         if (git_buf_len(&remote_name) == 0 || git_buf_len(&merge_name) == 0) {
    0          
429 0           git_error_set(GIT_ERROR_REFERENCE,
430             "branch '%s' does not have an upstream", refname);
431 0           error = GIT_ENOTFOUND;
432 0           goto cleanup;
433             }
434              
435 0 0         if (strcmp(".", git_buf_cstr(&remote_name)) != 0) {
436 0 0         if ((error = git_remote_lookup(&remote, repo, git_buf_cstr(&remote_name))) < 0)
437 0           goto cleanup;
438              
439 0           refspec = git_remote__matching_refspec(remote, git_buf_cstr(&merge_name));
440 0 0         if (!refspec) {
441 0           error = GIT_ENOTFOUND;
442 0           goto cleanup;
443             }
444              
445 0 0         if (git_refspec_transform(&buf, refspec, git_buf_cstr(&merge_name)) < 0)
446 0           goto cleanup;
447             } else
448 0 0         if (git_buf_set(&buf, git_buf_cstr(&merge_name), git_buf_len(&merge_name)) < 0)
449 0           goto cleanup;
450              
451 0           error = git_buf_set(out, git_buf_cstr(&buf), git_buf_len(&buf));
452              
453             cleanup:
454 4           git_config_free(config);
455 4           git_remote_free(remote);
456 4           git_buf_dispose(&remote_name);
457 4           git_buf_dispose(&merge_name);
458 4           git_buf_dispose(&buf);
459 4           return error;
460             }
461              
462 0           int git_branch_upstream_remote(git_buf *buf, git_repository *repo, const char *refname)
463             {
464             int error;
465             git_config *cfg;
466              
467 0 0         if (!git_reference__is_branch(refname))
468 0           return not_a_local_branch(refname);
469              
470 0 0         if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
471 0           return error;
472              
473 0           git_buf_sanitize(buf);
474              
475 0 0         if ((error = retrieve_upstream_configuration(buf, cfg, refname, "branch.%s.remote")) < 0)
476 0           return error;
477              
478 0 0         if (git_buf_len(buf) == 0) {
479 0           git_error_set(GIT_ERROR_REFERENCE, "branch '%s' does not have an upstream remote", refname);
480 0           error = GIT_ENOTFOUND;
481 0           git_buf_clear(buf);
482             }
483              
484 0           return error;
485             }
486              
487 0           int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refname)
488             {
489 0           git_strarray remote_list = {0};
490             size_t i;
491             git_remote *remote;
492             const git_refspec *fetchspec;
493 0           int error = 0;
494 0           char *remote_name = NULL;
495              
496 0 0         assert(buf && repo && refname);
    0          
    0          
497              
498 0           git_buf_sanitize(buf);
499              
500             /* Verify that this is a remote branch */
501 0 0         if (!git_reference__is_remote(refname)) {
502 0           git_error_set(GIT_ERROR_INVALID, "reference '%s' is not a remote branch.",
503             refname);
504 0           error = GIT_ERROR;
505 0           goto cleanup;
506             }
507              
508             /* Get the remotes */
509 0 0         if ((error = git_remote_list(&remote_list, repo)) < 0)
510 0           goto cleanup;
511              
512             /* Find matching remotes */
513 0 0         for (i = 0; i < remote_list.count; i++) {
514 0 0         if ((error = git_remote_lookup(&remote, repo, remote_list.strings[i])) < 0)
515 0           continue;
516              
517 0           fetchspec = git_remote__matching_dst_refspec(remote, refname);
518 0 0         if (fetchspec) {
519             /* If we have not already set out yet, then set
520             * it to the matching remote name. Otherwise
521             * multiple remotes match this reference, and it
522             * is ambiguous. */
523 0 0         if (!remote_name) {
524 0           remote_name = remote_list.strings[i];
525             } else {
526 0           git_remote_free(remote);
527              
528 0           git_error_set(GIT_ERROR_REFERENCE,
529             "reference '%s' is ambiguous", refname);
530 0           error = GIT_EAMBIGUOUS;
531 0           goto cleanup;
532             }
533             }
534              
535 0           git_remote_free(remote);
536             }
537              
538 0 0         if (remote_name) {
539 0           git_buf_clear(buf);
540 0           error = git_buf_puts(buf, remote_name);
541             } else {
542 0           git_error_set(GIT_ERROR_REFERENCE,
543             "could not determine remote for '%s'", refname);
544 0           error = GIT_ENOTFOUND;
545             }
546              
547             cleanup:
548 0 0         if (error < 0)
549 0           git_buf_dispose(buf);
550              
551 0           git_strarray_free(&remote_list);
552 0           return error;
553             }
554              
555 2           int git_branch_upstream(
556             git_reference **tracking_out,
557             const git_reference *branch)
558             {
559             int error;
560 2           git_buf tracking_name = GIT_BUF_INIT;
561              
562 2 50         if ((error = git_branch_upstream_name(&tracking_name,
563             git_reference_owner(branch), git_reference_name(branch))) < 0)
564 2           return error;
565              
566 0           error = git_reference_lookup(
567             tracking_out,
568             git_reference_owner(branch),
569             git_buf_cstr(&tracking_name));
570              
571 0           git_buf_dispose(&tracking_name);
572 2           return error;
573             }
574              
575 0           static int unset_upstream(git_config *config, const char *shortname)
576             {
577 0           git_buf buf = GIT_BUF_INIT;
578              
579 0 0         if (git_buf_printf(&buf, "branch.%s.remote", shortname) < 0)
580 0           return -1;
581              
582 0 0         if (git_config_delete_entry(config, git_buf_cstr(&buf)) < 0)
583 0           goto on_error;
584              
585 0           git_buf_clear(&buf);
586 0 0         if (git_buf_printf(&buf, "branch.%s.merge", shortname) < 0)
587 0           goto on_error;
588              
589 0 0         if (git_config_delete_entry(config, git_buf_cstr(&buf)) < 0)
590 0           goto on_error;
591              
592 0           git_buf_dispose(&buf);
593 0           return 0;
594              
595             on_error:
596 0           git_buf_dispose(&buf);
597 0           return -1;
598             }
599              
600 0           int git_branch_set_upstream(git_reference *branch, const char *branch_name)
601             {
602 0           git_buf key = GIT_BUF_INIT, remote_name = GIT_BUF_INIT, merge_refspec = GIT_BUF_INIT;
603             git_reference *upstream;
604             git_repository *repo;
605 0           git_remote *remote = NULL;
606             git_config *config;
607             const char *refname, *shortname;
608             int local, error;
609             const git_refspec *fetchspec;
610              
611 0           refname = git_reference_name(branch);
612 0 0         if (!git_reference__is_branch(refname))
613 0           return not_a_local_branch(refname);
614              
615 0 0         if (git_repository_config__weakptr(&config, git_reference_owner(branch)) < 0)
616 0           return -1;
617              
618 0           shortname = refname + strlen(GIT_REFS_HEADS_DIR);
619              
620             /* We're unsetting, delegate and bail-out */
621 0 0         if (branch_name == NULL)
622 0           return unset_upstream(config, shortname);
623              
624 0           repo = git_reference_owner(branch);
625              
626             /* First we need to resolve name to a branch */
627 0 0         if (git_branch_lookup(&upstream, repo, branch_name, GIT_BRANCH_LOCAL) == 0)
628 0           local = 1;
629 0 0         else if (git_branch_lookup(&upstream, repo, branch_name, GIT_BRANCH_REMOTE) == 0)
630 0           local = 0;
631             else {
632 0           git_error_set(GIT_ERROR_REFERENCE,
633             "cannot set upstream for branch '%s'", shortname);
634 0           return GIT_ENOTFOUND;
635             }
636              
637             /*
638             * If it's a local-tracking branch, its remote is "." (as "the local
639             * repository"), and the branch name is simply the refname.
640             * Otherwise we need to figure out what the remote-tracking branch's
641             * name on the remote is and use that.
642             */
643 0 0         if (local)
644 0           error = git_buf_puts(&remote_name, ".");
645             else
646 0           error = git_branch_remote_name(&remote_name, repo, git_reference_name(upstream));
647              
648 0 0         if (error < 0)
649 0           goto on_error;
650              
651             /* Update the upsteam branch config with the new name */
652 0 0         if (git_buf_printf(&key, "branch.%s.remote", shortname) < 0)
653 0           goto on_error;
654              
655 0 0         if (git_config_set_string(config, git_buf_cstr(&key), git_buf_cstr(&remote_name)) < 0)
656 0           goto on_error;
657              
658 0 0         if (local) {
659             /* A local branch uses the upstream refname directly */
660 0 0         if (git_buf_puts(&merge_refspec, git_reference_name(upstream)) < 0)
661 0           goto on_error;
662             } else {
663             /* We transform the upstream branch name according to the remote's refspecs */
664 0 0         if (git_remote_lookup(&remote, repo, git_buf_cstr(&remote_name)) < 0)
665 0           goto on_error;
666              
667 0           fetchspec = git_remote__matching_dst_refspec(remote, git_reference_name(upstream));
668 0 0         if (!fetchspec || git_refspec_rtransform(&merge_refspec, fetchspec, git_reference_name(upstream)) < 0)
    0          
669             goto on_error;
670              
671 0           git_remote_free(remote);
672 0           remote = NULL;
673             }
674              
675             /* Update the merge branch config with the refspec */
676 0           git_buf_clear(&key);
677 0 0         if (git_buf_printf(&key, "branch.%s.merge", shortname) < 0)
678 0           goto on_error;
679              
680 0 0         if (git_config_set_string(config, git_buf_cstr(&key), git_buf_cstr(&merge_refspec)) < 0)
681 0           goto on_error;
682              
683 0           git_reference_free(upstream);
684 0           git_buf_dispose(&key);
685 0           git_buf_dispose(&remote_name);
686 0           git_buf_dispose(&merge_refspec);
687              
688 0           return 0;
689              
690             on_error:
691 0           git_reference_free(upstream);
692 0           git_buf_dispose(&key);
693 0           git_buf_dispose(&remote_name);
694 0           git_buf_dispose(&merge_refspec);
695 0           git_remote_free(remote);
696              
697 0           return -1;
698             }
699              
700 2           int git_branch_is_head(
701             const git_reference *branch)
702             {
703             git_reference *head;
704 2           bool is_same = false;
705             int error;
706              
707 2 50         assert(branch);
708              
709 2 50         if (!git_reference_is_branch(branch))
710 0           return false;
711              
712 2           error = git_repository_head(&head, git_reference_owner(branch));
713              
714 2 50         if (error == GIT_EUNBORNBRANCH || error == GIT_ENOTFOUND)
    50          
715 0           return false;
716              
717 2 50         if (error < 0)
718 0           return -1;
719              
720 2           is_same = strcmp(
721             git_reference_name(branch),
722             git_reference_name(head)) == 0;
723              
724 2           git_reference_free(head);
725              
726 2           return is_same;
727             }