aboutsummaryrefslogtreecommitdiff
path: root/src/nix/command.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/nix/command.cc')
-rw-r--r--src/nix/command.cc117
1 files changed, 108 insertions, 9 deletions
diff --git a/src/nix/command.cc b/src/nix/command.cc
index 442bc6c53..71b027719 100644
--- a/src/nix/command.cc
+++ b/src/nix/command.cc
@@ -2,6 +2,9 @@
#include "store-api.hh"
#include "derivations.hh"
#include "nixexpr.hh"
+#include "profiles.hh"
+
+extern char * * environ;
namespace nix {
@@ -32,16 +35,18 @@ StorePathsCommand::StorePathsCommand(bool recursive)
: recursive(recursive)
{
if (recursive)
- mkFlag()
- .longName("no-recursive")
- .description("apply operation to specified paths only")
- .set(&this->recursive, false);
+ addFlag({
+ .longName = "no-recursive",
+ .description = "apply operation to specified paths only",
+ .handler = {&this->recursive, false},
+ });
else
- mkFlag()
- .longName("recursive")
- .shortName('r')
- .description("apply operation to closure of the specified paths")
- .set(&this->recursive, true);
+ addFlag({
+ .longName = "recursive",
+ .shortName = 'r',
+ .description = "apply operation to closure of the specified paths",
+ .handler = {&this->recursive, true},
+ });
mkFlag(0, "all", "apply operation to the entire store", &all);
}
@@ -96,4 +101,98 @@ Strings editorFor(const Pos & pos)
return args;
}
+MixProfile::MixProfile()
+{
+ addFlag({
+ .longName = "profile",
+ .description = "profile to update",
+ .labels = {"path"},
+ .handler = {&profile},
+ });
+}
+
+void MixProfile::updateProfile(const StorePath & storePath)
+{
+ if (!profile) return;
+ auto store = getStore().dynamic_pointer_cast<LocalFSStore>();
+ if (!store) throw Error("'--profile' is not supported for this Nix store");
+ auto profile2 = absPath(*profile);
+ switchLink(profile2,
+ createGeneration(
+ ref<LocalFSStore>(store),
+ profile2, store->printStorePath(storePath)));
+}
+
+void MixProfile::updateProfile(const Buildables & buildables)
+{
+ if (!profile) return;
+
+ std::optional<StorePath> result;
+
+ for (auto & buildable : buildables) {
+ for (auto & output : buildable.outputs) {
+ if (result)
+ throw Error("'--profile' requires that the arguments produce a single store path, but there are multiple");
+ result = output.second.clone();
+ }
+ }
+
+ if (!result)
+ throw Error("'--profile' requires that the arguments produce a single store path, but there are none");
+
+ updateProfile(*result);
+}
+
+MixDefaultProfile::MixDefaultProfile()
+{
+ profile = getDefaultProfile();
+}
+
+MixEnvironment::MixEnvironment() : ignoreEnvironment(false)
+{
+ addFlag({
+ .longName = "ignore-environment",
+ .shortName = 'i',
+ .description = "clear the entire environment (except those specified with --keep)",
+ .handler = {&ignoreEnvironment, true},
+ });
+
+ addFlag({
+ .longName = "keep",
+ .shortName = 'k',
+ .description = "keep specified environment variable",
+ .labels = {"name"},
+ .handler = {[&](std::string s) { keep.insert(s); }},
+ });
+
+ addFlag({
+ .longName = "unset",
+ .shortName = 'u',
+ .description = "unset specified environment variable",
+ .labels = {"name"},
+ .handler = {[&](std::string s) { unset.insert(s); }},
+ });
+}
+
+void MixEnvironment::setEnviron() {
+ if (ignoreEnvironment) {
+ if (!unset.empty())
+ throw UsageError("--unset does not make sense with --ignore-environment");
+
+ for (const auto & var : keep) {
+ auto val = getenv(var.c_str());
+ if (val) stringsEnv.emplace_back(fmt("%s=%s", var.c_str(), val));
+ }
+
+ vectorEnv = stringsToCharPtrs(stringsEnv);
+ environ = vectorEnv.data();
+ } else {
+ if (!keep.empty())
+ throw UsageError("--keep does not make sense without --ignore-environment");
+
+ for (const auto & var : unset)
+ unsetenv(var.c_str());
+ }
+}
+
}