* 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
					
				
					 3 changed files with 35 additions and 16 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue