#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