Hash :
39abd3ad
Author :
Date :
2016-11-04T13:39:54
worktree: compute workdir for worktrees opened via their gitdir When opening a worktree via the gitdir of its parent repository we fail to correctly set up the worktree's working directory. The problem here is two-fold: we first fail to see that the gitdir actually is a gitdir of a working tree and then subsequently fail to determine the working tree location from the gitdir. The first problem of not noticing a gitdir belongs to a worktree can be solved by checking for the existence of a `gitdir` file in the gitdir. This file points back to the gitlink file located in the working tree's working directory. As this file only exists for worktrees, it should be sufficient indication of the gitdir belonging to a worktree. The second problem, that is determining the location of the worktree's working directory, can then be solved by reading the `gitdir` file in the working directory's gitdir. When we now resolve relative paths and strip the final `.git` component, we have the actual worktree's working directory location.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
#include "clar_libgit2.h"
#include "repository.h"
#include "worktree_helpers.h"
#define WORKTREE_PARENT "submodules-worktree-parent"
#define WORKTREE_CHILD "submodules-worktree-child"
#define COMMON_REPO "testrepo"
#define WORKTREE_REPO "testrepo-worktree"
void test_worktree_open__repository(void)
{
worktree_fixture fixture =
WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO);
setup_fixture_worktree(&fixture);
cl_assert(git_repository_path(fixture.worktree) != NULL);
cl_assert(git_repository_workdir(fixture.worktree) != NULL);
cl_assert(!fixture.repo->is_worktree);
cl_assert(fixture.worktree->is_worktree);
cleanup_fixture_worktree(&fixture);
}
void test_worktree_open__open_discovered_worktree(void)
{
worktree_fixture fixture =
WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO);
git_buf path = GIT_BUF_INIT;
git_repository *repo;
setup_fixture_worktree(&fixture);
cl_git_pass(git_repository_discover(&path,
git_repository_workdir(fixture.worktree), false, NULL));
cl_git_pass(git_repository_open(&repo, path.ptr));
cl_assert_equal_s(git_repository_workdir(fixture.worktree),
git_repository_workdir(repo));
git_buf_free(&path);
git_repository_free(repo);
cleanup_fixture_worktree(&fixture);
}
void test_worktree_open__repository_with_nonexistent_parent(void)
{
git_repository *repo;
cl_fixture_sandbox(WORKTREE_REPO);
cl_git_pass(p_chdir(WORKTREE_REPO));
cl_git_pass(cl_rename(".gitted", ".git"));
cl_git_pass(p_chdir(".."));
cl_git_fail(git_repository_open(&repo, WORKTREE_REPO));
cl_fixture_cleanup(WORKTREE_REPO);
}
void test_worktree_open__submodule_worktree_parent(void)
{
worktree_fixture fixture =
WORKTREE_FIXTURE_INIT("submodules", WORKTREE_PARENT);
setup_fixture_worktree(&fixture);
cl_assert(git_repository_path(fixture.worktree) != NULL);
cl_assert(git_repository_workdir(fixture.worktree) != NULL);
cl_assert(!fixture.repo->is_worktree);
cl_assert(fixture.worktree->is_worktree);
cleanup_fixture_worktree(&fixture);
}
void test_worktree_open__submodule_worktree_child(void)
{
worktree_fixture parent_fixture =
WORKTREE_FIXTURE_INIT("submodules", WORKTREE_PARENT);
worktree_fixture child_fixture =
WORKTREE_FIXTURE_INIT(NULL, WORKTREE_CHILD);
setup_fixture_worktree(&parent_fixture);
cl_git_pass(p_rename(
"submodules/testrepo/.gitted",
"submodules/testrepo/.git"));
setup_fixture_worktree(&child_fixture);
cl_assert(!parent_fixture.repo->is_worktree);
cl_assert(parent_fixture.worktree->is_worktree);
cl_assert(child_fixture.worktree->is_worktree);
cleanup_fixture_worktree(&child_fixture);
cleanup_fixture_worktree(&parent_fixture);
}