From b2d6c6161e61c47f4d8a3faa5799160d100f4e8c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 24 Jul 2020 18:44:43 +0200 Subject: [PATCH 1/9] Move 'nix hash-*' and 'nix to-*' to 'nix hash' From the 'nix' UX review. --- src/nix/hash.cc | 52 +++++++++++++++++++++++++++++++++------------- tests/brotli.sh | 4 ++-- tests/fetchurl.sh | 8 +++---- tests/hash.sh | 10 ++++----- tests/pure-eval.sh | 2 +- tests/tarball.sh | 2 +- 6 files changed, 51 insertions(+), 27 deletions(-) diff --git a/src/nix/hash.cc b/src/nix/hash.cc index 7f3d5717a..101b67e6a 100644 --- a/src/nix/hash.cc +++ b/src/nix/hash.cc @@ -8,7 +8,7 @@ using namespace nix; -struct CmdHash : Command +struct CmdHashBase : Command { FileIngestionMethod mode; Base base = SRI; @@ -17,7 +17,7 @@ struct CmdHash : Command std::vector paths; std::optional modulus; - CmdHash(FileIngestionMethod mode) : mode(mode) + CmdHashBase(FileIngestionMethod mode) : mode(mode) { mkFlag(0, "sri", "print hash in SRI format", &base, SRI); mkFlag(0, "base64", "print hash in base-64", &base, Base64); @@ -51,8 +51,6 @@ struct CmdHash : Command return d; } - Category category() override { return catUtility; } - void run() override { for (auto path : paths) { @@ -79,9 +77,6 @@ struct CmdHash : Command } }; -static RegisterCommand rCmdHashFile("hash-file", [](){ return make_ref(FileIngestionMethod::Flat); }); -static RegisterCommand rCmdHashPath("hash-path", [](){ return make_ref(FileIngestionMethod::Recursive); }); - struct CmdToBase : Command { Base base; @@ -103,8 +98,6 @@ struct CmdToBase : Command "SRI"); } - Category category() override { return catUtility; } - void run() override { for (auto s : args) @@ -112,10 +105,41 @@ struct CmdToBase : Command } }; -static RegisterCommand rCmdToBase16("to-base16", [](){ return make_ref(Base16); }); -static RegisterCommand rCmdToBase32("to-base32", [](){ return make_ref(Base32); }); -static RegisterCommand rCmdToBase64("to-base64", [](){ return make_ref(Base64); }); -static RegisterCommand rCmdToSRI("to-sri", [](){ return make_ref(SRI); }); +struct CmdHash : NixMultiCommand +{ + CmdHash() + : MultiCommand({ + {"file", []() { return make_ref(FileIngestionMethod::Flat);; }}, + {"path", []() { return make_ref(FileIngestionMethod::Recursive); }}, + {"to-base16", []() { return make_ref(Base16); }}, + {"to-base32", []() { return make_ref(Base32); }}, + {"to-base64", []() { return make_ref(Base64); }}, + {"to-sri", []() { return make_ref(SRI); }}, + }) + { } + + std::string description() override + { + return "compute and convert cryptographic hashes"; + } + + Category category() override { return catUtility; } + + void run() override + { + if (!command) + throw UsageError("'nix hash' requires a sub-command."); + command->second->prepare(); + command->second->run(); + } + + void printHelp(const string & programName, std::ostream & out) override + { + MultiCommand::printHelp(programName, out); + } +}; + +static auto rCmdHash = registerCommand("hash"); /* Legacy nix-hash command. */ static int compatNixHash(int argc, char * * argv) @@ -149,7 +173,7 @@ static int compatNixHash(int argc, char * * argv) }); if (op == opHash) { - CmdHash cmd(flat ? FileIngestionMethod::Flat : FileIngestionMethod::Recursive); + CmdHashBase cmd(flat ? FileIngestionMethod::Flat : FileIngestionMethod::Recursive); cmd.ht = ht; cmd.base = base32 ? Base32 : Base16; cmd.truncate = truncate; diff --git a/tests/brotli.sh b/tests/brotli.sh index a3c6e55a8..dc9bbdb66 100644 --- a/tests/brotli.sh +++ b/tests/brotli.sh @@ -9,13 +9,13 @@ outPath=$(nix-build dependencies.nix --no-out-link) nix copy --to $cacheURI $outPath -HASH=$(nix hash-path $outPath) +HASH=$(nix hash path $outPath) clearStore clearCacheCache nix copy --from $cacheURI $outPath --no-check-sigs -HASH2=$(nix hash-path $outPath) +HASH2=$(nix hash path $outPath) [[ $HASH = $HASH2 ]] diff --git a/tests/fetchurl.sh b/tests/fetchurl.sh index 0f2044342..89ff08d4d 100644 --- a/tests/fetchurl.sh +++ b/tests/fetchurl.sh @@ -12,7 +12,7 @@ cmp $outPath fetchurl.sh # Now using a base-64 hash. clearStore -hash=$(nix hash-file --type sha512 --base64 ./fetchurl.sh) +hash=$(nix hash file --type sha512 --base64 ./fetchurl.sh) outPath=$(nix-build '' --argstr url file://$(pwd)/fetchurl.sh --argstr sha512 $hash --no-out-link) @@ -21,7 +21,7 @@ cmp $outPath fetchurl.sh # Now using an SRI hash. clearStore -hash=$(nix hash-file ./fetchurl.sh) +hash=$(nix hash file ./fetchurl.sh) [[ $hash =~ ^sha256- ]] @@ -34,14 +34,14 @@ clearStore other_store=file://$TEST_ROOT/other_store?store=/fnord/store -hash=$(nix hash-file --type sha256 --base16 ./fetchurl.sh) +hash=$(nix hash file --type sha256 --base16 ./fetchurl.sh) storePath=$(nix --store $other_store add-to-store --flat ./fetchurl.sh) outPath=$(nix-build '' --argstr url file:///no-such-dir/fetchurl.sh --argstr sha256 $hash --no-out-link --substituters $other_store) # Test hashed mirrors with an SRI hash. -nix-build '' --argstr url file:///no-such-dir/fetchurl.sh --argstr hash $(nix to-sri --type sha256 $hash) \ +nix-build '' --argstr url file:///no-such-dir/fetchurl.sh --argstr hash $(nix hash to-sri --type sha256 $hash) \ --no-out-link --substituters $other_store # Test unpacking a NAR. diff --git a/tests/hash.sh b/tests/hash.sh index 4cfc97901..e5f75e2cf 100644 --- a/tests/hash.sh +++ b/tests/hash.sh @@ -2,7 +2,7 @@ source common.sh try () { printf "%s" "$2" > $TEST_ROOT/vector - hash=$(nix hash-file --base16 $EXTRA --type "$1" $TEST_ROOT/vector) + hash=$(nix hash file --base16 $EXTRA --type "$1" $TEST_ROOT/vector) if test "$hash" != "$3"; then echo "hash $1, expected $3, got $hash" exit 1 @@ -69,17 +69,17 @@ try2 md5 "f78b733a68f5edbdf9413899339eaa4a" # Conversion. try3() { - h64=$(nix to-base64 --type "$1" "$2") + h64=$(nix hash to-base64 --type "$1" "$2") [ "$h64" = "$4" ] - sri=$(nix to-sri --type "$1" "$2") + sri=$(nix hash to-sri --type "$1" "$2") [ "$sri" = "$1-$4" ] h32=$(nix-hash --type "$1" --to-base32 "$2") [ "$h32" = "$3" ] h16=$(nix-hash --type "$1" --to-base16 "$h32") [ "$h16" = "$2" ] - h16=$(nix to-base16 --type "$1" "$h64") + h16=$(nix hash to-base16 --type "$1" "$h64") [ "$h16" = "$2" ] - h16=$(nix to-base16 "$sri") + h16=$(nix hash to-base16 "$sri") [ "$h16" = "$2" ] } try3 sha1 "800d59cfcd3c05e900cb4e214be48f6b886a08df" "vw46m23bizj4n8afrc0fj19wrp7mj3c0" "gA1Zz808BekAy04hS+SPa4hqCN8=" diff --git a/tests/pure-eval.sh b/tests/pure-eval.sh index 561ca53fb..c994fbb98 100644 --- a/tests/pure-eval.sh +++ b/tests/pure-eval.sh @@ -15,7 +15,7 @@ nix eval --expr 'assert 1 + 2 == 3; true' [[ $(nix eval --impure --expr "(import (builtins.fetchurl { url = file://$(pwd)/pure-eval.nix; })).x") == 123 ]] (! nix eval --expr "(import (builtins.fetchurl { url = file://$(pwd)/pure-eval.nix; })).x") -nix eval --expr "(import (builtins.fetchurl { url = file://$(pwd)/pure-eval.nix; sha256 = \"$(nix hash-file pure-eval.nix --type sha256)\"; })).x" +nix eval --expr "(import (builtins.fetchurl { url = file://$(pwd)/pure-eval.nix; sha256 = \"$(nix hash file pure-eval.nix --type sha256)\"; })).x" rm -rf $TEST_ROOT/eval-out nix eval --store dummy:// --write-to $TEST_ROOT/eval-out --expr '{ x = "foo" + "bar"; y = { z = "bla"; }; }' diff --git a/tests/tarball.sh b/tests/tarball.sh index fe65a22e4..d53ec8cd9 100644 --- a/tests/tarball.sh +++ b/tests/tarball.sh @@ -10,7 +10,7 @@ mkdir -p $tarroot cp dependencies.nix $tarroot/default.nix cp config.nix dependencies.builder*.sh $tarroot/ -hash=$(nix hash-path $tarroot) +hash=$(nix hash path $tarroot) test_tarball() { local ext="$1" From 5781f45c46d7f6c55f87528ab1e754d070bc99ee Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 3 Dec 2020 17:55:27 +0100 Subject: [PATCH 2/9] Allow registering subcommands of subcommands --- src/nix/command.cc | 16 +++++++++++++++- src/nix/command.hh | 13 +++++++++++-- src/nix/main.cc | 2 +- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/nix/command.cc b/src/nix/command.cc index 9a38c77f1..596217775 100644 --- a/src/nix/command.cc +++ b/src/nix/command.cc @@ -11,7 +11,21 @@ extern char * * environ __attribute__((weak)); namespace nix { -Commands * RegisterCommand::commands = nullptr; +RegisterCommand::Commands * RegisterCommand::commands = nullptr; + +nix::Commands RegisterCommand::getCommandsFor(const std::vector & prefix) +{ + nix::Commands res; + for (auto & [name, command] : *RegisterCommand::commands) + if (name.size() == prefix.size() + 1) { + bool equal = true; + for (size_t i = 0; i < prefix.size(); ++i) + if (name[i] != prefix[i]) equal = false; + if (equal) + res.insert_or_assign(name[prefix.size()], command); + } + return res; +} void NixMultiCommand::printHelp(const string & programName, std::ostream & out) { diff --git a/src/nix/command.hh b/src/nix/command.hh index d60c8aeb6..6882db195 100644 --- a/src/nix/command.hh +++ b/src/nix/command.hh @@ -176,20 +176,29 @@ struct StorePathCommand : public InstallablesCommand /* A helper class for registering commands globally. */ struct RegisterCommand { + typedef std::map, std::function()>> Commands; static Commands * commands; - RegisterCommand(const std::string & name, + RegisterCommand(std::vector && name, std::function()> command) { if (!commands) commands = new Commands; commands->emplace(name, command); } + + static nix::Commands getCommandsFor(const std::vector & prefix); }; template static RegisterCommand registerCommand(const std::string & name) { - return RegisterCommand(name, [](){ return make_ref(); }); + return RegisterCommand({name}, [](){ return make_ref(); }); +} + +template +static RegisterCommand registerCommand2(std::vector && name) +{ + return RegisterCommand(std::move(name), [](){ return make_ref(); }); } Buildables build(ref store, Realise mode, diff --git a/src/nix/main.cc b/src/nix/main.cc index a75f8ae65..6d8c66406 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -59,7 +59,7 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs bool useNet = true; bool refresh = false; - NixArgs() : MultiCommand(*RegisterCommand::commands), MixCommonArgs("nix") + NixArgs() : MultiCommand(RegisterCommand::getCommandsFor({})), MixCommonArgs("nix") { categories.clear(); categories[Command::catDefault] = "Main commands"; From 79c1967ded92574129c6a20116ef205a9c747bac Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 3 Dec 2020 18:06:46 +0100 Subject: [PATCH 3/9] Introduce 'nix store' command --- src/nix/store.cc | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/nix/store.cc diff --git a/src/nix/store.cc b/src/nix/store.cc new file mode 100644 index 000000000..e91bcc503 --- /dev/null +++ b/src/nix/store.cc @@ -0,0 +1,31 @@ +#include "command.hh" + +using namespace nix; + +struct CmdStore : virtual NixMultiCommand +{ + CmdStore() : MultiCommand(RegisterCommand::getCommandsFor({"store"})) + { } + + std::string description() override + { + return "manipulate a Nix store"; + } + + Category category() override { return catUtility; } + + void run() override + { + if (!command) + throw UsageError("'nix store' requires a sub-command."); + command->second->prepare(); + command->second->run(); + } + + void printHelp(const string & programName, std::ostream & out) override + { + MultiCommand::printHelp(programName, out); + } +}; + +static auto rCmdStore = registerCommand("store"); From ef583303f0720d8bc9d6351cd769f92d5dd678f3 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 24 Jul 2020 20:42:24 +0200 Subject: [PATCH 4/9] Move NAR-related commands to 'nix nar' --- src/nix/cat.cc | 6 ++---- src/nix/ls.cc | 8 +++----- src/nix/nar.cc | 31 +++++++++++++++++++++++++++++++ tests/binary-cache.sh | 6 +++--- tests/linux-sandbox.sh | 4 ++-- tests/nar-access.sh | 26 +++++++++++++------------- 6 files changed, 54 insertions(+), 27 deletions(-) create mode 100644 src/nix/nar.cc diff --git a/src/nix/cat.cc b/src/nix/cat.cc index eef172cfc..4fa1c9491 100644 --- a/src/nix/cat.cc +++ b/src/nix/cat.cc @@ -64,13 +64,11 @@ struct CmdCatNar : StoreCommand, MixCat return "print the contents of a file inside a NAR file on stdout"; } - Category category() override { return catUtility; } - void run(ref store) override { cat(makeNarAccessor(make_ref(readFile(narPath)))); } }; -static auto rCmdCatStore = registerCommand("cat-store"); -static auto rCmdCatNar = registerCommand("cat-nar"); +static auto rCmdCatStore = registerCommand2({"store", "cat"}); +static auto rCmdCatNar = registerCommand2({"nar", "cat"}); diff --git a/src/nix/ls.cc b/src/nix/ls.cc index f39fdb2fd..d5fec4d84 100644 --- a/src/nix/ls.cc +++ b/src/nix/ls.cc @@ -134,7 +134,7 @@ struct CmdLsNar : Command, MixLs return { Example{ "To list a specific file in a NAR:", - "nix ls-nar -l hello.nar /bin/hello" + "nix nar ls -l hello.nar /bin/hello" }, }; } @@ -144,13 +144,11 @@ struct CmdLsNar : Command, MixLs return "show information about a path inside a NAR file"; } - Category category() override { return catUtility; } - void run() override { list(makeNarAccessor(make_ref(readFile(narPath)))); } }; -static auto rCmdLsStore = registerCommand("ls-store"); -static auto rCmdLsNar = registerCommand("ls-nar"); +static auto rCmdLsStore = registerCommand2({"store", "ls"}); +static auto rCmdLsNar = registerCommand2({"nar", "ls"}); diff --git a/src/nix/nar.cc b/src/nix/nar.cc new file mode 100644 index 000000000..e239ce96a --- /dev/null +++ b/src/nix/nar.cc @@ -0,0 +1,31 @@ +#include "command.hh" + +using namespace nix; + +struct CmdNar : NixMultiCommand +{ + CmdNar() : MultiCommand(RegisterCommand::getCommandsFor({"nar"})) + { } + + std::string description() override + { + return "query the contents of NAR files"; + } + + Category category() override { return catUtility; } + + void run() override + { + if (!command) + throw UsageError("'nix nar' requires a sub-command."); + command->second->prepare(); + command->second->run(); + } + + void printHelp(const string & programName, std::ostream & out) override + { + MultiCommand::printHelp(programName, out); + } +}; + +static auto rCmdNar = registerCommand("nar"); diff --git a/tests/binary-cache.sh b/tests/binary-cache.sh index e3b3982fe..8cb17caf8 100644 --- a/tests/binary-cache.sh +++ b/tests/binary-cache.sh @@ -196,13 +196,13 @@ narCache=$TEST_ROOT/nar-cache rm -rf $narCache mkdir $narCache -[[ $(nix cat-store --store "file://$cacheDir?local-nar-cache=$narCache" $outPath/foobar) = FOOBAR ]] +[[ $(nix store cat --store "file://$cacheDir?local-nar-cache=$narCache" $outPath/foobar) = FOOBAR ]] rm -rfv "$cacheDir/nar" -[[ $(nix cat-store --store "file://$cacheDir?local-nar-cache=$narCache" $outPath/foobar) = FOOBAR ]] +[[ $(nix store cat --store "file://$cacheDir?local-nar-cache=$narCache" $outPath/foobar) = FOOBAR ]] -(! nix cat-store --store file://$cacheDir $outPath/foobar) +(! nix store cat --store file://$cacheDir $outPath/foobar) # Test NAR listing generation. diff --git a/tests/linux-sandbox.sh b/tests/linux-sandbox.sh index 16abd974c..70a90a907 100644 --- a/tests/linux-sandbox.sh +++ b/tests/linux-sandbox.sh @@ -22,9 +22,9 @@ outPath=$(nix-build dependencies.nix --no-out-link --sandbox-paths /nix/store) nix path-info -r $outPath | grep input-2 -nix ls-store -R -l $outPath | grep foobar +nix store ls -R -l $outPath | grep foobar -nix cat-store $outPath/foobar | grep FOOBAR +nix store cat $outPath/foobar | grep FOOBAR # Test --check without hash rewriting. nix-build dependencies.nix --no-out-link --check --sandbox-paths /nix/store diff --git a/tests/nar-access.sh b/tests/nar-access.sh index 88b997ca6..dcc2e8a36 100644 --- a/tests/nar-access.sh +++ b/tests/nar-access.sh @@ -9,45 +9,45 @@ cd "$TEST_ROOT" narFile="$TEST_ROOT/path.nar" nix-store --dump $storePath > $narFile -# Check that find and ls-nar match. +# Check that find and nar ls match. ( cd $storePath; find . | sort ) > files.find -nix ls-nar -R -d $narFile "" | sort > files.ls-nar +nix nar ls -R -d $narFile "" | sort > files.ls-nar diff -u files.find files.ls-nar # Check that file contents of data match. -nix cat-nar $narFile /foo/data > data.cat-nar +nix nar cat $narFile /foo/data > data.cat-nar diff -u data.cat-nar $storePath/foo/data # Check that file contents of baz match. -nix cat-nar $narFile /foo/baz > baz.cat-nar +nix nar cat $narFile /foo/baz > baz.cat-nar diff -u baz.cat-nar $storePath/foo/baz -nix cat-store $storePath/foo/baz > baz.cat-nar +nix store cat $storePath/foo/baz > baz.cat-nar diff -u baz.cat-nar $storePath/foo/baz # Test --json. diff -u \ - <(nix ls-nar --json $narFile / | jq -S) \ + <(nix nar ls --json $narFile / | jq -S) \ <(echo '{"type":"directory","entries":{"foo":{},"foo-x":{},"qux":{},"zyx":{}}}' | jq -S) diff -u \ - <(nix ls-nar --json -R $narFile /foo | jq -S) \ + <(nix nar ls --json -R $narFile /foo | jq -S) \ <(echo '{"type":"directory","entries":{"bar":{"type":"regular","size":0,"narOffset":368},"baz":{"type":"regular","size":0,"narOffset":552},"data":{"type":"regular","size":58,"narOffset":736}}}' | jq -S) diff -u \ - <(nix ls-nar --json -R $narFile /foo/bar | jq -S) \ + <(nix nar ls --json -R $narFile /foo/bar | jq -S) \ <(echo '{"type":"regular","size":0,"narOffset":368}' | jq -S) diff -u \ - <(nix ls-store --json $storePath | jq -S) \ + <(nix store ls --json $storePath | jq -S) \ <(echo '{"type":"directory","entries":{"foo":{},"foo-x":{},"qux":{},"zyx":{}}}' | jq -S) diff -u \ - <(nix ls-store --json -R $storePath/foo | jq -S) \ + <(nix store ls --json -R $storePath/foo | jq -S) \ <(echo '{"type":"directory","entries":{"bar":{"type":"regular","size":0},"baz":{"type":"regular","size":0},"data":{"type":"regular","size":58}}}' | jq -S) diff -u \ - <(nix ls-store --json -R $storePath/foo/bar| jq -S) \ + <(nix store ls --json -R $storePath/foo/bar| jq -S) \ <(echo '{"type":"regular","size":0}' | jq -S) # Test missing files. -nix ls-store --json -R $storePath/xyzzy 2>&1 | grep 'does not exist in NAR' -nix ls-store $storePath/xyzzy 2>&1 | grep 'does not exist' +nix store ls --json -R $storePath/xyzzy 2>&1 | grep 'does not exist in NAR' +nix store ls $storePath/xyzzy 2>&1 | grep 'does not exist' # Test failure to dump. if nix-store --dump $storePath >/dev/full ; then From 0c15ae5d4b3366a14bca885e02599a941a334920 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 24 Jul 2020 20:44:31 +0200 Subject: [PATCH 5/9] Add FIXME --- src/nix/show-derivation.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nix/show-derivation.cc b/src/nix/show-derivation.cc index 6d4f295d7..8e1a58ac2 100644 --- a/src/nix/show-derivation.cc +++ b/src/nix/show-derivation.cc @@ -1,4 +1,5 @@ // FIXME: integrate this with nix path-info? +// FIXME: rename to 'nix store show-derivation' or 'nix debug show-derivation'? #include "command.hh" #include "common-args.hh" From af373c2ece2c14ac652313a6f370dc344c85f86e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 3 Dec 2020 22:45:44 +0100 Subject: [PATCH 6/9] Add deprecated aliases for renamed commands --- src/libutil/args.cc | 5 +---- src/libutil/args.hh | 5 +++-- src/nix/main.cc | 30 +++++++++++++++++++++++++++++- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/libutil/args.cc b/src/libutil/args.cc index 8bd9c8aeb..61f9503ec 100644 --- a/src/libutil/args.cc +++ b/src/libutil/args.cc @@ -86,6 +86,7 @@ void Args::parseCmdline(const Strings & _cmdline) throw UsageError("unrecognised flag '%1%'", arg); } else { + pos = rewriteArgs(cmdline, pos); pendingArgs.push_back(*pos++); if (processArgs(pendingArgs, false)) pendingArgs.clear(); @@ -390,10 +391,6 @@ MultiCommand::MultiCommand(const Commands & commands) .optional = true, .handler = {[=](std::string s) { assert(!command); - if (auto alias = get(deprecatedAliases, s)) { - warn("'%s' is a deprecated alias for '%s'", s, *alias); - s = *alias; - } if (auto prefix = needsCompletion(s)) { for (auto & [name, command] : commands) if (hasPrefix(name, *prefix)) diff --git a/src/libutil/args.hh b/src/libutil/args.hh index 26f1bc11b..8069fd70f 100644 --- a/src/libutil/args.hh +++ b/src/libutil/args.hh @@ -115,6 +115,9 @@ protected: virtual bool processArgs(const Strings & args, bool finish); + virtual Strings::iterator rewriteArgs(Strings & args, Strings::iterator pos) + { return pos; } + std::set hiddenCategories; public: @@ -257,8 +260,6 @@ public: std::map categories; - std::map deprecatedAliases; - // Selected command, if any. std::optional>> command; diff --git a/src/nix/main.cc b/src/nix/main.cc index 6d8c66406..94f4cad3c 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -112,8 +112,36 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs .description = "consider all previously downloaded files out-of-date", .handler = {[&]() { refresh = true; }}, }); + } - deprecatedAliases.insert({"dev-shell", "develop"}); + std::map> aliases = { + {"dev-shell", {"develop"}}, + {"hash-file", {"hash", "file"}}, + {"hash-path", {"hash", "path"}}, + {"to-base16", {"hash", "to-base16"}}, + {"to-base32", {"hash", "to-base32"}}, + {"to-base64", {"hash", "to-base64"}}, + {"ls-nar", {"nar", "ls"}}, + {"ls-store", {"store", "ls"}}, + {"cat-nar", {"nar", "cat"}}, + {"cat-store", {"store", "cat"}}, + }; + + bool aliasUsed = false; + + Strings::iterator rewriteArgs(Strings & args, Strings::iterator pos) override + { + if (aliasUsed || command || pos == args.end()) return pos; + auto arg = *pos; + auto i = aliases.find(arg); + if (i == aliases.end()) return pos; + warn("'%s' is a deprecated alias for '%s'", + arg, concatStringsSep(" ", i->second)); + pos = args.erase(pos); + for (auto j = i->second.rbegin(); j != i->second.rend(); ++j) + pos = args.insert(pos, *j); + aliasUsed = true; + return pos; } void printFlags(std::ostream & out) override From a1cd805cba7a4408e75779bc4099f92e81fd6ac7 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 24 Jul 2020 21:04:26 +0200 Subject: [PATCH 7/9] Add 'nix nar dump-path' This only differs from 'nix store dump-path' in that the path doesn't need to be a store path. --- src/nix/dump-path.cc | 44 ++++++++++++++++++++++++++++++++++++++++++-- src/nix/main.cc | 1 + 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/nix/dump-path.cc b/src/nix/dump-path.cc index 6fd197531..4b225ae9f 100644 --- a/src/nix/dump-path.cc +++ b/src/nix/dump-path.cc @@ -1,5 +1,6 @@ #include "command.hh" #include "store-api.hh" +#include "archive.hh" using namespace nix; @@ -7,7 +8,7 @@ struct CmdDumpPath : StorePathCommand { std::string description() override { - return "dump a store path to stdout (in NAR format)"; + return "serialise a store path to stdout in NAR format"; } Examples examples() override @@ -30,4 +31,43 @@ struct CmdDumpPath : StorePathCommand } }; -static auto rDumpPath = registerCommand("dump-path"); + +static auto rDumpPath = registerCommand2({"store", "dump-path"}); + +struct CmdDumpPath2 : Command +{ + Path path; + + CmdDumpPath2() + { + expectArgs({ + .label = "path", + .handler = {&path}, + .completer = completePath + }); + } + + std::string description() override + { + return "serialise a path to stdout in NAR format"; + } + + Examples examples() override + { + return { + Example{ + "To serialise directory 'foo' as a NAR:", + "nix nar dump-path ./foo" + }, + }; + } + + void run() override + { + FdSink sink(STDOUT_FILENO); + dumpPath(path, sink); + sink.flush(); + } +}; + +static auto rDumpPath2 = registerCommand2({"nar", "dump-path"}); diff --git a/src/nix/main.cc b/src/nix/main.cc index 94f4cad3c..0002be291 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -125,6 +125,7 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs {"ls-store", {"store", "ls"}}, {"cat-nar", {"nar", "cat"}}, {"cat-store", {"store", "cat"}}, + {"dump-path", {"store", "dump-path"}}, }; bool aliasUsed = false; From ea2062a2d9144d78588675950fc04756f0d200a5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 24 Jul 2020 20:38:56 +0200 Subject: [PATCH 8/9] Move most store-related commands to 'nix store' --- src/nix/add-to-store.cc | 4 +-- src/nix/cat.cc | 2 -- src/nix/diff-closures.cc | 6 ++-- src/nix/dump-path.cc | 5 +-- src/nix/ls.cc | 4 +-- src/nix/main.cc | 18 ++++++++--- src/nix/make-content-addressable.cc | 8 ++--- src/nix/optimise-store.cc | 6 ++-- src/nix/ping-store.cc | 6 ++-- src/nix/sigs.cc | 8 ++--- src/nix/verify.cc | 8 ++--- tests/binary-cache.sh | 2 +- tests/fetchurl.sh | 2 +- tests/gc-auto.sh | 6 ++-- tests/recursive.sh | 4 +-- tests/signing.sh | 48 ++++++++++++++--------------- tests/ssh-relay.sh | 2 +- 17 files changed, 62 insertions(+), 77 deletions(-) diff --git a/src/nix/add-to-store.cc b/src/nix/add-to-store.cc index a2721431e..66822b0ff 100644 --- a/src/nix/add-to-store.cc +++ b/src/nix/add-to-store.cc @@ -43,8 +43,6 @@ struct CmdAddToStore : MixDryRun, StoreCommand ; } - Category category() override { return catUtility; } - void run(ref store) override { if (!namePart) namePart = baseNameOf(path); @@ -80,4 +78,4 @@ struct CmdAddToStore : MixDryRun, StoreCommand } }; -static auto rCmdAddToStore = registerCommand("add-to-store"); +static auto rCmdAddToStore = registerCommand2({"store", "add-path"}); diff --git a/src/nix/cat.cc b/src/nix/cat.cc index 4fa1c9491..2ecffc9a5 100644 --- a/src/nix/cat.cc +++ b/src/nix/cat.cc @@ -37,8 +37,6 @@ struct CmdCatStore : StoreCommand, MixCat return "print the contents of a file in the Nix store on stdout"; } - Category category() override { return catUtility; } - void run(ref store) override { cat(store->getFSAccessor()); diff --git a/src/nix/diff-closures.cc b/src/nix/diff-closures.cc index 30e7b20e1..f72b5eff7 100644 --- a/src/nix/diff-closures.cc +++ b/src/nix/diff-closures.cc @@ -121,14 +121,12 @@ struct CmdDiffClosures : SourceExprCommand return "show what packages and versions were added and removed between two closures"; } - Category category() override { return catSecondary; } - Examples examples() override { return { { "To show what got added and removed between two versions of the NixOS system profile:", - "nix diff-closures /nix/var/nix/profiles/system-655-link /nix/var/nix/profiles/system-658-link", + "nix store diff-closures /nix/var/nix/profiles/system-655-link /nix/var/nix/profiles/system-658-link", }, }; } @@ -143,4 +141,4 @@ struct CmdDiffClosures : SourceExprCommand } }; -static auto rCmdDiffClosures = registerCommand("diff-closures"); +static auto rCmdDiffClosures = registerCommand2({"store", "diff-closures"}); diff --git a/src/nix/dump-path.cc b/src/nix/dump-path.cc index 4b225ae9f..256db64a9 100644 --- a/src/nix/dump-path.cc +++ b/src/nix/dump-path.cc @@ -16,13 +16,11 @@ struct CmdDumpPath : StorePathCommand return { Example{ "To get a NAR from the binary cache https://cache.nixos.org/:", - "nix dump-path --store https://cache.nixos.org/ /nix/store/7crrmih8c52r8fbnqb933dxrsp44md93-glibc-2.25" + "nix store dump-path --store https://cache.nixos.org/ /nix/store/7crrmih8c52r8fbnqb933dxrsp44md93-glibc-2.25" }, }; } - Category category() override { return catUtility; } - void run(ref store, const StorePath & storePath) override { FdSink sink(STDOUT_FILENO); @@ -31,7 +29,6 @@ struct CmdDumpPath : StorePathCommand } }; - static auto rDumpPath = registerCommand2({"store", "dump-path"}); struct CmdDumpPath2 : Command diff --git a/src/nix/ls.cc b/src/nix/ls.cc index d5fec4d84..1f5ed6913 100644 --- a/src/nix/ls.cc +++ b/src/nix/ls.cc @@ -97,7 +97,7 @@ struct CmdLsStore : StoreCommand, MixLs return { Example{ "To list the contents of a store path in a binary cache:", - "nix ls-store --store https://cache.nixos.org/ -lR /nix/store/0i2jd68mp5g6h2sa5k9c85rb80sn8hi9-hello-2.10" + "nix store ls --store https://cache.nixos.org/ -lR /nix/store/0i2jd68mp5g6h2sa5k9c85rb80sn8hi9-hello-2.10" }, }; } @@ -107,8 +107,6 @@ struct CmdLsStore : StoreCommand, MixLs return "show information about a path in the Nix store"; } - Category category() override { return catUtility; } - void run(ref store) override { list(store->getFSAccessor()); diff --git a/src/nix/main.cc b/src/nix/main.cc index 0002be291..fb3bffeaf 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -115,17 +115,25 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs } std::map> aliases = { + {"add-to-store", {"store", "add-path"}}, + {"cat-nar", {"nar", "cat"}}, + {"cat-store", {"store", "cat"}}, + {"copy-sigs", {"store", "copy-sigs"}}, {"dev-shell", {"develop"}}, + {"diff-closures", {"store", "diff-closures"}}, + {"dump-path", {"store", "dump-path"}}, {"hash-file", {"hash", "file"}}, {"hash-path", {"hash", "path"}}, + {"ls-nar", {"nar", "ls"}}, + {"ls-store", {"store", "ls"}}, + {"make-content-addressable", {"store", "make-content-addressable"}}, + {"optimise-store", {"store", "optimise"}}, + {"ping-store", {"store", "ping"}}, + {"sign-paths", {"store", "sign-paths"}}, {"to-base16", {"hash", "to-base16"}}, {"to-base32", {"hash", "to-base32"}}, {"to-base64", {"hash", "to-base64"}}, - {"ls-nar", {"nar", "ls"}}, - {"ls-store", {"store", "ls"}}, - {"cat-nar", {"nar", "cat"}}, - {"cat-store", {"store", "cat"}}, - {"dump-path", {"store", "dump-path"}}, + {"verify", {"store", "verify"}}, }; bool aliasUsed = false; diff --git a/src/nix/make-content-addressable.cc b/src/nix/make-content-addressable.cc index 12c2cf776..0dade90ef 100644 --- a/src/nix/make-content-addressable.cc +++ b/src/nix/make-content-addressable.cc @@ -23,17 +23,15 @@ struct CmdMakeContentAddressable : StorePathsCommand, MixJSON return { Example{ "To create a content-addressable representation of GNU Hello (but not its dependencies):", - "nix make-content-addressable nixpkgs#hello" + "nix store make-content-addressable nixpkgs#hello" }, Example{ "To compute a content-addressable representation of the current NixOS system closure:", - "nix make-content-addressable -r /run/current-system" + "nix store make-content-addressable -r /run/current-system" }, }; } - Category category() override { return catUtility; } - void run(ref store, StorePaths storePaths) override { auto paths = store->topoSortPaths(StorePathSet(storePaths.begin(), storePaths.end())); @@ -108,4 +106,4 @@ struct CmdMakeContentAddressable : StorePathsCommand, MixJSON } }; -static auto rCmdMakeContentAddressable = registerCommand("make-content-addressable"); +static auto rCmdMakeContentAddressable = registerCommand2({"store", "make-content-addressable"}); diff --git a/src/nix/optimise-store.cc b/src/nix/optimise-store.cc index 51a7a9756..bc7f175ac 100644 --- a/src/nix/optimise-store.cc +++ b/src/nix/optimise-store.cc @@ -18,17 +18,15 @@ struct CmdOptimiseStore : StoreCommand return { Example{ "To optimise the Nix store:", - "nix optimise-store" + "nix store optimise" }, }; } - Category category() override { return catUtility; } - void run(ref store) override { store->optimiseStore(); } }; -static auto rCmdOptimiseStore = registerCommand("optimise-store"); +static auto rCmdOptimiseStore = registerCommand2({"store", "optimise"}); diff --git a/src/nix/ping-store.cc b/src/nix/ping-store.cc index 8db78d591..19b1a55c8 100644 --- a/src/nix/ping-store.cc +++ b/src/nix/ping-store.cc @@ -16,17 +16,15 @@ struct CmdPingStore : StoreCommand return { Example{ "To test whether connecting to a remote Nix store via SSH works:", - "nix ping-store --store ssh://mac1" + "nix store ping --store ssh://mac1" }, }; } - Category category() override { return catUtility; } - void run(ref store) override { store->connect(); } }; -static auto rCmdPingStore = registerCommand("ping-store"); +static auto rCmdPingStore = registerCommand2({"store", "ping"}); diff --git a/src/nix/sigs.cc b/src/nix/sigs.cc index 44916c77f..37b8a6712 100644 --- a/src/nix/sigs.cc +++ b/src/nix/sigs.cc @@ -27,8 +27,6 @@ struct CmdCopySigs : StorePathsCommand return "copy path signatures from substituters (like binary caches)"; } - Category category() override { return catUtility; } - void run(ref store, StorePaths storePaths) override { if (substituterUris.empty()) @@ -92,7 +90,7 @@ struct CmdCopySigs : StorePathsCommand } }; -static auto rCmdCopySigs = registerCommand("copy-sigs"); +static auto rCmdCopySigs = registerCommand2({"store", "copy-sigs"}); struct CmdSignPaths : StorePathsCommand { @@ -115,8 +113,6 @@ struct CmdSignPaths : StorePathsCommand return "sign the specified paths"; } - Category category() override { return catUtility; } - void run(ref store, StorePaths storePaths) override { if (secretKeyFile.empty()) @@ -144,4 +140,4 @@ struct CmdSignPaths : StorePathsCommand } }; -static auto rCmdSignPaths = registerCommand("sign-paths"); +static auto rCmdSignPaths = registerCommand2({"store", "sign-paths"}); diff --git a/src/nix/verify.cc b/src/nix/verify.cc index ec7333d03..bcf85d7dd 100644 --- a/src/nix/verify.cc +++ b/src/nix/verify.cc @@ -40,17 +40,15 @@ struct CmdVerify : StorePathsCommand return { Example{ "To verify the entire Nix store:", - "nix verify --all" + "nix store verify --all" }, Example{ "To check whether each path in the closure of Firefox has at least 2 signatures:", - "nix verify -r -n2 --no-contents $(type -p firefox)" + "nix store verify -r -n2 --no-contents $(type -p firefox)" }, }; } - Category category() override { return catSecondary; } - void run(ref store, StorePaths storePaths) override { std::vector> substituters; @@ -189,4 +187,4 @@ struct CmdVerify : StorePathsCommand } }; -static auto rCmdVerify = registerCommand("verify"); +static auto rCmdVerify = registerCommand2({"store", "verify"}); diff --git a/tests/binary-cache.sh b/tests/binary-cache.sh index 8cb17caf8..92ed36225 100644 --- a/tests/binary-cache.sh +++ b/tests/binary-cache.sh @@ -188,7 +188,7 @@ unset _NIX_FORCE_HTTP # Test 'nix verify --all' on a binary cache. -nix verify -vvvvv --all --store file://$cacheDir --no-trust +nix store verify -vvvvv --all --store file://$cacheDir --no-trust # Test local NAR caching. diff --git a/tests/fetchurl.sh b/tests/fetchurl.sh index 89ff08d4d..7ec25808c 100644 --- a/tests/fetchurl.sh +++ b/tests/fetchurl.sh @@ -36,7 +36,7 @@ other_store=file://$TEST_ROOT/other_store?store=/fnord/store hash=$(nix hash file --type sha256 --base16 ./fetchurl.sh) -storePath=$(nix --store $other_store add-to-store --flat ./fetchurl.sh) +storePath=$(nix --store $other_store store add-path --flat ./fetchurl.sh) outPath=$(nix-build '' --argstr url file:///no-such-dir/fetchurl.sh --argstr sha256 $hash --no-out-link --substituters $other_store) diff --git a/tests/gc-auto.sh b/tests/gc-auto.sh index 3add896c6..6867f2eb4 100644 --- a/tests/gc-auto.sh +++ b/tests/gc-auto.sh @@ -2,9 +2,9 @@ source common.sh clearStore -garbage1=$(nix add-to-store --name garbage1 ./nar-access.sh) -garbage2=$(nix add-to-store --name garbage2 ./nar-access.sh) -garbage3=$(nix add-to-store --name garbage3 ./nar-access.sh) +garbage1=$(nix store add-path --name garbage1 ./nar-access.sh) +garbage2=$(nix store add-path --name garbage2 ./nar-access.sh) +garbage3=$(nix store add-path --name garbage3 ./nar-access.sh) ls -l $garbage3 POSIXLY_CORRECT=1 du $garbage3 diff --git a/tests/recursive.sh b/tests/recursive.sh index 80a178cc7..b020ec710 100644 --- a/tests/recursive.sh +++ b/tests/recursive.sh @@ -7,7 +7,7 @@ clearStore rm -f $TEST_ROOT/result -export unreachable=$(nix add-to-store ./recursive.sh) +export unreachable=$(nix store add-path ./recursive.sh) NIX_BIN_DIR=$(dirname $(type -p nix)) nix --experimental-features 'nix-command recursive-nix' build -o $TEST_ROOT/result -L --impure --expr ' with import ./config.nix; @@ -38,7 +38,7 @@ NIX_BIN_DIR=$(dirname $(type -p nix)) nix --experimental-features 'nix-command r # Add something to the store. echo foobar > foobar - foobar=$(nix $opts add-to-store ./foobar) + foobar=$(nix $opts store add-path ./foobar) nix $opts path-info $foobar nix $opts build $foobar diff --git a/tests/signing.sh b/tests/signing.sh index 9e29e3fbf..bd6280cc6 100644 --- a/tests/signing.sh +++ b/tests/signing.sh @@ -17,40 +17,40 @@ info=$(nix path-info --json $outPath) [[ $info =~ 'cache1.example.org' ]] [[ $info =~ 'cache2.example.org' ]] -# Test "nix verify". -nix verify -r $outPath +# Test "nix store verify". +nix store verify -r $outPath -expect 2 nix verify -r $outPath --sigs-needed 1 +expect 2 nix store verify -r $outPath --sigs-needed 1 -nix verify -r $outPath --sigs-needed 1 --trusted-public-keys $pk1 +nix store verify -r $outPath --sigs-needed 1 --trusted-public-keys $pk1 -expect 2 nix verify -r $outPath --sigs-needed 2 --trusted-public-keys $pk1 +expect 2 nix store verify -r $outPath --sigs-needed 2 --trusted-public-keys $pk1 -nix verify -r $outPath --sigs-needed 2 --trusted-public-keys "$pk1 $pk2" +nix store verify -r $outPath --sigs-needed 2 --trusted-public-keys "$pk1 $pk2" -nix verify --all --sigs-needed 2 --trusted-public-keys "$pk1 $pk2" +nix store verify --all --sigs-needed 2 --trusted-public-keys "$pk1 $pk2" # Build something unsigned. outPath2=$(nix-build simple.nix --no-out-link) -nix verify -r $outPath +nix store verify -r $outPath # Verify that the path did not get signed but does have the ultimate bit. info=$(nix path-info --json $outPath2) [[ $info =~ '"ultimate":true' ]] (! [[ $info =~ 'signatures' ]]) -# Test "nix verify". -nix verify -r $outPath2 +# Test "nix store verify". +nix store verify -r $outPath2 -expect 2 nix verify -r $outPath2 --sigs-needed 1 +expect 2 nix store verify -r $outPath2 --sigs-needed 1 -expect 2 nix verify -r $outPath2 --sigs-needed 1 --trusted-public-keys $pk1 +expect 2 nix store verify -r $outPath2 --sigs-needed 1 --trusted-public-keys $pk1 -# Test "nix sign-paths". -nix sign-paths --key-file $TEST_ROOT/sk1 $outPath2 +# Test "nix store sign-paths". +nix store sign-paths --key-file $TEST_ROOT/sk1 $outPath2 -nix verify -r $outPath2 --sigs-needed 1 --trusted-public-keys $pk1 +nix store verify -r $outPath2 --sigs-needed 1 --trusted-public-keys $pk1 # Build something content-addressed. outPathCA=$(IMPURE_VAR1=foo IMPURE_VAR2=bar nix-build ./fixed.nix -A good.0 --no-out-link) @@ -59,12 +59,12 @@ outPathCA=$(IMPURE_VAR1=foo IMPURE_VAR2=bar nix-build ./fixed.nix -A good.0 --no # Content-addressed paths don't need signatures, so they verify # regardless of --sigs-needed. -nix verify $outPathCA -nix verify $outPathCA --sigs-needed 1000 +nix store verify $outPathCA +nix store verify $outPathCA --sigs-needed 1000 # Check that signing a content-addressed path doesn't overflow validSigs -nix sign-paths --key-file $TEST_ROOT/sk1 $outPathCA -nix verify -r $outPathCA --sigs-needed 1000 --trusted-public-keys $pk1 +nix store sign-paths --key-file $TEST_ROOT/sk1 $outPathCA +nix store verify -r $outPathCA --sigs-needed 1000 --trusted-public-keys $pk1 # Copy to a binary cache. nix copy --to file://$cacheDir $outPath2 @@ -76,7 +76,7 @@ info=$(nix path-info --store file://$cacheDir --json $outPath2) (! [[ $info =~ 'cache2.example.org' ]]) # Verify that adding a signature to a path in a binary cache works. -nix sign-paths --store file://$cacheDir --key-file $TEST_ROOT/sk2 $outPath2 +nix store sign-paths --store file://$cacheDir --key-file $TEST_ROOT/sk2 $outPath2 info=$(nix path-info --store file://$cacheDir --json $outPath2) [[ $info =~ 'cache1.example.org' ]] [[ $info =~ 'cache2.example.org' ]] @@ -89,17 +89,17 @@ rm -rf $TEST_ROOT/store0 # But succeed if we supply the public keys. nix copy --to $TEST_ROOT/store0 $outPath --trusted-public-keys $pk1 -expect 2 nix verify --store $TEST_ROOT/store0 -r $outPath +expect 2 nix store verify --store $TEST_ROOT/store0 -r $outPath -nix verify --store $TEST_ROOT/store0 -r $outPath --trusted-public-keys $pk1 -nix verify --store $TEST_ROOT/store0 -r $outPath --sigs-needed 2 --trusted-public-keys "$pk1 $pk2" +nix store verify --store $TEST_ROOT/store0 -r $outPath --trusted-public-keys $pk1 +nix store verify --store $TEST_ROOT/store0 -r $outPath --sigs-needed 2 --trusted-public-keys "$pk1 $pk2" # It should also succeed if we disable signature checking. (! nix copy --to $TEST_ROOT/store0 $outPath2) nix copy --to $TEST_ROOT/store0?require-sigs=false $outPath2 # But signatures should still get copied. -nix verify --store $TEST_ROOT/store0 -r $outPath2 --trusted-public-keys $pk1 +nix store verify --store $TEST_ROOT/store0 -r $outPath2 --trusted-public-keys $pk1 # Content-addressed stuff can be copied without signatures. nix copy --to $TEST_ROOT/store0 $outPathCA diff --git a/tests/ssh-relay.sh b/tests/ssh-relay.sh index dce50974b..053b2f00d 100644 --- a/tests/ssh-relay.sh +++ b/tests/ssh-relay.sh @@ -11,6 +11,6 @@ store+=$remote_store store+=$remote_store store+=$remote_store -out=$(nix add-to-store --store "$store" $TEST_ROOT/hello.sh) +out=$(nix store add-path --store "$store" $TEST_ROOT/hello.sh) [ foo = $(< $out) ] From fa8dad10edcebd942ce99e6413fa38e3fe883f15 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 3 Dec 2020 23:26:23 +0100 Subject: [PATCH 9/9] Typo --- src/nix/profile.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nix/profile.cc b/src/nix/profile.cc index 75426b2e3..8cf5ccd62 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -413,7 +413,7 @@ struct CmdProfileDiffClosures : virtual StoreCommand, MixDefaultProfile return { Example{ "To show what changed between each generation of the NixOS system profile:", - "nix profile diff-closure --profile /nix/var/nix/profiles/system" + "nix profile diff-closures --profile /nix/var/nix/profiles/system" }, }; }