From 33926ed1e75c06cbf70a920e462841cc9daa0520 Mon Sep 17 00:00:00 2001 From: Alexander Bantyev Date: Fri, 26 Nov 2021 18:03:07 +0300 Subject: [PATCH] nix repl: add :log Add a :log command that shows logs for a derivation. Closes https://github.com/NixOS/nix/issues/3504 Co-authored-by: Taeer Bar-Yam --- doc/manual/src/release-notes/rl-next.md | 2 ++ src/nix/repl.cc | 26 +++++++++++++++++++++++-- src/nix/repl.md | 7 +++++-- tests/repl.sh | 13 +++++++++++++ tests/simple-failing.builder.sh | 2 ++ tests/simple-failing.nix | 8 ++++++++ 6 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 tests/simple-failing.builder.sh create mode 100644 tests/simple-failing.nix diff --git a/doc/manual/src/release-notes/rl-next.md b/doc/manual/src/release-notes/rl-next.md index a6b22dfa7..cf2da9aa8 100644 --- a/doc/manual/src/release-notes/rl-next.md +++ b/doc/manual/src/release-notes/rl-next.md @@ -8,3 +8,5 @@ * New built-in function: `builtins.groupBy`, with the same functionality as Nixpkgs' `lib.groupBy`, but faster. + +* `nix repl` now has a `:log` command. diff --git a/src/nix/repl.cc b/src/nix/repl.cc index 2649eb0bd..42143871f 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -430,7 +430,8 @@ bool NixRepl::processLine(string line) << " :s Build dependencies of derivation, then start nix-shell\n" << " :t Describe result of evaluation\n" << " :u Build derivation, then start nix-shell\n" - << " :doc Show documentation of a builtin function\n"; + << " :doc Show documentation of a builtin function\n" + << " :log Show logs for a derivation\n"; } else if (command == ":a" || command == ":add") { @@ -500,7 +501,7 @@ bool NixRepl::processLine(string line) runNix("nix-shell", {state->store->printStorePath(drvPath)}); } - else if (command == ":b" || command == ":i" || command == ":s") { + else if (command == ":b" || command == ":i" || command == ":s" || command == ":log") { Value v; evalString(arg, v); StorePath drvPath = getDerivationPath(v); @@ -514,6 +515,27 @@ bool NixRepl::processLine(string line) logger->cout(" %s -> %s", outputName, state->store->printStorePath(outputPath)); } else if (command == ":i") { runNix("nix-env", {"-i", drvPathRaw}); + } else if (command == ":log") { + settings.readOnlyMode = true; + Finally roModeReset([&]() { + settings.readOnlyMode = false; + }); + auto subs = getDefaultSubstituters(); + + subs.push_front(state->store); + + bool foundLog = false; + RunPager pager; + for (auto & sub : subs) { + auto log = sub->getBuildLog(drvPath); + if (log) { + printInfo("got build log for '%s' from '%s'", drvPathRaw, sub->getUri()); + logger->writeToStdout(*log); + foundLog = true; + break; + } + } + if (!foundLog) throw Error("build log of '%s' is not available", drvPathRaw); } else { runNix("nix-shell", {drvPathRaw}); } diff --git a/src/nix/repl.md b/src/nix/repl.md index bba60f871..9b6f2bee3 100644 --- a/src/nix/repl.md +++ b/src/nix/repl.md @@ -35,14 +35,17 @@ R""( nix-repl> emacs.drvPath "/nix/store/lp0sjrhgg03y2n0l10n70rg0k7hhyz0l-emacs-27.1.drv" - nix-repl> drv = runCommand "hello" { buildInputs = [ hello ]; } "hello > $out" + nix-repl> drv = runCommand "hello" { buildInputs = [ hello ]; } "hello; hello > $out" - nix-repl> :b x + nix-repl> :b drv this derivation produced the following outputs: out -> /nix/store/0njwbgwmkwls0w5dv9mpc1pq5fj39q0l-hello nix-repl> builtins.readFile drv "Hello, world!\n" + + nix-repl> :log drv + Hello, world! ``` # Description diff --git a/tests/repl.sh b/tests/repl.sh index d360821f2..f592822bc 100644 --- a/tests/repl.sh +++ b/tests/repl.sh @@ -3,6 +3,13 @@ source common.sh replCmds=" simple = import ./simple.nix :b simple +:log simple +" + +replFailingCmds=" +failing = import ./simple-failing.nix +:b failing +:log failing " testRepl () { @@ -12,6 +19,12 @@ testRepl () { local outPath=$(echo "$replOutput" |& grep -o -E "$NIX_STORE_DIR/\w*-simple") nix path-info "${nixArgs[@]}" "$outPath" + # simple.nix prints a PATH during build + echo "$replOutput" | grep -qs 'PATH=' || fail "nix repl :log doesn't output logs" + local replOutput="$(nix repl "${nixArgs[@]}" <<< "$replFailingCmds")" + echo "$replOutput" + echo "$replOutput" | grep -qs 'This should fail' \ + || fail "nix repl :log doesn't output logs for a failed derivation" } # Simple test, try building a drv diff --git a/tests/simple-failing.builder.sh b/tests/simple-failing.builder.sh new file mode 100644 index 000000000..6285488ca --- /dev/null +++ b/tests/simple-failing.builder.sh @@ -0,0 +1,2 @@ +echo "This should fail" +exit 1 diff --git a/tests/simple-failing.nix b/tests/simple-failing.nix new file mode 100644 index 000000000..1e3a080ed --- /dev/null +++ b/tests/simple-failing.nix @@ -0,0 +1,8 @@ +with import ./config.nix; + +mkDerivation { + name = "simple-failing"; + builder = ./simple-failing.builder.sh; + PATH = ""; + goodPath = path; +}