forked from lix-project/lix
Simplify
This commit is contained in:
parent
dced45f146
commit
1785ba2980
|
@ -479,99 +479,10 @@ struct LocalStore::GCState
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
bool LocalStore::tryToDelete(
|
void LocalStore::deleteFromStore(GCState & state, std::string_view baseName)
|
||||||
GCState & state,
|
|
||||||
StorePathSet & visited,
|
|
||||||
const Path & path,
|
|
||||||
bool recursive)
|
|
||||||
{
|
{
|
||||||
checkInterrupt();
|
Path path = storeDir + "/" + std::string(baseName);
|
||||||
|
Path realPath = realStoreDir + "/" + std::string(baseName);
|
||||||
auto realPath = realStoreDir + "/" + std::string(baseNameOf(path));
|
|
||||||
if (realPath == linksDir) return false;
|
|
||||||
|
|
||||||
//Activity act(*logger, lvlDebug, format("considering whether to delete '%1%'") % path);
|
|
||||||
|
|
||||||
auto storePath = maybeParseStorePath(path);
|
|
||||||
|
|
||||||
/* Wake up any client waiting for deletion of this path to
|
|
||||||
finish. */
|
|
||||||
Finally releasePending([&]() {
|
|
||||||
auto shared(state.shared.lock());
|
|
||||||
shared->pending.reset();
|
|
||||||
state.wakeup.notify_all();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (storePath) {
|
|
||||||
|
|
||||||
if (!visited.insert(*storePath).second) return true;
|
|
||||||
|
|
||||||
if (state.alive.count(*storePath)) return false;
|
|
||||||
|
|
||||||
if (state.dead.count(*storePath)) return true;
|
|
||||||
|
|
||||||
if (state.roots.count(*storePath)) {
|
|
||||||
debug("cannot delete '%s' because it's a root", path);
|
|
||||||
state.alive.insert(*storePath);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isValidPath(*storePath)) {
|
|
||||||
StorePathSet incoming;
|
|
||||||
|
|
||||||
/* Don't delete this path if any of its referrers are alive. */
|
|
||||||
queryReferrers(*storePath, incoming);
|
|
||||||
|
|
||||||
/* If keep-derivations is set and this is a derivation, then
|
|
||||||
don't delete the derivation if any of the outputs are alive. */
|
|
||||||
if (state.gcKeepDerivations && storePath->isDerivation()) {
|
|
||||||
for (auto & [name, maybeOutPath] : queryPartialDerivationOutputMap(*storePath))
|
|
||||||
if (maybeOutPath &&
|
|
||||||
isValidPath(*maybeOutPath) &&
|
|
||||||
queryPathInfo(*maybeOutPath)->deriver == *storePath)
|
|
||||||
incoming.insert(*maybeOutPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If keep-outputs is set, then don't delete this path if there
|
|
||||||
are derivers of this path that are not garbage. */
|
|
||||||
if (state.gcKeepOutputs) {
|
|
||||||
auto derivers = queryValidDerivers(*storePath);
|
|
||||||
for (auto & i : derivers)
|
|
||||||
incoming.insert(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto & i : incoming)
|
|
||||||
if (i != *storePath
|
|
||||||
&& (recursive || state.options.pathsToDelete.count(i))
|
|
||||||
&& !tryToDelete(state, visited, printStorePath(i), recursive))
|
|
||||||
{
|
|
||||||
state.alive.insert(*storePath);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto hashPart = std::string(storePath->hashPart());
|
|
||||||
auto shared(state.shared.lock());
|
|
||||||
if (shared->tempRoots.count(hashPart))
|
|
||||||
return false;
|
|
||||||
shared->pending = hashPart;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.dead.insert(*storePath);
|
|
||||||
|
|
||||||
if (state.shouldDelete)
|
|
||||||
invalidatePathChecked(*storePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.shouldDelete) {
|
|
||||||
Path realPath = realStoreDir + "/" + std::string(baseNameOf(path));
|
|
||||||
|
|
||||||
struct stat st;
|
|
||||||
if (lstat(realPath.c_str(), &st)) {
|
|
||||||
if (errno == ENOENT) return true;
|
|
||||||
throw SysError("getting status of %1%", realPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
printInfo("deleting '%1%'", path);
|
printInfo("deleting '%1%'", path);
|
||||||
|
|
||||||
|
@ -585,6 +496,87 @@ bool LocalStore::tryToDelete(
|
||||||
printInfo("deleted more than %d bytes; stopping", state.options.maxFreed);
|
printInfo("deleted more than %d bytes; stopping", state.options.maxFreed);
|
||||||
throw GCLimitReached();
|
throw GCLimitReached();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LocalStore::tryToDelete(
|
||||||
|
GCState & state,
|
||||||
|
StorePathSet & visited,
|
||||||
|
const StorePath & path,
|
||||||
|
bool recursive)
|
||||||
|
{
|
||||||
|
checkInterrupt();
|
||||||
|
|
||||||
|
//Activity act(*logger, lvlDebug, format("considering whether to delete '%1%'") % path);
|
||||||
|
|
||||||
|
/* Wake up any client waiting for deletion of this path to
|
||||||
|
finish. */
|
||||||
|
Finally releasePending([&]() {
|
||||||
|
auto shared(state.shared.lock());
|
||||||
|
shared->pending.reset();
|
||||||
|
state.wakeup.notify_all();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!visited.insert(path).second) return true;
|
||||||
|
|
||||||
|
if (state.alive.count(path)) return false;
|
||||||
|
|
||||||
|
if (state.dead.count(path)) return true;
|
||||||
|
|
||||||
|
if (state.roots.count(path)) {
|
||||||
|
debug("cannot delete '%s' because it's a root", printStorePath(path));
|
||||||
|
state.alive.insert(path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isValidPath(path)) {
|
||||||
|
StorePathSet incoming;
|
||||||
|
|
||||||
|
/* Don't delete this path if any of its referrers are alive. */
|
||||||
|
queryReferrers(path, incoming);
|
||||||
|
|
||||||
|
/* If keep-derivations is set and this is a derivation, then
|
||||||
|
don't delete the derivation if any of the outputs are
|
||||||
|
alive. */
|
||||||
|
if (state.gcKeepDerivations && path.isDerivation()) {
|
||||||
|
for (auto & [name, maybeOutPath] : queryPartialDerivationOutputMap(path))
|
||||||
|
if (maybeOutPath &&
|
||||||
|
isValidPath(*maybeOutPath) &&
|
||||||
|
queryPathInfo(*maybeOutPath)->deriver == path)
|
||||||
|
incoming.insert(*maybeOutPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If keep-outputs is set, then don't delete this path if
|
||||||
|
there are derivers of this path that are not garbage. */
|
||||||
|
if (state.gcKeepOutputs) {
|
||||||
|
auto derivers = queryValidDerivers(path);
|
||||||
|
for (auto & i : derivers)
|
||||||
|
incoming.insert(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto & i : incoming)
|
||||||
|
if (i != path
|
||||||
|
&& (recursive || state.options.pathsToDelete.count(i))
|
||||||
|
&& !tryToDelete(state, visited, i, recursive))
|
||||||
|
{
|
||||||
|
state.alive.insert(path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto hashPart = std::string(path.hashPart());
|
||||||
|
auto shared(state.shared.lock());
|
||||||
|
if (shared->tempRoots.count(hashPart))
|
||||||
|
return false;
|
||||||
|
shared->pending = hashPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.dead.insert(path);
|
||||||
|
|
||||||
|
if (state.shouldDelete) {
|
||||||
|
invalidatePathChecked(path);
|
||||||
|
deleteFromStore(state, path.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -777,7 +769,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
|
||||||
|
|
||||||
for (auto & i : options.pathsToDelete) {
|
for (auto & i : options.pathsToDelete) {
|
||||||
StorePathSet visited;
|
StorePathSet visited;
|
||||||
if (!tryToDelete(state, visited, printStorePath(i), false))
|
if (!tryToDelete(state, visited, i, false))
|
||||||
throw Error(
|
throw Error(
|
||||||
"cannot delete path '%1%' since it is still alive. "
|
"cannot delete path '%1%' since it is still alive. "
|
||||||
"To find out why, use: "
|
"To find out why, use: "
|
||||||
|
@ -799,14 +791,20 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
|
||||||
/* Read the store and delete all paths that are invalid or
|
/* Read the store and delete all paths that are invalid or
|
||||||
unreachable. We don't use readDirectory() here so that
|
unreachable. We don't use readDirectory() here so that
|
||||||
GCing can start faster. */
|
GCing can start faster. */
|
||||||
|
auto linksName = baseNameOf(linksDir);
|
||||||
Paths entries;
|
Paths entries;
|
||||||
struct dirent * dirent;
|
struct dirent * dirent;
|
||||||
while (errno = 0, dirent = readdir(dir.get())) {
|
while (errno = 0, dirent = readdir(dir.get())) {
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
string name = dirent->d_name;
|
string name = dirent->d_name;
|
||||||
if (name == "." || name == "..") continue;
|
if (name == "." || name == ".." || name == linksName) continue;
|
||||||
|
|
||||||
|
if (auto storePath = maybeParseStorePath(storeDir + "/" + name)) {
|
||||||
StorePathSet visited;
|
StorePathSet visited;
|
||||||
tryToDelete(state, visited, storeDir + "/" + name, true);
|
tryToDelete(state, visited, *storePath, true);
|
||||||
|
} else
|
||||||
|
deleteFromStore(state, name);
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (GCLimitReached & e) {
|
} catch (GCLimitReached & e) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,9 +243,11 @@ private:
|
||||||
bool tryToDelete(
|
bool tryToDelete(
|
||||||
GCState & state,
|
GCState & state,
|
||||||
StorePathSet & visited,
|
StorePathSet & visited,
|
||||||
const Path & path,
|
const StorePath & path,
|
||||||
bool recursive);
|
bool recursive);
|
||||||
|
|
||||||
|
void deleteFromStore(GCState & state, std::string_view baseName);
|
||||||
|
|
||||||
void findRoots(const Path & path, unsigned char type, Roots & roots);
|
void findRoots(const Path & path, unsigned char type, Roots & roots);
|
||||||
|
|
||||||
void findRootsNoTemp(Roots & roots, bool censor);
|
void findRootsNoTemp(Roots & roots, bool censor);
|
||||||
|
|
Loading…
Reference in a new issue