Handle store symlinks in flake directories

E.g. 'nix path-info ./result' inside a flake directory now works
again.
This commit is contained in:
Eelco Dolstra 2019-06-21 15:29:05 +02:00
parent 4f6a7c8621
commit d132d057a8
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
5 changed files with 25 additions and 12 deletions

View file

@ -143,6 +143,14 @@ FlakeRef::FlakeRef(const std::string & uri_, bool allowRelative)
IsPath d; IsPath d;
if (allowRelative) { if (allowRelative) {
d.path = absPath(uri); d.path = absPath(uri);
try {
if (!S_ISDIR(lstat(d.path).st_mode))
throw BadFlakeRef("path '%s' is not a flake (sub)directory");
} catch (SysError & e) {
if (e.errNo == ENOENT || e.errNo == EISDIR)
throw BadFlakeRef("flake '%s' does not exist");
throw;
}
while (true) { while (true) {
if (pathExists(d.path + "/.git")) break; if (pathExists(d.path + "/.git")) break;
subdir = baseNameOf(d.path) + (subdir.empty() ? "" : "/" + subdir); subdir = baseNameOf(d.path) + (subdir.empty() ? "" : "/" + subdir);

View file

@ -55,7 +55,7 @@ Path Store::followLinksToStore(const Path & _path) const
path = absPath(target, dirOf(path)); path = absPath(target, dirOf(path));
} }
if (!isInStore(path)) if (!isInStore(path))
throw Error(format("path '%1%' is not in the Nix store") % path); throw NotInStore("path '%1%' is not in the Nix store", path);
return path; return path;
} }

View file

@ -26,6 +26,7 @@ MakeError(InvalidPath, Error)
MakeError(Unsupported, Error) MakeError(Unsupported, Error)
MakeError(SubstituteGone, Error) MakeError(SubstituteGone, Error)
MakeError(SubstituterDisabled, Error) MakeError(SubstituterDisabled, Error)
MakeError(NotInStore, Error)
struct BasicDerivation; struct BasicDerivation;

View file

@ -394,9 +394,18 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
} else { } else {
auto follow = [&](const std::string & s) -> std::optional<Path> {
try {
return store->followLinksToStorePath(s);
} catch (NotInStore &) {
return {};
}
};
for (auto & s : ss) { for (auto & s : ss) {
size_t colon; size_t colon;
std::optional<Path> storePath;
if (s.compare(0, 1, "(") == 0) if (s.compare(0, 1, "(") == 0)
result.push_back(std::make_shared<InstallableExpr>(*this, s)); result.push_back(std::make_shared<InstallableExpr>(*this, s));
@ -422,17 +431,8 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
getDefaultFlakeAttrPathPrefixes())); getDefaultFlakeAttrPathPrefixes()));
} }
else if (s.find('/') != std::string::npos || s == ".") { else if (s.find('/') != std::string::npos && (storePath = follow(s)))
Path storePath; result.push_back(std::make_shared<InstallableStorePath>(*storePath));
try {
storePath = store->toStorePath(store->followLinksToStore(s));
} catch (Error) { }
if (storePath != "")
result.push_back(std::make_shared<InstallableStorePath>(storePath));
else
result.push_back(std::make_shared<InstallableFlake>(*this, FlakeRef(s, true),
getDefaultFlakeAttrPaths()));
}
else else
throw Error("unsupported argument '%s'", s); throw Error("unsupported argument '%s'", s);

View file

@ -149,6 +149,10 @@ nix build -o $TEST_ROOT/result --flake-registry $registry flake1
nix build -o $TEST_ROOT/result --flake-registry $registry $flake1Dir nix build -o $TEST_ROOT/result --flake-registry $registry $flake1Dir
nix build -o $TEST_ROOT/result --flake-registry $registry file://$flake1Dir nix build -o $TEST_ROOT/result --flake-registry $registry file://$flake1Dir
# CHeck that store symlinks inside a flake are not interpreted as flakes.
nix build -o $flake1Dir/result --flake-registry $registry file://$flake1Dir
nix path-info $flake1Dir/result
# Building a flake with an unlocked dependency should fail in pure mode. # Building a flake with an unlocked dependency should fail in pure mode.
(! nix eval "(builtins.getFlake "$flake2Dir")") (! nix eval "(builtins.getFlake "$flake2Dir")")