about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/db.cc10
-rw-r--r--src/db.hh5
-rw-r--r--src/fstate.hh4
-rw-r--r--src/nix.cc9
-rw-r--r--src/store.cc121
-rw-r--r--src/store.hh2
-rw-r--r--src/util.hh2
7 files changed, 139 insertions, 14 deletions
diff --git a/src/db.cc b/src/db.cc
index 64f9813a400f..a8741342ce92 100644
--- a/src/db.cc
+++ b/src/db.cc
@@ -157,7 +157,7 @@ void delDB(const string & filename, const string & dbname,
 
 
 void enumDB(const string & filename, const string & dbname,
-    DBPairs & contents)
+    Strings & keys)
 {
     try {
 
@@ -168,11 +168,9 @@ void enumDB(const string & filename, const string & dbname,
         DbcClose cursorCloser(cursor);
 
         Dbt kt, dt;
-        while (cursor->get(&kt, &dt, DB_NEXT) != DB_NOTFOUND) {
-            string key((char *) kt.get_data(), kt.get_size());
-            string data((char *) dt.get_data(), dt.get_size());
-            contents.push_back(DBPair(key, data));
-        }
+        while (cursor->get(&kt, &dt, DB_NEXT) != DB_NOTFOUND)
+            keys.push_back(
+                string((char *) kt.get_data(), kt.get_size()));
 
     } catch (DbException e) { rethrow(e); }
 }
diff --git a/src/db.hh b/src/db.hh
index aee6ce9bff90..6f13eb30c813 100644
--- a/src/db.hh
+++ b/src/db.hh
@@ -8,9 +8,6 @@
 
 using namespace std;
 
-typedef pair<string, string> DBPair;
-typedef list<DBPair> DBPairs;
-
 void createDB(const string & filename, const string & dbname);
 
 bool queryDB(const string & filename, const string & dbname,
@@ -29,6 +26,6 @@ void delDB(const string & filename, const string & dbname,
     const string & key);
 
 void enumDB(const string & filename, const string & dbname,
-    DBPairs & contents);
+    Strings & keys);
 
 #endif /* !__DB_H */
diff --git a/src/fstate.hh b/src/fstate.hh
index 2ae876b7cd2e..0d89e7e360c7 100644
--- a/src/fstate.hh
+++ b/src/fstate.hh
@@ -1,8 +1,6 @@
 #ifndef __FSTATE_H
 #define __FSTATE_H
 
-#include <set>
-
 extern "C" {
 #include <aterm2.h>
 }
@@ -53,8 +51,6 @@ using namespace std;
 typedef ATerm FState;
 typedef ATerm Content;
 
-typedef set<string> StringSet;
-
 typedef list<FSId> FSIds;
 
 
diff --git a/src/nix.cc b/src/nix.cc
index fe762798e799..5785cd6b4cc2 100644
--- a/src/nix.cc
+++ b/src/nix.cc
@@ -283,6 +283,13 @@ static void opInit(Strings opFlags, Strings opArgs)
 }
 
 
+/* Verify the consistency of the Nix environment. */
+static void opVerify(Strings opFlags, Strings opArgs)
+{
+    verifyStore();
+}
+
+
 /* Scan the arguments; find the operation, set global flags, put all
    other flags in a list, and put all other arguments in another
    list. */
@@ -316,6 +323,8 @@ void run(Strings args)
             op = opRestore;
         else if (arg == "--init")
             op = opInit;
+        else if (arg == "--verify")
+            op = opVerify;
         else if (arg[0] == '-')
             opFlags.push_back(arg);
         else
diff --git a/src/store.cc b/src/store.cc
index d75458d8a55b..864213692ed8 100644
--- a/src/store.cc
+++ b/src/store.cc
@@ -260,3 +260,124 @@ void deleteFromStore(const string & path)
 
     deletePath(path);
 }
+
+
+void verifyStore()
+{
+    Strings paths;
+    enumDB(nixDB, dbPath2Id, paths);
+
+    for (Strings::iterator i = paths.begin();
+         i != paths.end(); i++)
+    {
+        bool erase = true;
+        string path = *i;
+
+        if (!pathExists(path)) {
+            debug(format("path `%1%' disappeared") % path);
+        }
+
+        else {
+            string id;
+            if (!queryDB(nixDB, dbPath2Id, path, id)) abort();
+
+            Strings idPaths;
+            queryListDB(nixDB, dbId2Paths, id, idPaths);
+
+            bool found = false;
+            for (Strings::iterator j = idPaths.begin();     
+                 j != idPaths.end(); j++)
+                if (path == *j) {
+                    found = true;
+                    break;
+                }
+
+            if (found)
+                erase = false;
+            else
+                /* !!! perhaps we should add path to idPaths? */
+                debug(format("reverse mapping for path `%1%' missing") % path);
+        }
+
+        if (erase) delDB(nixDB, dbPath2Id, path);
+    }
+
+    Strings ids;
+    enumDB(nixDB, dbId2Paths, ids);
+
+    for (Strings::iterator i = ids.begin();
+         i != ids.end(); i++)
+    {
+        FSId id = parseHash(*i);
+
+        Strings idPaths;
+        queryListDB(nixDB, dbId2Paths, id, idPaths);
+
+        for (Strings::iterator j = idPaths.begin();     
+             j != idPaths.end(); )
+        {
+            string id2;
+            if (!queryDB(nixDB, dbPath2Id, *j, id2) || 
+                id != parseHash(id2)) {
+                debug(format("erasing path `%1%' from mapping for id %2%") 
+                    % *j % (string) id);
+                j = idPaths.erase(j);
+            } else j++;
+        }
+
+        setListDB(nixDB, dbId2Paths, id, idPaths);
+    }
+
+    
+    Strings subs;
+    enumDB(nixDB, dbSubstitutes, subs);
+
+    for (Strings::iterator i = subs.begin();
+         i != subs.end(); i++)
+    {
+        FSId srcId = parseHash(*i);
+
+        Strings subIds;
+        queryListDB(nixDB, dbSubstitutes, srcId, subIds);
+
+        for (Strings::iterator j = subIds.begin();     
+             j != subIds.end(); )
+        {
+            FSId subId = parseHash(*j);
+            
+            Strings subPaths;
+            queryListDB(nixDB, dbId2Paths, subId, subPaths);
+            if (subPaths.size() == 0) {
+                debug(format("erasing substitute %1% for %2%") 
+                    % (string) subId % (string) srcId);
+                j = subIds.erase(j);
+            } else j++;
+        }
+
+        setListDB(nixDB, dbSubstitutes, srcId, subIds);
+    }
+
+    Strings sucs;
+    enumDB(nixDB, dbSuccessors, sucs);
+
+    for (Strings::iterator i = sucs.begin();
+         i != sucs.end(); i++)
+    {
+        FSId id1 = parseHash(*i);
+
+        string id2;
+        if (!queryDB(nixDB, dbSuccessors, id1, id2)) abort();
+        
+        Strings id2Paths;
+        queryListDB(nixDB, dbId2Paths, id2, id2Paths);
+        if (id2Paths.size() == 0) {
+            Strings id2Subs;
+            queryListDB(nixDB, dbSubstitutes, id2, id2Subs);
+            if (id2Subs.size() == 0) {
+                debug(format("successor %1% for %2% missing") 
+                    % id2 % (string) id1);
+                delDB(nixDB, dbSuccessors, (string) id1);
+            }
+        }
+    }
+}
diff --git a/src/store.hh b/src/store.hh
index 7dd0f72e6f7c..78d5529e7724 100644
--- a/src/store.hh
+++ b/src/store.hh
@@ -35,5 +35,7 @@ void addToStore(string srcPath, string & dstPath, FSId & id,
 /* Delete a value from the nixStore directory. */
 void deleteFromStore(const string & path);
 
+void verifyStore();
+
 
 #endif /* !__STORE_H */
diff --git a/src/util.hh b/src/util.hh
index 684bafbb55d6..611612a589c6 100644
--- a/src/util.hh
+++ b/src/util.hh
@@ -3,6 +3,7 @@
 
 #include <string>
 #include <list>
+#include <set>
 #include <sstream>
 
 #include <unistd.h>
@@ -38,6 +39,7 @@ public:
 
 
 typedef list<string> Strings;
+typedef set<string> StringSet;
 
 
 /* The canonical system name, as returned by config.guess. */