lix-releng-staging/src/nix/command.cc

171 lines
4.2 KiB
C++
Raw Normal View History

#include "command.hh"
#include "store-api.hh"
#include "derivations.hh"
#include "nixexpr.hh"
namespace nix {
Commands * RegisterCommand::commands = 0;
2016-04-21 12:58:32 +00:00
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);
}
StoreCommand::StoreCommand()
{
}
ref<Store> StoreCommand::getStore()
{
if (!_store)
_store = createStore();
return ref<Store>(_store);
}
ref<Store> StoreCommand::createStore()
{
return openStore();
}
void StoreCommand::run()
{
run(getStore());
}
2017-09-27 16:28:54 +00:00
StorePathsCommand::StorePathsCommand(bool recursive)
: recursive(recursive)
{
2017-09-27 16:28:54 +00:00
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.size())
throw UsageError("'--all' does not expect arguments");
for (auto & p : store->queryAllValidPaths())
storePaths.push_back(p);
}
else {
Allow content-addressable paths to have references This adds a command 'nix make-content-addressable' that rewrites the specified store paths into content-addressable paths. The advantage of such paths is that 1) they can be imported without signatures; 2) they can enable deduplication in cases where derivation changes do not cause output changes (apart from store path hashes). For example, $ nix make-content-addressable -r nixpkgs.cowsay rewrote '/nix/store/g1g31ah55xdia1jdqabv1imf6mcw0nb1-glibc-2.25-49' to '/nix/store/48jfj7bg78a8n4f2nhg269rgw1936vj4-glibc-2.25-49' ... rewrote '/nix/store/qbi6rzpk0bxjw8lw6azn2mc7ynnn455q-cowsay-3.03+dfsg1-16' to '/nix/store/iq6g2x4q62xp7y7493bibx0qn5w7xz67-cowsay-3.03+dfsg1-16' We can then copy the resulting closure to another store without signatures: $ nix copy --trusted-public-keys '' ---to ~/my-nix /nix/store/iq6g2x4q62xp7y7493bibx0qn5w7xz67-cowsay-3.03+dfsg1-16 In order to support self-references in content-addressable paths, these paths are hashed "modulo" self-references, meaning that self-references are zeroed out during hashing. Somewhat annoyingly, this means that the NAR hash stored in the Nix database is no longer necessarily equal to the output of "nix hash-path"; for content-addressable paths, you need to pass the --modulo flag: $ nix path-info --json /nix/store/iq6g2x4q62xp7y7493bibx0qn5w7xz67-cowsay-3.03+dfsg1-16 | jq -r .[].narHash sha256:0ri611gdilz2c9rsibqhsipbfs9vwcqvs811a52i2bnkhv7w9mgw $ nix hash-path --type sha256 --base32 /nix/store/iq6g2x4q62xp7y7493bibx0qn5w7xz67-cowsay-3.03+dfsg1-16 1ggznh07khq0hz6id09pqws3a8q9pn03ya3c03nwck1kwq8rclzs $ nix hash-path --type sha256 --base32 /nix/store/iq6g2x4q62xp7y7493bibx0qn5w7xz67-cowsay-3.03+dfsg1-16 --modulo iq6g2x4q62xp7y7493bibx0qn5w7xz67 0ri611gdilz2c9rsibqhsipbfs9vwcqvs811a52i2bnkhv7w9mgw
2018-03-29 22:56:13 +00:00
for (auto & p : toStorePaths(store, realiseMode, 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());
}
Strings editorFor(const Pos & pos)
{
auto editor = getEnv("EDITOR", "cat");
auto args = tokenizeString<Strings>(editor);
if (pos.line > 0 && (
editor.find("emacs") != std::string::npos ||
editor.find("nano") != std::string::npos ||
editor.find("vim") != std::string::npos))
args.push_back(fmt("+%d", pos.line));
args.push_back(pos.file);
return args;
}
}