forked from lix-project/lix
* Support for fixed-output hashes over directory trees (i.e., over the
NAR dump of the path).
This commit is contained in:
parent
eda2c3c253
commit
3a2c3f0cf2
|
@ -25,7 +25,7 @@ if test -z "$hash"; then
|
||||||
tmpPath1=/tmp/nix-prefetch-url-$$ # !!! security?
|
tmpPath1=/tmp/nix-prefetch-url-$$ # !!! security?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Perform the checkout.
|
# Perform the download.
|
||||||
@curl@ --fail --location --max-redirs 20 "$url" > $tmpPath1
|
@curl@ --fail --location --max-redirs 20 "$url" > $tmpPath1
|
||||||
|
|
||||||
# Compute the hash.
|
# Compute the hash.
|
||||||
|
@ -47,7 +47,7 @@ storeExpr=$( \
|
||||||
| @bindir@/nix-instantiate -)
|
| @bindir@/nix-instantiate -)
|
||||||
|
|
||||||
# Realise it.
|
# Realise it.
|
||||||
finalPath=$(@bindir@/nix-store -q --force-realise $storeExpr)
|
finalPath=$(@bindir@/nix-store -r $storeExpr)
|
||||||
|
|
||||||
if ! test -n "$QUIET"; then echo "path is $finalPath" >&2; fi
|
if ! test -n "$QUIET"; then echo "path is $finalPath" >&2; fi
|
||||||
|
|
||||||
|
|
|
@ -194,6 +194,7 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args)
|
||||||
|
|
||||||
string outputHash;
|
string outputHash;
|
||||||
string outputHashAlgo;
|
string outputHashAlgo;
|
||||||
|
bool outputHashRecursive = false;
|
||||||
|
|
||||||
for (ATermIterator i(attrs.keys()); i; ++i) {
|
for (ATermIterator i(attrs.keys()); i; ++i) {
|
||||||
string key = aterm2String(*i);
|
string key = aterm2String(*i);
|
||||||
|
@ -228,6 +229,11 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args)
|
||||||
else if (key == "name") drvName = s;
|
else if (key == "name") drvName = s;
|
||||||
else if (key == "outputHash") outputHash = s;
|
else if (key == "outputHash") outputHash = s;
|
||||||
else if (key == "outputHashAlgo") outputHashAlgo = s;
|
else if (key == "outputHashAlgo") outputHashAlgo = s;
|
||||||
|
else if (key == "outputHashMode") {
|
||||||
|
if (s == "recursive") outputHashRecursive = true;
|
||||||
|
else if (s == "flat") outputHashRecursive = false;
|
||||||
|
else throw Error(format("invalid value `%1%' for `outputHashMode' attribute") % s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,6 +261,7 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args)
|
||||||
h = parseHash32(ht, outputHash);
|
h = parseHash32(ht, outputHash);
|
||||||
string s = outputHash;
|
string s = outputHash;
|
||||||
outputHash = printHash(h);
|
outputHash = printHash(h);
|
||||||
|
if (outputHashRecursive) outputHashAlgo = "r:" + outputHashAlgo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the derivation name. It shouldn't contain whitespace,
|
/* Check the derivation name. It shouldn't contain whitespace,
|
||||||
|
|
|
@ -1082,25 +1082,37 @@ void DerivationGoal::computeClosure()
|
||||||
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 (i->second.hash != "") {
|
||||||
HashType ht = parseHashType(i->second.hashAlgo);
|
|
||||||
|
bool recursive = false;
|
||||||
|
string algo = i->second.hashAlgo;
|
||||||
|
|
||||||
|
if (string(algo, 0, 2) == "r:") {
|
||||||
|
recursive = true;
|
||||||
|
algo = string(algo, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!recursive) {
|
||||||
|
/* The output path should be a regular file without
|
||||||
|
execute permission. */
|
||||||
|
struct stat st;
|
||||||
|
if (lstat(path.c_str(), &st))
|
||||||
|
throw SysError(format("getting attributes of path `%1%'") % path);
|
||||||
|
if (!S_ISREG(st.st_mode) || (st.st_mode & S_IXUSR) != 0)
|
||||||
|
throw Error(
|
||||||
|
format("output path `%1% should be a non-executable regular file")
|
||||||
|
% path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the hash. */
|
||||||
|
HashType ht = parseHashType(algo);
|
||||||
if (ht == htUnknown)
|
if (ht == htUnknown)
|
||||||
throw Error(format("unknown hash algorithm `%1%'") % i->second.hashAlgo);
|
throw Error(format("unknown hash algorithm `%1%'") % algo);
|
||||||
Hash h = parseHash(ht, i->second.hash);
|
Hash h = parseHash(ht, i->second.hash);
|
||||||
Hash h2 = hashFile(ht, path);
|
Hash h2 = recursive ? hashPath(ht, path) : hashFile(ht, path);
|
||||||
if (h != h2)
|
if (h != h2)
|
||||||
throw Error(
|
throw Error(
|
||||||
format("output path `%1% should have %2% hash `%3%', instead has `%4%'")
|
format("output path `%1% should have %2% hash `%3%', instead has `%4%'")
|
||||||
% path % i->second.hashAlgo % printHash(h) % printHash(h2));
|
% path % algo % printHash(h) % printHash(h2));
|
||||||
|
|
||||||
/* Also, the output path should be a regular file withouth
|
|
||||||
execute permission. */
|
|
||||||
struct stat st;
|
|
||||||
if (lstat(path.c_str(), &st))
|
|
||||||
throw SysError(format("getting attributes of path `%1%'") % path);
|
|
||||||
if (!S_ISREG(st.st_mode) || (st.st_mode & S_IXUSR) != 0)
|
|
||||||
throw Error(
|
|
||||||
format("output path `%1% should be a non-executable regular file")
|
|
||||||
% path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
canonicalisePathMetaData(path);
|
canonicalisePathMetaData(path);
|
||||||
|
|
Loading…
Reference in a new issue