aboutsummaryrefslogtreecommitdiff
path: root/src/nix
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2021-07-27 14:23:24 +0200
committerEelco Dolstra <edolstra@gmail.com>2021-07-27 14:24:03 +0200
commited5ad59dc16d8207f14c23f7fca903ee408eb54e (patch)
treef306c29b27760194717677327a547a6f9dcc3334 /src/nix
parentc000cec27fcb16548606830410be265eb082f777 (diff)
nix develop: Support chroot stores
Fixes #5024.
Diffstat (limited to 'src/nix')
-rw-r--r--src/nix/develop.cc9
-rw-r--r--src/nix/run.cc63
-rw-r--r--src/nix/run.hh11
3 files changed, 44 insertions, 39 deletions
diff --git a/src/nix/develop.cc b/src/nix/develop.cc
index 9a93cdb03..55023545d 100644
--- a/src/nix/develop.cc
+++ b/src/nix/develop.cc
@@ -7,6 +7,7 @@
#include "derivations.hh"
#include "affinity.hh"
#include "progress-bar.hh"
+#include "run.hh"
#include <nlohmann/json.hpp>
@@ -472,8 +473,6 @@ struct CmdDevelop : Common, MixEnvironment
writeFull(rcFileFd.get(), script);
- stopProgressBar();
-
setEnviron();
// prevent garbage collection until shell exits
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}
: Strings{std::string(baseNameOf(shell)), "--rcfile", rcFilePath};
- restoreProcessContext();
-
- execvp(shell.c_str(), stringsToCharPtrs(args).data());
-
- throw SysError("executing shell '%s'", shell);
+ runProgramInStore(store, shell, args);
}
};
diff --git a/src/nix/run.cc b/src/nix/run.cc
index 0c8afec2d..7597b61f7 100644
--- a/src/nix/run.cc
+++ b/src/nix/run.cc
@@ -1,3 +1,4 @@
+#include "run.hh"
#include "command.hh"
#include "common-args.hh"
#include "shared.hh"
@@ -20,45 +21,43 @@ using namespace nix;
std::string chrootHelperName = "__run_in_chroot";
-struct RunCommon : virtual Command
-{
+namespace nix {
- using Command::run;
+void runProgramInStore(ref<Store> store,
+ const std::string & program,
+ const Strings & args)
+{
+ stopProgressBar();
- void runProgram(ref<Store> store,
- const std::string & program,
- const Strings & args)
- {
- stopProgressBar();
+ restoreProcessContext();
- restoreProcessContext();
+ /* If this is a diverted store (i.e. its "logical" location
+ (typically /nix/store) differs from its "physical" location
+ (e.g. /home/eelco/nix/store), then run the command in a
+ chroot. For non-root users, this requires running it in new
+ mount and user namespaces. Unfortunately,
+ unshare(CLONE_NEWUSER) doesn't work in a multithreaded program
+ (which "nix" is), so we exec() a single-threaded helper program
+ (chrootHelper() below) to do the work. */
+ auto store2 = store.dynamic_pointer_cast<LocalStore>();
- /* If this is a diverted store (i.e. its "logical" location
- (typically /nix/store) differs from its "physical" location
- (e.g. /home/eelco/nix/store), then run the command in a
- chroot. For non-root users, this requires running it in new
- mount and user namespaces. Unfortunately,
- unshare(CLONE_NEWUSER) doesn't work in a multithreaded
- program (which "nix" is), so we exec() a single-threaded
- helper program (chrootHelper() below) to do the work. */
- auto store2 = store.dynamic_pointer_cast<LocalStore>();
+ if (store2 && store->storeDir != store2->getRealStoreDir()) {
+ Strings helperArgs = { chrootHelperName, store->storeDir, store2->getRealStoreDir(), program };
+ for (auto & arg : args) helperArgs.push_back(arg);
- if (store2 && store->storeDir != store2->getRealStoreDir()) {
- Strings helperArgs = { chrootHelperName, store->storeDir, store2->getRealStoreDir(), program };
- for (auto & arg : args) helperArgs.push_back(arg);
+ execv(readLink("/proc/self/exe").c_str(), stringsToCharPtrs(helperArgs).data());
- execv(readLink("/proc/self/exe").c_str(), stringsToCharPtrs(helperArgs).data());
+ throw SysError("could not execute chroot helper");
+ }
- throw SysError("could not execute chroot helper");
- }
+ 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;
@@ -125,13 +124,13 @@ struct CmdShell : InstallablesCommand, RunCommon, MixEnvironment
Strings args;
for (auto & arg : command) args.push_back(arg);
- runProgram(store, *command.begin(), args);
+ runProgramInStore(store, *command.begin(), args);
}
};
static auto rCmdShell = registerCommand<CmdShell>("shell");
-struct CmdRun : InstallableCommand, RunCommon
+struct CmdRun : InstallableCommand
{
using InstallableCommand::run;
@@ -183,7 +182,7 @@ struct CmdRun : InstallableCommand, RunCommon
Strings allArgs{app.program};
for (auto & i : args) allArgs.push_back(i);
- runProgram(store, app.program, allArgs);
+ runProgramInStore(store, app.program, allArgs);
}
};
diff --git a/src/nix/run.hh b/src/nix/run.hh
new file mode 100644
index 000000000..6180a87dd
--- /dev/null
+++ b/src/nix/run.hh
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "store-api.hh"
+
+namespace nix {
+
+void runProgramInStore(ref<Store> store,
+ const std::string & program,
+ const Strings & args);
+
+}