diff options
Diffstat (limited to 'nix/writeTree/default.nix')
-rw-r--r-- | nix/writeTree/default.nix | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/nix/writeTree/default.nix b/nix/writeTree/default.nix new file mode 100644 index 000000000000..43ece9b19f97 --- /dev/null +++ b/nix/writeTree/default.nix @@ -0,0 +1,51 @@ +{ depot, lib, pkgs, ... }: +let + inherit (lib) fix pipe mapAttrsToList isAttrs concatLines isString; + + inherit (depot.nix.utils) isDirectory isRegularFile; + + esc = s: lib.escapeShellArg /* ensure paths import into store */ "${s}"; + + writeTreeAtPath = path: tree: + '' + mkdir -p "$out/"${esc path} + '' + + pipe tree [ + (mapAttrsToList (k: v: + # TODO(sterni): a more discoverable isPathLike would fit into //nix/utils + # ATTN: This check has the flaw that it accepts paths without context + # that would not be available in the sandbox! + if lib.types.path.check v then + if isRegularFile v then + "cp --reflink=auto ${esc v} \"$out/\"${esc path}/${esc k}" + else if isDirectory v then '' + mkdir -p "$out/"${esc path} + cp -r --reflink=auto ${esc v} "$out/"${esc path}/${esc k} + '' + else + throw "invalid path type (expected file or directory)" + else if isAttrs v then + writeTreeAtPath "${path}/${k}" v + else if isString v then + "cp --reflink=auto ${esc v} \"$out/\"${esc path}/${esc k}" + else + throw "invalid type (expected file, directory, or attrs)")) + concatLines + ]; + + /* Create a directory tree specified by a Nix attribute set structure. + + Each value in `tree` should either be a file, a directory, or another tree + attribute set. Those paths will be written to a directory tree + corresponding to the structure of the attribute set. + + Type: string -> attrSet -> derivation + */ + writeTree = name: tree: + pkgs.runCommandLocal name { } (writeTreeAtPath "" tree); +in + +# __functor trick so readTree can add the tests attribute +{ + __functor = _: writeTree; +} |