Don't require --fallback to recover from disappeared binary cache NARs
This commit is contained in:
		
							parent
							
								
									691b7582c7
								
							
						
					
					
						commit
						4ac4f675df
					
				
					 4 changed files with 41 additions and 17 deletions
				
			
		|  | @ -218,7 +218,11 @@ void BinaryCacheStore::narFromPath(const Path & storePath, Sink & sink) | |||
|     auto info = queryPathInfo(storePath).cast<const NarInfo>(); | ||||
| 
 | ||||
|     auto source = sinkToSource([this, url{info->url}](Sink & sink) { | ||||
|         try { | ||||
|             getFile(url, sink); | ||||
|         } catch (NoSuchBinaryCacheFile & e) { | ||||
|             throw SubstituteGone(e.what()); | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     stats.narRead++; | ||||
|  |  | |||
|  | @ -733,7 +733,7 @@ private: | |||
| 
 | ||||
|     /* Whether to retry substituting the outputs after building the
 | ||||
|        inputs. */ | ||||
|     bool retrySubstitution = false; | ||||
|     bool retrySubstitution; | ||||
| 
 | ||||
|     /* The derivation stored at drvPath. */ | ||||
|     std::unique_ptr<BasicDerivation> drv; | ||||
|  | @ -1123,6 +1123,8 @@ void DerivationGoal::haveDerivation() | |||
| { | ||||
|     trace("have derivation"); | ||||
| 
 | ||||
|     retrySubstitution = false; | ||||
| 
 | ||||
|     for (auto & i : drv->outputs) | ||||
|         worker.store.addTempRoot(i.second.path); | ||||
| 
 | ||||
|  | @ -1161,7 +1163,7 @@ void DerivationGoal::outputsSubstituted() | |||
|     /*  If the substitutes form an incomplete closure, then we should
 | ||||
|         build the dependencies of this derivation, but after that, we | ||||
|         can still use the substitutes for this derivation itself. */ | ||||
|     if (nrIncompleteClosure > 0 && !retrySubstitution) retrySubstitution = true; | ||||
|     if (nrIncompleteClosure > 0) retrySubstitution = true; | ||||
| 
 | ||||
|     nrFailed = nrNoSubstituters = nrIncompleteClosure = 0; | ||||
| 
 | ||||
|  | @ -3524,8 +3526,8 @@ private: | |||
|     /* The current substituter. */ | ||||
|     std::shared_ptr<Store> sub; | ||||
| 
 | ||||
|     /* Whether any substituter can realise this path. */ | ||||
|     bool hasSubstitute; | ||||
|     /* Whether a substituter failed. */ | ||||
|     bool substituterFailed = false; | ||||
| 
 | ||||
|     /* Path info returned by the substituter's query info operation. */ | ||||
|     std::shared_ptr<const ValidPathInfo> info; | ||||
|  | @ -3589,7 +3591,6 @@ public: | |||
| 
 | ||||
| SubstitutionGoal::SubstitutionGoal(const Path & storePath, Worker & worker, RepairFlag repair) | ||||
|     : Goal(worker) | ||||
|     , hasSubstitute(false) | ||||
|     , repair(repair) | ||||
| { | ||||
|     this->storePath = storePath; | ||||
|  | @ -3653,9 +3654,9 @@ void SubstitutionGoal::tryNext() | |||
|         /* Hack: don't indicate failure if there were no substituters.
 | ||||
|            In that case the calling derivation should just do a | ||||
|            build. */ | ||||
|         amDone(hasSubstitute ? ecFailed : ecNoSubstituters); | ||||
|         amDone(substituterFailed ? ecFailed : ecNoSubstituters); | ||||
| 
 | ||||
|         if (hasSubstitute) { | ||||
|         if (substituterFailed) { | ||||
|             worker.failedSubstitutions++; | ||||
|             worker.updateProgress(); | ||||
|         } | ||||
|  | @ -3691,8 +3692,6 @@ void SubstitutionGoal::tryNext() | |||
| 
 | ||||
|     worker.updateProgress(); | ||||
| 
 | ||||
|     hasSubstitute = true; | ||||
| 
 | ||||
|     /* Bail out early if this substituter lacks a valid
 | ||||
|        signature. LocalStore::addToStore() also checks for this, but | ||||
|        only after we've downloaded the path. */ | ||||
|  | @ -3807,8 +3806,19 @@ void SubstitutionGoal::finished() | |||
|         state = &SubstitutionGoal::init; | ||||
|         worker.waitForAWhile(shared_from_this()); | ||||
|         return; | ||||
|     } catch (Error & e) { | ||||
|         printError(e.msg()); | ||||
|     } catch (std::exception & e) { | ||||
|         printError(e.what()); | ||||
| 
 | ||||
|         /* Cause the parent build to fail unless --fallback is given,
 | ||||
|            or the substitute has disappeared. The latter case behaves | ||||
|            the same as the substitute never having existed in the | ||||
|            first place. */ | ||||
|         try { | ||||
|             throw; | ||||
|         } catch (SubstituteGone &) { | ||||
|         } catch (...) { | ||||
|             substituterFailed = true; | ||||
|         } | ||||
| 
 | ||||
|         /* Try the next substitute. */ | ||||
|         state = &SubstitutionGoal::tryNext; | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ MakeError(SubstError, Error) | |||
| MakeError(BuildError, Error) /* denotes a permanent build failure */ | ||||
| MakeError(InvalidPath, Error) | ||||
| MakeError(Unsupported, Error) | ||||
| MakeError(SubstituteGone, Error) | ||||
| 
 | ||||
| 
 | ||||
| struct BasicDerivation; | ||||
|  |  | |||
|  | @ -76,19 +76,28 @@ if nix-store --substituters "file://$cacheDir" -r $outPath; then | |||
| fi | ||||
| 
 | ||||
| 
 | ||||
| # Test whether fallback works if we have cached info but the | ||||
| # corresponding NAR has disappeared. | ||||
| # Test whether fallback works if a NAR has disappeared. This does not require --fallback. | ||||
| clearStore | ||||
| 
 | ||||
| nix-build --substituters "file://$cacheDir" dependencies.nix --dry-run # get info | ||||
| 
 | ||||
| mkdir $cacheDir/tmp | ||||
| mv $cacheDir/nar $cacheDir/nar2 | ||||
| 
 | ||||
| nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result | ||||
| 
 | ||||
| mv $cacheDir/nar2 $cacheDir/nar | ||||
| 
 | ||||
| 
 | ||||
| # Test whether fallback works if a NAR is corrupted. This does require --fallback. | ||||
| clearStore | ||||
| 
 | ||||
| mv $cacheDir/nar $cacheDir/nar2 | ||||
| mkdir $cacheDir/nar | ||||
| for i in $(cd $cacheDir/nar2 && echo *); do touch $cacheDir/nar/$i; done | ||||
| 
 | ||||
| (! nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result) | ||||
| 
 | ||||
| nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result --fallback | ||||
| 
 | ||||
| rm -rf $cacheDir/nar | ||||
| mv $cacheDir/nar2 $cacheDir/nar | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue