From 59700c09788ef1933aa8a70f7cea74d5f0b42ed0 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 27 Jun 2025 15:08:17 +0200 Subject: [PATCH] nix store delete: Show the first root that prevents deletion Examples: error: Cannot delete path '/nix/store/6fcrjgfjip2ww3sx51rrmmghfsf60jvi-patchelf-0.14.3' because it's referenced by the GC root '/home/eelco/Dev/nix-master/build/result'. error: Cannot delete path '/nix/store/rn0qyn3kmky26xgpr2n10vr787g57lff-cowsay-3.8.4' because it's referenced by the GC root '/proc/3600568/environ'. --- src/libstore/gc.cc | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 680a9f0e1..05b1a1d0c 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -458,7 +458,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) bool gcKeepOutputs = settings.gcKeepOutputs; bool gcKeepDerivations = settings.gcKeepDerivations; - std::unordered_set roots, dead, alive; + Roots roots; + std::unordered_set dead, alive; struct Shared { @@ -612,11 +613,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) /* Find the roots. Since we've grabbed the GC lock, the set of permanent roots cannot increase now. */ printInfo("finding garbage collector roots..."); - Roots rootMap; if (!options.ignoreLiveness) - findRootsNoTemp(rootMap, true); - - for (auto & i : rootMap) roots.insert(i.first); + findRootsNoTemp(roots, true); /* Read the temporary roots created before we acquired the global GC root. Any new roots will be sent to our socket. */ @@ -715,11 +713,12 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) }; /* If this is a root, bail out. */ - if (roots.count(*path)) { + if (auto i = roots.find(*path); i != roots.end()) { if (options.action == GCOptions::gcDeleteSpecific) throw Error( - "Cannot delete path '%s' because it's a GC root.", - printStorePath(start)); + "Cannot delete path '%s' because it's referenced by the GC root '%s'.", + printStorePath(start), + *i->second.begin()); debug("cannot delete '%s' because it's a root", printStorePath(*path)); return markAlive(); }