forked from lix-project/lix
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.
This commit is contained in:
parent
9958bd6992
commit
8e3a7bd712
|
@ -773,6 +773,7 @@ $ nix-store --add ./foo.c
|
||||||
<command>nix-store</command>
|
<command>nix-store</command>
|
||||||
<arg choice='plain'><option>--verify</option></arg>
|
<arg choice='plain'><option>--verify</option></arg>
|
||||||
<arg><option>--check-contents</option></arg>
|
<arg><option>--check-contents</option></arg>
|
||||||
|
<arg><option>--repair</option></arg>
|
||||||
</cmdsynopsis>
|
</cmdsynopsis>
|
||||||
</refsection>
|
</refsection>
|
||||||
|
|
||||||
|
@ -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
|
the Nix store or database being modified by non-Nix tools, or of bugs
|
||||||
in Nix itself.</para>
|
in Nix itself.</para>
|
||||||
|
|
||||||
<para>There is one option:
|
<para>This operation has the following options:
|
||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
|
|
||||||
|
@ -800,6 +801,16 @@ in Nix itself.</para>
|
||||||
|
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry><term><option>--repair</option></term>
|
||||||
|
|
||||||
|
<listitem><para>If any valid path is missing from the store, or
|
||||||
|
(if <option>--check-contents</option> is given) the contents of a
|
||||||
|
valid path has been modified, then try to repair the path by
|
||||||
|
redownloading it. See <command>nix-store --repair-path</command>
|
||||||
|
for details.</para></listitem>
|
||||||
|
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
|
||||||
</para>
|
</para>
|
||||||
|
|
|
@ -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..."));
|
printMsg(lvlError, format("reading the Nix store..."));
|
||||||
|
|
||||||
|
bool errors = false;
|
||||||
|
|
||||||
/* Acquire the global GC lock to prevent a garbage collection. */
|
/* Acquire the global GC lock to prevent a garbage collection. */
|
||||||
AutoCloseFD fdGCLock = openGCLock(ltWrite);
|
AutoCloseFD fdGCLock = openGCLock(ltWrite);
|
||||||
|
|
||||||
|
@ -1560,7 +1562,7 @@ void LocalStore::verifyStore(bool checkContents)
|
||||||
PathSet validPaths2 = queryAllValidPaths(), validPaths, done;
|
PathSet validPaths2 = queryAllValidPaths(), validPaths, done;
|
||||||
|
|
||||||
foreach (PathSet::iterator, i, validPaths2)
|
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
|
/* Release the GC lock so that checking content hashes (which can
|
||||||
take ages) doesn't block the GC or builds. */
|
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! "
|
printMsg(lvlError, format("path `%1%' was modified! "
|
||||||
"expected hash `%2%', got `%3%'")
|
"expected hash `%2%', got `%3%'")
|
||||||
% *i % printHash(info.hash) % printHash(current.first));
|
% *i % printHash(info.hash) % printHash(current.first));
|
||||||
|
if (repair) repairPath(*i); else errors = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
bool update = false;
|
bool update = false;
|
||||||
|
@ -1611,14 +1614,17 @@ void LocalStore::verifyStore(bool checkContents)
|
||||||
errors on invalid paths. */
|
errors on invalid paths. */
|
||||||
if (isValidPath(*i)) throw;
|
if (isValidPath(*i)) throw;
|
||||||
printMsg(lvlError, format("warning: %1%") % e.msg());
|
printMsg(lvlError, format("warning: %1%") % e.msg());
|
||||||
|
errors = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LocalStore::verifyPath(const Path & path, const PathSet & store,
|
void LocalStore::verifyPath(const Path & path, const PathSet & store,
|
||||||
PathSet & done, PathSet & validPaths)
|
PathSet & done, PathSet & validPaths, bool repair, bool & errors)
|
||||||
{
|
{
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
|
|
||||||
|
@ -1638,7 +1644,7 @@ void LocalStore::verifyPath(const Path & path, const PathSet & store,
|
||||||
PathSet referrers; queryReferrers(path, referrers);
|
PathSet referrers; queryReferrers(path, referrers);
|
||||||
foreach (PathSet::iterator, i, referrers)
|
foreach (PathSet::iterator, i, referrers)
|
||||||
if (*i != path) {
|
if (*i != path) {
|
||||||
verifyPath(*i, store, done, validPaths);
|
verifyPath(*i, store, done, validPaths, repair, errors);
|
||||||
if (validPaths.find(*i) != validPaths.end())
|
if (validPaths.find(*i) != validPaths.end())
|
||||||
canInvalidate = false;
|
canInvalidate = false;
|
||||||
}
|
}
|
||||||
|
@ -1646,8 +1652,17 @@ void LocalStore::verifyPath(const Path & path, const PathSet & store,
|
||||||
if (canInvalidate) {
|
if (canInvalidate) {
|
||||||
printMsg(lvlError, format("path `%1%' disappeared, removing from database...") % path);
|
printMsg(lvlError, format("path `%1%' disappeared, removing from database...") % path);
|
||||||
invalidatePath(path);
|
invalidatePath(path);
|
||||||
} else
|
} else {
|
||||||
printMsg(lvlError, format("path `%1%' disappeared, but it still has valid referrers!") % path);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,8 +171,9 @@ public:
|
||||||
/* Optimise a single store path. */
|
/* Optimise a single store path. */
|
||||||
void optimisePath(const Path & path);
|
void optimisePath(const Path & path);
|
||||||
|
|
||||||
/* Check the integrity of the Nix store. */
|
/* Check the integrity of the Nix store. Returns true if errors
|
||||||
void verifyStore(bool checkContents);
|
remain. */
|
||||||
|
bool verifyStore(bool checkContents, bool repair);
|
||||||
|
|
||||||
/* Register the validity of a path, i.e., that `path' exists, that
|
/* 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
|
the paths referenced by it exists, and in the case of an output
|
||||||
|
@ -250,7 +251,7 @@ private:
|
||||||
void invalidatePathChecked(const Path & path);
|
void invalidatePathChecked(const Path & path);
|
||||||
|
|
||||||
void verifyPath(const Path & path, const PathSet & store,
|
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);
|
void updatePathInfo(const ValidPathInfo & info);
|
||||||
|
|
||||||
|
|
|
@ -703,13 +703,18 @@ static void opVerify(Strings opFlags, Strings opArgs)
|
||||||
throw UsageError("no arguments expected");
|
throw UsageError("no arguments expected");
|
||||||
|
|
||||||
bool checkContents = false;
|
bool checkContents = false;
|
||||||
|
bool repair = false;
|
||||||
|
|
||||||
for (Strings::iterator i = opFlags.begin();
|
for (Strings::iterator i = opFlags.begin();
|
||||||
i != opFlags.end(); ++i)
|
i != opFlags.end(); ++i)
|
||||||
if (*i == "--check-contents") checkContents = true;
|
if (*i == "--check-contents") checkContents = true;
|
||||||
|
else if (*i == "--repair") repair = true;
|
||||||
else throw UsageError(format("unknown flag `%1%'") % *i);
|
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) {
|
foreach (Strings::iterator, i, opArgs) {
|
||||||
Path path = followLinksToStorePath(*i);
|
Path path = followLinksToStorePath(*i);
|
||||||
printMsg(lvlTalkative, format("repairing path `%1%'...") % path);
|
|
||||||
ensureLocalStore().repairPath(path);
|
ensureLocalStore().repairPath(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue