Add 'prog/lang-nix/nix-freeze-derivation/' from commit 'c72b1964d4e379a43c73c2c03483ac4a0ceb5c84'
git-subtree-dir: prog/lang-nix/nix-freeze-derivation git-subtree-mainline:4f3dfcc1ae
git-subtree-split:c72b1964d4
This commit is contained in:
commit
26daab923d
|
@ -0,0 +1,71 @@
|
|||
nix-freeze-derivation
|
||||
=====================
|
||||
|
||||
This project provides Nix function that makes derivation, with every
|
||||
file in input derivation replaced with symlink to single file in Nix
|
||||
storage. For example, let's freeze derivation for `nnn` file manager:
|
||||
|
||||
let
|
||||
nixpkgs = import <nixpkgs> { };
|
||||
nix-freeze-derivation = nixpkgs.fetchgit {
|
||||
url = "https://git.sr.ht/~kaction/nix-freeze-derivation";
|
||||
rev = "...";
|
||||
sha256 = "...";
|
||||
};
|
||||
freeze = nixpkgs.callPackage nix-freeze-derivation {};
|
||||
in {
|
||||
frozen-nnn = freeze nnn;
|
||||
inherit nnn;
|
||||
}
|
||||
|
||||
Here is original derivation:
|
||||
|
||||
├── bin
|
||||
│ └── nnn
|
||||
└── share
|
||||
├── bash-completion
|
||||
│ └── completions
|
||||
│ └── nnn.bash
|
||||
├── fish
|
||||
│ └── vendor_completions.d
|
||||
│ └── nnn.fish
|
||||
├── man
|
||||
│ └── man1
|
||||
│ └── nnn.1.gz
|
||||
└── zsh
|
||||
└── site-functions
|
||||
└── _nnn
|
||||
|
||||
And here is frozen derivation:
|
||||
|
||||
├── bin
|
||||
│ └── nnn -> /nix/store/zshsj2hy2c8fiqh3vw08yq5lq8k4abx9-frozen-file
|
||||
└── share
|
||||
├── bash-completion
|
||||
│ └── completions
|
||||
│ └── nnn.bash -> /nix/store/8qf7q4j6aizbd6kgfp8dgwchf789v7dl-frozen-file
|
||||
├── fish
|
||||
│ └── vendor_completions.d
|
||||
│ └── nnn.fish -> /nix/store/58rm78igazcsgcik4hwj4d2mkzn5h6sn-frozen-file
|
||||
├── man
|
||||
│ └── man1
|
||||
│ └── nnn.1.gz -> /nix/store/7grf462gxkp1jifyw8gz41v30z8v3442-frozen-file
|
||||
└── zsh
|
||||
└── site-functions
|
||||
└── _nnn -> /nix/store/11k4jkycz9zj7s708m9jw41yyskr7aas-frozen-file
|
||||
|
||||
For almost all intentions and purposes frozen derivation is equivalent
|
||||
to original one, but copying it between machines only copies changed
|
||||
files. On other hand, freezing derivation takes some time, especially
|
||||
noticable with derivation that do not involve real compiling. For
|
||||
example, freezing Python package can take as much time as building
|
||||
package itself.
|
||||
|
||||
`nix-freeze-derivation` was inspired by `nix-freeze-tree`[^1], which is
|
||||
much faster and can freeze arbitrary path, not just derivation.
|
||||
Unfortunately, `nix-freeze-tree` does not work with derivations that has
|
||||
propagated build inputs[^2], that is why `nix-freeze-derivation` was
|
||||
created.
|
||||
|
||||
[^1] https://git.sr.ht/~jack/nix-freeze-tree
|
||||
[^2] https://todo.sr.ht/~jack/nix-freeze-tree/7
|
|
@ -0,0 +1,70 @@
|
|||
{ 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
|
|
@ -0,0 +1,6 @@
|
|||
with (import <nixpkgs> {});
|
||||
let freeze = callPackage ./default.nix {};
|
||||
in {
|
||||
frozen-nnn = freeze nnn;
|
||||
inherit nnn;
|
||||
}
|
Loading…
Reference in New Issue