-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support for rerunning fixed output derivations if any of their inputs change
- Loading branch information
Showing
7 changed files
with
445 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,10 @@ | ||
{ pkgs }: | ||
{ pkgs, lib, nixTestRunner }: | ||
|
||
with pkgs.lib; { | ||
# Add your library functions here | ||
# | ||
# hexint = x: hexvals.${toLower x}; | ||
rec { | ||
# I use this to keep individual features also importable independently | ||
# of other code in this NUR repo. | ||
inherit (pkgs.callPackage ./rerun-fixed.nix {}) rerunFixedDerivationOnChange; | ||
|
||
runTests = nixTestRunner.runTests; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
{ pkgs, lib }: | ||
|
||
rec { | ||
/* Creates a fixed output derivation that reruns if any of its inputs change. | ||
Type: rerunFixedDerivationOnChange -> derivation -> derivation | ||
Example: | ||
let myFixedOutputDerivation = pkgs.stdenv.mkDerivation { | ||
# ... | ||
outputHash = "sha256:..."; | ||
outputHashMode = "recursive"; | ||
}; | ||
in | ||
nur.repos.kolloch.lib.rerunFixedDerivationOnChange myFixedOutputDerivation; | ||
Usually, fixed output derivations are only rerun if their name or hash | ||
changes (i.e. when their output path changes). This makes the derivation | ||
definition irrelevant if the output is in the cache. | ||
With this helper, you can make sure that the commands that are specified | ||
where at least ran once -- with the exact versions of the buildInputs that | ||
you specified. It does so by putting a hash of all the inputs into the | ||
name. | ||
Caveat: It uses "import from derivation" under the hood. See implementation | ||
for an explanation why. | ||
Implementation | ||
Getting the hash is easy, in principle, because nix already does that work | ||
for us when creating the output paths for non-fixed output derivations. | ||
Therefore, if we create a non-fixed output derivation with the same inputs, | ||
the hash in the output path should change with every change in inputs. | ||
Unfortunately, we cannot use parts of the output path in the name of our | ||
derivation directly. | ||
Nix prevents this because supposedly it is not what you want. I don't think | ||
that it is actually problematic in principle. | ||
To work around this, I use an import-from-derivation call to get the output | ||
path. The disadvantage is that all the dependencies of your fixed output | ||
derivation will be build in the eval phase. | ||
*/ | ||
rerunFixedDerivationOnChange = fixedOutputDerivation: | ||
assert (lib.assertMsg | ||
(fixedOutputDerivation ? outputHash) | ||
"rerunOnChangedInputs expects a fixedOutputDerivation"); | ||
|
||
let | ||
# The name of the original derivation. | ||
name = fixedOutputDerivation.name or "fixed"; | ||
|
||
# A hash that includes all inputs of the fixedOutputDerivation. | ||
# | ||
# Creates a derivation that has all the same inputs and | ||
# simply outputs it's output path. | ||
# | ||
# If we could simply access the output path from nix | ||
# and use it as a part of the name, this would be much easier. | ||
inputsHash = | ||
let | ||
# Args to rename. | ||
renameArgs = [ "builder" "args" ]; | ||
renamedArgs = | ||
let declash = attrName: | ||
if fixedOutputDerivation ? attrName | ||
then declash "${attrName}_" | ||
else attrName; | ||
copyName = attrName: "original_${declash attrName}"; | ||
copy = attrName: | ||
{ | ||
name = copyName attrName; | ||
value = fixedOutputDerivation."${attrName}"; | ||
}; | ||
copies = builtins.map copy renameArgs; | ||
in | ||
builtins.listToAttrs copies; | ||
# Args to replace with null | ||
nullArgs = renameArgs ++ [ "outputHash" "outputHashAlgo" "outputHashMode" ]; | ||
nulledArgs = | ||
let nullMe = name: | ||
{ | ||
inherit name; | ||
value = null; | ||
}; | ||
nulled = builtins.map nullMe nullArgs; | ||
in | ||
builtins.listToAttrs nulled; | ||
outputPathBuilderArgs = | ||
assert builtins.isAttrs renamedArgs; | ||
assert builtins.isAttrs nulledArgs; | ||
renamedArgs // nulledArgs // { | ||
name = "outpath-for-${name}"; | ||
builder = "${pkgs.bash}/bin/bash"; | ||
args = ["-c" "set -x; echo $out > $out" ]; | ||
}; | ||
outputPathBuilder = | ||
assert builtins.isAttrs outputPathBuilderArgs; | ||
if fixedOutputDerivation ? overrideAttrs | ||
then fixedOutputDerivation.overrideAttrs (attrs: outputPathBuilderArgs) | ||
else fixedOutputDerivation.overrideDerivation (attrs: outputPathBuilderArgs); | ||
outputPath = | ||
assert lib.isDerivation outputPathBuilder; | ||
builtins.readFile outputPathBuilder; | ||
in builtins.substring 11 32 outputPath; | ||
|
||
# This is the basic idea: Add the inputsHash to the name | ||
# to force a rebuild whenever the inputs change. | ||
nameWithHash = { name = "${inputsHash}_${name}"; }; | ||
|
||
# Make "overrideAttrs" and "overrideDerivation" work as expected. | ||
# That means that we need to keep overriding the name. | ||
overrideAttrs = f: rerunFixedDerivationOnChange (fixedOutputDerivation.overrideAttrs f); | ||
overrideDerivation = f: rerunFixedDerivationOnChange (fixedOutputDerivation.overrideDerivation f); | ||
in | ||
if fixedOutputDerivation ? overrideAttrs | ||
then | ||
(fixedOutputDerivation.overrideAttrs (attrs: nameWithHash)) | ||
// { inherit overrideAttrs overrideDerivation; } | ||
else | ||
(fixedOutputDerivation.overrideDerivation (attrs: nameWithHash)) | ||
// { inherit overrideDerivation; }; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
{ | ||
"niv": { | ||
"branch": "master", | ||
"description": "Easy dependency management for Nix projects", | ||
"homepage": "https://github.com/nmattia/niv", | ||
"owner": "nmattia", | ||
"repo": "niv", | ||
"rev": "f73bf8d584148677b01859677a63191c31911eae", | ||
"sha256": "0jlmrx633jvqrqlyhlzpvdrnim128gc81q5psz2lpp2af8p8q9qs", | ||
"type": "tarball", | ||
"url": "https://github.com/nmattia/niv/archive/f73bf8d584148677b01859677a63191c31911eae.tar.gz", | ||
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" | ||
}, | ||
"nix-test-runner": { | ||
"branch": "master", | ||
"description": "Test runner for nix expressions", | ||
"homepage": "", | ||
"owner": "stoeffel", | ||
"repo": "nix-test-runner", | ||
"rev": "545306ab20a561ef79567e68fa0e25e1ed340ef1", | ||
"sha256": "0iz5kmls6mwwa7lxpi4cq3yq36ygk2vrf0k54xyis736ikx6xky1", | ||
"type": "tarball", | ||
"url": "https://github.com/stoeffel/nix-test-runner/archive/545306ab20a561ef79567e68fa0e25e1ed340ef1.tar.gz", | ||
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" | ||
}, | ||
"nixpkgs": { | ||
"branch": "nixos-20.03", | ||
"description": "A read-only mirror of NixOS/nixpkgs tracking the released channels. Send issues and PRs to", | ||
"homepage": "https://github.com/NixOS/nixpkgs", | ||
"owner": "NixOS", | ||
"repo": "nixpkgs-channels", | ||
"rev": "ab3adfe1c769c22b6629e59ea0ef88ec8ee4563f", | ||
"sha256": "1m4wvrrcvif198ssqbdw897c8h84l0cy7q75lyfzdsz9khm1y2n1", | ||
"type": "tarball", | ||
"url": "https://github.com/NixOS/nixpkgs-channels/archive/ab3adfe1c769c22b6629e59ea0ef88ec8ee4563f.tar.gz", | ||
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" | ||
} | ||
} |
Oops, something went wrong.