about summary refs log tree commit diff
path: root/src/libstore/local-store.cc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2012-10-02T19·04-0400
committerEelco Dolstra <eelco.dolstra@logicblox.com>2012-10-02T19·12-0400
commit8e3a7bd71253f02eb1a9fbb996166727b1283887 (patch)
tree622c2de46ea29a6d42defc50b65112c5b6022138 /src/libstore/local-store.cc
parent9958bd6992e2b3e7bacb493a372d17d5a5b95d90 (diff)
nix-store --verify: Add an option ‘--repair’ to repair all missing/corrupt paths
Also, return a non-zero exit code if errors remain after
verifying/repairing.
Diffstat (limited to 'src/libstore/local-store.cc')
-rw-r--r--src/libstore/local-store.cc25
1 files changed, 20 insertions, 5 deletions
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index 6882e9328b..e038cd4b29 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -1544,10 +1544,12 @@ void LocalStore::invalidatePathChecked(const Path & path)
 }
 
 
-void LocalStore::verifyStore(bool checkContents)
+bool LocalStore::verifyStore(bool checkContents, bool repair)
 {
     printMsg(lvlError, format("reading the Nix store..."));
 
+    bool errors = false;
+
     /* Acquire the global GC lock to prevent a garbage collection. */
     AutoCloseFD fdGCLock = openGCLock(ltWrite);
 
@@ -1560,7 +1562,7 @@ void LocalStore::verifyStore(bool checkContents)
     PathSet validPaths2 = queryAllValidPaths(), validPaths, done;
 
     foreach (PathSet::iterator, i, validPaths2)
-        verifyPath(*i, store, done, validPaths);
+        verifyPath(*i, store, done, validPaths, repair, errors);
 
     /* Release the GC lock so that checking content hashes (which can
        take ages) doesn't block the GC or builds. */
@@ -1584,6 +1586,7 @@ void LocalStore::verifyStore(bool checkContents)
                     printMsg(lvlError, format("path `%1%' was modified! "
                             "expected hash `%2%', got `%3%'")
                         % *i % printHash(info.hash) % printHash(current.first));
+                    if (repair) repairPath(*i); else errors = true;
                 } else {
 
                     bool update = false;
@@ -1611,14 +1614,17 @@ void LocalStore::verifyStore(bool checkContents)
                    errors on invalid paths. */
                 if (isValidPath(*i)) throw;
                 printMsg(lvlError, format("warning: %1%") % e.msg());
+                errors = true;
             }
         }
     }
+
+    return errors;
 }
 
 
 void LocalStore::verifyPath(const Path & path, const PathSet & store,
-    PathSet & done, PathSet & validPaths)
+    PathSet & done, PathSet & validPaths, bool repair, bool & errors)
 {
     checkInterrupt();
 
@@ -1638,7 +1644,7 @@ void LocalStore::verifyPath(const Path & path, const PathSet & store,
         PathSet referrers; queryReferrers(path, referrers);
         foreach (PathSet::iterator, i, referrers)
             if (*i != path) {
-                verifyPath(*i, store, done, validPaths);
+                verifyPath(*i, store, done, validPaths, repair, errors);
                 if (validPaths.find(*i) != validPaths.end())
                     canInvalidate = false;
             }
@@ -1646,8 +1652,17 @@ void LocalStore::verifyPath(const Path & path, const PathSet & store,
         if (canInvalidate) {
             printMsg(lvlError, format("path `%1%' disappeared, removing from database...") % path);
             invalidatePath(path);
-        } else
+        } else {
             printMsg(lvlError, format("path `%1%' disappeared, but it still has valid referrers!") % path);
+            if (repair)
+                try {
+                    repairPath(path);
+                } catch (Error & e) {
+                    printMsg(lvlError, format("warning: %1%") % e.msg());
+                    errors = true;
+                }
+            else errors = true;
+        }
 
         return;
     }