deletePath(): Succeed if path doesn't exist
Also makes it robust against concurrent deletions.
This commit is contained in:
		
							parent
							
								
									28e7e29abd
								
							
						
					
					
						commit
						152b1d6bf9
					
				
					 5 changed files with 23 additions and 23 deletions
				
			
		|  | @ -1310,7 +1310,6 @@ void DerivationGoal::tryToBuild() | ||||||
|     for (auto & i : drv->outputs) { |     for (auto & i : drv->outputs) { | ||||||
|         Path path = i.second.path; |         Path path = i.second.path; | ||||||
|         if (worker.store.isValidPath(path)) continue; |         if (worker.store.isValidPath(path)) continue; | ||||||
|         if (!pathExists(path)) continue; |  | ||||||
|         debug(format("removing invalid path ‘%1%’") % path); |         debug(format("removing invalid path ‘%1%’") % path); | ||||||
|         deletePath(path); |         deletePath(path); | ||||||
|     } |     } | ||||||
|  | @ -1390,8 +1389,7 @@ void replaceValidPath(const Path & storePath, const Path tmpPath) | ||||||
|         rename(storePath.c_str(), oldPath.c_str()); |         rename(storePath.c_str(), oldPath.c_str()); | ||||||
|     if (rename(tmpPath.c_str(), storePath.c_str()) == -1) |     if (rename(tmpPath.c_str(), storePath.c_str()) == -1) | ||||||
|         throw SysError(format("moving ‘%1%’ to ‘%2%’") % tmpPath % storePath); |         throw SysError(format("moving ‘%1%’ to ‘%2%’") % tmpPath % storePath); | ||||||
|     if (pathExists(oldPath)) |     deletePath(oldPath); | ||||||
|         deletePath(oldPath); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -1490,7 +1488,7 @@ void DerivationGoal::buildDone() | ||||||
| 
 | 
 | ||||||
|         /* Delete unused redirected outputs (when doing hash rewriting). */ |         /* Delete unused redirected outputs (when doing hash rewriting). */ | ||||||
|         for (auto & i : redirectedOutputs) |         for (auto & i : redirectedOutputs) | ||||||
|             if (pathExists(i.second)) deletePath(i.second); |             deletePath(i.second); | ||||||
| 
 | 
 | ||||||
|         /* Delete the chroot (if we were using one). */ |         /* Delete the chroot (if we were using one). */ | ||||||
|         autoDelChroot.reset(); /* this runs the destructor */ |         autoDelChroot.reset(); /* this runs the destructor */ | ||||||
|  | @ -1939,7 +1937,7 @@ void DerivationGoal::startBuilder() | ||||||
|            to ensure that we can create hard-links to non-directory |            to ensure that we can create hard-links to non-directory | ||||||
|            inputs in the fake Nix store in the chroot (see below). */ |            inputs in the fake Nix store in the chroot (see below). */ | ||||||
|         chrootRootDir = drvPath + ".chroot"; |         chrootRootDir = drvPath + ".chroot"; | ||||||
|         if (pathExists(chrootRootDir)) deletePath(chrootRootDir); |         deletePath(chrootRootDir); | ||||||
| 
 | 
 | ||||||
|         /* Clean up the chroot directory automatically. */ |         /* Clean up the chroot directory automatically. */ | ||||||
|         autoDelChroot = std::make_shared<AutoDelete>(chrootRootDir); |         autoDelChroot = std::make_shared<AutoDelete>(chrootRootDir); | ||||||
|  | @ -2514,7 +2512,7 @@ void DerivationGoal::runChild() | ||||||
|             debug(sandboxProfile); |             debug(sandboxProfile); | ||||||
| 
 | 
 | ||||||
|             Path sandboxFile = drvPath + ".sb"; |             Path sandboxFile = drvPath + ".sb"; | ||||||
|             if (pathExists(sandboxFile)) deletePath(sandboxFile); |             deletePath(sandboxFile); | ||||||
|             autoDelSandbox.reset(sandboxFile, false); |             autoDelSandbox.reset(sandboxFile, false); | ||||||
| 
 | 
 | ||||||
|             writeFile(sandboxFile, sandboxProfile); |             writeFile(sandboxFile, sandboxProfile); | ||||||
|  | @ -2706,8 +2704,7 @@ void DerivationGoal::registerOutputs() | ||||||
|                     return; |                     return; | ||||||
|                 if (actualPath != dest) { |                 if (actualPath != dest) { | ||||||
|                     PathLocks outputLocks({dest}); |                     PathLocks outputLocks({dest}); | ||||||
|                     if (pathExists(dest)) |                     deletePath(dest); | ||||||
|                         deletePath(dest); |  | ||||||
|                     if (rename(actualPath.c_str(), dest.c_str()) == -1) |                     if (rename(actualPath.c_str(), dest.c_str()) == -1) | ||||||
|                         throw SysError(format("moving ‘%1%’ to ‘%2%’") % actualPath % dest); |                         throw SysError(format("moving ‘%1%’ to ‘%2%’") % actualPath % dest); | ||||||
|                 } |                 } | ||||||
|  | @ -2738,7 +2735,7 @@ void DerivationGoal::registerOutputs() | ||||||
|             if (hash.first != info.narHash) { |             if (hash.first != info.narHash) { | ||||||
|                 if (settings.keepFailed) { |                 if (settings.keepFailed) { | ||||||
|                     Path dst = path + checkSuffix; |                     Path dst = path + checkSuffix; | ||||||
|                     if (pathExists(dst)) deletePath(dst); |                     deletePath(dst); | ||||||
|                     if (rename(actualPath.c_str(), dst.c_str())) |                     if (rename(actualPath.c_str(), dst.c_str())) | ||||||
|                         throw SysError(format("renaming ‘%1%’ to ‘%2%’") % actualPath % dst); |                         throw SysError(format("renaming ‘%1%’ to ‘%2%’") % actualPath % dst); | ||||||
|                     throw Error(format("derivation ‘%1%’ may not be deterministic: output ‘%2%’ differs from ‘%3%’") |                     throw Error(format("derivation ‘%1%’ may not be deterministic: output ‘%2%’ differs from ‘%3%’") | ||||||
|  | @ -2830,7 +2827,7 @@ void DerivationGoal::registerOutputs() | ||||||
|     if (settings.keepFailed) { |     if (settings.keepFailed) { | ||||||
|         for (auto & i : drv->outputs) { |         for (auto & i : drv->outputs) { | ||||||
|             Path prev = i.second.path + checkSuffix; |             Path prev = i.second.path + checkSuffix; | ||||||
|             if (pathExists(prev)) deletePath(prev); |             deletePath(prev); | ||||||
|             if (curRound < nrRounds) { |             if (curRound < nrRounds) { | ||||||
|                 Path dst = i.second.path + checkSuffix; |                 Path dst = i.second.path + checkSuffix; | ||||||
|                 if (rename(i.second.path.c_str(), dst.c_str())) |                 if (rename(i.second.path.c_str(), dst.c_str())) | ||||||
|  | @ -2998,7 +2995,7 @@ Path DerivationGoal::addHashRewrite(const Path & path) | ||||||
|     string h1 = string(path, settings.nixStore.size() + 1, 32); |     string h1 = string(path, settings.nixStore.size() + 1, 32); | ||||||
|     string h2 = string(printHash32(hashString(htSHA256, "rewrite:" + drvPath + ":" + path)), 0, 32); |     string h2 = string(printHash32(hashString(htSHA256, "rewrite:" + drvPath + ":" + path)), 0, 32); | ||||||
|     Path p = settings.nixStore + "/" + h2 + string(path, settings.nixStore.size() + 33); |     Path p = settings.nixStore + "/" + h2 + string(path, settings.nixStore.size() + 33); | ||||||
|     if (pathExists(p)) deletePath(p); |     deletePath(p); | ||||||
|     assert(path.size() == p.size()); |     assert(path.size() == p.size()); | ||||||
|     rewritesToTmp[h1] = h2; |     rewritesToTmp[h1] = h2; | ||||||
|     rewritesFromTmp[h2] = h1; |     rewritesFromTmp[h2] = h1; | ||||||
|  | @ -3259,8 +3256,7 @@ void SubstitutionGoal::tryToRun() | ||||||
|     destPath = repair ? storePath + ".tmp" : storePath; |     destPath = repair ? storePath + ".tmp" : storePath; | ||||||
| 
 | 
 | ||||||
|     /* Remove the (stale) output path if it exists. */ |     /* Remove the (stale) output path if it exists. */ | ||||||
|     if (pathExists(destPath)) |     deletePath(destPath); | ||||||
|         deletePath(destPath); |  | ||||||
| 
 | 
 | ||||||
|     worker.store.setSubstituterEnv(); |     worker.store.setSubstituterEnv(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -608,7 +608,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) | ||||||
| 
 | 
 | ||||||
|     state.shouldDelete = options.action == GCOptions::gcDeleteDead || options.action == GCOptions::gcDeleteSpecific; |     state.shouldDelete = options.action == GCOptions::gcDeleteDead || options.action == GCOptions::gcDeleteSpecific; | ||||||
| 
 | 
 | ||||||
|     if (state.shouldDelete && pathExists(reservedPath)) |     if (state.shouldDelete) | ||||||
|         deletePath(reservedPath); |         deletePath(reservedPath); | ||||||
| 
 | 
 | ||||||
|     /* Acquire the global GC root.  This prevents
 |     /* Acquire the global GC root.  This prevents
 | ||||||
|  |  | ||||||
|  | @ -1365,7 +1365,7 @@ Path LocalStore::addToStoreFromDump(const string & dump, const string & name, | ||||||
| 
 | 
 | ||||||
|         if (repair || !isValidPath(dstPath)) { |         if (repair || !isValidPath(dstPath)) { | ||||||
| 
 | 
 | ||||||
|             if (pathExists(dstPath)) deletePath(dstPath); |             deletePath(dstPath); | ||||||
| 
 | 
 | ||||||
|             if (recursive) { |             if (recursive) { | ||||||
|                 StringSource source(dump); |                 StringSource source(dump); | ||||||
|  | @ -1434,7 +1434,7 @@ Path LocalStore::addTextToStore(const string & name, const string & s, | ||||||
| 
 | 
 | ||||||
|         if (repair || !isValidPath(dstPath)) { |         if (repair || !isValidPath(dstPath)) { | ||||||
| 
 | 
 | ||||||
|             if (pathExists(dstPath)) deletePath(dstPath); |             deletePath(dstPath); | ||||||
| 
 | 
 | ||||||
|             writeFile(dstPath, s); |             writeFile(dstPath, s); | ||||||
| 
 | 
 | ||||||
|  | @ -1659,7 +1659,7 @@ Path LocalStore::importPath(bool requireSignature, Source & source) | ||||||
| 
 | 
 | ||||||
|         if (!isValidPath(dstPath)) { |         if (!isValidPath(dstPath)) { | ||||||
| 
 | 
 | ||||||
|             if (pathExists(dstPath)) deletePath(dstPath); |             deletePath(dstPath); | ||||||
| 
 | 
 | ||||||
|             if (rename(unpacked.c_str(), dstPath.c_str()) == -1) |             if (rename(unpacked.c_str(), dstPath.c_str()) == -1) | ||||||
|                 throw SysError(format("cannot move ‘%1%’ to ‘%2%’") |                 throw SysError(format("cannot move ‘%1%’ to ‘%2%’") | ||||||
|  |  | ||||||
|  | @ -320,9 +320,11 @@ static void _deletePath(const Path & path, unsigned long long & bytesFreed) | ||||||
| { | { | ||||||
|     checkInterrupt(); |     checkInterrupt(); | ||||||
| 
 | 
 | ||||||
|     printMsg(lvlVomit, format("%1%") % path); |     struct stat st; | ||||||
| 
 |     if (lstat(path.c_str(), &st) == -1) { | ||||||
|     struct stat st = lstat(path); |         if (errno == ENOENT) return; | ||||||
|  |         throw SysError(format("getting status of ‘%1%’") % path); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (!S_ISDIR(st.st_mode) && st.st_nlink == 1) |     if (!S_ISDIR(st.st_mode) && st.st_nlink == 1) | ||||||
|         bytesFreed += st.st_blocks * 512; |         bytesFreed += st.st_blocks * 512; | ||||||
|  | @ -338,8 +340,10 @@ static void _deletePath(const Path & path, unsigned long long & bytesFreed) | ||||||
|             _deletePath(path + "/" + i.name, bytesFreed); |             _deletePath(path + "/" + i.name, bytesFreed); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (remove(path.c_str()) == -1) |     if (remove(path.c_str()) == -1) { | ||||||
|  |         if (errno == ENOENT) return; | ||||||
|         throw SysError(format("cannot unlink ‘%1%’") % path); |         throw SysError(format("cannot unlink ‘%1%’") % path); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -92,8 +92,8 @@ string readLine(int fd); | ||||||
| void writeLine(int fd, string s); | void writeLine(int fd, string s); | ||||||
| 
 | 
 | ||||||
| /* Delete a path; i.e., in the case of a directory, it is deleted
 | /* Delete a path; i.e., in the case of a directory, it is deleted
 | ||||||
|    recursively.  Don't use this at home, kids.  The second variant |    recursively. It's not an error if the path does not exist. The | ||||||
|    returns the number of bytes and blocks freed. */ |    second variant returns the number of bytes and blocks freed. */ | ||||||
| void deletePath(const Path & path); | void deletePath(const Path & path); | ||||||
| 
 | 
 | ||||||
| void deletePath(const Path & path, unsigned long long & bytesFreed); | void deletePath(const Path & path, unsigned long long & bytesFreed); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue