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