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.cc165
1 files changed, 92 insertions, 73 deletions
diff --git a/src/nix/command.cc b/src/nix/command.cc
index 724f03e5d..de761166b 100644
--- a/src/nix/command.cc
+++ b/src/nix/command.cc
@@ -2,82 +2,11 @@
#include "store-api.hh"
#include "derivations.hh"
#include "nixexpr.hh"
+#include "profiles.hh"
namespace nix {
-Commands * RegisterCommand::commands = 0;
-
-void Command::printHelp(const string & programName, std::ostream & out)
-{
- Args::printHelp(programName, out);
-
- auto exs = examples();
- if (!exs.empty()) {
- out << "\n";
- out << "Examples:\n";
- for (auto & ex : exs)
- out << "\n"
- << " " << ex.description << "\n" // FIXME: wrap
- << " $ " << ex.command << "\n";
- }
-}
-
-MultiCommand::MultiCommand(const Commands & _commands)
- : commands(_commands)
-{
- expectedArgs.push_back(ExpectedArg{"command", 1, true, [=](std::vector<std::string> ss) {
- assert(!command);
- auto i = commands.find(ss[0]);
- if (i == commands.end())
- throw UsageError("'%s' is not a recognised command", ss[0]);
- command = i->second;
- }});
-}
-
-void MultiCommand::printHelp(const string & programName, std::ostream & out)
-{
- if (command) {
- command->printHelp(programName + " " + command->name(), out);
- return;
- }
-
- out << "Usage: " << programName << " <COMMAND> <FLAGS>... <ARGS>...\n";
-
- out << "\n";
- out << "Common flags:\n";
- printFlags(out);
-
- out << "\n";
- out << "Available commands:\n";
-
- Table2 table;
- for (auto & command : commands) {
- auto descr = command.second->description();
- if (!descr.empty())
- table.push_back(std::make_pair(command.second->name(), descr));
- }
- printTable(out, table);
-
-#if 0
- out << "\n";
- out << "For full documentation, run 'man " << programName << "' or 'man " << programName << "-<COMMAND>'.\n";
-#endif
-}
-
-bool MultiCommand::processFlag(Strings::iterator & pos, Strings::iterator end)
-{
- if (Args::processFlag(pos, end)) return true;
- if (command && command->processFlag(pos, end)) return true;
- return false;
-}
-
-bool MultiCommand::processArgs(const Strings & args, bool finish)
-{
- if (command)
- return command->processArgs(args, finish);
- else
- return Args::processArgs(args, finish);
-}
+Commands * RegisterCommand::commands = nullptr;
StoreCommand::StoreCommand()
{
@@ -167,4 +96,94 @@ Strings editorFor(const Pos & pos)
return args;
}
+MixProfile::MixProfile()
+{
+ mkFlag()
+ .longName("profile")
+ .description("profile to update")
+ .labels({"path"})
+ .dest(&profile);
+}
+
+void MixProfile::updateProfile(const Path & 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, storePath));
+}
+
+void MixProfile::updateProfile(const Buildables & buildables)
+{
+ if (!profile) return;
+
+ std::optional<Path> 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;
+ }
+ }
+
+ 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) {
+ mkFlag()
+ .longName("ignore-environment")
+ .shortName('i')
+ .description("clear the entire environment (except those specified with --keep)")
+ .set(&ignoreEnvironment, true);
+
+ mkFlag()
+ .longName("keep")
+ .shortName('k')
+ .description("keep specified environment variable")
+ .arity(1)
+ .labels({"name"})
+ .handler([&](std::vector<std::string> ss) { keep.insert(ss.front()); });
+
+ mkFlag()
+ .longName("unset")
+ .shortName('u')
+ .description("unset specified environment variable")
+ .arity(1)
+ .labels({"name"})
+ .handler([&](std::vector<std::string> ss) { unset.insert(ss.front()); });
+}
+
+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());
+ }
+}
+
}