branch.c 19.5 KB
Newer Older
1
/*
Edward Thomson committed
2
 * Copyright (C) the libgit2 contributors. All rights reserved.
3 4 5 6 7
 *
 * This file is part of libgit2, distributed under the GNU GPL v2 with
 * a Linking Exception. For full terms see the included COPYING file.
 */

8 9
#include "branch.h"

10
#include "buf.h"
11 12
#include "commit.h"
#include "tag.h"
13 14
#include "config.h"
#include "refspec.h"
15
#include "refs.h"
16
#include "remote.h"
17
#include "annotated_commit.h"
18
#include "worktree.h"
19

20 21
#include "git2/branch.h"

22 23 24 25
static int retrieve_branch_reference(
	git_reference **branch_reference_out,
	git_repository *repo,
	const char *branch_name,
26
	bool is_remote)
27
{
Russell Belfer committed
28 29
	git_reference *branch = NULL;
	int error = 0;
30
	char *prefix;
31
	git_str ref_name = GIT_STR_INIT;
32 33 34

	prefix = is_remote ? GIT_REFS_REMOTES_DIR : GIT_REFS_HEADS_DIR;

35
	if ((error = git_str_joinpath(&ref_name, prefix, branch_name)) < 0)
Russell Belfer committed
36 37
		/* OOM */;
	else if ((error = git_reference_lookup(&branch, repo, ref_name.ptr)) < 0)
38 39
		git_error_set(
			GIT_ERROR_REFERENCE, "cannot locate %s branch '%s'",
Russell Belfer committed
40
			is_remote ? "remote-tracking" : "local", branch_name);
41

Russell Belfer committed
42
	*branch_reference_out = branch; /* will be NULL on error */
43

44
	git_str_dispose(&ref_name);
45 46 47
	return error;
}

48
static int not_a_local_branch(const char *reference_name)
49
{
50 51
	git_error_set(
		GIT_ERROR_INVALID,
52
		"reference '%s' is not a local branch.", reference_name);
53 54 55
	return -1;
}

56
static int create_branch(
57 58 59 60
	git_reference **ref_out,
	git_repository *repository,
	const char *branch_name,
	const git_commit *commit,
61
	const char *from,
62
	int force)
63
{
64
	int is_unmovable_head = 0;
65
	git_reference *branch = NULL;
66 67
	git_str canonical_branch_name = GIT_STR_INIT,
			  log_message = GIT_STR_INIT;
68
	int error = -1;
69
	int bare = git_repository_is_bare(repository);
70

71 72 73 74
	GIT_ASSERT_ARG(branch_name);
	GIT_ASSERT_ARG(commit);
	GIT_ASSERT_ARG(ref_out);
	GIT_ASSERT_ARG(git_commit_owner(commit) == repository);
75

76
	if (!git__strcmp(branch_name, "HEAD")) {
77
		git_error_set(GIT_ERROR_REFERENCE, "'HEAD' is not a valid branch name");
78 79 80 81
		error = -1;
		goto cleanup;
	}

82
	if (force && !bare && git_branch_lookup(&branch, repository, branch_name, GIT_BRANCH_LOCAL) == 0) {
83 84 85 86 87
		error = git_branch_is_head(branch);
		git_reference_free(branch);
		branch = NULL;

		if (error < 0)
88
			goto cleanup;
89

90
		is_unmovable_head = error;
91
	}
92

93
	if (is_unmovable_head && force) {
94
		git_error_set(GIT_ERROR_REFERENCE, "cannot force update branch '%s' as it is "
95 96
			"the current HEAD of the repository.", branch_name);
		error = -1;
97 98
		goto cleanup;
	}
nulltoken committed
99

100
	if (git_str_joinpath(&canonical_branch_name, GIT_REFS_HEADS_DIR, branch_name) < 0)
101
		goto cleanup;
102

103
	if (git_str_printf(&log_message, "branch: Created from %s", from) < 0)
104 105 106
		goto cleanup;

	error = git_reference_create(&branch, repository,
107 108
		git_str_cstr(&canonical_branch_name), git_commit_id(commit), force,
		git_str_cstr(&log_message));
109 110

	if (!error)
111
		*ref_out = branch;
112

113
cleanup:
114 115
	git_str_dispose(&canonical_branch_name);
	git_str_dispose(&log_message);
116 117 118
	return error;
}

119 120 121 122 123 124 125
int git_branch_create(
	git_reference **ref_out,
	git_repository *repository,
	const char *branch_name,
	const git_commit *commit,
	int force)
{
126 127 128 129
	char commit_id[GIT_OID_HEXSZ + 1];

	git_oid_tostr(commit_id, GIT_OID_HEXSZ + 1, git_commit_id(commit));
	return create_branch(ref_out, repository, branch_name, commit, commit_id, force);
130 131 132 133 134 135 136 137 138
}

int git_branch_create_from_annotated(
	git_reference **ref_out,
	git_repository *repository,
	const char *branch_name,
	const git_annotated_commit *commit,
	int force)
{
139 140
	return create_branch(ref_out,
		repository, branch_name, commit->commit, commit->description, force);
141 142
}

143
static int branch_is_checked_out(git_repository *worktree, void *payload)
144
{
145
	git_reference *branch = (git_reference *) payload;
146
	git_reference *head = NULL;
147
	int error;
148

149 150 151 152 153 154 155 156
	if (git_repository_is_bare(worktree))
		return 0;

	if ((error = git_reference_lookup(&head, worktree, GIT_HEAD_FILE)) < 0) {
		if (error == GIT_ENOTFOUND)
			error = 0;
		goto out;
	}
157

158 159
	if (git_reference_type(head) != GIT_REFERENCE_SYMBOLIC)
		goto out;
160

161 162 163
	error = !git__strcmp(head->target.symbolic, branch->name);

out:
164
	git_reference_free(head);
165
	return error;
166
}
167

168 169
int git_branch_is_checked_out(const git_reference *branch)
{
170 171
	GIT_ASSERT_ARG(branch);

172 173
	if (!git_reference_is_branch(branch))
		return 0;
174 175
	return git_repository_foreach_worktree(git_reference_owner(branch),
					       branch_is_checked_out, (void *)branch) == 1;
176 177
}

178
int git_branch_delete(git_reference *branch)
179
{
180
	int is_head;
181
	git_str config_section = GIT_STR_INIT;
182
	int error = -1;
183

184
	GIT_ASSERT_ARG(branch);
185

186
	if (!git_reference_is_branch(branch) && !git_reference_is_remote(branch)) {
187
		git_error_set(GIT_ERROR_INVALID, "reference '%s' is not a valid branch.",
188 189
			git_reference_name(branch));
		return GIT_ENOTFOUND;
190
	}
191

192 193
	if ((is_head = git_branch_is_head(branch)) < 0)
		return is_head;
194

195
	if (is_head) {
196
		git_error_set(GIT_ERROR_REFERENCE, "cannot delete branch '%s' as it is "
197
			"the current HEAD of the repository.", git_reference_name(branch));
198
		return -1;
199 200
	}

201
	if (git_reference_is_branch(branch) && git_branch_is_checked_out(branch)) {
202
		git_error_set(GIT_ERROR_REFERENCE, "Cannot delete branch '%s' as it is "
203 204 205 206
			"the current HEAD of a linked repository.", git_reference_name(branch));
		return -1;
	}

207
	if (git_str_join(&config_section, '.', "branch",
208
			git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR)) < 0)
209 210 211
		goto on_error;

	if (git_config_rename_section(
212
		git_reference_owner(branch), git_str_cstr(&config_section), NULL) < 0)
213
		goto on_error;
214

215
	error = git_reference_delete(branch);
216 217

on_error:
218
	git_str_dispose(&config_section);
219
	return error;
220 221
}

222
typedef struct {
223
	git_reference_iterator *iter;
224 225 226
	unsigned int flags;
} branch_iter;

227
int git_branch_next(git_reference **out, git_branch_t *out_type, git_branch_iterator *_iter)
228 229
{
	branch_iter *iter = (branch_iter *) _iter;
Vicent Marti committed
230
	git_reference *ref;
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
	int error;

	while ((error = git_reference_next(&ref, iter->iter)) == 0) {
		if ((iter->flags & GIT_BRANCH_LOCAL) &&
		    !git__prefixcmp(ref->name, GIT_REFS_HEADS_DIR)) {
			*out = ref;
			*out_type = GIT_BRANCH_LOCAL;

			return 0;
		} else  if ((iter->flags & GIT_BRANCH_REMOTE) &&
			    !git__prefixcmp(ref->name, GIT_REFS_REMOTES_DIR)) {
			*out = ref;
			*out_type = GIT_BRANCH_REMOTE;

			return 0;
		} else {
			git_reference_free(ref);
		}
	}
250

251 252
	return error;
}
253

254 255 256
int git_branch_iterator_new(
	git_branch_iterator **out,
	git_repository *repo,
257
	git_branch_t list_flags)
258 259
{
	branch_iter *iter;
260

261
	iter = git__calloc(1, sizeof(branch_iter));
262
	GIT_ERROR_CHECK_ALLOC(iter);
Vicent Marti committed
263

264
	iter->flags = list_flags;
265

266 267 268
	if (git_reference_iterator_new(&iter->iter, repo) < 0) {
		git__free(iter);
		return -1;
269 270
	}

271
	*out = (git_branch_iterator *) iter;
272

273 274 275 276 277 278 279
	return 0;
}

void git_branch_iterator_free(git_branch_iterator *_iter)
{
	branch_iter *iter = (branch_iter *) _iter;

280 281 282
	if (iter == NULL)
		return;

283 284
	git_reference_iterator_free(iter->iter);
	git__free(iter);
285 286
}

287
int git_branch_move(
288
	git_reference **out,
289 290
	git_reference *branch,
	const char *new_branch_name,
291
	int force)
292
{
293 294 295 296
	git_str new_reference_name = GIT_STR_INIT,
	        old_config_section = GIT_STR_INIT,
	        new_config_section = GIT_STR_INIT,
	        log_message = GIT_STR_INIT;
297
	int error;
298

299 300
	GIT_ASSERT_ARG(branch);
	GIT_ASSERT_ARG(new_branch_name);
301 302

	if (!git_reference_is_branch(branch))
303
		return not_a_local_branch(git_reference_name(branch));
304

305
	if ((error = git_str_joinpath(&new_reference_name, GIT_REFS_HEADS_DIR, new_branch_name)) < 0)
306
		goto done;
307

308 309
	if ((error = git_str_printf(&log_message, "branch: renamed %s to %s",
				    git_reference_name(branch), git_str_cstr(&new_reference_name))) < 0)
310 311
			goto done;

312
	/* first update ref then config so failure won't trash config */
Vicent Marti committed
313

314
	error = git_reference_rename(
315 316
		out, branch, git_str_cstr(&new_reference_name), force,
		git_str_cstr(&log_message));
317
	if (error < 0)
318
		goto done;
319

320
	git_str_join(&old_config_section, '.', "branch",
321
		git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR));
322
	git_str_join(&new_config_section, '.', "branch", new_branch_name);
323 324 325

	error = git_config_rename_section(
		git_reference_owner(branch),
326 327
		git_str_cstr(&old_config_section),
		git_str_cstr(&new_config_section));
328

329
done:
330 331 332 333
	git_str_dispose(&new_reference_name);
	git_str_dispose(&old_config_section);
	git_str_dispose(&new_config_section);
	git_str_dispose(&log_message);
334

335
	return error;
336
}
337 338

int git_branch_lookup(
339 340 341 342
	git_reference **ref_out,
	git_repository *repo,
	const char *branch_name,
	git_branch_t branch_type)
343
{
344
	int error = -1;
345 346 347 348

	GIT_ASSERT_ARG(ref_out);
	GIT_ASSERT_ARG(repo);
	GIT_ASSERT_ARG(branch_name);
349

350 351 352 353 354 355 356 357 358 359 360
	switch (branch_type) {
	case GIT_BRANCH_LOCAL:
	case GIT_BRANCH_REMOTE:
		error = retrieve_branch_reference(ref_out, repo, branch_name, branch_type == GIT_BRANCH_REMOTE);
		break;
	case GIT_BRANCH_ALL:
		error = retrieve_branch_reference(ref_out, repo, branch_name, false);
		if (error == GIT_ENOTFOUND)
			error = retrieve_branch_reference(ref_out, repo, branch_name, true);
		break;
	default:
361
		GIT_ASSERT(false);
362 363
	}
	return error;
364
}
365

Jacques Germishuys committed
366 367 368
int git_branch_name(
	const char **out,
	const git_reference *ref)
369 370 371
{
	const char *branch_name;

372 373
	GIT_ASSERT_ARG(out);
	GIT_ASSERT_ARG(ref);
374 375 376 377 378 379 380 381

	branch_name = ref->name;

	if (git_reference_is_branch(ref)) {
		branch_name += strlen(GIT_REFS_HEADS_DIR);
	} else if (git_reference_is_remote(ref)) {
		branch_name += strlen(GIT_REFS_REMOTES_DIR);
	} else {
382
		git_error_set(GIT_ERROR_INVALID,
383
				"reference '%s' is neither a local nor a remote branch.", ref->name);
384 385 386 387 388 389
		return -1;
	}
	*out = branch_name;
	return 0;
}

390
static int retrieve_upstream_configuration(
391
	git_str *out,
392
	const git_config *config,
393 394
	const char *canonical_branch_name,
	const char *format)
395
{
396
	git_str buf = GIT_STR_INIT;
397 398
	int error;

399
	if (git_str_printf(&buf, format,
400
		canonical_branch_name + strlen(GIT_REFS_HEADS_DIR)) < 0)
401 402
			return -1;

403 404
	error = git_config__get_string_buf(out, config, git_str_cstr(&buf));
	git_str_dispose(&buf);
405 406 407
	return error;
}

408 409
int git_branch_upstream_name(
	git_buf *out,
410
	git_repository *repo,
411
	const char *refname)
412
{
413 414 415 416 417 418 419 420 421 422 423
	GIT_BUF_WRAP_PRIVATE(out, git_branch__upstream_name, repo, refname);
}

int git_branch__upstream_name(
	git_str *out,
	git_repository *repo,
	const char *refname)
{
	git_str remote_name = GIT_STR_INIT;
	git_str merge_name = GIT_STR_INIT;
	git_str buf = GIT_STR_INIT;
424 425 426
	int error = -1;
	git_remote *remote = NULL;
	const git_refspec *refspec;
427
	git_config *config;
428

429
	GIT_ASSERT_ARG(out);
430
	GIT_ASSERT_ARG(repo);
431
	GIT_ASSERT_ARG(refname);
432 433 434

	if (!git_reference__is_branch(refname))
		return not_a_local_branch(refname);
435

436
	if ((error = git_repository_config_snapshot(&config, repo)) < 0)
437 438
		return error;

439
	if ((error = retrieve_upstream_configuration(
440
		&remote_name, config, refname, "branch.%s.remote")) < 0)
441
			goto cleanup;
442

443
	if ((error = retrieve_upstream_configuration(
444
		&merge_name, config, refname, "branch.%s.merge")) < 0)
445
			goto cleanup;
446

447
	if (git_str_len(&remote_name) == 0 || git_str_len(&merge_name) == 0) {
448
		git_error_set(GIT_ERROR_REFERENCE,
449
			"branch '%s' does not have an upstream", refname);
nulltoken committed
450 451 452
		error = GIT_ENOTFOUND;
		goto cleanup;
	}
453

454 455
	if (strcmp(".", git_str_cstr(&remote_name)) != 0) {
		if ((error = git_remote_lookup(&remote, repo, git_str_cstr(&remote_name))) < 0)
456 457
			goto cleanup;

458
		refspec = git_remote__matching_refspec(remote, git_str_cstr(&merge_name));
459 460 461
		if (!refspec) {
			error = GIT_ENOTFOUND;
			goto cleanup;
462 463
		}

464
		if (git_refspec__transform(&buf, refspec, git_str_cstr(&merge_name)) < 0)
465 466
			goto cleanup;
	} else
467
		if (git_str_set(&buf, git_str_cstr(&merge_name), git_str_len(&merge_name)) < 0)
468 469
			goto cleanup;

470
	git_str_swap(out, &buf);
471 472

cleanup:
473
	git_config_free(config);
474
	git_remote_free(remote);
475 476 477
	git_str_dispose(&remote_name);
	git_str_dispose(&merge_name);
	git_str_dispose(&buf);
478 479
	return error;
}
480

481 482 483 484 485 486
static int git_branch_upstream_with_format(
	git_str *out,
	git_repository *repo,
	const char *refname,
	const char *format,
	const char *format_name)
487 488
{
	git_config *cfg;
489
	int error;
490 491 492 493

	if (!git_reference__is_branch(refname))
		return not_a_local_branch(refname);

494 495
	if ((error = git_repository_config__weakptr(&cfg, repo)) < 0 ||
	    (error = retrieve_upstream_configuration(out, cfg, refname, format)) < 0)
496 497
		return error;

498
	if (git_str_len(out) == 0) {
499
		git_error_set(GIT_ERROR_REFERENCE, "branch '%s' does not have an upstream %s", refname, format_name);
500 501 502
		error = GIT_ENOTFOUND;
	}

503 504 505
	return error;
}

506 507 508 509
int git_branch_upstream_remote(
	git_buf *out,
	git_repository *repo,
	const char *refname)
510
{
511
	GIT_BUF_WRAP_PRIVATE(out, git_branch__upstream_remote, repo, refname);
512 513
}

514 515 516 517
int git_branch__upstream_remote(
	git_str *out,
	git_repository *repo,
	const char *refname)
518
{
519
	return git_branch_upstream_with_format(out, repo, refname, "branch.%s.remote", "remote");
520 521
}

522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
int git_branch_upstream_merge(
	git_buf *out,
	git_repository *repo,
	const char *refname)
{
	GIT_BUF_WRAP_PRIVATE(out, git_branch__upstream_merge, repo, refname);
}

int git_branch__upstream_merge(
	git_str *out,
	git_repository *repo,
	const char *refname)
{
	return git_branch_upstream_with_format(out, repo, refname, "branch.%s.merge", "merge");
}

int git_branch_remote_name(
	git_buf *out,
	git_repository *repo,
	const char *refname)
{
	GIT_BUF_WRAP_PRIVATE(out, git_branch__remote_name, repo, refname);
}

int git_branch__remote_name(
	git_str *out,
	git_repository *repo,
	const char *refname)
550 551
{
	git_strarray remote_list = {0};
552
	size_t i;
553 554 555 556 557
	git_remote *remote;
	const git_refspec *fetchspec;
	int error = 0;
	char *remote_name = NULL;

558
	GIT_ASSERT_ARG(out);
559 560
	GIT_ASSERT_ARG(repo);
	GIT_ASSERT_ARG(refname);
561

562
	/* Verify that this is a remote branch */
563
	if (!git_reference__is_remote(refname)) {
564
		git_error_set(GIT_ERROR_INVALID, "reference '%s' is not a remote branch.",
565
			refname);
566 567 568 569 570 571 572 573 574 575
		error = GIT_ERROR;
		goto cleanup;
	}

	/* Get the remotes */
	if ((error = git_remote_list(&remote_list, repo)) < 0)
		goto cleanup;

	/* Find matching remotes */
	for (i = 0; i < remote_list.count; i++) {
576
		if ((error = git_remote_lookup(&remote, repo, remote_list.strings[i])) < 0)
577
			continue;
578

579
		fetchspec = git_remote__matching_dst_refspec(remote, refname);
580
		if (fetchspec) {
581 582 583 584 585 586 587 588
			/* If we have not already set out yet, then set
			 * it to the matching remote name. Otherwise
			 * multiple remotes match this reference, and it
			 * is ambiguous. */
			if (!remote_name) {
				remote_name = remote_list.strings[i];
			} else {
				git_remote_free(remote);
589

590
				git_error_set(GIT_ERROR_REFERENCE,
591
					"reference '%s' is ambiguous", refname);
592 593 594 595 596 597 598 599 600
				error = GIT_EAMBIGUOUS;
				goto cleanup;
			}
		}

		git_remote_free(remote);
	}

	if (remote_name) {
601 602
		git_str_clear(out);
		error = git_str_puts(out, remote_name);
603
	} else {
604
		git_error_set(GIT_ERROR_REFERENCE,
605
			"could not determine remote for '%s'", refname);
606 607 608 609
		error = GIT_ENOTFOUND;
	}

cleanup:
610
	if (error < 0)
611
		git_str_dispose(out);
612

613
	git_strarray_dispose(&remote_list);
614 615 616
	return error;
}

617
int git_branch_upstream(
Jacques Germishuys committed
618 619
	git_reference **tracking_out,
	const git_reference *branch)
620 621
{
	int error;
622
	git_str tracking_name = GIT_STR_INIT;
623

624
	if ((error = git_branch__upstream_name(&tracking_name,
625 626 627 628 629 630
		git_reference_owner(branch), git_reference_name(branch))) < 0)
			return error;

	error = git_reference_lookup(
		tracking_out,
		git_reference_owner(branch),
631
		git_str_cstr(&tracking_name));
632

633
	git_str_dispose(&tracking_name);
634 635 636
	return error;
}

637 638
static int unset_upstream(git_config *config, const char *shortname)
{
639
	git_str buf = GIT_STR_INIT;
640

641
	if (git_str_printf(&buf, "branch.%s.remote", shortname) < 0)
642 643
		return -1;

644
	if (git_config_delete_entry(config, git_str_cstr(&buf)) < 0)
645 646
		goto on_error;

647 648
	git_str_clear(&buf);
	if (git_str_printf(&buf, "branch.%s.merge", shortname) < 0)
649 650
		goto on_error;

651
	if (git_config_delete_entry(config, git_str_cstr(&buf)) < 0)
652 653
		goto on_error;

654
	git_str_dispose(&buf);
655 656 657
	return 0;

on_error:
658
	git_str_dispose(&buf);
659 660 661
	return -1;
}

662
int git_branch_set_upstream(git_reference *branch, const char *branch_name)
663
{
664
	git_str key = GIT_STR_INIT, remote_name = GIT_STR_INIT, merge_refspec = GIT_STR_INIT;
665 666 667 668
	git_reference *upstream;
	git_repository *repo;
	git_remote *remote = NULL;
	git_config *config;
669
	const char *refname, *shortname;
670
	int local, error;
671 672
	const git_refspec *fetchspec;

673 674 675
	refname = git_reference_name(branch);
	if (!git_reference__is_branch(refname))
		return not_a_local_branch(refname);
676 677 678 679

	if (git_repository_config__weakptr(&config, git_reference_owner(branch)) < 0)
		return -1;

680
	shortname = refname + strlen(GIT_REFS_HEADS_DIR);
681

682 683
	/* We're unsetting, delegate and bail-out */
	if (branch_name == NULL)
684 685 686 687
		return unset_upstream(config, shortname);

	repo = git_reference_owner(branch);

688 689
	/* First we need to resolve name to a branch */
	if (git_branch_lookup(&upstream, repo, branch_name, GIT_BRANCH_LOCAL) == 0)
690
		local = 1;
691
	else if (git_branch_lookup(&upstream, repo, branch_name, GIT_BRANCH_REMOTE) == 0)
692
		local = 0;
693
	else {
694
		git_error_set(GIT_ERROR_REFERENCE,
695
			"cannot set upstream for branch '%s'", shortname);
696
		return GIT_ENOTFOUND;
697
	}
698 699

	/*
700 701 702 703
	 * If it's a local-tracking branch, its remote is "." (as "the local
	 * repository"), and the branch name is simply the refname.
	 * Otherwise we need to figure out what the remote-tracking branch's
	 * name on the remote is and use that.
704 705
	 */
	if (local)
706
		error = git_str_puts(&remote_name, ".");
707
	else
708
		error = git_branch__remote_name(&remote_name, repo, git_reference_name(upstream));
709 710 711

	if (error < 0)
		goto on_error;
712

Dimitris Apostolou committed
713
	/* Update the upstream branch config with the new name */
714
	if (git_str_printf(&key, "branch.%s.remote", shortname) < 0)
715 716
		goto on_error;

717
	if (git_config_set_string(config, git_str_cstr(&key), git_str_cstr(&remote_name)) < 0)
718 719 720
		goto on_error;

	if (local) {
721
		/* A local branch uses the upstream refname directly */
722
		if (git_str_puts(&merge_refspec, git_reference_name(upstream)) < 0)
723 724
			goto on_error;
	} else {
725
		/* We transform the upstream branch name according to the remote's refspecs */
726
		if (git_remote_lookup(&remote, repo, git_str_cstr(&remote_name)) < 0)
727 728
			goto on_error;

729
		fetchspec = git_remote__matching_dst_refspec(remote, git_reference_name(upstream));
730
		if (!fetchspec || git_refspec__rtransform(&merge_refspec, fetchspec, git_reference_name(upstream)) < 0)
731 732 733 734 735 736
			goto on_error;

		git_remote_free(remote);
		remote = NULL;
	}

737
	/* Update the merge branch config with the refspec */
738 739
	git_str_clear(&key);
	if (git_str_printf(&key, "branch.%s.merge", shortname) < 0)
740 741
		goto on_error;

742
	if (git_config_set_string(config, git_str_cstr(&key), git_str_cstr(&merge_refspec)) < 0)
743 744 745
		goto on_error;

	git_reference_free(upstream);
746 747 748
	git_str_dispose(&key);
	git_str_dispose(&remote_name);
	git_str_dispose(&merge_refspec);
749 750 751 752 753

	return 0;

on_error:
	git_reference_free(upstream);
754 755 756
	git_str_dispose(&key);
	git_str_dispose(&remote_name);
	git_str_dispose(&merge_refspec);
757 758 759 760 761
	git_remote_free(remote);

	return -1;
}

762
int git_branch_is_head(
763
		const git_reference *branch)
764 765 766
{
	git_reference *head;
	bool is_same = false;
767
	int error;
768

769
	GIT_ASSERT_ARG(branch);
770 771 772 773

	if (!git_reference_is_branch(branch))
		return false;

774 775
	error = git_repository_head(&head, git_reference_owner(branch));

776
	if (error == GIT_EUNBORNBRANCH || error == GIT_ENOTFOUND)
777 778 779
		return false;

	if (error < 0)
780 781 782 783 784 785 786 787 788 789
		return -1;

	is_same = strcmp(
		git_reference_name(branch),
		git_reference_name(head)) == 0;

	git_reference_free(head);

	return is_same;
}
790 791 792

int git_branch_name_is_valid(int *valid, const char *name)
{
793
	git_str ref_name = GIT_STR_INIT;
794 795 796 797 798 799 800 801 802 803 804 805 806 807 808
	int error = 0;

	GIT_ASSERT(valid);

	*valid = 0;

	/*
	 * Discourage branch name starting with dash,
	 * https://github.com/git/git/commit/6348624010888b
	 * and discourage HEAD as branch name,
	 * https://github.com/git/git/commit/a625b092cc5994
	 */
	if (!name || name[0] == '-' || !git__strcmp(name, "HEAD"))
		goto done;

809 810
	if ((error = git_str_puts(&ref_name, GIT_REFS_HEADS_DIR)) < 0 ||
	    (error = git_str_puts(&ref_name, name)) < 0)
811 812 813 814 815
		goto done;

	error = git_reference_name_is_valid(valid, ref_name.ptr);

done:
816
	git_str_dispose(&ref_name);
817 818
	return error;
}