From 951a00c281d7572dda37968d315b14592b3f69a8 Mon Sep 17 00:00:00 2001 From: DavHau Date: Wed, 26 Jul 2023 17:24:43 +0200 Subject: [PATCH] writers: init --- flake-parts/writers/default.nix | 45 +++++++++++++++++ flake-parts/writers/writers.nix | 89 +++++++++++++++++++++++++++++++++ flake.nix | 1 + 3 files changed, 135 insertions(+) create mode 100644 flake-parts/writers/default.nix create mode 100644 flake-parts/writers/writers.nix diff --git a/flake-parts/writers/default.nix b/flake-parts/writers/default.nix new file mode 100644 index 00000000..bd733e27 --- /dev/null +++ b/flake-parts/writers/default.nix @@ -0,0 +1,45 @@ +{ flake-parts-lib, ... }: { + options.perSystem = flake-parts-lib.mkPerSystemOption ( + { config + , lib + , pkgs + , ... + }: + let + writers = pkgs.callPackage ./writers.nix { }; + in + { + options.writers = { + writePureShellScript = lib.mkOption { + type = lib.types.functionTo (lib.types.functionTo lib.types.package); + description = '' + Create a script that runs in a `pure` environment, in the sense that: + - the behavior is similar to `nix-shell --pure` + - `PATH` only contains exactly the packages passed via the `PATH` arg + - `NIX_PATH` is set to the path of the current `pkgs` + - `TMPDIR` is set up and cleaned up even if the script fails + - out, if set, is kept as-is + - all environment variables are unset, except: + - the ones listed in `keepVars` defined in ./default.nix + - the ones listed via the `KEEP_VARS` variable + ''; + }; + writePureShellScriptBin = lib.mkOption { + type = lib.types.functionTo (lib.types.functionTo (lib.types.functionTo lib.types.package)); + description = '' + Creates a script in a `bin/` directory in the output; suitable for use with `lib.makeBinPath`, etc. + See {option}`writers.writePureShellScript` + ''; + }; + }; + + config.writers = { + inherit + (writers) + writePureShellScript + writePureShellScriptBin + ; + }; + } + ); +} diff --git a/flake-parts/writers/writers.nix b/flake-parts/writers/writers.nix new file mode 100644 index 00000000..ed928773 --- /dev/null +++ b/flake-parts/writers/writers.nix @@ -0,0 +1,89 @@ +{ lib +, bash +, coreutils +, gawk +, path +, # nixpkgs path + writeScript +, writeScriptBin +, ... +}: +let + # Docs at modules/flake-parts/writers.nix + writePureShellScript = PATH: script: + writeScript "script.sh" (mkScript PATH script); + + # Docs at modules/flake-parts/writers.nix + writePureShellScriptBin = binName: PATH: script: + writeScriptBin binName (mkScript PATH script); + + mkScript = PATH: scriptText: '' + #!${bash}/bin/bash + set -Eeuo pipefail + + export PATH="${lib.makeBinPath PATH}" + export NIX_PATH=nixpkgs=${path} + + export TMPDIR=$(${coreutils}/bin/mktemp -d) + + trap "${coreutils}/bin/chmod -R +w '$TMPDIR'; ${coreutils}/bin/rm -rf '$TMPDIR'" EXIT + + if [ -z "''${IMPURE:-}" ]; then + ${cleanEnv} + fi + + ${scriptText} + ''; + + # list taken from nix source: src/nix-build/nix-build.cc + keepVars = lib.concatStringsSep " " [ + "HOME" + "XDG_RUNTIME_DIR" + "USER" + "LOGNAME" + "DISPLAY" + "WAYLAND_DISPLAY" + "WAYLAND_SOCKET" + "PATH" + "TERM" + "IN_NIX_SHELL" + "NIX_SHELL_PRESERVE_PROMPT" + "TZ" + "PAGER" + "NIX_BUILD_SHELL" + "SHLVL" + "http_proxy" + "https_proxy" + "ftp_proxy" + "all_proxy" + "no_proxy" + + # We want to keep our own variables as well + "out" + "IMPURE" + "KEEP_VARS" + "NIX_PATH" + "TMPDIR" + ]; + + cleanEnv = '' + + KEEP_VARS="''${KEEP_VARS:-}" + + unsetVars=$( + ${coreutils}/bin/comm \ + <(${gawk}/bin/awk 'BEGIN{for(v in ENVIRON) print v}' | ${coreutils}/bin/cut -d = -f 1 | ${coreutils}/bin/sort) \ + <(echo "${keepVars} $KEEP_VARS" | ${coreutils}/bin/tr " " "\n" | ${coreutils}/bin/sort) \ + -2 \ + -3 + ) + + unset $unsetVars + ''; +in +{ + inherit + writePureShellScript + writePureShellScriptBin + ; +} diff --git a/flake.nix b/flake.nix index 04529f4c..ec91eb68 100644 --- a/flake.nix +++ b/flake.nix @@ -20,6 +20,7 @@ imports = [ ./flake-parts/packages.nix ./flake-parts/formatting.nix + ./flake-parts/writers ./templates/flake-module.nix ./templates/python-project/flake-module.nix ./pkgs/clan-cli/flake-module.nix