about summary refs log tree commit diff
path: root/third_party/nix/src/nix/command.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/nix/src/nix/command.cc')
-rw-r--r--third_party/nix/src/nix/command.cc156
1 files changed, 156 insertions, 0 deletions
diff --git a/third_party/nix/src/nix/command.cc b/third_party/nix/src/nix/command.cc
new file mode 100644
index 000000000000..f7f183ab0ab7
--- /dev/null
+++ b/third_party/nix/src/nix/command.cc
@@ -0,0 +1,156 @@
+#include "nix/command.hh"
+
+#include <utility>
+
+#include "libstore/derivations.hh"
+#include "libstore/store-api.hh"
+
+namespace nix {
+
+Commands* RegisterCommand::commands = nullptr;
+
+void Command::printHelp(const std::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(Commands _commands)
+    : commands(std::move(_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 std::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);
+  }
+  return Args::processArgs(args, finish);
+}
+
+StoreCommand::StoreCommand() = default;
+
+ref<Store> StoreCommand::getStore() {
+  if (!_store) {
+    _store = createStore();
+  }
+  return ref<Store>(_store);
+}
+
+ref<Store> StoreCommand::createStore() { return openStore(); }
+
+void StoreCommand::run() { run(getStore()); }
+
+StorePathsCommand::StorePathsCommand(bool recursive) : recursive(recursive) {
+  if (recursive) {
+    mkFlag()
+        .longName("no-recursive")
+        .description("apply operation to specified paths only")
+        .set(&this->recursive, false);
+  } else {
+    mkFlag()
+        .longName("recursive")
+        .shortName('r')
+        .description("apply operation to closure of the specified paths")
+        .set(&this->recursive, true);
+  }
+
+  mkFlag(0, "all", "apply operation to the entire store", &all);
+}
+
+void StorePathsCommand::run(ref<Store> store) {
+  Paths storePaths;
+
+  if (all) {
+    if (!installables.empty() != 0u) {
+      throw UsageError("'--all' does not expect arguments");
+    }
+    for (auto& p : store->queryAllValidPaths()) {
+      storePaths.push_back(p);
+    }
+  }
+
+  else {
+    for (auto& p : toStorePaths(store, NoBuild, installables)) {
+      storePaths.push_back(p);
+    }
+
+    if (recursive) {
+      PathSet closure;
+      store->computeFSClosure(PathSet(storePaths.begin(), storePaths.end()),
+                              closure, false, false);
+      storePaths = Paths(closure.begin(), closure.end());
+    }
+  }
+
+  run(store, storePaths);
+}
+
+void StorePathCommand::run(ref<Store> store) {
+  auto storePaths = toStorePaths(store, NoBuild, installables);
+
+  if (storePaths.size() != 1) {
+    throw UsageError("this command requires exactly one store path");
+  }
+
+  run(store, *storePaths.begin());
+}
+
+}  // namespace nix