nix develop: Support chroot stores

Fixes #5024.
This commit is contained in:
Eelco Dolstra 2021-07-27 14:23:24 +02:00
parent c000cec27f
commit ed5ad59dc1
3 changed files with 46 additions and 41 deletions

View file

@ -7,6 +7,7 @@
#include "derivations.hh" #include "derivations.hh"
#include "affinity.hh" #include "affinity.hh"
#include "progress-bar.hh" #include "progress-bar.hh"
#include "run.hh"
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
@ -472,8 +473,6 @@ struct CmdDevelop : Common, MixEnvironment
writeFull(rcFileFd.get(), script); writeFull(rcFileFd.get(), script);
stopProgressBar();
setEnviron(); setEnviron();
// prevent garbage collection until shell exits // prevent garbage collection until shell exits
setenv("NIX_GCROOT", gcroot.data(), 1); setenv("NIX_GCROOT", gcroot.data(), 1);
@ -506,11 +505,7 @@ struct CmdDevelop : Common, MixEnvironment
auto args = phase || !command.empty() ? Strings{std::string(baseNameOf(shell)), rcFilePath} auto args = phase || !command.empty() ? Strings{std::string(baseNameOf(shell)), rcFilePath}
: Strings{std::string(baseNameOf(shell)), "--rcfile", rcFilePath}; : Strings{std::string(baseNameOf(shell)), "--rcfile", rcFilePath};
restoreProcessContext(); runProgramInStore(store, shell, args);
execvp(shell.c_str(), stringsToCharPtrs(args).data());
throw SysError("executing shell '%s'", shell);
} }
}; };

View file

@ -1,3 +1,4 @@
#include "run.hh"
#include "command.hh" #include "command.hh"
#include "common-args.hh" #include "common-args.hh"
#include "shared.hh" #include "shared.hh"
@ -20,15 +21,12 @@ using namespace nix;
std::string chrootHelperName = "__run_in_chroot"; std::string chrootHelperName = "__run_in_chroot";
struct RunCommon : virtual Command namespace nix {
{
using Command::run; void runProgramInStore(ref<Store> store,
void runProgram(ref<Store> store,
const std::string & program, const std::string & program,
const Strings & args) const Strings & args)
{ {
stopProgressBar(); stopProgressBar();
restoreProcessContext(); restoreProcessContext();
@ -38,9 +36,9 @@ struct RunCommon : virtual Command
(e.g. /home/eelco/nix/store), then run the command in a (e.g. /home/eelco/nix/store), then run the command in a
chroot. For non-root users, this requires running it in new chroot. For non-root users, this requires running it in new
mount and user namespaces. Unfortunately, mount and user namespaces. Unfortunately,
unshare(CLONE_NEWUSER) doesn't work in a multithreaded unshare(CLONE_NEWUSER) doesn't work in a multithreaded program
program (which "nix" is), so we exec() a single-threaded (which "nix" is), so we exec() a single-threaded helper program
helper program (chrootHelper() below) to do the work. */ (chrootHelper() below) to do the work. */
auto store2 = store.dynamic_pointer_cast<LocalStore>(); auto store2 = store.dynamic_pointer_cast<LocalStore>();
if (store2 && store->storeDir != store2->getRealStoreDir()) { if (store2 && store->storeDir != store2->getRealStoreDir()) {
@ -55,10 +53,11 @@ struct RunCommon : virtual Command
execvp(program.c_str(), stringsToCharPtrs(args).data()); execvp(program.c_str(), stringsToCharPtrs(args).data());
throw SysError("unable to execute '%s'", program); throw SysError("unable to execute '%s'", program);
} }
};
struct CmdShell : InstallablesCommand, RunCommon, MixEnvironment }
struct CmdShell : InstallablesCommand, MixEnvironment
{ {
using InstallablesCommand::run; using InstallablesCommand::run;
@ -125,13 +124,13 @@ struct CmdShell : InstallablesCommand, RunCommon, MixEnvironment
Strings args; Strings args;
for (auto & arg : command) args.push_back(arg); for (auto & arg : command) args.push_back(arg);
runProgram(store, *command.begin(), args); runProgramInStore(store, *command.begin(), args);
} }
}; };
static auto rCmdShell = registerCommand<CmdShell>("shell"); static auto rCmdShell = registerCommand<CmdShell>("shell");
struct CmdRun : InstallableCommand, RunCommon struct CmdRun : InstallableCommand
{ {
using InstallableCommand::run; using InstallableCommand::run;
@ -183,7 +182,7 @@ struct CmdRun : InstallableCommand, RunCommon
Strings allArgs{app.program}; Strings allArgs{app.program};
for (auto & i : args) allArgs.push_back(i); for (auto & i : args) allArgs.push_back(i);
runProgram(store, app.program, allArgs); runProgramInStore(store, app.program, allArgs);
} }
}; };

11
src/nix/run.hh Normal file
View file

@ -0,0 +1,11 @@
#pragma once
#include "store-api.hh"
namespace nix {
void runProgramInStore(ref<Store> store,
const std::string & program,
const Strings & args);
}