From 384518d09dc16b8a7dae22069e0c612e4b65c5e8 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 27 Oct 2015 14:17:52 +0100 Subject: [PATCH] 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. --- src/repository.c | 6 ++++++ tests/worktree/refs.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/repository.c b/src/repository.c index 445005e96..8753636cb 100644 --- a/src/repository.c +++ b/src/repository.c @@ -2529,6 +2529,12 @@ int git_repository_set_head( if (error < 0 && error != GIT_ENOTFOUND) goto cleanup; + if (ref && current->type == GIT_REF_SYMBOLIC && git__strcmp(current->target.symbolic, ref->name) && + git_reference_is_branch(ref) && git_branch_is_checked_out(ref)) { + error = -1; + goto cleanup; + } + if (!error) { if (git_reference_is_branch(ref)) { error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE, diff --git a/tests/worktree/refs.c b/tests/worktree/refs.c index 38f612713..ccac8be29 100644 --- a/tests/worktree/refs.c +++ b/tests/worktree/refs.c @@ -68,6 +68,41 @@ void test_worktree_refs__read_head(void) git_reference_free(head); } +void test_worktree_refs__set_head_fails_when_worktree_wants_linked_repos_HEAD(void) +{ + git_reference *head; + + cl_git_pass(git_repository_head(&head, fixture.repo)); + cl_git_fail(git_repository_set_head(fixture.worktree, git_reference_name(head))); + + git_reference_free(head); +} + +void test_worktree_refs__set_head_fails_when_main_repo_wants_worktree_head(void) +{ + git_reference *head; + + cl_git_pass(git_repository_head(&head, fixture.worktree)); + cl_git_fail(git_repository_set_head(fixture.repo, git_reference_name(head))); + + git_reference_free(head); +} + +void test_worktree_refs__set_head_works_for_current_HEAD(void) +{ + git_reference *head; + + cl_git_pass(git_repository_head(&head, fixture.repo)); + cl_git_pass(git_repository_set_head(fixture.repo, git_reference_name(head))); + + git_reference_free(head); +} + +void test_worktree_refs__set_head_fails_when_already_checked_out(void) +{ + cl_git_fail(git_repository_set_head(fixture.repo, "refs/heads/testrepo-worktree")); +} + void test_worktree_refs__delete_fails_for_checked_out_branch(void) { git_reference *branch;