aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/primops.cc7
-rw-r--r--src/libstore/build.cc40
2 files changed, 33 insertions, 14 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index da9d1e635..a2f27b4dc 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -194,6 +194,7 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args)
string outputHash;
string outputHashAlgo;
+ bool outputHashRecursive = false;
for (ATermIterator i(attrs.keys()); i; ++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 == "outputHash") outputHash = 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);
string s = outputHash;
outputHash = printHash(h);
+ if (outputHashRecursive) outputHashAlgo = "r:" + outputHashAlgo;
}
/* Check the derivation name. It shouldn't contain whitespace,
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 1ba521eb3..f6b081aaf 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -1082,25 +1082,37 @@ void DerivationGoal::computeClosure()
outputs (i.e., the content hash should match the specified
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)
- 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 h2 = hashFile(ht, path);
+ Hash h2 = recursive ? hashPath(ht, path) : hashFile(ht, path);
if (h != h2)
throw Error(
format("output path `%1% should have %2% hash `%3%', instead has `%4%'")
- % path % i->second.hashAlgo % 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);
+ % path % algo % printHash(h) % printHash(h2));
}
canonicalisePathMetaData(path);