From a0fb6144972e9526e54f38954185b76b7447db11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 25 Aug 2020 16:42:03 +0100 Subject: [PATCH] add `allowSubstitutes = false` example --- README.md | 15 +++++++++--- scripts/force_cached.nix | 39 ++++++++++++++++++++++++++++++++ scripts/force_cached_example.nix | 8 +++++++ 3 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 scripts/force_cached.nix create mode 100644 scripts/force_cached_example.nix diff --git a/README.md b/README.md index 1796271..81ac491 100644 --- a/README.md +++ b/README.md @@ -82,11 +82,20 @@ $ nix-build-uncached ./ci.nix If your package set you are building has packages at the top level scope that have the attribute `allowSubstitutes = false;` set, than `nix-build-uncached` -will build/download them everytime. A workaround is to use the following -[gist](https://gist.github.com/7bc9210b1c4d0afe390f0d425b50e02f): +will build/download them everytime. This attribute is set for some builders such +as `writeText` or `writeScriptBin`. A workaround is to use the following +[nix library](./scripts/force_cached.nix) and save it as +`force_cached.nix`. Than wrap your attribute set like this: ```nix -# TODO example +let + pkgs = import {}; +in (pkgs.callPackage ./force_cached.nix {}) { + hello = pkgs.writeScriptBin "hello" '' + #!/bin/sh + exec ${pkgs.hello}/bin/hello + ''; +} ``` diff --git a/scripts/force_cached.nix b/scripts/force_cached.nix new file mode 100644 index 0000000..ce87edc --- /dev/null +++ b/scripts/force_cached.nix @@ -0,0 +1,39 @@ +{ coreutils }: + +attrs: +with builtins; +let + # Copied from + isDerivation = x: isAttrs x && x ? type && x.type == "derivation"; + + # Return true if `nix-build` would traverse that attribute set to look for + # more derivations to build. + hasRecurseIntoAttrs = x: isAttrs x && (x.recurseForDerivations or false); + + # Wraps derivations that disallow substitutes so that they can be cached. + toCachedDrv = drv: + if !(drv.allowSubstitutes or true) then + derivation + { + name = "${drv.name}-to-cached"; + system = drv.system; + builder = "/bin/sh"; + args = [ "-c" "${coreutils}/bin/ln -s ${drv} $out" ]; + } + else + drv; + + op = _: val: + if isDerivation val then + toCachedDrv val + else if hasRecurseIntoAttrs val then + forceCached val + else + val + ; + + # Traverses a tree of derivation and wrap all of those that disallow + # substitutes. + forceCached = attrs: mapAttrs op attrs; +in +forceCached attrs diff --git a/scripts/force_cached_example.nix b/scripts/force_cached_example.nix new file mode 100644 index 0000000..f12830e --- /dev/null +++ b/scripts/force_cached_example.nix @@ -0,0 +1,8 @@ +let + pkgs = import {}; +in (pkgs.callPackage ./force_cached.nix {}) { + hello = pkgs.writeScriptBin "hello" '' + #!/bin/sh + exec ${pkgs.hello}/bin/hello + ''; +}