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…
	
	Add table
		Add a link
		
	
		Reference in a new issue