Try and help if a file is missing at eval time

When evaluating a local git flake, if a file a missing at eval-time but
present in the source directory, tell the user that he probably forgot
to check it out

Fix #4507
This commit is contained in:
regnat 2021-07-07 14:29:58 +02:00
parent e1db5992ec
commit 663187219a
3 changed files with 74 additions and 15 deletions

View File

@ -528,26 +528,45 @@ std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableF
auto cache = openEvalCache(*state, lockedFlake); auto cache = openEvalCache(*state, lockedFlake);
auto root = cache->getRoot(); auto root = cache->getRoot();
for (auto & attrPath : getActualAttrPaths()) { try {
auto attr = root->findAlongAttrPath( for (auto & attrPath : getActualAttrPaths()) {
parseAttrPath(*state, attrPath), auto attr = root->findAlongAttrPath(
true parseAttrPath(*state, attrPath),
); true
);
if (!attr) continue; if (!attr) continue;
if (!attr->isDerivation()) if (!attr->isDerivation())
throw Error("flake output attribute '%s' is not a derivation", attrPath); throw Error("flake output attribute '%s' is not a derivation", attrPath);
auto drvPath = attr->forceDerivation(); auto drvPath = attr->forceDerivation();
auto drvInfo = DerivationInfo{ auto drvInfo = DerivationInfo{
std::move(drvPath), std::move(drvPath),
state->store->maybeParseStorePath(attr->getAttr(state->sOutPath)->getString()), state->store->maybeParseStorePath(attr->getAttr(state->sOutPath)->getString()),
attr->getAttr(state->sOutputName)->getString() attr->getAttr(state->sOutputName)->getString()
}; };
return {attrPath, lockedFlake->flake.lockedRef, std::move(drvInfo)}; return {attrPath, lockedFlake->flake.lockedRef, std::move(drvInfo)};
}
} catch (FileError & e) {
if (e.errNo != ENOENT) throw;
if (!state->store->isInStore(e.path)) throw;
auto resolvedInput = lockedFlake->flake.resolvedRef.input;
auto [sourceStorePath, relPath] = state->store->toStorePath(e.path);
if (sourceStorePath != lockedFlake->flake.lockedRef.input.computeStorePath(*state->store)) throw;
if (fetchers::maybeGetStrAttr(resolvedInput.attrs, "type").value_or("") != "git") throw;
if (auto repositoryPath = resolvedInput.getSourcePath()) {
auto sourcePath = *repositoryPath + "/" + relPath;
if (pathExists(sourcePath))
e.addTrace(
noPos,
"The file is present in '%s'. "
"Did you forget to track it in Git?",
*repositoryPath);
}
throw;
} }
throw Error("flake '%s' does not provide attribute %s", throw Error("flake '%s' does not provide attribute %s",

View File

@ -0,0 +1,39 @@
source common.sh
if [[ -z $(type -p git) ]]; then
echo "Git not installed; skipping flake tests"
exit 99
fi
clearStore
rm -rf $TEST_HOME/.cache $TEST_HOME/.config
repo=$TEST_ROOT/flake
rm -rf $repo $repo.tmp
mkdir $repo
git -C $repo init
git -C $repo config user.email "foobar@example.com"
git -C $repo config user.name "Foobar"
cat > $repo/flake.nix <<EOF
{
description = "Bla bla";
outputs = inputs: rec {
packages.$system.foo = import ./simple.nix;
defaultPackage.$system = packages.$system.foo;
};
}
EOF
git -C $repo add flake.nix
git -C $repo commit -m 'Initial'
cp ./simple.nix $repo/
nix build $repo |& grep -q "Did you forget to track it in Git" || \
fail "Trying to access a non git-tracked file should suggest that it is probably the issue"
rm $repo/simple.nix
nix build $repo |& (! grep -q "Did you forget to track it in Git") || \
fail "Trying to use an absent file shouldnt suggest to git add it"

View File

@ -47,6 +47,7 @@ nix_tests = \
describe-stores.sh \ describe-stores.sh \
flakes.sh \ flakes.sh \
flake-local-settings.sh \ flake-local-settings.sh \
flake-missing-file.sh \
build.sh \ build.sh \
compute-levels.sh \ compute-levels.sh \
repl.sh ca/repl.sh \ repl.sh ca/repl.sh \