fix: Consider fetchGit locked when narHash is present

`fetchGit` has been modified a long time ago to use fetchTree, however,
we don't care about `lastModified` because we are not in a flake
context, this hack introduces a `git-locked` type of input that only
cares about `narHash` being present. This is needed to avoid fetching
the remote repo each time `fetchGit` is evaluated whith the result
present in the store.

Change-Id: I521c6fcccf8cf12945594f205d7fd4c8c2cf89e9
This commit is contained in:
Tom Hubrecht
2025-05-28 22:24:23 +00:00
parent b792279780
commit e468102508
7 changed files with 73 additions and 0 deletions
+4
View File
@@ -48,6 +48,10 @@ attribute with the following attributes (all except `url` optional):
With this argument being true, it's possible to load a `rev` from *any* `ref`
(by default only `rev`s from the specified `ref` are supported).
- `narHash`
If given, the source is first looked-up in the Nix store and the [substituters](@docroot@/command-ref/conf-file.md#conf-substituters), and only fetched if not available.
The return value is an attrset containing the following keys:
- `lastModified` (`integer`)
+7
View File
@@ -169,6 +169,13 @@ static void fetchTree(
"attribute 'name' isnt supported in call to 'fetchTree'"
).atPos(pos).debugThrow();
// HACK: When using `fetchGit`, locking with only the hash should happen
// as we don't care about flake shenanigans about `lastModified`
if (type == "git" && attrs.contains("narHash")) {
using namespace std::literals::string_literals;
attrs["type"] = "\0git-locked"s;
}
input = fetchers::Input::fromAttrs(std::move(attrs));
} else {
auto url = state.coerceToString(pos, *args[0], context,
+1
View File
@@ -10,6 +10,7 @@ std::unique_ptr<InputScheme> makePathInputScheme();
std::unique_ptr<InputScheme> makeFileInputScheme();
std::unique_ptr<InputScheme> makeTarballInputScheme();
std::unique_ptr<InputScheme> makeGitInputScheme();
std::unique_ptr<InputScheme> makeGitLockedInputScheme();
std::unique_ptr<InputScheme> makeMercurialInputScheme();
std::unique_ptr<InputScheme> makeGitHubInputScheme();
std::unique_ptr<InputScheme> makeGitLabInputScheme();
+1
View File
@@ -22,6 +22,7 @@ void initLibFetchers()
registerInputScheme(makeTarballInputScheme());
registerInputScheme(makeFileInputScheme());
registerInputScheme(makeGitInputScheme());
registerInputScheme(makeGitLockedInputScheme());
registerInputScheme(makeMercurialInputScheme());
registerInputScheme(makeGitHubInputScheme());
registerInputScheme(makeGitLabInputScheme());
+18
View File
@@ -823,4 +823,22 @@ std::unique_ptr<InputScheme> makeGitInputScheme()
return std::make_unique<GitInputScheme>();
}
struct GitLockedInputScheme : GitInputScheme {
std::string schemeType() const override {
using namespace std::literals::string_literals;
return "\0git-locked"s;
}
bool hasAllInfo(const Input & input) const override {
return true;
}
};
std::unique_ptr<InputScheme> makeGitLockedInputScheme()
{
return std::make_unique<GitLockedInputScheme>();
}
}
+41
View File
@@ -0,0 +1,41 @@
source common.sh
requireGit
clearStore
# Intentionally not in a canonical form
# See https://github.com/NixOS/nix/issues/6195
repo=$TEST_ROOT/./git
export _NIX_FORCE_HTTP=1
rm -rf "$repo" "$TEST_HOME/.cache/nix"
mkdir "$repo" && pushd "$repo"
git init --initial-branch=main
git config user.email "foobar@example.com"
git config user.name "Foobar"
echo utrecht >hello
touch .gitignore
git add hello .gitignore
git commit -m 'Bla1'
rev1=$(git rev-parse HEAD)
git tag -a tag1 -m tag1
# Compute the hash of the output
path=$(nix eval --impure --raw --expr "(builtins.fetchGit \"file://$repo\").outPath")
hash=$(nix-hash --type sha256 --base32 "$path")
narHash=$(nix-hash --to-sri --type sha256 "$hash")
# Remove the repo, and the local cache
popd && rm -rf "$repo" "$TEST_HOME/.cache/nix"
# The path is locked and can be fetched
path2=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"main\"; rev=\"$rev1\"; narHash = \"$narHash\"; })")
[[ "$path" = "$path2" ]]
# When no narHash is present the fetching fails
! nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"main\"; rev=\"$rev1\"; })"
+1
View File
@@ -76,6 +76,7 @@ functional_tests_scripts = [
'tarball.sh',
'fetchers.sh',
'fetchGit.sh',
'fetchGitLocked.sh',
'fetchurl.sh',
'fetchPath.sh',
'fetchTree-file.sh',