From f96d2dea266760e5587356e72d1cadaace5f7d5b Mon Sep 17 00:00:00 2001
From: Eelco Dolstra <e.dolstra@tudelft.nl>
Date: Fri, 23 Dec 2005 21:36:44 +0000
Subject: [PATCH] * Added a flag `--ignore-liveness' to `nix-store --delete'. 
 It   deletes a path even if it is reachable from a root.  However, it   won't
 delete a path that still has referrers (since that would   violate store
 invariants).

  Don't try this at home.  It's a useful hack for recovering from
  certain situations in a somewhat clean way (e.g., holes in closures
  due to disk corruption).
---
 src/libstore/gc.cc    |  5 +++--
 src/libstore/gc.hh    |  2 +-
 src/nix-store/main.cc | 11 ++++++++---
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index c02f59f2c..5f4f5b27f 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -304,7 +304,7 @@ static Paths topoSort(const PathSet & paths)
 
 
 void collectGarbage(GCAction action, const PathSet & pathsToDelete,
-    PathSet & result, unsigned long long & bytesFreed)
+    bool ignoreLiveness, PathSet & result, unsigned long long & bytesFreed)
 {
     result.clear();
     bytesFreed = 0;
@@ -323,7 +323,8 @@ void collectGarbage(GCAction action, const PathSet & pathsToDelete,
        permanent roots cannot increase now. */
     Path rootsDir = canonPath((format("%1%/%2%") % nixStateDir % gcRootsDir).str());
     PathSet roots;
-    findRoots(rootsDir, true, roots);
+    if (!ignoreLiveness)
+        findRoots(rootsDir, true, roots);
 
     if (action == gcReturnRoots) {
         result = roots;
diff --git a/src/libstore/gc.hh b/src/libstore/gc.hh
index b05d88f93..c6b13bc47 100644
--- a/src/libstore/gc.hh
+++ b/src/libstore/gc.hh
@@ -21,7 +21,7 @@ typedef enum {
    set of paths not reachable from the roots.  If `action' is
    `gcDeleteDead', actually delete the latter set. */
 void collectGarbage(GCAction action, const PathSet & pathsToDelete,
-    PathSet & result, unsigned long long & bytesFreed);
+    bool ignoreLiveness, PathSet & result, unsigned long long & bytesFreed);
 
 /* Register a temporary GC root.  This root will automatically
    disappear when this process exits.  WARNING: this function should
diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc
index 6f1fab13d..88e6720c0 100644
--- a/src/nix-store/main.cc
+++ b/src/nix-store/main.cc
@@ -518,7 +518,7 @@ static void opGC(Strings opFlags, Strings opArgs)
 
     PathSet result;
     PrintFreed freed(action == gcDeleteDead);
-    collectGarbage(action, PathSet(), result, freed.bytesFreed);
+    collectGarbage(action, PathSet(), false, result, freed.bytesFreed);
 
     if (action != gcDeleteDead) {
         for (PathSet::iterator i = result.begin(); i != result.end(); ++i)
@@ -532,7 +532,12 @@ static void opGC(Strings opFlags, Strings opArgs)
    roots). */
 static void opDelete(Strings opFlags, Strings opArgs)
 {
-    if (!opFlags.empty()) throw UsageError("unknown flag");
+    bool ignoreLiveness;
+    
+    for (Strings::iterator i = opFlags.begin();
+         i != opFlags.end(); ++i)
+        if (*i == "--ignore-liveness") ignoreLiveness = true;
+        else throw UsageError(format("unknown flag `%1%'") % *i);
 
     PathSet pathsToDelete;
     for (Strings::iterator i = opArgs.begin();
@@ -541,7 +546,7 @@ static void opDelete(Strings opFlags, Strings opArgs)
     
     PathSet dummy;
     PrintFreed freed(true);
-    collectGarbage(gcDeleteSpecific, pathsToDelete,
+    collectGarbage(gcDeleteSpecific, pathsToDelete, ignoreLiveness,
         dummy, freed.bytesFreed);
 }
 
-- 
GitLab