From 17e6b85d05b3d32df244b1d4e89aa41fd8bdcae8 Mon Sep 17 00:00:00 2001
From: Eelco Dolstra <edolstra@gmail.com>
Date: Fri, 28 Apr 2023 16:57:37 +0200
Subject: [PATCH] nix: Support the --repair flag

---
 src/libcmd/command.cc                  |  2 ++
 src/libcmd/common-eval-args.hh         |  3 ++-
 src/libmain/common-args.hh             | 18 ++++++++++++++++++
 src/nix-build/nix-build.cc             |  9 ++-------
 src/nix-env/nix-env.cc                 |  5 +----
 src/nix-instantiate/nix-instantiate.cc |  5 +----
 src/nix/build.cc                       |  3 ++-
 7 files changed, 28 insertions(+), 17 deletions(-)

diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc
index bedf11e2c..6c4648b34 100644
--- a/src/libcmd/command.cc
+++ b/src/libcmd/command.cc
@@ -121,6 +121,8 @@ ref<EvalState> EvalCommand::getEvalState()
             #endif
             ;
 
+        evalState->repair = repair;
+
         if (startReplOnEvalErrors) {
             evalState->debugRepl = &AbstractNixRepl::runSimple;
         };
diff --git a/src/libcmd/common-eval-args.hh b/src/libcmd/common-eval-args.hh
index 83edcfb85..b65cb5b20 100644
--- a/src/libcmd/common-eval-args.hh
+++ b/src/libcmd/common-eval-args.hh
@@ -2,6 +2,7 @@
 ///@file
 
 #include "args.hh"
+#include "common-args.hh"
 
 namespace nix {
 
@@ -10,7 +11,7 @@ class EvalState;
 class Bindings;
 struct SourcePath;
 
-struct MixEvalArgs : virtual Args
+struct MixEvalArgs : virtual Args, virtual MixRepair
 {
     static constexpr auto category = "Common evaluation options";
 
diff --git a/src/libmain/common-args.hh b/src/libmain/common-args.hh
index e7ed0d934..c35406c3b 100644
--- a/src/libmain/common-args.hh
+++ b/src/libmain/common-args.hh
@@ -2,6 +2,7 @@
 ///@file
 
 #include "args.hh"
+#include "repair-flag.hh"
 
 namespace nix {
 
@@ -49,4 +50,21 @@ struct MixJSON : virtual Args
     }
 };
 
+struct MixRepair : virtual Args
+{
+    RepairFlag repair = NoRepair;
+
+    MixRepair()
+    {
+        addFlag({
+            .longName = "repair",
+            .description =
+                "During evaluation, rewrite missing or corrupted files in the Nix store. "
+                "During building, rebuild missing or corrupted store paths.",
+            .category = miscCategory,
+            .handler = {&repair, Repair},
+        });
+    }
+};
+
 }
diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc
index 251f00edf..6510df8f0 100644
--- a/src/nix-build/nix-build.cc
+++ b/src/nix-build/nix-build.cc
@@ -84,7 +84,6 @@ static void main_nix_build(int argc, char * * argv)
     auto interactive = isatty(STDIN_FILENO) && isatty(STDERR_FILENO);
     Strings attrPaths;
     Strings left;
-    RepairFlag repair = NoRepair;
     BuildMode buildMode = bmNormal;
     bool readStdin = false;
 
@@ -169,11 +168,6 @@ static void main_nix_build(int argc, char * * argv)
         else if (*arg == "--dry-run")
             dryRun = true;
 
-        else if (*arg == "--repair") {
-            repair = Repair;
-            buildMode = bmRepair;
-        }
-
         else if (*arg == "--run-env") // obsolete
             runEnv = true;
 
@@ -249,7 +243,8 @@ static void main_nix_build(int argc, char * * argv)
     auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store;
 
     auto state = std::make_unique<EvalState>(myArgs.searchPath, evalStore, store);
-    state->repair = repair;
+    state->repair = myArgs.repair;
+    if (myArgs.repair) buildMode = bmRepair;
 
     auto autoArgs = myArgs.getAutoArgs(*state);
 
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index 8b3f903f6..5e94f2d14 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -1391,7 +1391,6 @@ static int main_nix_env(int argc, char * * argv)
         Operation op = 0;
         std::string opName;
         bool showHelp = false;
-        RepairFlag repair = NoRepair;
         std::string file;
 
         Globals globals;
@@ -1489,8 +1488,6 @@ static int main_nix_env(int argc, char * * argv)
                 globals.instSource.systemFilter = getArg(*arg, arg, end);
             else if (*arg == "--prebuilt-only" || *arg == "-b")
                 globals.prebuiltOnly = true;
-            else if (*arg == "--repair")
-                repair = Repair;
             else if (*arg != "" && arg->at(0) == '-') {
                 opFlags.push_back(*arg);
                 /* FIXME: hacky */
@@ -1515,7 +1512,7 @@ static int main_nix_env(int argc, char * * argv)
         auto store = openStore();
 
         globals.state = std::shared_ptr<EvalState>(new EvalState(myArgs.searchPath, store));
-        globals.state->repair = repair;
+        globals.state->repair = myArgs.repair;
 
         globals.instSource.nixExprPath = std::make_shared<SourcePath>(
             file != ""
diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc
index fa6cc2bd7..446b27e66 100644
--- a/src/nix-instantiate/nix-instantiate.cc
+++ b/src/nix-instantiate/nix-instantiate.cc
@@ -102,7 +102,6 @@ static int main_nix_instantiate(int argc, char * * argv)
         bool strict = false;
         Strings attrPaths;
         bool wantsReadWrite = false;
-        RepairFlag repair = NoRepair;
 
         struct MyArgs : LegacyArgs, MixEvalArgs
         {
@@ -140,8 +139,6 @@ static int main_nix_instantiate(int argc, char * * argv)
                 xmlOutputSourceLocation = false;
             else if (*arg == "--strict")
                 strict = true;
-            else if (*arg == "--repair")
-                repair = Repair;
             else if (*arg == "--dry-run")
                 settings.readOnlyMode = true;
             else if (*arg != "" && arg->at(0) == '-')
@@ -160,7 +157,7 @@ static int main_nix_instantiate(int argc, char * * argv)
         auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store;
 
         auto state = std::make_unique<EvalState>(myArgs.searchPath, evalStore, store);
-        state->repair = repair;
+        state->repair = myArgs.repair;
 
         Bindings & autoArgs = *myArgs.getAutoArgs(*state);
 
diff --git a/src/nix/build.cc b/src/nix/build.cc
index abf946214..ad1842a4e 100644
--- a/src/nix/build.cc
+++ b/src/nix/build.cc
@@ -133,7 +133,8 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
         auto buildables = Installable::build(
             getEvalStore(), store,
             Realise::Outputs,
-            installables, buildMode);
+            installables,
+            repair ? bmRepair : buildMode);
 
         if (json) logger->cout("%s", builtPathsWithResultToJSON(buildables, store).dump());