out of store symlinks?

This commit is contained in:
2025-05-20 14:55:57 +02:00
parent 9052cd67c2
commit 1845c938dc
10 changed files with 528 additions and 460 deletions
+69
View File
@@ -0,0 +1,69 @@
# Taken from: https://github.com/urob/dotfiles/blob/main/lib/mkSymlinkAttrs.nix
# This function adds and interpretes outOfStoreSymlink option to home.file attribute sets.
#
# Usage:
# home.file = mkSymlinkAttrs {
# .foo = { source = "foo"; outOfStoreSymlink = true; recursive = true; };
# .bar = { source = "foo/bar"; outOfStoreSymlink = true; };
# };
{ pkgs, hm, context, runtimeRoot, ... }:
let
inherit (pkgs) lib;
# Swap a path inside the nix store with the same path in runtimeRoot
runtimePath = path:
let
rootStr = toString context; # context is the `self` passed to flake outputs
pathStr = toString path;
in
assert lib.assertMsg (lib.hasPrefix rootStr pathStr)
"${pathStr} does not start with ${rootStr}";
runtimeRoot + lib.removePrefix rootStr pathStr;
# Make outOfStoreSymlink against runtimeRoot. This replicates
# config.lib.file.mkOutOfStoreSymlink as_mkOutOfStoreSymlink and wraps it to
# replace the target path in the nix store with the original target path
# inside runtimeRoot. This is necessary because flakes live in the nix store.
mkOutOfStoreSymlink =
let
_mkOutOfStoreSymlink = path:
let
pathStr = toString path;
name = hm.strings.storeFileName (baseNameOf pathStr);
in
pkgs.runCommandLocal name { } ''ln -s ${lib.strings.escapeShellArg pathStr} $out'';
in
file: _mkOutOfStoreSymlink (runtimePath file);
# Recursively make OutOfStoreSymlinks for all files inside path.
mkRecursiveOutOfStoreSymlink = path: link:
builtins.listToAttrs (
map
(file: {
name = link + "${lib.removePrefix (toString path) (toString file)}";
value = { source = mkOutOfStoreSymlink file; };
})
(lib.filesystem.listFilesRecursive path)
);
# Remove custom attributes from attribute set.
rmopts = attrs: builtins.removeAttrs attrs [ "source" "recursive" "outOfStoreSymlink" ];
in fileAttrs: lib.attrsets.concatMapAttrs
(
name: value:
# Make outOfStoreSymlinks
if value.outOfStoreSymlink or false
then
if value.recursive or false
then
lib.attrsets.mapAttrs
(_: attrs: attrs // rmopts value)
(mkRecursiveOutOfStoreSymlink value.source name)
else { "${name}" = { source = mkOutOfStoreSymlink value.source; } // rmopts value; }
# Handle all other cases as usual
else { "${name}" = value; }
)
fileAttrs