about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libstore/gc.cc17
-rw-r--r--src/libstore/gc.hh6
-rw-r--r--src/nix-store/main.cc25
3 files changed, 35 insertions, 13 deletions
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index aed7c2294b04..9af957693f0c 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -2,6 +2,11 @@
 #include "globals.hh"
 
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+
 void followLivePaths(Path nePath, PathSet & live)
 {
     /* Just to be sure, canonicalise the path.  It is important to do
@@ -62,16 +67,26 @@ PathSet findLivePaths(const Paths & roots)
 }
 
 
-PathSet findDeadPaths(const PathSet & live)
+PathSet findDeadPaths(const PathSet & live, time_t minAge)
 {
     PathSet dead;
 
     startNest(nest, lvlDebug, "finding dead paths");
 
+    time_t now = time(0);
+
     Strings storeNames = readDirectory(nixStore);
 
     for (Strings::iterator i = storeNames.begin(); i != storeNames.end(); ++i) {
         Path p = canonPath(nixStore + "/" + *i);
+
+        if (minAge > 0) {
+            struct stat st;
+            if (lstat(p.c_str(), &st) != 0)
+                throw SysError(format("obtaining information about `%1%'") % p);
+            if (st.st_atime + minAge >= now) continue;
+        }
+        
         if (live.find(p) == live.end()) {
             debug(format("dead path `%1%'") % p);
             dead.insert(p);
diff --git a/src/libstore/gc.hh b/src/libstore/gc.hh
index 997057ba9b7b..1ada419da439 100644
--- a/src/libstore/gc.hh
+++ b/src/libstore/gc.hh
@@ -17,8 +17,10 @@ PathSet findLivePaths(const Paths & roots);
 
 /* Given a set of "live" store paths, determine the set of "dead"
    store paths (which are simply all store paths that are not in the
-   live set). */
-PathSet findDeadPaths(const PathSet & live);
+   live set).  The value `minAge' specifies the minimum age in seconds
+   for an unreachable file to be considered dead (0 meaning that any
+   unreachable file is dead). */
+PathSet findDeadPaths(const PathSet & live, time_t minAge);
 
 
 #endif /* !__GC_H */
diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc
index 7bc8565d293d..e9948c7cf8ac 100644
--- a/src/nix-store/main.cc
+++ b/src/nix-store/main.cc
@@ -212,17 +212,22 @@ static void opIsValid(Strings opFlags, Strings opArgs)
 
 static void opGC(Strings opFlags, Strings opArgs)
 {
-    if (opFlags.size() != 1) throw UsageError("missing flag");
-    if (!opArgs.empty())
-        throw UsageError("no arguments expected");
-
     /* Do what? */
-    string flag = opFlags.front();
     enum { soPrintLive, soPrintDead, soDelete } subOp;
-    if (flag == "--print-live") subOp = soPrintLive;
-    else if (flag == "--print-dead") subOp = soPrintDead;
-    else if (flag == "--delete") subOp = soDelete;
-    else throw UsageError(format("bad sub-operation `%1%' in GC") % flag);
+    time_t minAge = 0;
+    for (Strings::iterator i = opFlags.begin();
+         i != opFlags.end(); ++i)
+        if (*i == "--print-live") subOp = soPrintLive;
+        else if (*i == "--print-dead") subOp = soPrintDead;
+        else if (*i == "--delete") subOp = soDelete;
+        else if (*i == "--min-age") {
+            if (opArgs.size() == 0)
+                throw UsageError("`--min-age' requires an argument");
+            istringstream st(opArgs.front());
+            st >> minAge;
+            if (!st) throw Error("number expected");
+        }
+        else throw UsageError(format("bad sub-operation `%1%' in GC") % *i);
         
     Paths roots;
     while (1) {
@@ -240,7 +245,7 @@ static void opGC(Strings opFlags, Strings opArgs)
         return;
     }
 
-    PathSet dead = findDeadPaths(live);
+    PathSet dead = findDeadPaths(live, minAge * 3600);
 
     if (subOp == soPrintDead) {
         for (PathSet::iterator i = dead.begin(); i != dead.end(); ++i)