aboutsummaryrefslogtreecommitdiffstats
path: root/modules/by-name/di/direnv
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-08-17 22:27:54 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-08-17 22:27:54 +0200
commitaa55de1820a5ae27ac32b9b0e33b18ae592b46fb (patch)
tree3588105ee84d057c90b3ff2ff18d5d4e50fc4afc /modules/by-name/di/direnv
parenttreewide: Update (diff)
downloadnixos-config-aa55de1820a5ae27ac32b9b0e33b18ae592b46fb.zip
modules/direnv: Implement pre-cached devshells
That means, that the devshells are only build once and centrally updated. Ideally, they would be built upon system update, but I haven't figured out a way to run `nix print-dev-env` in a nix build sandbox yet (and hope, that it's not necessary anymore once, that functionality moves to nixpkgs' `mkShell`).
Diffstat (limited to '')
-rw-r--r--modules/by-name/di/direnv/module.nix39
-rwxr-xr-xmodules/by-name/di/direnv/pre-cache.sh78
2 files changed, 107 insertions, 10 deletions
diff --git a/modules/by-name/di/direnv/module.nix b/modules/by-name/di/direnv/module.nix
index 363f5cea..743375af 100644
--- a/modules/by-name/di/direnv/module.nix
+++ b/modules/by-name/di/direnv/module.nix
@@ -11,26 +11,45 @@
config,
lib,
pkgs,
+ sources,
...
}: let
cfg = config.soispha.programs.direnv;
+
+ devshells = sources.loadFlake "devshells";
+
+ pre-cache = pkgs.runCommand "pre-cache.sh" {} ''
+ cat "${./pre-cache.sh}" > $out
+
+ substituteInPlace $out \
+ --replace-fail "%DEVSHELLS_REPO%" "${devshells}"
+ '';
in {
options.soispha.programs.direnv = {
enable = lib.mkEnableOption "direnv";
};
- config.home-manager.users.soispha.programs.direnv = lib.mkIf cfg.enable {
- enable = true;
-
- nix-direnv = {
+ config.home-manager.users.soispha = lib.mkIf cfg.enable {
+ programs.direnv = {
enable = true;
- package = pkgs.nix-direnv.override {nix = config.nix.package;};
- };
- config = {
- warn_timeout = 0;
- # strict_env = true;
- # disable_stdin = true;
+ package = pkgs.direnv-patched;
+
+ nix-direnv = {
+ enable = true;
+ package = pkgs.nix-direnv.override {nix = config.nix.package;};
+ };
+
+ config = {
+ warn_timeout = 0;
+ strict_env = true;
+ # disable_stdin = true;
+ };
+ };
+ xdg.configFile = {
+ "direnv/lib/hm-pre-cache.sh" = {
+ source = pre-cache;
+ };
};
};
}
diff --git a/modules/by-name/di/direnv/pre-cache.sh b/modules/by-name/di/direnv/pre-cache.sh
new file mode 100755
index 00000000..13c0cd37
--- /dev/null
+++ b/modules/by-name/di/direnv/pre-cache.sh
@@ -0,0 +1,78 @@
+#! /usr/bin/env sh
+
+_pre_cache_log() {
+ printf "pre-cache: %s\n" "$1"
+}
+_pre_cache_preflight() {
+ set -eu
+ _nix_direnv_preflight
+
+ repo="%DEVSHELLS_REPO%"
+ system="x86_64-linux"
+ cache_dir="$XDG_CACHE_HOME/pre_cache"
+ [ -d "$cache_dir" ] || mkdir --parents "$cache_dir"
+
+ repo_ref=$(git -C "$repo" rev-parse HEAD)
+ final_cache="$cache_dir/$repo_ref"
+
+ if ! [ -d "$final_cache" ]; then
+ _pre_cache_log "Cache dir invalidated"
+
+ # There is not yet a final cache directory, so the ref must have changed.
+ # Therefore we delete the whole cache directory, so we invalidate old cached shells.
+ set -u
+ rm --recursive "$cache_dir"
+
+ mkdir --parents "$final_cache"
+ fi
+}
+
+_pre_cache_load_shell() {
+ lang="$1"
+ lang_cache="$final_cache/$lang"
+
+ if ! [ -f "$lang_cache" ]; then
+ tmp_profile="$final_cache/__tmp_profile"
+ profile="$final_cache/__profile"
+
+ # It does not already exists, we need to evaluate it.
+ _nix print-dev-env --profile "$tmp_profile" "$repo#$lang" >"$lang_cache"
+
+ _nix_add_gcroot "$tmp_profile" "$profile"
+ rm "$tmp_profile" "$tmp_profile"*
+ fi
+
+ _pre_cache_log "Loaded dev-shell for $lang."
+ _nix_import_env "$lang_cache"
+}
+
+_pre_cache_build_shells() {
+ installables=""
+
+ for lang in "$@"; do
+ new_part="$repo#devShells.$system.$lang"
+
+ if [ -z "$installables" ]; then
+ installables="$new_part"
+ else
+ installables="$installables $new_part"
+ fi
+ done
+
+ # We want shell-spliting
+ # shellcheck disable=SC2086
+ _nix build --no-link $installables
+
+}
+
+pre_cache_load() {
+ _pre_cache_preflight
+
+ _pre_cache_build_shells "$@"
+
+ for lan in "$@"; do
+ _pre_cache_load_shell "$lan"
+ done
+}
+
+# vim: ft=sh