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