From c169ea59049f861aaba429f48b828d0820b74d1d Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Fri, 15 Nov 2019 13:04:42 +0100 Subject: [PATCH] builtins.fetchGit: Fix build when fetching a git worktree Worktrees[1] are a feature of git which allow you to check out a ref in a different directory. While playing around with flakes I realized that git repositories in a worktree checkout break when trying to build a flake: ``` $ git worktree add ../nixpkgs-flakes nixpkgs-flakes $ cd ../nixpkgs-flakes $ nix build .#hello error: opening directory '/home/ma27/Projects/nixpkgs-flakes/.git/refs/heads': Not a directory ``` This issue has been fixed by determining with `git rev-parse --git-common-dir` where the actual `.git` directory is. Please note that this issue only exists on the `flakes` branch, fetching worktree checkouts with Nix master seems to work fine. [1] https://git-scm.com/docs/git-worktree --- src/libstore/fetchers/git.cc | 11 ++++++++++- tests/fetchGit.sh | 8 ++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/libstore/fetchers/git.cc b/src/libstore/fetchers/git.cc index 134d44ecd..9276b0993 100644 --- a/src/libstore/fetchers/git.cc +++ b/src/libstore/fetchers/git.cc @@ -217,7 +217,16 @@ struct GitInput : Input /* Check whether this repo has any commits. There are probably better ways to do this. */ - bool haveCommits = !readDirectory(actualUrl + "/.git/refs/heads").empty(); + auto gitDir = actualUrl + "/.git"; + auto commonGitDir = chomp(runProgram( + "git", + true, + { "-C", actualUrl, "rev-parse", "--git-common-dir" } + )); + if (commonGitDir != ".git") + gitDir = commonGitDir; + + bool haveCommits = !readDirectory(gitDir + "/refs/heads").empty(); try { if (haveCommits) { diff --git a/tests/fetchGit.sh b/tests/fetchGit.sh index ac0d78f12..d44586977 100644 --- a/tests/fetchGit.sh +++ b/tests/fetchGit.sh @@ -25,8 +25,16 @@ rev1=$(git -C $repo rev-parse HEAD) echo world > $repo/hello git -C $repo commit -m 'Bla2' -a +git -C $repo worktree add $TEST_ROOT/worktree +echo hello >> $TEST_ROOT/worktree/hello rev2=$(git -C $repo rev-parse HEAD) +# Fetch a worktree +unset _NIX_FORCE_HTTP +path0=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$TEST_ROOT/worktree).outPath") +export _NIX_FORCE_HTTP=1 +[[ $(tail -n 1 $path0/hello) = "hello" ]] + # Fetch the default branch. path=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).outPath") [[ $(cat $path/hello) = world ]]