on iko/ghcjs-patch-master help sign in
Materialization: add scripts for fixing materialized files and shas, expose via passthru and errors (#653)

* Add script for fixing materialized files This is useful in two ways: - We reference it in the error message, so users can more easily copy-paste the correct call, rather than several lines of commands. - We add it to `passthru`, so users can reference it directly when they know they need to update the files, without having to first run a build and find it on stderr. * Add script for calculating the sha This is useful in two ways: - It makes it easier for users to copy from the message. - We add it to `passthru` so users can call it directly if they know they need to update the sha, without having to run a build and copy it from stderr. * Refactor unchecked a bit Put the positive logic first, use the materialized files by preference if they're there. * Allow the updater script to take an argument * Use double brackets * Fix a dependency * Separate generating and updating scripts

commit908a3114d8c8892f0663a466a80a0b833e09ce6c authorMichael Peyton Jones <michael.peyton-jones@iohk.io> dateMon 8 Jun 2020, 11:19 (6 years ago) parent179363a
2 files changed+49−34
lib/materialize.nix+48−33 overlays/haskell.nix+1−1
lib/materialize.nix+48−33
@@ -1,4 +1,4 @@
1−{ pkgs, nix, runCommand, checkMaterialization }@defaults:
1+{ pkgs, nix, runCommand, writeShellScript, checkMaterialization }@defaults:
22{ sha256 ? null # Has to make this a fixed output derivation
33, sha256Arg ? "sha256"
44 # Name of the sha256 argument for more meaningful
@@ -34,37 +34,31 @@ let
3434 else x;
3535
3636 unchecked =
37− if reasonNotSafe != null
37+ let
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}";
40+ in if reasonNotSafe != null
3841 then
3942 # Warn the user if they tried to pin stuff down when it is not safe
4043 traceIgnoringSha256 reasonNotSafe
4144 (traceIgnoringMaterialized reasonNotSafe calculateNoHash)
42− else if sha256 == null && materialized == null
45+ else if materialized != null
46+ then calculateUseMaterialized
47+ else if sha256 != null
4348 then
44− # Let the user know how to calculate a sha256 to use to make this
45− # a fixed output derivation.
46− builtins.trace ("Get `${sha256Arg}` with `nix-hash --base32 --type sha256 "
47− + toString calculateNoHash + "/`") (traceIgnoringMaterialized
48− "${sha256Arg} is not set" calculateNoHash)
49− else if materialized == null
50− then
51− # To avoid any IFD dependencies add a `materialized` copy somewhere
52− # and pass it in.
53− builtins.trace ("To materialize, point `materialized` to a copy of " + toString calculateUseHash)
54− calculateUseHash
55− else
56− # Everything is in place we can safely use the sha256 and materialized
57− calculateUseMaterialized;
49+ # Let the user know how to materialize if they want to.
50+ builtins.trace materializeMessage calculateUseHash
51+ else # materialized == null && sha256 == null
52+ # Let the user know how to calculate a sha256 or materialize if they want to.
53+ builtins.trace sha256message (builtins.trace materializeMessage calculateNoHash);
5854
5955 # Build fully and check the hash and materialized versions
60− checked = runCommand name {
61− buildInputs = [ nix ];
62− } (''
56+ checked = runCommand name {} (''
6357 ERR=$(mktemp -d)/errors.txt
6458 ''
6559 + (pkgs.lib.optionalString (sha256 != null) ''
66− NEW_HASH=$(nix-hash --base32 --type sha256 ${calculateNoHash})
67− if [ "${sha256}" != "$NEW_HASH" ]; then
60+ NEW_HASH=$(${calculateMaterializedSha})
61+ if [[ ${sha256} != $NEW_HASH ]]; then
6862 echo Changes to ${name} not reflected in ${sha256Arg}
6963 diff -ru ${calculateUseHash} ${calculateNoHash} || true
7064 echo "Calculated hash for ${name} was not ${sha256}. New hash is :" >> $ERR
@@ -76,9 +70,7 @@ let
7670 + (
7771 if materialized != null && !__pathExists materialized
7872 then ''
79− echo "Materialized nix used for ${name} is missing. To fix run :" >> $ERR
80− echo " cp -r ${calculateNoHash} ${toString materialized}" >> $ERR
81− echo " chmod -R +w ${toString materialized}" >> $ERR
73+ echo "Materialized nix used for ${name} is missing. To fix run: ${updateMaterialized}" >> $ERR
8274 cat $ERR
8375 false
8476 ''
@@ -89,14 +81,11 @@ let
8981 else
9082 echo Changes to plan not reflected in materialized nix for ${name}
9183 diff -ru ${materialized} ${calculateNoHash} || true
92− echo "Materialized nix used for ${name} incorrect. To fix run :" >> $ERR
93− echo " rm -rf ${toString materialized}" >> $ERR
94− echo " cp -r ${calculateNoHash} ${toString materialized}" >> $ERR
95− echo " chmod -R +w ${toString materialized}" >> $ERR
84+ echo "Materialized nix used for ${name} incorrect. To fix run: ${updateMaterialized}" >> $ERR
9685 fi
9786 '')
9887 + ''
99− if [ -e $ERR ]; then
88+ if [[ -e $ERR ]]; then
10089 cat $ERR
10190 false
10291 else
@@ -129,13 +118,39 @@ let
129118 # Make sure output files can be removed from the sandbox
130119 chmod -R +w $out
131120 '';
121+ calculateMaterializedSha =
122+ writeShellScript "calculateSha" ''${nix}/nix-hash --base32 --type sha256 ${calculateNoHash}'';
123+
124+ # Generate the materialized files in a particular path.
125+ generateMaterialized =
126+ writeShellScript "generateMaterialized" ''
127+ TARGET=$1
128+
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!"
132+ exit 1
133+ fi
134+
135+ # Generate the files
136+ rm -rf $TARGET
137+ cp -r ${calculateNoHash} "$TARGET"
138+ chmod -R +w "$TARGET"
139+ '';
140+ # Update the materialized files at 'materialized', which must already be set.
141+ updateMaterialized =
142+ assert materialized != null;
143+ writeShellScript "updateMaterialized" ''${generateMaterialized} ${toString materialized}'';
132144
133145 # Materialized location was specified, but the files are not there.
134146 missingMaterialized = materialized != null && !__pathExists materialized;
135147
136−in
137148 # Use the checked version if requested or if the `materialized` version
138149 # is missing (perhaps deleted or not created yet).
139− if checkMaterialization || missingMaterialized
150+ result = if checkMaterialization || missingMaterialized
140151 then checked
141− else unchecked
152+ else unchecked;
153+
154+in result
155+ # Also include the scripts for fixing materialization files in passthru.
156+ // { passthru = (result.passthru or {}) // { inherit generateMaterialized updateMaterialized calculateMaterializedSha; }; }
overlays/haskell.nix+1−1
@@ -248,7 +248,7 @@ final: prev: {
248248 inherit (final.evalPackages) nix;
249249 inherit (final.haskell-nix) checkMaterialization;
250250 pkgs = final.evalPackages.pkgs;
251− inherit (final.evalPackages.pkgs) runCommand;
251+ inherit (final.evalPackages.pkgs) runCommand writeShellScript;
252252 };
253253
254254 update-index-state-hashes = import ../scripts/update-index-state-hashes.nix {