@@ -1,4 +1,4 @@
1−{ pkgs, nix, runCommand, checkMaterialization }@defaults:
1+{ pkgs, nix, runCommand, writeShellScript, checkMaterialization }@defaults:
2{ sha256 ? null # Has to make this a fixed output derivation
2{ sha256 ? null # Has to make this a fixed output derivation
3, sha256Arg ? "sha256"
3, sha256Arg ? "sha256"
4 # Name of the sha256 argument for more meaningful
4 # Name of the sha256 argument for more meaningful
@@ -34,37 +34,31 @@ let
36 unchecked =
36 unchecked =
38+ sha256message = "To make this a fixed-output derivation but not materialized, set `${sha256Arg}` to the output of ${calculateMaterializedSha}";
39+ materializeMessage = "To materialize the output entirely, pass a writable path as the `materialized` argument and pass that path to ${generateMaterialized}";
37− if reasonNotSafe != null
40+ in if reasonNotSafe != null
39 # Warn the user if they tried to pin stuff down when it is not safe
42 # Warn the user if they tried to pin stuff down when it is not safe
40 traceIgnoringSha256 reasonNotSafe
43 traceIgnoringSha256 reasonNotSafe
41 (traceIgnoringMaterialized reasonNotSafe calculateNoHash)
44 (traceIgnoringMaterialized reasonNotSafe calculateNoHash)
42− else if sha256 == null && materialized == null
45+ else if materialized != null
46+ then calculateUseMaterialized
47+ else if sha256 != null
44− # Let the user know how to calculate a sha256 to use to make this
49+ # Let the user know how to materialize if they want to.
45− # a fixed output derivation.
50+ builtins.trace materializeMessage calculateUseHash
46− builtins.trace ("Get `${sha256Arg}` with `nix-hash --base32 --type sha256 "
51+ else # materialized == null && sha256 == null
47− + toString calculateNoHash + "/`") (traceIgnoringMaterialized
52+ # Let the user know how to calculate a sha256 or materialize if they want to.
48− "${sha256Arg} is not set" calculateNoHash)
53+ builtins.trace sha256message (builtins.trace materializeMessage calculateNoHash);
49− else if materialized == null
51− # To avoid any IFD dependencies add a `materialized` copy somewhere
53− builtins.trace ("To materialize, point `materialized` to a copy of " + toString calculateUseHash)
56− # Everything is in place we can safely use the sha256 and materialized
57− calculateUseMaterialized;
59 # Build fully and check the hash and materialized versions
55 # Build fully and check the hash and materialized versions
60− checked = runCommand name {
56+ checked = runCommand name {} (''
61− buildInputs = [ nix ];
63 ERR=$(mktemp -d)/errors.txt
57 ERR=$(mktemp -d)/errors.txt
65 + (pkgs.lib.optionalString (sha256 != null) ''
59 + (pkgs.lib.optionalString (sha256 != null) ''
66− NEW_HASH=$(nix-hash --base32 --type sha256 ${calculateNoHash})
60+ NEW_HASH=$(${calculateMaterializedSha})
67− if [ "${sha256}" != "$NEW_HASH" ]; then
61+ if [[ ${sha256} != $NEW_HASH ]]; then
68 echo Changes to ${name} not reflected in ${sha256Arg}
62 echo Changes to ${name} not reflected in ${sha256Arg}
69 diff -ru ${calculateUseHash} ${calculateNoHash} || true
63 diff -ru ${calculateUseHash} ${calculateNoHash} || true
70 echo "Calculated hash for ${name} was not ${sha256}. New hash is :" >> $ERR
64 echo "Calculated hash for ${name} was not ${sha256}. New hash is :" >> $ERR
@@ -76,9 +70,7 @@ let
77 if materialized != null && !__pathExists materialized
71 if materialized != null && !__pathExists materialized
79− echo "Materialized nix used for ${name} is missing. To fix run :" >> $ERR
73+ echo "Materialized nix used for ${name} is missing. To fix run: ${updateMaterialized}" >> $ERR
80− echo " cp -r ${calculateNoHash} ${toString materialized}" >> $ERR
81− echo " chmod -R +w ${toString materialized}" >> $ERR
@@ -89,14 +81,11 @@ let
90 echo Changes to plan not reflected in materialized nix for ${name}
82 echo Changes to plan not reflected in materialized nix for ${name}
91 diff -ru ${materialized} ${calculateNoHash} || true
83 diff -ru ${materialized} ${calculateNoHash} || true
92− echo "Materialized nix used for ${name} incorrect. To fix run :" >> $ERR
84+ echo "Materialized nix used for ${name} incorrect. To fix run: ${updateMaterialized}" >> $ERR
93− echo " rm -rf ${toString materialized}" >> $ERR
94− echo " cp -r ${calculateNoHash} ${toString materialized}" >> $ERR
95− echo " chmod -R +w ${toString materialized}" >> $ERR
99− if [ -e $ERR ]; then
88+ if [[ -e $ERR ]]; then
@@ -129,13 +118,39 @@ let
129 # Make sure output files can be removed from the sandbox
118 # Make sure output files can be removed from the sandbox
130 chmod -R +w $out
119 chmod -R +w $out
121+ calculateMaterializedSha =
122+ writeShellScript "calculateSha" ''${nix}/nix-hash --base32 --type sha256 ${calculateNoHash}'';
124+ # Generate the materialized files in a particular path.
125+ generateMaterialized =
126+ writeShellScript "generateMaterialized" ''
129+ # Crudely try and guard people from writing to the Nix store accidentally
130+ if [[ ''${TARGET##/nix/store/} != $TARGET ]]; then
131+ echo "Attempted to write to $TARGET in the Nix store! Put your materialized files somewhere else!"
135+ # Generate the files
137+ cp -r ${calculateNoHash} "$TARGET"
138+ chmod -R +w "$TARGET"
140+ # Update the materialized files at 'materialized', which must already be set.
141+ updateMaterialized =
142+ assert materialized != null;
143+ writeShellScript "updateMaterialized" ''${generateMaterialized} ${toString materialized}'';
133 # Materialized location was specified, but the files are not there.
145 # Materialized location was specified, but the files are not there.
134 missingMaterialized = materialized != null && !__pathExists materialized;
146 missingMaterialized = materialized != null && !__pathExists materialized;
137 # Use the checked version if requested or if the `materialized` version
148 # Use the checked version if requested or if the `materialized` version
138 # is missing (perhaps deleted or not created yet).
149 # is missing (perhaps deleted or not created yet).
139− if checkMaterialization || missingMaterialized
150+ result = if checkMaterialization || missingMaterialized
140 then checked
151 then checked
141− else unchecked
152+ else unchecked;
155+ # Also include the scripts for fixing materialization files in passthru.
156+ // { passthru = (result.passthru or {}) // { inherit generateMaterialized updateMaterialized calculateMaterializedSha; }; }