78 lines
2.2 KiB
Nix
78 lines
2.2 KiB
Nix
{
|
|
lib,
|
|
stdenv,
|
|
runCommand,
|
|
rsync,
|
|
}: drv: let
|
|
join = dir: name: dir + ("/" + name);
|
|
files = scan drv;
|
|
scan = path: let
|
|
f = k: v:
|
|
if v == "directory"
|
|
then scan (join path k)
|
|
else [(join path k)];
|
|
in
|
|
lib.pipe path [
|
|
builtins.readDir
|
|
(builtins.mapAttrs f)
|
|
builtins.attrValues
|
|
lib.concatLists
|
|
];
|
|
pathDerivation = path: let
|
|
location =
|
|
builtins.replaceStrings [(builtins.toString drv)] [""] path;
|
|
name = lib.pipe location [
|
|
(builtins.substring 1 (-1))
|
|
(builtins.replaceStrings ["/"] ["."])
|
|
|
|
# Nix is too smart and too paranoid for what I am doing here.
|
|
# It infers that "name" string is derived from path, hence
|
|
# depends on it. I know better.
|
|
builtins.unsafeDiscardStringContext
|
|
];
|
|
|
|
# Break reference to original derivation.
|
|
#
|
|
# Reference to file in form ${path} copies file to store, if is is
|
|
# not already there. And if it is already there, as part of other
|
|
# derivation, reference to contained derivation is retained, which
|
|
# is not what we need here. So here we make intermediate
|
|
# derivation that contains copy of file at $out.
|
|
file = runCommand "frozen-file" {} ''
|
|
cp -v ${path} $out
|
|
'';
|
|
in
|
|
stdenv.mkDerivation {
|
|
name = "${name}";
|
|
phases = ["installPhase"];
|
|
inherit (drv) propagatedBuildInputs;
|
|
|
|
# Link file, copy symlink. Distinction is important to make sure
|
|
# relative symlinks are not broken. Actually, there should not be
|
|
# relative symlinks in first place, but still.
|
|
installPhase = ''
|
|
mkdir -p $out/${location}
|
|
rmdir $out/${location}
|
|
if test -h ${file} ; then
|
|
cp -v ${file} $out/${location}
|
|
else
|
|
ln -s ${file} $out/${location}
|
|
fi
|
|
'';
|
|
};
|
|
|
|
rsyncCommand = path: let
|
|
src = pathDerivation path;
|
|
in "rsync -az ${src}/* $out/";
|
|
|
|
union = stdenv.mkDerivation {
|
|
inherit (drv) name buildInputs propagatedBuildInputs checkInputs;
|
|
nativeBuildInputs = [rsync];
|
|
phases = ["installPhase"];
|
|
installPhase =
|
|
"mkdir -p $out;"
|
|
+ builtins.concatStringsSep ";" (builtins.map rsyncCommand files);
|
|
};
|
|
in
|
|
union
|