1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-24 22:11:15 +02:00

git/revCount: improve error message when we have incomplete git history

This commit is contained in:
Jörg Thalheim 2025-05-25 16:27:51 +02:00
parent 0479db934c
commit b1ccfaa080
4 changed files with 80 additions and 15 deletions

View file

@ -322,8 +322,17 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
for (size_t n = 0; n < git_commit_parentcount(commit->get()); ++n) {
git_commit * parent;
if (git_commit_parent(&parent, commit->get(), n))
throw Error("getting parent of Git commit '%s': %s", *git_commit_id(commit->get()), git_error_last()->message);
if (git_commit_parent(&parent, commit->get(), n)) {
throw Error(
"Failed to retrieve the parent of Git commit '%s': %s. "
"This may be due to an incomplete repository history. "
"To resolve this, either enable the shallow parameter in your flake URL (?shallow=1) "
"or add set the shallow parameter to true in builtins.fetchGit, "
"or fetch the complete history for this branch.",
*git_commit_id(commit->get()),
git_error_last()->message
);
}
todo.push(Commit(parent));
}
}

View file

@ -12,7 +12,7 @@ repo=$TEST_ROOT/./git
export _NIX_FORCE_HTTP=1
rm -rf $repo ${repo}-tmp $TEST_HOME/.cache/nix $TEST_ROOT/worktree $TEST_ROOT/shallow $TEST_ROOT/minimal
rm -rf $repo ${repo}-tmp $TEST_HOME/.cache/nix $TEST_ROOT/worktree $TEST_ROOT/minimal
git init $repo
git -C $repo config user.email "foobar@example.com"
@ -216,18 +216,6 @@ git -C $TEST_ROOT/minimal fetch $repo $rev2
git -C $TEST_ROOT/minimal checkout $rev2
[[ $(nix eval --impure --raw --expr "(builtins.fetchGit { url = $TEST_ROOT/minimal; }).rev") = $rev2 ]]
# Fetching a shallow repo shouldn't work by default, because we can't
# return a revCount.
git clone --depth 1 file://$repo $TEST_ROOT/shallow
(! nix eval --impure --raw --expr "(builtins.fetchGit { url = $TEST_ROOT/shallow; ref = \"dev\"; }).outPath")
# But you can request a shallow clone, which won't return a revCount.
path6=$(nix eval --impure --raw --expr "(builtins.fetchTree { type = \"git\"; url = \"file://$TEST_ROOT/shallow\"; ref = \"dev\"; shallow = true; }).outPath")
[[ $path3 = $path6 ]]
[[ $(nix eval --impure --expr "(builtins.fetchTree { type = \"git\"; url = \"file://$TEST_ROOT/shallow\"; ref = \"dev\"; shallow = true; }).revCount or 123") == 123 ]]
expectStderr 1 nix eval --expr 'builtins.fetchTree { type = "git"; url = "file:///foo"; }' | grepQuiet "'fetchTree' will not fetch unlocked input"
# Explicit ref = "HEAD" should work, and produce the same outPath as without ref
path7=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"HEAD\"; }).outPath")
path8=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; }).outPath")

View file

@ -0,0 +1,67 @@
#!/usr/bin/env bash
# shellcheck source=common.sh
source common.sh
requireGit
# Create a test repo with multiple commits for all our tests
git init "$TEST_ROOT/shallow-parent"
git -C "$TEST_ROOT/shallow-parent" config user.email "foobar@example.com"
git -C "$TEST_ROOT/shallow-parent" config user.name "Foobar"
# Add several commits to have history
echo "{ outputs = _: {}; }" > "$TEST_ROOT/shallow-parent/flake.nix"
echo "" > "$TEST_ROOT/shallow-parent/file.txt"
git -C "$TEST_ROOT/shallow-parent" add file.txt flake.nix
git -C "$TEST_ROOT/shallow-parent" commit -m "First commit"
echo "second" > "$TEST_ROOT/shallow-parent/file.txt"
git -C "$TEST_ROOT/shallow-parent" commit -m "Second commit" -a
echo "third" > "$TEST_ROOT/shallow-parent/file.txt"
git -C "$TEST_ROOT/shallow-parent" commit -m "Third commit" -a
# Add a branch for testing ref fetching
git -C "$TEST_ROOT/shallow-parent" checkout -b dev
echo "branch content" > "$TEST_ROOT/shallow-parent/branch-file.txt"
git -C "$TEST_ROOT/shallow-parent" add branch-file.txt
git -C "$TEST_ROOT/shallow-parent" commit -m "Branch commit"
# Make a shallow clone (depth=1)
git clone --depth 1 "file://$TEST_ROOT/shallow-parent" "$TEST_ROOT/shallow-clone"
# Test 1: Fetching a shallow repo shouldn't work by default, because we can't
# return a revCount.
(! nix eval --impure --raw --expr "(builtins.fetchGit { url = \"$TEST_ROOT/shallow-clone\"; ref = \"dev\"; }).outPath")
# Test 2: But you can request a shallow clone, which won't return a revCount.
path=$(nix eval --impure --raw --expr "(builtins.fetchTree { type = \"git\"; url = \"file://$TEST_ROOT/shallow-clone\"; ref = \"dev\"; shallow = true; }).outPath")
# Verify file from dev branch exists
[[ -f "$path/branch-file.txt" ]]
# Verify revCount is missing
[[ $(nix eval --impure --expr "(builtins.fetchTree { type = \"git\"; url = \"file://$TEST_ROOT/shallow-clone\"; ref = \"dev\"; shallow = true; }).revCount or 123") == 123 ]]
# Test 3: Check unlocked input error message
expectStderr 1 nix eval --expr 'builtins.fetchTree { type = "git"; url = "file:///foo"; }' | grepQuiet "'fetchTree' will not fetch unlocked input"
# Test 4: Regression test for revCount in worktrees derived from shallow clones
# Add a worktree to the shallow clone
git -C "$TEST_ROOT/shallow-clone" worktree add "$TEST_ROOT/shallow-worktree"
# Prior to the fix, this would error out because of the shallow clone's
# inability to find parent commits. Now it should return an error.
if nix eval --impure --expr "(builtins.fetchGit { url = \"file://$TEST_ROOT/shallow-worktree\"; }).revCount" 2>/dev/null; then
echo "fetchGit unexpectedly succeeded on shallow clone" >&2
exit 1
fi
# Also verify that fetchTree fails similarly
if nix eval --impure --expr "(builtins.fetchTree { type = \"git\"; url = \"file://$TEST_ROOT/shallow-worktree\"; }).revCount" 2>/dev/null; then
echo "fetchTree unexpectedly succeeded on shallow clone" >&2
exit 1
fi
# Verify that we can shallow fetch the worktree
git -C "$TEST_ROOT/shallow-worktree" rev-list --count HEAD >/dev/null
nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$TEST_ROOT/shallow-worktree\"; shallow = true; }).rev"

View file

@ -73,6 +73,7 @@ suites = [
'gc-runtime.sh',
'tarball.sh',
'fetchGit.sh',
'fetchGitShallow.sh',
'fetchurl.sh',
'fetchPath.sh',
'fetchTree-file.sh',