mirror of
https://github.com/NixOS/nix
synced 2025-06-25 10:41:16 +02:00
nix shell: Resolve symlinks in storeFS
`storeFS` is the `MountedSourceAccessor` that wraps `store->getFSAccessor()`.
This commit is contained in:
parent
eb643d034f
commit
9d3595646d
4 changed files with 42 additions and 33 deletions
|
@ -246,22 +246,8 @@ EvalState::EvalState(
|
|||
}
|
||||
, repair(NoRepair)
|
||||
, emptyBindings(0)
|
||||
, rootFS(
|
||||
({
|
||||
/* In pure eval mode, we provide a filesystem that only
|
||||
contains the Nix store.
|
||||
|
||||
If we have a chroot store and pure eval is not enabled,
|
||||
use a union accessor to make the chroot store available
|
||||
at its logical location while still having the
|
||||
underlying directory available. This is necessary for
|
||||
instance if we're evaluating a file from the physical
|
||||
/nix/store while using a chroot store. */
|
||||
auto accessor = getFSSourceAccessor();
|
||||
|
||||
auto realStoreDir = dirOf(store->toRealPath(StorePath::dummy));
|
||||
if (settings.pureEval || store->storeDir != realStoreDir) {
|
||||
auto storeFS = makeMountedSourceAccessor(
|
||||
, storeFS(
|
||||
makeMountedSourceAccessor(
|
||||
{
|
||||
{CanonPath::root, makeEmptySourceAccessor()},
|
||||
/* In the pure eval case, we can simply require
|
||||
|
@ -283,7 +269,22 @@ EvalState::EvalState(
|
|||
catch it, so we don't need to do this hack.
|
||||
*/
|
||||
{CanonPath(store->storeDir), store->getFSAccessor(settings.pureEval)},
|
||||
});
|
||||
}))
|
||||
, rootFS(
|
||||
({
|
||||
/* In pure eval mode, we provide a filesystem that only
|
||||
contains the Nix store.
|
||||
|
||||
If we have a chroot store and pure eval is not enabled,
|
||||
use a union accessor to make the chroot store available
|
||||
at its logical location while still having the
|
||||
underlying directory available. This is necessary for
|
||||
instance if we're evaluating a file from the physical
|
||||
/nix/store while using a chroot store. */
|
||||
auto accessor = getFSSourceAccessor();
|
||||
|
||||
auto realStoreDir = dirOf(store->toRealPath(StorePath::dummy));
|
||||
if (settings.pureEval || store->storeDir != realStoreDir) {
|
||||
accessor = settings.pureEval
|
||||
? storeFS
|
||||
: makeUnionSourceAccessor({accessor, storeFS});
|
||||
|
|
|
@ -265,6 +265,11 @@ public:
|
|||
/** `"unknown"` */
|
||||
Value vStringUnknown;
|
||||
|
||||
/**
|
||||
* The accessor corresponding to `store`.
|
||||
*/
|
||||
const ref<SourceAccessor> storeFS;
|
||||
|
||||
/**
|
||||
* The accessor for the root filesystem.
|
||||
*/
|
||||
|
|
|
@ -65,11 +65,11 @@ struct CmdShell : InstallablesCommand, MixEnvironment
|
|||
|
||||
void run(ref<Store> store, Installables && installables) override
|
||||
{
|
||||
auto state = getEvalState();
|
||||
|
||||
auto outPaths =
|
||||
Installable::toStorePaths(getEvalStore(), store, Realise::Outputs, OperateOn::Output, installables);
|
||||
|
||||
auto accessor = store->getFSAccessor();
|
||||
|
||||
std::unordered_set<StorePath> done;
|
||||
std::queue<StorePath> todo;
|
||||
for (auto & path : outPaths)
|
||||
|
@ -85,13 +85,16 @@ struct CmdShell : InstallablesCommand, MixEnvironment
|
|||
if (!done.insert(path).second)
|
||||
continue;
|
||||
|
||||
if (true)
|
||||
pathAdditions.push_back(store->printStorePath(path) + "/bin");
|
||||
auto binDir = state->storeFS->resolveSymlinks(CanonPath(store->printStorePath(path)) / "bin");
|
||||
if (!store->isInStore(binDir.abs()))
|
||||
throw Error("path '%s' is not in the Nix store", binDir);
|
||||
|
||||
auto propPath =
|
||||
accessor->resolveSymlinks(CanonPath(path.to_string()) / "nix-support" / "propagated-user-env-packages");
|
||||
if (auto st = accessor->maybeLstat(propPath); st && st->type == SourceAccessor::tRegular) {
|
||||
for (auto & p : tokenizeString<Paths>(accessor->readFile(propPath)))
|
||||
pathAdditions.push_back(binDir.abs());
|
||||
|
||||
auto propPath = state->storeFS->resolveSymlinks(
|
||||
CanonPath(store->printStorePath(path)) / "nix-support" / "propagated-user-env-packages");
|
||||
if (auto st = state->storeFS->maybeLstat(propPath); st && st->type == SourceAccessor::tRegular) {
|
||||
for (auto & p : tokenizeString<Paths>(state->storeFS->readFile(propPath)))
|
||||
todo.push(store->parseStorePath(p));
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +111,7 @@ struct CmdShell : InstallablesCommand, MixEnvironment
|
|||
|
||||
// Release our references to eval caches to ensure they are persisted to disk, because
|
||||
// we are about to exec out of this process without running C++ destructors.
|
||||
getEvalState()->evalCaches.clear();
|
||||
state->evalCaches.clear();
|
||||
|
||||
execProgramInStore(store, UseLookupPath::Use, *command.begin(), args);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ nix shell -f shell-hello.nix 'hello^*' -c hello2 | grep 'Hello2'
|
|||
nix shell -f shell-hello.nix hello-symlink -c hello | grep 'Hello World'
|
||||
|
||||
# Test that symlinks outside of the store don't work.
|
||||
expect 1 nix shell -f shell-hello.nix forbidden-symlink -c hello 2>&1 | grepQuiet "points outside source tree"
|
||||
expect 1 nix shell -f shell-hello.nix forbidden-symlink -c hello 2>&1 | grepQuiet "is not in the Nix store"
|
||||
|
||||
# Test that we're not setting any more environment variables than necessary.
|
||||
# For instance, we might set an environment variable temporarily to affect some
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue