From e8d6ee7c1b90a2fe6d824f1a875acc56799ae6e2 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 25 Sep 2017 13:43:35 +0200 Subject: [PATCH] Add "nix show-derivation" This debug command prints a store derivation in JSON format. For example: $ nix show-derivation nixpkgs.hello { "/nix/store/ayjwpwwiyy04nh9z71rsdgd3q7bra7ch-hello-2.10.drv": { "outputs": { "out": { "path": "/nix/store/w5w4v29ql0qwqhczkdxs94ix2lh7ibgs-hello-2.10" } }, "inputSrcs": [ "/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh" ], "inputDrvs": { "/nix/store/13839aqdf6x4k3b785rw5f2l7857l6y3-bash-4.4-p12.drv": [ "out" ], "/nix/store/vgdx7fdc7d4iirmnwj2py1nrvr5qwzj7-hello-2.10.tar.gz.drv": [ "out" ], "/nix/store/x3kkd0vsqfflbvwf1055l9mr39bg0ms0-stdenv.drv": [ "out" ] }, "platform": "x86_64-linux", "builder": "/nix/store/qp5fw57d38bd1n07ss4zxh88zg67c3vg-bash-4.4-p12/bin/bash", "args": [ "-e", "/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh" ], "env": { "buildInputs": "", "builder": "/nix/store/qp5fw57d38bd1n07ss4zxh88zg67c3vg-bash-4.4-p12/bin/bash", "configureFlags": "", "doCheck": "1", "name": "hello-2.10", "nativeBuildInputs": "", "out": "/nix/store/w5w4v29ql0qwqhczkdxs94ix2lh7ibgs-hello-2.10", "propagatedBuildInputs": "", "propagatedNativeBuildInputs": "", "src": "/nix/store/3x7dwzq014bblazs7kq20p9hyzz0qh8g-hello-2.10.tar.gz", "stdenv": "/nix/store/6zngq1rdh0ans9qyckqimqibgnlvlfrm-stdenv", "system": "x86_64-linux" } } } This removes the need for pp-aterm. --- src/nix/command.hh | 4 ++ src/nix/installables.cc | 24 ++++++++ src/nix/show-derivation.cc | 119 +++++++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 src/nix/show-derivation.cc diff --git a/src/nix/command.hh b/src/nix/command.hh index 182b01ef9..82400f31c 100644 --- a/src/nix/command.hh +++ b/src/nix/command.hh @@ -207,4 +207,8 @@ PathSet toStorePaths(ref store, RealiseMode mode, Path toStorePath(ref store, RealiseMode mode, std::shared_ptr installable); +PathSet toDerivations(ref store, + std::vector> installables, + bool useDeriver = false); + } diff --git a/src/nix/installables.cc b/src/nix/installables.cc index 76df05fa3..b60f71b14 100644 --- a/src/nix/installables.cc +++ b/src/nix/installables.cc @@ -303,6 +303,30 @@ Path toStorePath(ref store, RealiseMode mode, return *paths.begin(); } +PathSet toDerivations(ref store, + std::vector> installables, bool useDeriver) +{ + PathSet drvPaths; + + for (auto & i : installables) + for (auto & b : i->toBuildables()) { + if (b.drvPath.empty()) { + if (!useDeriver) + throw Error("argument '%s' did not evaluate to a derivation", i->what()); + for (auto & output : b.outputs) { + auto derivers = store->queryValidDerivers(output.second); + if (derivers.empty()) + throw Error("'%s' does not have a known deriver", i->what()); + // FIXME: use all derivers? + drvPaths.insert(*derivers.begin()); + } + } else + drvPaths.insert(b.drvPath); + } + + return drvPaths; +} + void InstallablesCommand::prepare() { installables = parseInstallables(*this, getStore(), _installables, useDefaultInstallables()); diff --git a/src/nix/show-derivation.cc b/src/nix/show-derivation.cc new file mode 100644 index 000000000..ee94fded3 --- /dev/null +++ b/src/nix/show-derivation.cc @@ -0,0 +1,119 @@ +// FIXME: integrate this with nix path-info? + +#include "command.hh" +#include "common-args.hh" +#include "store-api.hh" +#include "archive.hh" +#include "json.hh" +#include "derivations.hh" + +using namespace nix; + +struct CmdShowDerivation : InstallablesCommand +{ + bool recursive = false; + + CmdShowDerivation() + { + mkFlag() + .longName("recursive") + .shortName('r') + .description("include the dependencies of the specified derivations") + .set(&recursive, true); + } + + std::string name() override + { + return "show-derivation"; + } + + std::string description() override + { + return "show the contents of a store derivation"; + } + + Examples examples() override + { + return { + Example{ + "To show the store derivation that results from evaluating the Hello package:", + "nix show-derivation nixpkgs.hello" + }, + Example{ + "To show the full derivation graph (if available) that produced your NixOS system:", + "nix show-derivation -r /run/current-system" + }, + }; + } + + void run(ref store) override + { + auto drvPaths = toDerivations(store, installables, true); + + if (recursive) { + PathSet closure; + store->computeFSClosure(drvPaths, closure); + drvPaths = closure; + } + + { + + JSONObject jsonRoot(std::cout, true); + + for (auto & drvPath : drvPaths) { + if (!isDerivation(drvPath)) continue; + + auto drvObj(jsonRoot.object(drvPath)); + + auto drv = readDerivation(drvPath); + + { + auto outputsObj(drvObj.object("outputs")); + for (auto & output : drv.outputs) { + auto outputObj(outputsObj.object(output.first)); + outputObj.attr("path", output.second.path); + if (output.second.hash != "") { + outputObj.attr("hashAlgo", output.second.hashAlgo); + outputObj.attr("hash", output.second.hash); + } + } + } + + { + auto inputsList(drvObj.list("inputSrcs")); + for (auto & input : drv.inputSrcs) + inputsList.elem(input); + } + + { + auto inputDrvsObj(drvObj.object("inputDrvs")); + for (auto & input : drv.inputDrvs) { + auto inputList(inputDrvsObj.list(input.first)); + for (auto & outputId : input.second) + inputList.elem(outputId); + } + } + + drvObj.attr("platform", drv.platform); + drvObj.attr("builder", drv.builder); + + { + auto argsList(drvObj.list("args")); + for (auto & arg : drv.args) + argsList.elem(arg); + } + + { + auto envObj(drvObj.object("env")); + for (auto & var : drv.env) + envObj.attr(var.first, var.second); + } + } + + } + + std::cout << "\n"; + } +}; + +static RegisterCommand r1(make_ref());