diff --git a/doc/manual/nix-store.xml b/doc/manual/nix-store.xml
index 633dcd871..719bfe097 100644
--- a/doc/manual/nix-store.xml
+++ b/doc/manual/nix-store.xml
@@ -773,6 +773,7 @@ $ nix-store --add ./foo.c
nix-store
+
@@ -785,7 +786,7 @@ automatically repaired. Inconsistencies are generally the result of
the Nix store or database being modified by non-Nix tools, or of bugs
in Nix itself.
-There is one option:
+This operation has the following options:
@@ -800,6 +801,16 @@ in Nix itself.
+
+
+ If any valid path is missing from the store, or
+ (if is given) the contents of a
+ valid path has been modified, then try to repair the path by
+ redownloading it. See nix-store --repair-path
+ for details.
+
+
+
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index 6882e9328..e038cd4b2 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;
}
diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh
index 80db10de1..9f1c8280a 100644
--- a/src/libstore/local-store.hh
+++ b/src/libstore/local-store.hh
@@ -171,8 +171,9 @@ public:
/* Optimise a single store path. */
void optimisePath(const Path & path);
- /* Check the integrity of the Nix store. */
- void verifyStore(bool checkContents);
+ /* Check the integrity of the Nix store. Returns true if errors
+ remain. */
+ bool verifyStore(bool checkContents, bool repair);
/* Register the validity of a path, i.e., that `path' exists, that
the paths referenced by it exists, and in the case of an output
@@ -250,7 +251,7 @@ private:
void invalidatePathChecked(const Path & path);
void verifyPath(const Path & path, const PathSet & store,
- PathSet & done, PathSet & validPaths);
+ PathSet & done, PathSet & validPaths, bool repair, bool & errors);
void updatePathInfo(const ValidPathInfo & info);
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index ce415ce4a..0ed8b6d74 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -703,13 +703,18 @@ static void opVerify(Strings opFlags, Strings opArgs)
throw UsageError("no arguments expected");
bool checkContents = false;
+ bool repair = false;
for (Strings::iterator i = opFlags.begin();
i != opFlags.end(); ++i)
if (*i == "--check-contents") checkContents = true;
+ else if (*i == "--repair") repair = true;
else throw UsageError(format("unknown flag `%1%'") % *i);
- ensureLocalStore().verifyStore(checkContents);
+ if (ensureLocalStore().verifyStore(checkContents, repair)) {
+ printMsg(lvlError, "warning: not all errors were fixed");
+ exitCode = 1;
+ }
}
@@ -743,7 +748,6 @@ static void opRepairPath(Strings opFlags, Strings opArgs)
foreach (Strings::iterator, i, opArgs) {
Path path = followLinksToStorePath(*i);
- printMsg(lvlTalkative, format("repairing path `%1%'...") % path);
ensureLocalStore().repairPath(path);
}
}