Skip to content

Commit 384518d

Browse files
committed
repository: restrict checking out checked out branches
If a branch is already checked out in a working tree we are not allowed to check out that branch in another repository. Introduce this restriction when setting a repository's HEAD.
1 parent 143e539 commit 384518d

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

src/repository.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2529,6 +2529,12 @@ int git_repository_set_head(
25292529
if (error < 0 && error != GIT_ENOTFOUND)
25302530
goto cleanup;
25312531

2532+
if (ref && current->type == GIT_REF_SYMBOLIC && git__strcmp(current->target.symbolic, ref->name) &&
2533+
git_reference_is_branch(ref) && git_branch_is_checked_out(ref)) {
2534+
error = -1;
2535+
goto cleanup;
2536+
}
2537+
25322538
if (!error) {
25332539
if (git_reference_is_branch(ref)) {
25342540
error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE,

tests/worktree/refs.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,41 @@ void test_worktree_refs__read_head(void)
6868
git_reference_free(head);
6969
}
7070

71+
void test_worktree_refs__set_head_fails_when_worktree_wants_linked_repos_HEAD(void)
72+
{
73+
git_reference *head;
74+
75+
cl_git_pass(git_repository_head(&head, fixture.repo));
76+
cl_git_fail(git_repository_set_head(fixture.worktree, git_reference_name(head)));
77+
78+
git_reference_free(head);
79+
}
80+
81+
void test_worktree_refs__set_head_fails_when_main_repo_wants_worktree_head(void)
82+
{
83+
git_reference *head;
84+
85+
cl_git_pass(git_repository_head(&head, fixture.worktree));
86+
cl_git_fail(git_repository_set_head(fixture.repo, git_reference_name(head)));
87+
88+
git_reference_free(head);
89+
}
90+
91+
void test_worktree_refs__set_head_works_for_current_HEAD(void)
92+
{
93+
git_reference *head;
94+
95+
cl_git_pass(git_repository_head(&head, fixture.repo));
96+
cl_git_pass(git_repository_set_head(fixture.repo, git_reference_name(head)));
97+
98+
git_reference_free(head);
99+
}
100+
101+
void test_worktree_refs__set_head_fails_when_already_checked_out(void)
102+
{
103+
cl_git_fail(git_repository_set_head(fixture.repo, "refs/heads/testrepo-worktree"));
104+
}
105+
71106
void test_worktree_refs__delete_fails_for_checked_out_branch(void)
72107
{
73108
git_reference *branch;

0 commit comments

Comments
 (0)