From 2191dab65726012b057402e13132dd7a062d8440 Mon Sep 17 00:00:00 2001 From: Kevin Amado Date: Fri, 11 Mar 2022 08:57:28 -0500 Subject: [PATCH 1/5] nix-fmt: add command --- src/nix/flake.cc | 12 ++++++++++ src/nix/fmt.cc | 53 +++++++++++++++++++++++++++++++++++++++++++++ src/nix/fmt.md | 53 +++++++++++++++++++++++++++++++++++++++++++++ tests/fmt.sh | 28 ++++++++++++++++++++++++ tests/fmt.simple.sh | 1 + tests/local.mk | 1 + 6 files changed, 148 insertions(+) create mode 100644 src/nix/fmt.cc create mode 100644 src/nix/fmt.md create mode 100644 tests/fmt.sh create mode 100755 tests/fmt.simple.sh diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 47a380238..9830ce841 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -527,6 +527,16 @@ struct CmdFlakeCheck : FlakeCommand } } + else if (name == "formatter") { + state->forceAttrs(vOutput, pos); + for (auto & attr : *vOutput.attrs) { + checkSystemName(attr.name, *attr.pos); + checkApp( + fmt("%s.%s", name, attr.name), + *attr.value, *attr.pos); + } + } + else if (name == "packages" || name == "devShells") { state->forceAttrs(vOutput, pos); for (auto & attr : *vOutput.attrs) { @@ -1010,6 +1020,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON || (attrPath.size() == 1 && ( attrPath[0] == "defaultPackage" || attrPath[0] == "devShell" + || attrPath[0] == "formatter" || attrPath[0] == "nixosConfigurations" || attrPath[0] == "nixosModules" || attrPath[0] == "defaultApp" @@ -1059,6 +1070,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON else if ( (attrPath.size() == 2 && attrPath[0] == "defaultApp") || + (attrPath.size() == 2 && attrPath[0] == "formatter") || (attrPath.size() == 3 && attrPath[0] == "apps")) { auto aType = visitor.maybeGetAttr("type"); diff --git a/src/nix/fmt.cc b/src/nix/fmt.cc new file mode 100644 index 000000000..e5d44bd38 --- /dev/null +++ b/src/nix/fmt.cc @@ -0,0 +1,53 @@ +#include "command.hh" +#include "run.hh" + +using namespace nix; + +struct CmdFmt : SourceExprCommand { + std::vector args; + + CmdFmt() { expectArgs({.label = "args", .handler = {&args}}); } + + std::string description() override { + return "reformat your code in the standard style"; + } + + std::string doc() override { + return + #include "fmt.md" + ; + } + + Category category() override { return catSecondary; } + + Strings getDefaultFlakeAttrPaths() override { + return Strings{"formatter." + settings.thisSystem.get()}; + } + + Strings getDefaultFlakeAttrPathPrefixes() override { return Strings{}; } + + void run(ref store) { + auto evalState = getEvalState(); + auto evalStore = getEvalStore(); + + auto installable = parseInstallable(store, "."); + auto app = installable->toApp(*evalState).resolve(evalStore, store); + + Strings programArgs{app.program}; + + // Propagate arguments from the CLI + if (args.empty()) { + // Format the current flake out of the box + programArgs.push_back("."); + } else { + // User wants more power, let them decide which paths to include/exclude + for (auto &i : args) { + programArgs.push_back(i); + } + } + + runProgramInStore(store, app.program, programArgs); + }; +}; + +static auto r2 = registerCommand("fmt"); diff --git a/src/nix/fmt.md b/src/nix/fmt.md new file mode 100644 index 000000000..1c78bb36f --- /dev/null +++ b/src/nix/fmt.md @@ -0,0 +1,53 @@ +R""( + +# Examples + +With [nixpkgs-fmt](https://github.com/nix-community/nixpkgs-fmt): + +```nix +# flake.nix +{ + outputs = { nixpkgs, self }: { + formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.nixpkgs-fmt; + }; +} +``` + +- Format the current flake: `$ nix fmt` + +- Format a specific folder or file: `$ nix fmt ./folder ./file.nix` + +With [nixfmt](https://github.com/serokell/nixfmt): + +```nix +# flake.nix +{ + outputs = { nixpkgs, self }: { + formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.nixfmt; + }; +} +``` + +- Format specific files: `$ nix fmt ./file1.nix ./file2.nix` + +With [Alejandra](https://github.com/kamadorueda/alejandra): + +```nix +# flake.nix +{ + outputs = { nixpkgs, self }: { + formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.alejandra; + }; +} +``` + +- Format the current flake: `$ nix fmt` + +- Format a specific folder or file: `$ nix fmt ./folder ./file.nix` + +# Description + +`nix fmt` will rewrite all Nix files (\*.nix) to a canonical format +using the formatter specified in your flake. + +)"" diff --git a/tests/fmt.sh b/tests/fmt.sh new file mode 100644 index 000000000..7df1c82d3 --- /dev/null +++ b/tests/fmt.sh @@ -0,0 +1,28 @@ +source common.sh + +set -o pipefail + +clearStore +rm -rf $TEST_HOME/.cache $TEST_HOME/.config $TEST_HOME/.local + +cp ./simple.nix ./simple.builder.sh ./fmt.simple.sh ./config.nix $TEST_HOME + +cd $TEST_HOME + +nix fmt --help | grep "Format" + +cat << EOF > flake.nix +{ + outputs = _: { + formatter.$system = { + type = "app"; + program = ./fmt.simple.sh; + }; + }; +} +EOF +nix fmt ./file ./folder | grep 'Formatting: ./file ./folder' +nix flake check +nix flake show | grep -P 'x86_64-linux|x86_64-darwin' + +clearStore diff --git a/tests/fmt.simple.sh b/tests/fmt.simple.sh new file mode 100755 index 000000000..4c8c67ebb --- /dev/null +++ b/tests/fmt.simple.sh @@ -0,0 +1 @@ +echo Formatting: "${@}" diff --git a/tests/local.mk b/tests/local.mk index 8032fc38a..b42a5bccb 100644 --- a/tests/local.mk +++ b/tests/local.mk @@ -77,6 +77,7 @@ nix_tests = \ post-hook.sh \ function-trace.sh \ flake-local-settings.sh \ + fmt.sh \ eval-store.sh \ why-depends.sh \ import-derivation.sh \ From c9e58aa5ff75351a5bb5af1258e019beef13721a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 19 Apr 2022 20:48:13 +0200 Subject: [PATCH 2/5] Require formatters to be packages Because of 9b41239d8fdcc3fe50febe718c15833ebc224354, a formatter can no longer be a package *or* an app. So let's require it to be a package for now. --- src/nix/app.cc | 4 ++-- src/nix/flake.cc | 3 +-- tests/fmt.sh | 10 ++++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/nix/app.cc b/src/nix/app.cc index 6b6b31a12..df7303e15 100644 --- a/src/nix/app.cc +++ b/src/nix/app.cc @@ -35,7 +35,7 @@ struct InstallableDerivedPath : Installable /** * Return the rewrites that are needed to resolve a string whose context is - * included in `dependencies` + * included in `dependencies`. */ StringPairs resolveRewrites(Store & store, const BuiltPaths dependencies) { @@ -51,7 +51,7 @@ StringPairs resolveRewrites(Store & store, const BuiltPaths dependencies) } /** - * Resolve the given string assuming the given context + * Resolve the given string assuming the given context. */ std::string resolveString(Store & store, const std::string & toResolve, const BuiltPaths dependencies) { diff --git a/src/nix/flake.cc b/src/nix/flake.cc index dbd157248..04b23ed0f 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -1038,7 +1038,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON } else if ( - (attrPath.size() == 2 && (attrPath[0] == "defaultPackage" || attrPath[0] == "devShell")) + (attrPath.size() == 2 && (attrPath[0] == "defaultPackage" || attrPath[0] == "devShell" || attrPath[0] == "formatter")) || (attrPath.size() == 3 && (attrPath[0] == "checks" || attrPath[0] == "packages" || attrPath[0] == "devShells")) ) { @@ -1071,7 +1071,6 @@ struct CmdFlakeShow : FlakeCommand, MixJSON else if ( (attrPath.size() == 2 && attrPath[0] == "defaultApp") || - (attrPath.size() == 2 && attrPath[0] == "formatter") || (attrPath.size() == 3 && attrPath[0] == "apps")) { auto aType = visitor.maybeGetAttr("type"); diff --git a/tests/fmt.sh b/tests/fmt.sh index 7df1c82d3..2b482f14a 100644 --- a/tests/fmt.sh +++ b/tests/fmt.sh @@ -14,10 +14,12 @@ nix fmt --help | grep "Format" cat << EOF > flake.nix { outputs = _: { - formatter.$system = { - type = "app"; - program = ./fmt.simple.sh; - }; + formatter.$system = + with import ./config.nix; + mkDerivation { + name = "formatter"; + buildCommand = "mkdir -p \$out/bin; cp \${./fmt.simple.sh} \$out/bin/formatter"; + }; }; } EOF From 1cdad1074c42bb0b086f09b083db2f3c0f930b0e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 19 Apr 2022 21:12:33 +0200 Subject: [PATCH 3/5] Move rl-next.md to rl-2.8.md --- doc/manual/src/SUMMARY.md.in | 1 + doc/manual/src/release-notes/rl-2.8.md | 53 +++++++++++++++++++++++++ doc/manual/src/release-notes/rl-next.md | 45 --------------------- 3 files changed, 54 insertions(+), 45 deletions(-) create mode 100644 doc/manual/src/release-notes/rl-2.8.md diff --git a/doc/manual/src/SUMMARY.md.in b/doc/manual/src/SUMMARY.md.in index f0f9457d2..860222337 100644 --- a/doc/manual/src/SUMMARY.md.in +++ b/doc/manual/src/SUMMARY.md.in @@ -72,6 +72,7 @@ - [CLI guideline](contributing/cli-guideline.md) - [Release Notes](release-notes/release-notes.md) - [Release X.Y (202?-??-??)](release-notes/rl-next.md) + - [Release 2.8 (2022-04-19)](release-notes/rl-2.8.md) - [Release 2.7 (2022-03-07)](release-notes/rl-2.7.md) - [Release 2.6 (2022-01-24)](release-notes/rl-2.6.md) - [Release 2.5 (2021-12-13)](release-notes/rl-2.5.md) diff --git a/doc/manual/src/release-notes/rl-2.8.md b/doc/manual/src/release-notes/rl-2.8.md new file mode 100644 index 000000000..9778e8c3a --- /dev/null +++ b/doc/manual/src/release-notes/rl-2.8.md @@ -0,0 +1,53 @@ +# Release 2.8 (2022-04-19) + +* New experimental command: `nix fmt`, which applies a formatter + defined by the `formatter.` flake output to the Nix + expressions in a flake. + +* Various Nix commands can now read expressions from standard input + using `--file -`. + +* New experimental builtin function `builtins.fetchClosure` that + copies a closure from a binary cache at evaluation time and rewrites + it to content-addressed form (if it isn't already). Like + `builtins.storePath`, this allows importing pre-built store paths; + the difference is that it doesn't require the user to configure + binary caches and trusted public keys. + + This function is only available if you enable the experimental + feature `fetch-closure`. + +* New experimental feature: *impure derivations*. These are + derivations that can produce a different result every time they're + built. Here is an example: + + ```nix + stdenv.mkDerivation { + name = "impure"; + __impure = true; # marks this derivation as impure + buildCommand = "date > $out"; + } + ``` + + Running `nix build` twice on this expression will build the + derivation twice, producing two different content-addressed store + paths. Like fixed-output derivations, impure derivations have access + to the network. Only fixed-output derivations and impure derivations + can depend on an impure derivation. + +* `nix store make-content-addressable` has been renamed to `nix store + make-content-addressed`. + +* The `nixosModule` flake output attribute has been renamed consistent + with the `.default` renames in Nix 2.7. + + * `nixosModule` → `nixosModules.default` + + As before, the old output will continue to work, but `nix flake check` will + issue a warning about it. + +* `nix run` is now stricter in what it accepts: members of the `apps` + flake output are now required to be apps (as defined in [the + manual](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-run.html#apps)), + and members of `packages` or `legacyPackages` must be derivations + (not apps). diff --git a/doc/manual/src/release-notes/rl-next.md b/doc/manual/src/release-notes/rl-next.md index 6ebbe5eb4..c869b5e2f 100644 --- a/doc/manual/src/release-notes/rl-next.md +++ b/doc/manual/src/release-notes/rl-next.md @@ -1,46 +1 @@ # Release X.Y (202?-??-??) - -* Various nix commands can now read expressions from stdin with `--file -`. - -* `nix store make-content-addressable` has been renamed to `nix store - make-content-addressed`. - -* New experimental builtin function `builtins.fetchClosure` that - copies a closure from a binary cache at evaluation time and rewrites - it to content-addressed form (if it isn't already). Like - `builtins.storePath`, this allows importing pre-built store paths; - the difference is that it doesn't require the user to configure - binary caches and trusted public keys. - - This function is only available if you enable the experimental - feature `fetch-closure`. - -* New experimental feature: *impure derivations*. These are - derivations that can produce a different result every time they're - built. Here is an example: - - ```nix - stdenv.mkDerivation { - name = "impure"; - __impure = true; # marks this derivation as impure - buildCommand = "date > $out"; - } - ``` - - Running `nix build` twice on this expression will build the - derivation twice, producing two different content-addressed store - paths. Like fixed-output derivations, impure derivations have access - to the network. Only fixed-output derivations and impure derivations - can depend on an impure derivation. - -* The `nixosModule` flake output attribute has been renamed consistent - with the `.default` renames in nix 2.7. - - * `nixosModule` → `nixosModules.default` - - As before, the old output will continue to work, but `nix flake check` will - issue a warning about it. - -* `nix run` is now stricter wrt what it accepts: - * Members of `apps` are now required to be apps (as defined in [the manual](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-run.html#apps)) - * Member of `packages` or `legacyPackages` cannot be of type "app" when used by `nix run`. From a3c843e6357be9d1cf84c1e030b8e5169815d827 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 19 Apr 2022 21:47:13 +0200 Subject: [PATCH 4/5] Fix 'nix fmt' test --- tests/fmt.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fmt.sh b/tests/fmt.sh index 2b482f14a..bc05118ff 100644 --- a/tests/fmt.sh +++ b/tests/fmt.sh @@ -25,6 +25,6 @@ cat << EOF > flake.nix EOF nix fmt ./file ./folder | grep 'Formatting: ./file ./folder' nix flake check -nix flake show | grep -P 'x86_64-linux|x86_64-darwin' +nix flake show | grep -P "package 'formatter'" clearStore From ee57f91413c9d01f1027eccbe01f7706c94919ac Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 19 Apr 2022 21:48:17 +0200 Subject: [PATCH 5/5] Bump version --- .version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.version b/.version index 6533b6687..f3ac133c5 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.8.0 \ No newline at end of file +2.9.0 \ No newline at end of file