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