diff --git a/doc/manual/release-notes.xml b/doc/manual/release-notes.xml
index 7d0bfe7fd..3712a8b91 100644
--- a/doc/manual/release-notes.xml
+++ b/doc/manual/release-notes.xml
@@ -40,6 +40,10 @@
TODO: Nix expression search path (import <foo/bar.nix>).
+
+ TODO: nix-store --verify-path command.
+
+
diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc
index f0035c358..8532cdaad 100644
--- a/src/libmain/shared.cc
+++ b/src/libmain/shared.cc
@@ -187,12 +187,11 @@ static void initAndRun(int argc, char * * argv)
ignore options for the ATerm library. */
for (Strings::iterator i = args.begin(); i != args.end(); ++i) {
string arg = *i;
- if (string(arg, 0, 4) == "-at-") ;
- else if (arg.length() > 2 && arg[0] == '-' && arg[1] != '-' && !isdigit(arg[1])) {
+ if (arg.length() > 2 && arg[0] == '-' && arg[1] != '-' && !isdigit(arg[1])) {
for (unsigned int j = 1; j < arg.length(); j++)
if (isalpha(arg[j]))
remaining.push_back((string) "-" + arg[j]);
- else {
+ else {
remaining.push_back(string(arg, j));
break;
}
@@ -332,6 +331,9 @@ static void * oomHandler(size_t requested)
}
+int exitCode = 0;
+
+
}
@@ -390,7 +392,5 @@ int main(int argc, char * * argv)
return 1;
}
- return 0;
+ return exitCode;
}
-
-
diff --git a/src/libmain/shared.hh b/src/libmain/shared.hh
index bd3d19531..1d6a6ec57 100644
--- a/src/libmain/shared.hh
+++ b/src/libmain/shared.hh
@@ -53,6 +53,9 @@ struct RemoveTempRoots
~RemoveTempRoots();
};
+/* Exit code of the program. */
+extern int exitCode;
+
}
diff --git a/src/nix-store/help.txt b/src/nix-store/help.txt
index 478251851..f3e65a528 100644
--- a/src/nix-store/help.txt
+++ b/src/nix-store/help.txt
@@ -25,6 +25,7 @@ Operations:
valid
--verify: verify Nix structures
+ --verify-path: verify whether the given store paths haven't been modified
--optimise: optimise the Nix store by hard-linking identical files
--query-failed-paths: list paths that failed to build (if enabled)
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index 00dab5f32..371ca54af 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -466,11 +466,12 @@ static void opCheckValidity(Strings opFlags, Strings opArgs)
i != opArgs.end(); ++i)
{
Path path = followLinksToStorePath(*i);
- if (!store->isValidPath(path))
+ if (!store->isValidPath(path)) {
if (printInvalid)
cout << format("%1%\n") % path;
else
throw Error(format("path `%1%' is not valid") % path);
+ }
}
}
@@ -648,6 +649,27 @@ static void opVerify(Strings opFlags, Strings opArgs)
}
+/* Verify whether the contents of the given store path have not changed. */
+static void opVerifyPath(Strings opFlags, Strings opArgs)
+{
+ if (!opFlags.empty())
+ throw UsageError("no flags expected");
+
+ foreach (Strings::iterator, i, opArgs) {
+ Path path = followLinksToStorePath(*i);
+ printMsg(lvlTalkative, format("checking path `%1%'...") % path);
+ ValidPathInfo info = store->queryPathInfo(path);
+ HashResult current = hashPath(info.hash.type, path);
+ if (current.first != info.hash) {
+ printMsg(lvlError,
+ format("path `%1%' was modified! expected hash `%2%', got `%3%'")
+ % path % printHash(info.hash) % printHash(current.first));
+ exitCode = 1;
+ }
+ }
+}
+
+
static void showOptimiseStats(OptimiseStats & stats)
{
printMsg(lvlError,
@@ -750,6 +772,8 @@ void run(Strings args)
op = opInit;
else if (arg == "--verify")
op = opVerify;
+ else if (arg == "--verify-path")
+ op = opVerifyPath;
else if (arg == "--optimise")
op = opOptimise;
else if (arg == "--query-failed-paths")