Remove nix-build --hash
Instead, if a fixed-output derivation produces has an incorrect output hash, we now unconditionally move the outputs to the path corresponding with the actual hash and register it as valid. Thus, after correcting the hash in the Nix expression (e.g. in a fetchurl call), the fixed-output derivation doesn't have to be built again. It would still be good to have a command for reporting the actual hash of a fixed-output derivation (instead of throwing an error), but "nix-build --hash" didn't do that.
This commit is contained in:
parent
de96daf54f
commit
84722d67d2
|
@ -99,11 +99,11 @@
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>New build mode <command>nix-build --hash</command> that
|
<para>If a fixed-output derivation produces a result with an
|
||||||
builds a derivation, computes the hash of the output, and moves
|
incorrect hash, the output path will be moved to the location
|
||||||
the output to the store path corresponding to what a fixed-output
|
corresponding to the actual hash and registered as valid. Thus, a
|
||||||
derivation with that hash would produce.
|
subsequent build of the fixed-output derivation with the correct
|
||||||
(Add docs and examples; see d367b8e7875161e655deaa96bf8a5dd0bcf8229e)</para>
|
hash is unnecessary.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
|
|
|
@ -1124,11 +1124,6 @@ void DerivationGoal::haveDerivation()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reject doing a hash build of anything other than a fixed-output
|
|
||||||
derivation. */
|
|
||||||
if (buildMode == bmHash && !drv->isFixedOutput())
|
|
||||||
throw Error("cannot do a hash build of non-fixed-output derivation '%1%'", drvPath);
|
|
||||||
|
|
||||||
/* We are first going to try to create the invalid output paths
|
/* We are first going to try to create the invalid output paths
|
||||||
through substitutes. If that doesn't work, we'll build
|
through substitutes. If that doesn't work, we'll build
|
||||||
them. */
|
them. */
|
||||||
|
@ -1320,9 +1315,7 @@ void DerivationGoal::inputsRealised()
|
||||||
allPaths.insert(inputPaths.begin(), inputPaths.end());
|
allPaths.insert(inputPaths.begin(), inputPaths.end());
|
||||||
|
|
||||||
/* Is this a fixed-output derivation? */
|
/* Is this a fixed-output derivation? */
|
||||||
fixedOutput = true;
|
fixedOutput = drv->isFixedOutput();
|
||||||
for (auto & i : drv->outputs)
|
|
||||||
if (i.second.hash == "") fixedOutput = false;
|
|
||||||
|
|
||||||
/* Don't repeat fixed-output derivations since they're already
|
/* Don't repeat fixed-output derivations since they're already
|
||||||
verified by their output hash.*/
|
verified by their output hash.*/
|
||||||
|
@ -3019,6 +3012,8 @@ void DerivationGoal::registerOutputs()
|
||||||
bool runDiffHook = settings.runDiffHook;
|
bool runDiffHook = settings.runDiffHook;
|
||||||
bool keepPreviousRound = settings.keepFailed || runDiffHook;
|
bool keepPreviousRound = settings.keepFailed || runDiffHook;
|
||||||
|
|
||||||
|
std::exception_ptr delayedException;
|
||||||
|
|
||||||
/* Check whether the output paths were created, and grep each
|
/* Check whether the output paths were created, and grep each
|
||||||
output path to determine what other paths it references. Also make all
|
output path to determine what other paths it references. Also make all
|
||||||
output paths read-only. */
|
output paths read-only. */
|
||||||
|
@ -3093,7 +3088,7 @@ void DerivationGoal::registerOutputs()
|
||||||
/* Check that fixed-output derivations produced the right
|
/* Check that fixed-output derivations produced the right
|
||||||
outputs (i.e., the content hash should match the specified
|
outputs (i.e., the content hash should match the specified
|
||||||
hash). */
|
hash). */
|
||||||
if (i.second.hash != "") {
|
if (fixedOutput) {
|
||||||
|
|
||||||
bool recursive; Hash h;
|
bool recursive; Hash h;
|
||||||
i.second.parseHashInfo(recursive, h);
|
i.second.parseHashInfo(recursive, h);
|
||||||
|
@ -3109,27 +3104,34 @@ void DerivationGoal::registerOutputs()
|
||||||
/* Check the hash. In hash mode, move the path produced by
|
/* Check the hash. In hash mode, move the path produced by
|
||||||
the derivation to its content-addressed location. */
|
the derivation to its content-addressed location. */
|
||||||
Hash h2 = recursive ? hashPath(h.type, actualPath).first : hashFile(h.type, actualPath);
|
Hash h2 = recursive ? hashPath(h.type, actualPath).first : hashFile(h.type, actualPath);
|
||||||
if (buildMode == bmHash) {
|
|
||||||
Path dest = worker.store.makeFixedOutputPath(recursive, h2, drv->env["name"]);
|
Path dest = worker.store.makeFixedOutputPath(recursive, h2, drv->env["name"]);
|
||||||
printError(format("build produced path '%1%' with %2% hash '%3%'")
|
|
||||||
% dest % printHashType(h.type) % printHash16or32(h2));
|
if (h != h2) {
|
||||||
if (worker.store.isValidPath(dest))
|
|
||||||
return;
|
/* Throw an error after registering the path as
|
||||||
|
valid. */
|
||||||
|
delayedException = std::make_exception_ptr(
|
||||||
|
BuildError("fixed-output derivation produced path '%s' with %s hash '%s' instead of the expected hash '%s'",
|
||||||
|
dest, printHashType(h.type), printHash16or32(h2), printHash16or32(h)));
|
||||||
|
|
||||||
Path actualDest = worker.store.toRealPath(dest);
|
Path actualDest = worker.store.toRealPath(dest);
|
||||||
|
|
||||||
|
if (worker.store.isValidPath(dest))
|
||||||
|
std::rethrow_exception(delayedException);
|
||||||
|
|
||||||
if (actualPath != actualDest) {
|
if (actualPath != actualDest) {
|
||||||
PathLocks outputLocks({actualDest});
|
PathLocks outputLocks({actualDest});
|
||||||
deletePath(actualDest);
|
deletePath(actualDest);
|
||||||
if (rename(actualPath.c_str(), actualDest.c_str()) == -1)
|
if (rename(actualPath.c_str(), actualDest.c_str()) == -1)
|
||||||
throw SysError(format("moving '%1%' to '%2%'") % actualPath % dest);
|
throw SysError(format("moving '%1%' to '%2%'") % actualPath % dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
path = dest;
|
path = dest;
|
||||||
actualPath = actualDest;
|
actualPath = actualDest;
|
||||||
} else {
|
|
||||||
if (h != h2)
|
|
||||||
throw BuildError(
|
|
||||||
format("output path '%1%' has %2% hash '%3%' when '%4%' was expected")
|
|
||||||
% path % i.second.hashAlgo % printHash16or32(h2) % printHash16or32(h));
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
assert(path == dest);
|
||||||
|
|
||||||
info.ca = makeFixedOutputCA(recursive, h2);
|
info.ca = makeFixedOutputCA(recursive, h2);
|
||||||
}
|
}
|
||||||
|
@ -3306,6 +3308,11 @@ void DerivationGoal::registerOutputs()
|
||||||
paths referenced by each of them. If there are cycles in the
|
paths referenced by each of them. If there are cycles in the
|
||||||
outputs, this will fail. */
|
outputs, this will fail. */
|
||||||
worker.store.registerValidPaths(infos);
|
worker.store.registerValidPaths(infos);
|
||||||
|
|
||||||
|
/* In case of a fixed-output derivation hash mismatch, throw an
|
||||||
|
exception now that we have registered the output as valid. */
|
||||||
|
if (delayedException)
|
||||||
|
std::rethrow_exception(delayedException);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -192,7 +192,7 @@ struct ValidPathInfo
|
||||||
typedef list<ValidPathInfo> ValidPathInfos;
|
typedef list<ValidPathInfo> ValidPathInfos;
|
||||||
|
|
||||||
|
|
||||||
enum BuildMode { bmNormal, bmRepair, bmCheck, bmHash };
|
enum BuildMode { bmNormal, bmRepair, bmCheck };
|
||||||
|
|
||||||
|
|
||||||
struct BuildResult
|
struct BuildResult
|
||||||
|
|
|
@ -167,9 +167,6 @@ void mainWrapped(int argc, char * * argv)
|
||||||
buildMode = bmRepair;
|
buildMode = bmRepair;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (*arg == "--hash")
|
|
||||||
buildMode = bmHash;
|
|
||||||
|
|
||||||
else if (*arg == "--run-env") // obsolete
|
else if (*arg == "--run-env") // obsolete
|
||||||
runEnv = true;
|
runEnv = true;
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,6 @@ static void opRealise(Strings opFlags, Strings opArgs)
|
||||||
if (i == "--dry-run") dryRun = true;
|
if (i == "--dry-run") dryRun = true;
|
||||||
else if (i == "--repair") buildMode = bmRepair;
|
else if (i == "--repair") buildMode = bmRepair;
|
||||||
else if (i == "--check") buildMode = bmCheck;
|
else if (i == "--check") buildMode = bmCheck;
|
||||||
else if (i == "--hash") buildMode = bmHash;
|
|
||||||
else if (i == "--ignore-unknown") ignoreUnknown = true;
|
else if (i == "--ignore-unknown") ignoreUnknown = true;
|
||||||
else throw UsageError(format("unknown flag '%1%'") % i);
|
else throw UsageError(format("unknown flag '%1%'") % i);
|
||||||
|
|
||||||
|
|
|
@ -5,15 +5,22 @@ clearStore
|
||||||
export IMPURE_VAR1=foo
|
export IMPURE_VAR1=foo
|
||||||
export IMPURE_VAR2=bar
|
export IMPURE_VAR2=bar
|
||||||
|
|
||||||
|
path=$(nix-store -q $(nix-instantiate fixed.nix -A good.0))
|
||||||
|
|
||||||
|
echo 'testing bad...'
|
||||||
|
nix-build fixed.nix -A bad --no-out-link && fail "should fail"
|
||||||
|
|
||||||
|
# Building with the bad hash should produce the "good" output path as
|
||||||
|
# a side-effect.
|
||||||
|
[[ -e $path ]]
|
||||||
|
nix path-info --json $path | grep fixed:md5:2qk15sxzzjlnpjk9brn7j8ppcd
|
||||||
|
|
||||||
echo 'testing good...'
|
echo 'testing good...'
|
||||||
nix-build fixed.nix -A good --no-out-link
|
nix-build fixed.nix -A good --no-out-link
|
||||||
|
|
||||||
echo 'testing good2...'
|
echo 'testing good2...'
|
||||||
nix-build fixed.nix -A good2 --no-out-link
|
nix-build fixed.nix -A good2 --no-out-link
|
||||||
|
|
||||||
echo 'testing bad...'
|
|
||||||
nix-build fixed.nix -A bad --no-out-link && fail "should fail"
|
|
||||||
|
|
||||||
echo 'testing reallyBad...'
|
echo 'testing reallyBad...'
|
||||||
nix-instantiate fixed.nix -A reallyBad && fail "should fail"
|
nix-instantiate fixed.nix -A reallyBad && fail "should fail"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue