tvl-depot/nix/writeTree/default.nix
sterni 77a6eb4f51 feat(nix/writeTree): don't require IfD for drvs in tree
As far as I can tell we can handle files and directories using the same
cp(1) invocation, so we no longer need to potentially IfD derivations in
the tree to figure out whether they are files or directories.

Change-Id: Iabe648c30a747fa42768558715e388552024764a
Reviewed-on: https://cl.tvl.fyi/c/depot/+/10996
Reviewed-by: aspen <root@gws.fyi>
Autosubmit: sterni <sternenseemann@systemli.org>
Tested-by: BuildkiteCI
2024-02-21 20:52:20 +00:00

43 lines
1.3 KiB
Nix

{ depot, lib, pkgs, ... }:
let
inherit (lib) fix pipe mapAttrsToList isAttrs concatLines isString isDerivation isPath;
# TODO(sterni): move to //nix/utils with clearer naming and alternative similar to lib.types.path
isPathLike = value:
isPath value
|| isDerivation value
|| (isString value && builtins.hasContext value);
esc = s: lib.escapeShellArg /* ensure paths import into store */ "${s}";
writeTreeAtPath = path: tree:
''
mkdir -p "$out/"${esc path}
''
+ pipe tree [
(mapAttrsToList (k: v:
if isPathLike v then
"cp -R --reflink=auto ${v} \"$out/\"${esc path}/${esc k}"
else if lib.isAttrs v then
writeTreeAtPath (path + "/" + k) v
else
throw "invalid type (expected path, derivation, string with context, 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;
}