2 * Copyright (C) the libgit2 contributors. All rights reserved.
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.
16 #include "annotated_commit.h"
19 #include "git2/branch.h"
21 static int retrieve_branch_reference(
22 git_reference
**branch_reference_out
,
24 const char *branch_name
,
27 git_reference
*branch
= NULL
;
30 git_buf ref_name
= GIT_BUF_INIT
;
32 prefix
= is_remote
? GIT_REFS_REMOTES_DIR
: GIT_REFS_HEADS_DIR
;
34 if ((error
= git_buf_joinpath(&ref_name
, prefix
, branch_name
)) < 0)
36 else if ((error
= git_reference_lookup(&branch
, repo
, ref_name
.ptr
)) < 0)
38 GIT_ERROR_REFERENCE
, "cannot locate %s branch '%s'",
39 is_remote
? "remote-tracking" : "local", branch_name
);
41 *branch_reference_out
= branch
; /* will be NULL on error */
43 git_buf_dispose(&ref_name
);
47 static int not_a_local_branch(const char *reference_name
)
51 "reference '%s' is not a local branch.", reference_name
);
55 static int create_branch(
56 git_reference
**ref_out
,
57 git_repository
*repository
,
58 const char *branch_name
,
59 const git_commit
*commit
,
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
;
68 int bare
= git_repository_is_bare(repository
);
70 assert(branch_name
&& commit
&& ref_out
);
71 assert(git_object_owner((const git_object
*)commit
) == repository
);
73 if (!git__strcmp(branch_name
, "HEAD")) {
74 git_error_set(GIT_ERROR_REFERENCE
, "'HEAD' is not a valid branch name");
79 if (force
&& !bare
&& git_branch_lookup(&branch
, repository
, branch_name
, GIT_BRANCH_LOCAL
) == 0) {
80 error
= git_branch_is_head(branch
);
81 git_reference_free(branch
);
87 is_unmovable_head
= error
;
90 if (is_unmovable_head
&& force
) {
91 git_error_set(GIT_ERROR_REFERENCE
, "cannot force update branch '%s' as it is "
92 "the current HEAD of the repository.", branch_name
);
97 if (git_buf_joinpath(&canonical_branch_name
, GIT_REFS_HEADS_DIR
, branch_name
) < 0)
100 if (git_buf_printf(&log_message
, "branch: Created from %s", from
) < 0)
103 error
= git_reference_create(&branch
, repository
,
104 git_buf_cstr(&canonical_branch_name
), git_commit_id(commit
), force
,
105 git_buf_cstr(&log_message
));
111 git_buf_dispose(&canonical_branch_name
);
112 git_buf_dispose(&log_message
);
116 int git_branch_create(
117 git_reference
**ref_out
,
118 git_repository
*repository
,
119 const char *branch_name
,
120 const git_commit
*commit
,
123 return create_branch(ref_out
, repository
, branch_name
, commit
, git_oid_tostr_s(git_commit_id(commit
)), force
);
126 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
,
133 return create_branch(ref_out
,
134 repository
, branch_name
, commit
->commit
, commit
->description
, force
);
137 static int branch_equals(git_repository
*repo
, const char *path
, void *payload
)
139 git_reference
*branch
= (git_reference
*) payload
;
140 git_reference
*head
= NULL
;
143 if (git_reference__read_head(&head
, repo
, path
) < 0 ||
144 git_reference_type(head
) != GIT_REFERENCE_SYMBOLIC
)
147 equal
= !git__strcmp(head
->target
.symbolic
, branch
->name
);
150 git_reference_free(head
);
154 int git_branch_is_checked_out(const git_reference
*branch
)
156 git_repository
*repo
;
161 if (!git_reference_is_branch(branch
))
164 repo
= git_reference_owner(branch
);
166 if (git_repository_is_bare(repo
))
167 flags
|= GIT_REPOSITORY_FOREACH_HEAD_SKIP_REPO
;
169 return git_repository_foreach_head(repo
, branch_equals
, flags
, (void *) branch
) == 1;
172 int git_branch_delete(git_reference
*branch
)
175 git_buf config_section
= GIT_BUF_INIT
;
180 if (!git_reference_is_branch(branch
) && !git_reference_is_remote(branch
)) {
181 git_error_set(GIT_ERROR_INVALID
, "reference '%s' is not a valid branch.",
182 git_reference_name(branch
));
183 return GIT_ENOTFOUND
;
186 if ((is_head
= git_branch_is_head(branch
)) < 0)
190 git_error_set(GIT_ERROR_REFERENCE
, "cannot delete branch '%s' as it is "
191 "the current HEAD of the repository.", git_reference_name(branch
));
195 if (git_reference_is_branch(branch
) && git_branch_is_checked_out(branch
)) {
196 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
));
201 if (git_buf_join(&config_section
, '.', "branch",
202 git_reference_name(branch
) + strlen(GIT_REFS_HEADS_DIR
)) < 0)
205 if (git_config_rename_section(
206 git_reference_owner(branch
), git_buf_cstr(&config_section
), NULL
) < 0)
209 error
= git_reference_delete(branch
);
212 git_buf_dispose(&config_section
);
217 git_reference_iterator
*iter
;
221 int git_branch_next(git_reference
**out
, git_branch_t
*out_type
, git_branch_iterator
*_iter
)
223 branch_iter
*iter
= (branch_iter
*) _iter
;
227 while ((error
= git_reference_next(&ref
, iter
->iter
)) == 0) {
228 if ((iter
->flags
& GIT_BRANCH_LOCAL
) &&
229 !git__prefixcmp(ref
->name
, GIT_REFS_HEADS_DIR
)) {
231 *out_type
= GIT_BRANCH_LOCAL
;
234 } else if ((iter
->flags
& GIT_BRANCH_REMOTE
) &&
235 !git__prefixcmp(ref
->name
, GIT_REFS_REMOTES_DIR
)) {
237 *out_type
= GIT_BRANCH_REMOTE
;
241 git_reference_free(ref
);
248 int git_branch_iterator_new(
249 git_branch_iterator
**out
,
250 git_repository
*repo
,
251 git_branch_t list_flags
)
255 iter
= git__calloc(1, sizeof(branch_iter
));
256 GIT_ERROR_CHECK_ALLOC(iter
);
258 iter
->flags
= list_flags
;
260 if (git_reference_iterator_new(&iter
->iter
, repo
) < 0) {
265 *out
= (git_branch_iterator
*) iter
;
270 void git_branch_iterator_free(git_branch_iterator
*_iter
)
272 branch_iter
*iter
= (branch_iter
*) _iter
;
277 git_reference_iterator_free(iter
->iter
);
283 git_reference
*branch
,
284 const char *new_branch_name
,
287 git_buf new_reference_name
= GIT_BUF_INIT
,
288 old_config_section
= GIT_BUF_INIT
,
289 new_config_section
= GIT_BUF_INIT
,
290 log_message
= GIT_BUF_INIT
;
293 assert(branch
&& new_branch_name
);
295 if (!git_reference_is_branch(branch
))
296 return not_a_local_branch(git_reference_name(branch
));
298 if ((error
= git_buf_joinpath(&new_reference_name
, GIT_REFS_HEADS_DIR
, new_branch_name
)) < 0)
301 if ((error
= git_buf_printf(&log_message
, "branch: renamed %s to %s",
302 git_reference_name(branch
), git_buf_cstr(&new_reference_name
))) < 0)
305 /* first update ref then config so failure won't trash config */
307 error
= git_reference_rename(
308 out
, branch
, git_buf_cstr(&new_reference_name
), force
,
309 git_buf_cstr(&log_message
));
313 git_buf_join(&old_config_section
, '.', "branch",
314 git_reference_name(branch
) + strlen(GIT_REFS_HEADS_DIR
));
315 git_buf_join(&new_config_section
, '.', "branch", new_branch_name
);
317 error
= git_config_rename_section(
318 git_reference_owner(branch
),
319 git_buf_cstr(&old_config_section
),
320 git_buf_cstr(&new_config_section
));
323 git_buf_dispose(&new_reference_name
);
324 git_buf_dispose(&old_config_section
);
325 git_buf_dispose(&new_config_section
);
326 git_buf_dispose(&log_message
);
331 int git_branch_lookup(
332 git_reference
**ref_out
,
333 git_repository
*repo
,
334 const char *branch_name
,
335 git_branch_t branch_type
)
338 assert(ref_out
&& repo
&& branch_name
);
340 switch (branch_type
) {
341 case GIT_BRANCH_LOCAL
:
342 case GIT_BRANCH_REMOTE
:
343 error
= retrieve_branch_reference(ref_out
, repo
, branch_name
, branch_type
== GIT_BRANCH_REMOTE
);
346 error
= retrieve_branch_reference(ref_out
, repo
, branch_name
, false);
347 if (error
== GIT_ENOTFOUND
)
348 error
= retrieve_branch_reference(ref_out
, repo
, branch_name
, true);
358 const git_reference
*ref
)
360 const char *branch_name
;
364 branch_name
= ref
->name
;
366 if (git_reference_is_branch(ref
)) {
367 branch_name
+= strlen(GIT_REFS_HEADS_DIR
);
368 } else if (git_reference_is_remote(ref
)) {
369 branch_name
+= strlen(GIT_REFS_REMOTES_DIR
);
371 git_error_set(GIT_ERROR_INVALID
,
372 "reference '%s' is neither a local nor a remote branch.", ref
->name
);
379 static int retrieve_upstream_configuration(
381 const git_config
*config
,
382 const char *canonical_branch_name
,
385 git_buf buf
= GIT_BUF_INIT
;
388 if (git_buf_printf(&buf
, format
,
389 canonical_branch_name
+ strlen(GIT_REFS_HEADS_DIR
)) < 0)
392 error
= git_config_get_string_buf(out
, config
, git_buf_cstr(&buf
));
393 git_buf_dispose(&buf
);
397 int git_branch_upstream_name(
399 git_repository
*repo
,
402 git_buf remote_name
= GIT_BUF_INIT
;
403 git_buf merge_name
= GIT_BUF_INIT
;
404 git_buf buf
= GIT_BUF_INIT
;
406 git_remote
*remote
= NULL
;
407 const git_refspec
*refspec
;
410 assert(out
&& refname
);
412 git_buf_sanitize(out
);
414 if (!git_reference__is_branch(refname
))
415 return not_a_local_branch(refname
);
417 if ((error
= git_repository_config_snapshot(&config
, repo
)) < 0)
420 if ((error
= retrieve_upstream_configuration(
421 &remote_name
, config
, refname
, "branch.%s.remote")) < 0)
424 if ((error
= retrieve_upstream_configuration(
425 &merge_name
, config
, refname
, "branch.%s.merge")) < 0)
428 if (git_buf_len(&remote_name
) == 0 || git_buf_len(&merge_name
) == 0) {
429 git_error_set(GIT_ERROR_REFERENCE
,
430 "branch '%s' does not have an upstream", refname
);
431 error
= GIT_ENOTFOUND
;
435 if (strcmp(".", git_buf_cstr(&remote_name
)) != 0) {
436 if ((error
= git_remote_lookup(&remote
, repo
, git_buf_cstr(&remote_name
))) < 0)
439 refspec
= git_remote__matching_refspec(remote
, git_buf_cstr(&merge_name
));
441 error
= GIT_ENOTFOUND
;
445 if (git_refspec_transform(&buf
, refspec
, git_buf_cstr(&merge_name
)) < 0)
448 if (git_buf_set(&buf
, git_buf_cstr(&merge_name
), git_buf_len(&merge_name
)) < 0)
451 error
= git_buf_set(out
, git_buf_cstr(&buf
), git_buf_len(&buf
));
454 git_config_free(config
);
455 git_remote_free(remote
);
456 git_buf_dispose(&remote_name
);
457 git_buf_dispose(&merge_name
);
458 git_buf_dispose(&buf
);
462 int git_branch_upstream_remote(git_buf
*buf
, git_repository
*repo
, const char *refname
)
467 if (!git_reference__is_branch(refname
))
468 return not_a_local_branch(refname
);
470 if ((error
= git_repository_config__weakptr(&cfg
, repo
)) < 0)
473 git_buf_sanitize(buf
);
475 if ((error
= retrieve_upstream_configuration(buf
, cfg
, refname
, "branch.%s.remote")) < 0)
478 if (git_buf_len(buf
) == 0) {
479 git_error_set(GIT_ERROR_REFERENCE
, "branch '%s' does not have an upstream remote", refname
);
480 error
= GIT_ENOTFOUND
;
487 int git_branch_remote_name(git_buf
*buf
, git_repository
*repo
, const char *refname
)
489 git_strarray remote_list
= {0};
492 const git_refspec
*fetchspec
;
494 char *remote_name
= NULL
;
496 assert(buf
&& repo
&& refname
);
498 git_buf_sanitize(buf
);
500 /* Verify that this is a remote branch */
501 if (!git_reference__is_remote(refname
)) {
502 git_error_set(GIT_ERROR_INVALID
, "reference '%s' is not a remote branch.",
508 /* Get the remotes */
509 if ((error
= git_remote_list(&remote_list
, repo
)) < 0)
512 /* Find matching remotes */
513 for (i
= 0; i
< remote_list
.count
; i
++) {
514 if ((error
= git_remote_lookup(&remote
, repo
, remote_list
.strings
[i
])) < 0)
517 fetchspec
= git_remote__matching_dst_refspec(remote
, refname
);
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
524 remote_name
= remote_list
.strings
[i
];
526 git_remote_free(remote
);
528 git_error_set(GIT_ERROR_REFERENCE
,
529 "reference '%s' is ambiguous", refname
);
530 error
= GIT_EAMBIGUOUS
;
535 git_remote_free(remote
);
540 error
= git_buf_puts(buf
, remote_name
);
542 git_error_set(GIT_ERROR_REFERENCE
,
543 "could not determine remote for '%s'", refname
);
544 error
= GIT_ENOTFOUND
;
549 git_buf_dispose(buf
);
551 git_strarray_free(&remote_list
);
555 int git_branch_upstream(
556 git_reference
**tracking_out
,
557 const git_reference
*branch
)
560 git_buf tracking_name
= GIT_BUF_INIT
;
562 if ((error
= git_branch_upstream_name(&tracking_name
,
563 git_reference_owner(branch
), git_reference_name(branch
))) < 0)
566 error
= git_reference_lookup(
568 git_reference_owner(branch
),
569 git_buf_cstr(&tracking_name
));
571 git_buf_dispose(&tracking_name
);
575 static int unset_upstream(git_config
*config
, const char *shortname
)
577 git_buf buf
= GIT_BUF_INIT
;
579 if (git_buf_printf(&buf
, "branch.%s.remote", shortname
) < 0)
582 if (git_config_delete_entry(config
, git_buf_cstr(&buf
)) < 0)
586 if (git_buf_printf(&buf
, "branch.%s.merge", shortname
) < 0)
589 if (git_config_delete_entry(config
, git_buf_cstr(&buf
)) < 0)
592 git_buf_dispose(&buf
);
596 git_buf_dispose(&buf
);
600 int git_branch_set_upstream(git_reference
*branch
, const char *branch_name
)
602 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 git_remote
*remote
= NULL
;
607 const char *refname
, *shortname
;
609 const git_refspec
*fetchspec
;
611 refname
= git_reference_name(branch
);
612 if (!git_reference__is_branch(refname
))
613 return not_a_local_branch(refname
);
615 if (git_repository_config__weakptr(&config
, git_reference_owner(branch
)) < 0)
618 shortname
= refname
+ strlen(GIT_REFS_HEADS_DIR
);
620 /* We're unsetting, delegate and bail-out */
621 if (branch_name
== NULL
)
622 return unset_upstream(config
, shortname
);
624 repo
= git_reference_owner(branch
);
626 /* First we need to resolve name to a branch */
627 if (git_branch_lookup(&upstream
, repo
, branch_name
, GIT_BRANCH_LOCAL
) == 0)
629 else if (git_branch_lookup(&upstream
, repo
, branch_name
, GIT_BRANCH_REMOTE
) == 0)
632 git_error_set(GIT_ERROR_REFERENCE
,
633 "cannot set upstream for branch '%s'", shortname
);
634 return GIT_ENOTFOUND
;
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.
644 error
= git_buf_puts(&remote_name
, ".");
646 error
= git_branch_remote_name(&remote_name
, repo
, git_reference_name(upstream
));
651 /* Update the upsteam branch config with the new name */
652 if (git_buf_printf(&key
, "branch.%s.remote", shortname
) < 0)
655 if (git_config_set_string(config
, git_buf_cstr(&key
), git_buf_cstr(&remote_name
)) < 0)
659 /* A local branch uses the upstream refname directly */
660 if (git_buf_puts(&merge_refspec
, git_reference_name(upstream
)) < 0)
663 /* We transform the upstream branch name according to the remote's refspecs */
664 if (git_remote_lookup(&remote
, repo
, git_buf_cstr(&remote_name
)) < 0)
667 fetchspec
= git_remote__matching_dst_refspec(remote
, git_reference_name(upstream
));
668 if (!fetchspec
|| git_refspec_rtransform(&merge_refspec
, fetchspec
, git_reference_name(upstream
)) < 0)
671 git_remote_free(remote
);
675 /* Update the merge branch config with the refspec */
677 if (git_buf_printf(&key
, "branch.%s.merge", shortname
) < 0)
680 if (git_config_set_string(config
, git_buf_cstr(&key
), git_buf_cstr(&merge_refspec
)) < 0)
683 git_reference_free(upstream
);
684 git_buf_dispose(&key
);
685 git_buf_dispose(&remote_name
);
686 git_buf_dispose(&merge_refspec
);
691 git_reference_free(upstream
);
692 git_buf_dispose(&key
);
693 git_buf_dispose(&remote_name
);
694 git_buf_dispose(&merge_refspec
);
695 git_remote_free(remote
);
700 int git_branch_is_head(
701 const git_reference
*branch
)
704 bool is_same
= false;
709 if (!git_reference_is_branch(branch
))
712 error
= git_repository_head(&head
, git_reference_owner(branch
));
714 if (error
== GIT_EUNBORNBRANCH
|| error
== GIT_ENOTFOUND
)
721 git_reference_name(branch
),
722 git_reference_name(head
)) == 0;
724 git_reference_free(head
);