Add build mode to compute fixed-output derivation hashes
For example,
$ nix-build --hash -A nix-repl.src
will build the fixed-output derivation nix-repl.src (a fetchFromGitHub
call), but instead of *verifying* the hash given in the Nix
expression, it prints out the resulting hash, and then moves the
result to its content-addressed location in the Nix store. E.g
build produced path ‘/nix/store/504a4k6zi69dq0yjc0bm12pa65bccxam-nix-repl-8a2f5f0607540ffe56b56d52db544373e1efb980-src’ with sha256 hash ‘0cjablz01i0g9smnavhf86imwx1f9mnh5flax75i615ml71gsr88’
The goal of this is to make all nix-prefetch-* scripts unnecessary: we
can just let Nix run the real thing (i.e., the corresponding fetch*
derivation).
Another example:
$ nix-build --hash -E 'with import <nixpkgs> {}; fetchgit { url = "https://github.com/NixOS/nix.git"; sha256 = "ffffffffffffffffffffffffffffffffffffffffffffffffffff"; }'
...
git revision is 9e7c1a4bbd
...
build produced path ‘/nix/store/gmsnh9i7x4mb7pyd2ns7n3c9l90jfsi1-nix’ with sha256 hash ‘1188xb621diw89n25rifqg9lxnzpz7nj5bfh4i1y3dnis0dmc0zp’
(Having to specify a fake sha256 hash is a bit annoying...)
This commit is contained in:
parent
9e7c1a4bbd
commit
d367b8e787
3 changed files with 34 additions and 7 deletions
|
@ -1045,6 +1045,15 @@ void DerivationGoal::haveDerivation()
|
||||||
for (auto & i : invalidOutputs)
|
for (auto & i : invalidOutputs)
|
||||||
if (pathFailed(i)) return;
|
if (pathFailed(i)) return;
|
||||||
|
|
||||||
|
/* Reject doing a hash build of anything other than a fixed-output
|
||||||
|
derivation. */
|
||||||
|
if (buildMode == bmHash) {
|
||||||
|
if (drv->outputs.size() != 1 ||
|
||||||
|
drv->outputs.find("out") == drv->outputs.end() ||
|
||||||
|
drv->outputs["out"].hashAlgo == "")
|
||||||
|
throw Error(format("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. */
|
||||||
|
@ -2727,13 +2736,30 @@ void DerivationGoal::registerOutputs()
|
||||||
format("output path ‘%1%’ should be a non-executable regular file") % path);
|
format("output path ‘%1%’ should be a non-executable regular file") % path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the hash. */
|
/* Check the hash. In hash mode, move the path produced by
|
||||||
|
the derivation to its content-addressed location. */
|
||||||
Hash h2 = recursive ? hashPath(ht, actualPath).first : hashFile(ht, actualPath);
|
Hash h2 = recursive ? hashPath(ht, actualPath).first : hashFile(ht, actualPath);
|
||||||
|
if (buildMode == bmHash) {
|
||||||
|
Path dest = makeFixedOutputPath(recursive, ht, h2, drv->env["name"]);
|
||||||
|
printMsg(lvlError, format("build produced path ‘%1%’ with %2% hash ‘%3%’")
|
||||||
|
% dest % printHashType(ht) % printHash16or32(h2));
|
||||||
|
if (worker.store.isValidPath(dest))
|
||||||
|
return;
|
||||||
|
if (actualPath != dest) {
|
||||||
|
PathLocks outputLocks({dest});
|
||||||
|
if (pathExists(dest))
|
||||||
|
deletePath(dest);
|
||||||
|
if (rename(actualPath.c_str(), dest.c_str()) == -1)
|
||||||
|
throw SysError(format("moving ‘%1%’ to ‘%2%’") % actualPath % dest);
|
||||||
|
}
|
||||||
|
path = actualPath = dest;
|
||||||
|
} else {
|
||||||
if (h != h2)
|
if (h != h2)
|
||||||
throw BuildError(
|
throw BuildError(
|
||||||
format("output path ‘%1%’ has %2% hash ‘%3%’ when ‘%4%’ was expected")
|
format("output path ‘%1%’ has %2% hash ‘%3%’ when ‘%4%’ was expected")
|
||||||
% path % i.second.hashAlgo % printHash16or32(h2) % printHash16or32(h));
|
% path % i.second.hashAlgo % printHash16or32(h2) % printHash16or32(h));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Get rid of all weird permissions. This also checks that
|
/* Get rid of all weird permissions. This also checks that
|
||||||
all files are owned by the build user, if applicable. */
|
all files are owned by the build user, if applicable. */
|
||||||
|
@ -2748,7 +2774,7 @@ void DerivationGoal::registerOutputs()
|
||||||
PathSet references = scanForReferences(actualPath, allPaths, hash);
|
PathSet references = scanForReferences(actualPath, allPaths, hash);
|
||||||
|
|
||||||
if (buildMode == bmCheck) {
|
if (buildMode == bmCheck) {
|
||||||
if (!store->isValidPath(path)) continue;
|
if (!worker.store.isValidPath(path)) continue;
|
||||||
ValidPathInfo info = worker.store.queryPathInfo(path);
|
ValidPathInfo info = worker.store.queryPathInfo(path);
|
||||||
if (hash.first != info.hash) {
|
if (hash.first != info.hash) {
|
||||||
if (settings.keepFailed) {
|
if (settings.keepFailed) {
|
||||||
|
|
|
@ -103,7 +103,7 @@ struct ValidPathInfo
|
||||||
typedef list<ValidPathInfo> ValidPathInfos;
|
typedef list<ValidPathInfo> ValidPathInfos;
|
||||||
|
|
||||||
|
|
||||||
enum BuildMode { bmNormal, bmRepair, bmCheck };
|
enum BuildMode { bmNormal, bmRepair, bmCheck, bmHash };
|
||||||
|
|
||||||
|
|
||||||
struct BuildResult
|
struct BuildResult
|
||||||
|
|
|
@ -117,6 +117,7 @@ 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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue