diff --git a/src/libexpr/eval-cache.cc b/src/libexpr/eval-cache.cc index 0d732f59c..8850032ba 100644 --- a/src/libexpr/eval-cache.cc +++ b/src/libexpr/eval-cache.cc @@ -1,3 +1,4 @@ +#include "nix/expr/value.hh" #include "nix/util/users.hh" #include "nix/expr/eval-cache.hh" #include "nix/store/sqlite.hh" @@ -762,6 +763,14 @@ std::vector AttrCursor::getAttrs() return attrs; } +bool AttrCursor::isNull() +{ + // <<< TODO: caching? >>> + auto & v = forceValue(); + + return v.type() == nNull; +} + bool AttrCursor::isDerivation() { auto aType = maybeGetAttr("type"); diff --git a/src/libexpr/include/nix/expr/eval-cache.hh b/src/libexpr/include/nix/expr/eval-cache.hh index 31873f7a3..d6b92e049 100644 --- a/src/libexpr/include/nix/expr/eval-cache.hh +++ b/src/libexpr/include/nix/expr/eval-cache.hh @@ -153,6 +153,8 @@ public: bool isDerivation(); + bool isNull(); + Value & forceValue(); /** diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 95cf85663..4ee85ca8a 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -1340,10 +1340,14 @@ struct CmdFlakeShow : FlakeCommand, MixJSON } } else { try { - if (visitor.isDerivation()) - showDerivation(); - else - throw Error("expected a derivation"); + if (visitor.isNull()) { + j = nullptr; + } else{ + if (visitor.isDerivation()) + showDerivation(); + else + throw Error("expected a derivation"); + } } catch (IFDError & e) { if (!json) { logger->cout(fmt("%s " ANSI_WARNING "omitted due to use of import from derivation" ANSI_NORMAL, headerPrefix)); diff --git a/tests/functional/flakes/common.sh b/tests/functional/flakes/common.sh index 422cab96c..b47364a4f 100644 --- a/tests/functional/flakes/common.sh +++ b/tests/functional/flakes/common.sh @@ -16,6 +16,7 @@ writeSimpleFlake() { foo = import ./simple.nix; fooScript = (import ./shell.nix {}).foo; default = foo; + noPackage = null; }; packages.someOtherSystem = rec { foo = import ./simple.nix; diff --git a/tests/functional/flakes/show.sh b/tests/functional/flakes/show.sh index 7fcc6aca9..0e730c64e 100755 --- a/tests/functional/flakes/show.sh +++ b/tests/functional/flakes/show.sh @@ -53,7 +53,7 @@ cat >flake.nix < show-output.json nix eval --impure --expr ' let show_output = builtins.fromJSON (builtins.readFile ./show-output.json); in -assert show_output == { }; +assert show_output == { formatter = { x86_64-linux = null; }; }; true ' diff --git a/tests/functional/formatter.sh b/tests/functional/formatter.sh index 6631dd6b8..5d25c0b6d 100755 --- a/tests/functional/formatter.sh +++ b/tests/functional/formatter.sh @@ -85,3 +85,40 @@ rm ./my-result # Flake outputs check. nix flake check nix flake show | grep -P "package 'formatter'" + +function expectFailWithOutputMatching() { + outputMustMatch=$1 + + if output=$(nix fmt 2>&1); then + echo >&2 "nix fmt unexpectedly succeeded" + exit 1 + fi + + if ! echo "$output" | grep "$outputMustMatch"; then + echo >&2 "Expected nix fmt output to match:" + echo >&2 "$outputMustMatch" + echo >&2 "However, the actual output was:" + echo >&2 "$output" + exit 1 + fi +} + +# Try a flake with no formatter. +cat << EOF > flake.nix +{ + outputs = _: {}; +} +EOF +expectFailWithOutputMatching "does not provide attribute 'formatter.$system'" +# Confirm that a null formatter is treated as if there is no formatter. +cat << EOF > flake.nix +{ + outputs = _: { + formatter.$system = null; + }; +} +EOF +if nix fmt | grep "does not provide attribute 'formatter.$system'"; then + echo >&2 "nix fmt unexpectedly succeeded" + exit 1 +fi