summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2019-09-04 11:04:44 +0200
committerLudovic Courtès <ludo@gnu.org>2019-09-08 11:49:24 +0200
commitf6919ebdc6b0ce0286814cc6ab0564b1a4c67f5f (patch)
tree6b9d4a206bc2f530756ad55935e7704fb54a6563
parentbc69ea2d605810cc32e13ed03d5848b8dc358b61 (diff)
daemon: Run 'guix substitute' directly and assume a single substituter.
The daemon had a mechanism that allows it to handle a list of substituters and try them sequentially; this removes it. * nix/scripts/substitute.in: Remove. * nix/local.mk (nodist_pkglibexec_SCRIPTS): Remove. * config-daemon.ac: Don't output 'nix/scripts/substitute'. * nix/libstore/build.cc (SubstitutionGoal)[subs, sub, hasSubstitute]: Remove. [tryNext]: Make private. (SubstitutionGoal::SubstitutionGoal, SubstitutionGoal::init): Remove now unneeded initializers. (SubstitutionGoal::tryNext): Adjust to assume a single substituter: call 'amDone' upfront when we couldn't find substitutes. (SubstitutionGoal::tryToRun): Adjust to run 'guix substitute' via 'settings.guixProgram'. (SubstitutionGoal::finished): Call 'amDone(ecFailed)' upon failure instead of setting 'state' to 'tryNext'. * nix/libstore/globals.hh (Settings)[substituters]: Remove. * nix/libstore/local-store.cc (LocalStore::~LocalStore): Adjust to handle a single substituter. (LocalStore::startSubstituter): Remove 'path' parameter. Adjust to invoke 'settings.guixProgram'. Don't refer to 'run.program', which no longer exists. (LocalStore::querySubstitutablePaths): Adjust for 'runningSubstituters' being a singleton instead of a list. (LocalStore::querySubstitutablePathInfos): Likewise, and remove 'substituter' parameter. * nix/libstore/local-store.hh (RunningSubstituter)[program]: Remove. (LocalStore)[runningSubstituters]: Remove. [runningSubstituter]: New field. [querySubstitutablePathInfos]: Remove 'substituter' parameter. [startSubstituter]: Remove 'substituter' parameter. * nix/nix-daemon/guix-daemon.cc (main): Remove references to 'settings.substituters'. * nix/nix-daemon/nix-daemon.cc (performOp): Ignore the user's "build-use-substitutes" value when 'settings.useSubstitutes' is false.
-rw-r--r--config-daemon.ac2
-rw-r--r--nix/libstore/build.cc52
-rw-r--r--nix/libstore/globals.hh5
-rw-r--r--nix/libstore/local-store.cc97
-rw-r--r--nix/libstore/local-store.hh12
-rw-r--r--nix/local.mk3
-rw-r--r--nix/nix-daemon/guix-daemon.cc11
-rw-r--r--nix/nix-daemon/nix-daemon.cc8
-rw-r--r--nix/scripts/substitute.in11
9 files changed, 85 insertions, 116 deletions
diff --git a/config-daemon.ac b/config-daemon.ac
index 3d92e8f7789..bf94815966d 100644
--- a/config-daemon.ac
+++ b/config-daemon.ac
@@ -148,8 +148,6 @@ if test "x$guix_build_daemon" = "xyes"; then
148 AC_SUBST([GUIX_TEST_ROOT]) 148 AC_SUBST([GUIX_TEST_ROOT])
149 149
150 GUIX_CHECK_LOCALSTATEDIR 150 GUIX_CHECK_LOCALSTATEDIR
151 AC_CONFIG_FILES([nix/scripts/substitute],
152 [chmod +x nix/scripts/substitute])
153fi 151fi
154 152
155AM_CONDITIONAL([HAVE_LIBBZ2], [test "x$HAVE_LIBBZ2" = "xyes"]) 153AM_CONDITIONAL([HAVE_LIBBZ2], [test "x$HAVE_LIBBZ2" = "xyes"])
diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc
index 9f1f88933a2..ad53b814137 100644
--- a/nix/libstore/build.cc
+++ b/nix/libstore/build.cc
@@ -2863,15 +2863,6 @@ private:
2863 /* The store path that should be realised through a substitute. */ 2863 /* The store path that should be realised through a substitute. */
2864 Path storePath; 2864 Path storePath;
2865 2865
2866 /* The remaining substituters. */
2867 Paths subs;
2868
2869 /* The current substituter. */
2870 Path sub;
2871
2872 /* Whether any substituter can realise this path */
2873 bool hasSubstitute;
2874
2875 /* Path info returned by the substituter's query info operation. */ 2866 /* Path info returned by the substituter's query info operation. */
2876 SubstitutablePathInfo info; 2867 SubstitutablePathInfo info;
2877 2868
@@ -2897,6 +2888,8 @@ private:
2897 typedef void (SubstitutionGoal::*GoalState)(); 2888 typedef void (SubstitutionGoal::*GoalState)();
2898 GoalState state; 2889 GoalState state;
2899 2890
2891 void tryNext();
2892
2900public: 2893public:
2901 SubstitutionGoal(const Path & storePath, Worker & worker, bool repair = false); 2894 SubstitutionGoal(const Path & storePath, Worker & worker, bool repair = false);
2902 ~SubstitutionGoal(); 2895 ~SubstitutionGoal();
@@ -2914,7 +2907,6 @@ public:
2914 2907
2915 /* The states. */ 2908 /* The states. */
2916 void init(); 2909 void init();
2917 void tryNext();
2918 void gotInfo(); 2910 void gotInfo();
2919 void referencesValid(); 2911 void referencesValid();
2920 void tryToRun(); 2912 void tryToRun();
@@ -2930,7 +2922,6 @@ public:
2930 2922
2931SubstitutionGoal::SubstitutionGoal(const Path & storePath, Worker & worker, bool repair) 2923SubstitutionGoal::SubstitutionGoal(const Path & storePath, Worker & worker, bool repair)
2932 : Goal(worker) 2924 : Goal(worker)
2933 , hasSubstitute(false)
2934 , repair(repair) 2925 , repair(repair)
2935{ 2926{
2936 this->storePath = storePath; 2927 this->storePath = storePath;
@@ -2980,37 +2971,31 @@ void SubstitutionGoal::init()
2980 if (settings.readOnlyMode) 2971 if (settings.readOnlyMode)
2981 throw Error(format("cannot substitute path `%1%' - no write access to the store") % storePath); 2972 throw Error(format("cannot substitute path `%1%' - no write access to the store") % storePath);
2982 2973
2983 subs = settings.substituters;
2984
2985 tryNext(); 2974 tryNext();
2986} 2975}
2987 2976
2988 2977
2989void SubstitutionGoal::tryNext() 2978void SubstitutionGoal::tryNext()
2990{ 2979{
2991 trace("trying next substituter"); 2980 trace("trying substituter");
2992 2981
2993 if (subs.size() == 0) { 2982 SubstitutablePathInfos infos;
2983 PathSet dummy(singleton<PathSet>(storePath));
2984 worker.store.querySubstitutablePathInfos(dummy, infos);
2985 SubstitutablePathInfos::iterator k = infos.find(storePath);
2986 if (k == infos.end()) {
2994 /* None left. Terminate this goal and let someone else deal 2987 /* None left. Terminate this goal and let someone else deal
2995 with it. */ 2988 with it. */
2996 debug(format("path `%1%' is required, but there is no substituter that can build it") % storePath); 2989 debug(format("path `%1%' is required, but there is no substituter that can build it") % storePath);
2997 /* Hack: don't indicate failure if there were no substituters. 2990 /* Hack: don't indicate failure if there were no substituters.
2998 In that case the calling derivation should just do a 2991 In that case the calling derivation should just do a
2999 build. */ 2992 build. */
3000 amDone(hasSubstitute ? ecFailed : ecNoSubstituters); 2993 amDone(ecNoSubstituters);
3001 return; 2994 return;
3002 } 2995 }
3003 2996
3004 sub = subs.front(); 2997 /* Found a substitute. */
3005 subs.pop_front();
3006
3007 SubstitutablePathInfos infos;
3008 PathSet dummy(singleton<PathSet>(storePath));
3009 worker.store.querySubstitutablePathInfos(sub, dummy, infos);
3010 SubstitutablePathInfos::iterator k = infos.find(storePath);
3011 if (k == infos.end()) { tryNext(); return; }
3012 info = k->second; 2998 info = k->second;
3013 hasSubstitute = true;
3014 2999
3015 /* To maintain the closure invariant, we first have to realise the 3000 /* To maintain the closure invariant, we first have to realise the
3016 paths referenced by this one. */ 3001 paths referenced by this one. */
@@ -3098,7 +3083,8 @@ void SubstitutionGoal::tryToRun()
3098 3083
3099 /* Fill in the arguments. */ 3084 /* Fill in the arguments. */
3100 Strings args; 3085 Strings args;
3101 args.push_back(baseNameOf(sub)); 3086 args.push_back("guix");
3087 args.push_back("substitute");
3102 args.push_back("--substitute"); 3088 args.push_back("--substitute");
3103 args.push_back(storePath); 3089 args.push_back(storePath);
3104 args.push_back(destPath); 3090 args.push_back(destPath);
@@ -3111,9 +3097,9 @@ void SubstitutionGoal::tryToRun()
3111 if (dup2(outPipe.writeSide, STDOUT_FILENO) == -1) 3097 if (dup2(outPipe.writeSide, STDOUT_FILENO) == -1)
3112 throw SysError("cannot dup output pipe into stdout"); 3098 throw SysError("cannot dup output pipe into stdout");
3113 3099
3114 execv(sub.c_str(), stringsToCharPtrs(args).data()); 3100 execv(settings.guixProgram.c_str(), stringsToCharPtrs(args).data());
3115 3101
3116 throw SysError(format("executing `%1%'") % sub); 3102 throw SysError(format("executing `%1% substitute'") % settings.guixProgram);
3117 }); 3103 });
3118 3104
3119 pid.setSeparatePG(true); 3105 pid.setSeparatePG(true);
@@ -3126,7 +3112,9 @@ void SubstitutionGoal::tryToRun()
3126 state = &SubstitutionGoal::finished; 3112 state = &SubstitutionGoal::finished;
3127 3113
3128 if (settings.printBuildTrace) 3114 if (settings.printBuildTrace)
3129 printMsg(lvlError, format("@ substituter-started %1% %2%") % storePath % sub); 3115 /* The second element in the message used to be the name of the
3116 substituter but we're left with only one. */
3117 printMsg(lvlError, format("@ substituter-started %1% substitute") % storePath);
3130} 3118}
3131 3119
3132 3120
@@ -3192,9 +3180,7 @@ void SubstitutionGoal::finished()
3192 % storePath % status % e.msg()); 3180 % storePath % status % e.msg());
3193 } 3181 }
3194 3182
3195 /* Try the next substitute. */ 3183 amDone(ecFailed);
3196 state = &SubstitutionGoal::tryNext;
3197 worker.wakeUp(shared_from_this());
3198 return; 3184 return;
3199 } 3185 }
3200 3186
diff --git a/nix/libstore/globals.hh b/nix/libstore/globals.hh
index 0d9315a41a9..0069c85956c 100644
--- a/nix/libstore/globals.hh
+++ b/nix/libstore/globals.hh
@@ -115,11 +115,6 @@ struct Settings {
115 means infinity. */ 115 means infinity. */
116 time_t buildTimeout; 116 time_t buildTimeout;
117 117
118 /* The substituters. There are programs that can somehow realise
119 a store path without building, e.g., by downloading it or
120 copying it from a CD. */
121 Paths substituters;
122
123 /* Whether to use build hooks (for distributed builds). Sometimes 118 /* Whether to use build hooks (for distributed builds). Sometimes
124 users want to disable this from the command-line. */ 119 users want to disable this from the command-line. */
125 bool useBuildHook; 120 bool useBuildHook;
diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc
index 951c35faf3d..3b08492c643 100644
--- a/nix/libstore/local-store.cc
+++ b/nix/libstore/local-store.cc
@@ -184,13 +184,15 @@ LocalStore::LocalStore(bool reserveSpace)
184LocalStore::~LocalStore() 184LocalStore::~LocalStore()
185{ 185{
186 try { 186 try {
187 foreach (RunningSubstituters::iterator, i, runningSubstituters) { 187 if (runningSubstituter) {
188 if (i->second.disabled) continue; 188 RunningSubstituter &i = *runningSubstituter;
189 i->second.to.close(); 189 if (!i.disabled) {
190 i->second.from.close(); 190 i.to.close();
191 i->second.error.close(); 191 i.from.close();
192 if (i->second.pid != -1) 192 i.error.close();
193 i->second.pid.wait(true); 193 if (i.pid != -1)
194 i.pid.wait(true);
195 }
194 } 196 }
195 } catch (...) { 197 } catch (...) {
196 ignoreException(); 198 ignoreException();
@@ -808,11 +810,12 @@ void LocalStore::setSubstituterEnv()
808} 810}
809 811
810 812
811void LocalStore::startSubstituter(const Path & substituter, RunningSubstituter & run) 813void LocalStore::startSubstituter(RunningSubstituter & run)
812{ 814{
813 if (run.disabled || run.pid != -1) return; 815 if (run.disabled || run.pid != -1) return;
814 816
815 debug(format("starting substituter program `%1%'") % substituter); 817 debug(format("starting substituter program `%1% substitute'")
818 % settings.guixProgram);
816 819
817 Pipe toPipe, fromPipe, errorPipe; 820 Pipe toPipe, fromPipe, errorPipe;
818 821
@@ -829,11 +832,10 @@ void LocalStore::startSubstituter(const Path & substituter, RunningSubstituter &
829 throw SysError("dupping stdout"); 832 throw SysError("dupping stdout");
830 if (dup2(errorPipe.writeSide, STDERR_FILENO) == -1) 833 if (dup2(errorPipe.writeSide, STDERR_FILENO) == -1)
831 throw SysError("dupping stderr"); 834 throw SysError("dupping stderr");
832 execl(substituter.c_str(), substituter.c_str(), "--query", NULL); 835 execl(settings.guixProgram.c_str(), "guix", "substitute", "--query", NULL);
833 throw SysError(format("executing `%1%'") % substituter); 836 throw SysError(format("executing `%1%'") % settings.guixProgram);
834 }); 837 });
835 838
836 run.program = baseNameOf(substituter);
837 run.to = toPipe.writeSide.borrow(); 839 run.to = toPipe.writeSide.borrow();
838 run.from = run.fromBuf.fd = fromPipe.readSide.borrow(); 840 run.from = run.fromBuf.fd = fromPipe.readSide.borrow();
839 run.error = errorPipe.readSide.borrow(); 841 run.error = errorPipe.readSide.borrow();
@@ -889,13 +891,14 @@ string LocalStore::getLineFromSubstituter(RunningSubstituter & run)
889 if (errno == EINTR) continue; 891 if (errno == EINTR) continue;
890 throw SysError("reading from substituter's stderr"); 892 throw SysError("reading from substituter's stderr");
891 } 893 }
892 if (n == 0) throw EndOfFile(format("substituter `%1%' died unexpectedly") % run.program); 894 if (n == 0) throw EndOfFile(format("`%1% substitute' died unexpectedly")
895 % settings.guixProgram);
893 err.append(buf, n); 896 err.append(buf, n);
894 string::size_type p; 897 string::size_type p;
895 while (((p = err.find('\n')) != string::npos) 898 while (((p = err.find('\n')) != string::npos)
896 || ((p = err.find('\r')) != string::npos)) { 899 || ((p = err.find('\r')) != string::npos)) {
897 string thing(err, 0, p + 1); 900 string thing(err, 0, p + 1);
898 writeToStderr(run.program + ": " + thing); 901 writeToStderr("substitute: " + thing);
899 err = string(err, p + 1); 902 err = string(err, p + 1);
900 } 903 }
901 } 904 }
@@ -907,7 +910,7 @@ string LocalStore::getLineFromSubstituter(RunningSubstituter & run)
907 unsigned char c; 910 unsigned char c;
908 run.fromBuf(&c, 1); 911 run.fromBuf(&c, 1);
909 if (c == '\n') { 912 if (c == '\n') {
910 if (!err.empty()) printMsg(lvlError, run.program + ": " + err); 913 if (!err.empty()) printMsg(lvlError, "substitute: " + err);
911 return res; 914 return res;
912 } 915 }
913 res += c; 916 res += c;
@@ -930,38 +933,47 @@ PathSet LocalStore::querySubstitutablePaths(const PathSet & paths)
930{ 933{
931 PathSet res; 934 PathSet res;
932 935
933 if (!settings.useSubstitutes) return res; 936 if (!settings.useSubstitutes || paths.empty()) return res;
934 937
935 foreach (Paths::iterator, i, settings.substituters) { 938 if (!runningSubstituter) {
936 if (res.size() == paths.size()) break; 939 std::unique_ptr<RunningSubstituter>fresh(new RunningSubstituter);
937 RunningSubstituter & run(runningSubstituters[*i]); 940 runningSubstituter.swap(fresh);
938 startSubstituter(*i, run); 941 }
939 if (run.disabled) continue; 942
940 string s = "have "; 943 RunningSubstituter & run = *runningSubstituter;
941 foreach (PathSet::const_iterator, j, paths) 944 startSubstituter(run);
942 if (res.find(*j) == res.end()) { s += *j; s += " "; } 945
943 writeLine(run.to, s); 946 if (!run.disabled) {
944 while (true) { 947 string s = "have ";
945 /* FIXME: we only read stderr when an error occurs, so 948 foreach (PathSet::const_iterator, j, paths)
946 substituters should only write (short) messages to 949 if (res.find(*j) == res.end()) { s += *j; s += " "; }
947 stderr when they fail. I.e. they shouldn't write debug 950 writeLine(run.to, s);
948 output. */ 951 while (true) {
949 Path path = getLineFromSubstituter(run); 952 /* FIXME: we only read stderr when an error occurs, so
950 if (path == "") break; 953 substituters should only write (short) messages to
951 res.insert(path); 954 stderr when they fail. I.e. they shouldn't write debug
952 } 955 output. */
956 Path path = getLineFromSubstituter(run);
957 if (path == "") break;
958 res.insert(path);
959 }
953 } 960 }
961
954 return res; 962 return res;
955} 963}
956 964
957 965
958void LocalStore::querySubstitutablePathInfos(const Path & substituter, 966void LocalStore::querySubstitutablePathInfos(PathSet & paths, SubstitutablePathInfos & infos)
959 PathSet & paths, SubstitutablePathInfos & infos)
960{ 967{
961 if (!settings.useSubstitutes) return; 968 if (!settings.useSubstitutes) return;
962 969
963 RunningSubstituter & run(runningSubstituters[substituter]); 970 if (!runningSubstituter) {
964 startSubstituter(substituter, run); 971 std::unique_ptr<RunningSubstituter>fresh(new RunningSubstituter);
972 runningSubstituter.swap(fresh);
973 }
974
975 RunningSubstituter & run = *runningSubstituter;
976 startSubstituter(run);
965 if (run.disabled) return; 977 if (run.disabled) return;
966 978
967 string s = "info "; 979 string s = "info ";
@@ -993,10 +1005,9 @@ void LocalStore::querySubstitutablePathInfos(const Path & substituter,
993void LocalStore::querySubstitutablePathInfos(const PathSet & paths, 1005void LocalStore::querySubstitutablePathInfos(const PathSet & paths,
994 SubstitutablePathInfos & infos) 1006 SubstitutablePathInfos & infos)
995{ 1007{
996 PathSet todo = paths; 1008 if (!paths.empty()) {
997 foreach (Paths::iterator, i, settings.substituters) { 1009 PathSet todo = paths;
998 if (todo.empty()) break; 1010 querySubstitutablePathInfos(todo, infos);
999 querySubstitutablePathInfos(*i, todo, infos);
1000 } 1011 }
1001} 1012}
1002 1013
diff --git a/nix/libstore/local-store.hh b/nix/libstore/local-store.hh
index 4e6b4cfc1df..4113fafcb5d 100644
--- a/nix/libstore/local-store.hh
+++ b/nix/libstore/local-store.hh
@@ -40,7 +40,6 @@ struct OptimiseStats
40 40
41struct RunningSubstituter 41struct RunningSubstituter
42{ 42{
43 Path program;
44 Pid pid; 43 Pid pid;
45 AutoCloseFD to, from, error; 44 AutoCloseFD to, from, error;
46 FdSource fromBuf; 45 FdSource fromBuf;
@@ -52,8 +51,8 @@ struct RunningSubstituter
52class LocalStore : public StoreAPI 51class LocalStore : public StoreAPI
53{ 52{
54private: 53private:
55 typedef std::map<Path, RunningSubstituter> RunningSubstituters; 54 /* The currently running substituter or empty. */
56 RunningSubstituters runningSubstituters; 55 std::unique_ptr<RunningSubstituter> runningSubstituter;
57 56
58 Path linksDir; 57 Path linksDir;
59 58
@@ -93,8 +92,8 @@ public:
93 92
94 PathSet querySubstitutablePaths(const PathSet & paths); 93 PathSet querySubstitutablePaths(const PathSet & paths);
95 94
96 void querySubstitutablePathInfos(const Path & substituter, 95 void querySubstitutablePathInfos(PathSet & paths,
97 PathSet & paths, SubstitutablePathInfos & infos); 96 SubstitutablePathInfos & infos);
98 97
99 void querySubstitutablePathInfos(const PathSet & paths, 98 void querySubstitutablePathInfos(const PathSet & paths,
100 SubstitutablePathInfos & infos); 99 SubstitutablePathInfos & infos);
@@ -261,8 +260,7 @@ private:
261 260
262 void removeUnusedLinks(const GCState & state); 261 void removeUnusedLinks(const GCState & state);
263 262
264 void startSubstituter(const Path & substituter, 263 void startSubstituter(RunningSubstituter & runningSubstituter);
265 RunningSubstituter & runningSubstituter);
266 264
267 string getLineFromSubstituter(RunningSubstituter & run); 265 string getLineFromSubstituter(RunningSubstituter & run);
268 266
diff --git a/nix/local.mk b/nix/local.mk
index 8e52c77bd9b..18e9ba76048 100644
--- a/nix/local.mk
+++ b/nix/local.mk
@@ -154,9 +154,6 @@ noinst_HEADERS = \
154 (lambda (in) \ 154 (lambda (in) \
155 (write (get-string-all in) out)))))" 155 (write (get-string-all in) out)))))"
156 156
157nodist_pkglibexec_SCRIPTS = \
158 %D%/scripts/substitute
159
160# The '.service' files for systemd. 157# The '.service' files for systemd.
161systemdservicedir = $(libdir)/systemd/system 158systemdservicedir = $(libdir)/systemd/system
162nodist_systemdservice_DATA = etc/guix-daemon.service etc/guix-publish.service 159nodist_systemdservice_DATA = etc/guix-daemon.service etc/guix-publish.service
diff --git a/nix/nix-daemon/guix-daemon.cc b/nix/nix-daemon/guix-daemon.cc
index 73962af5848..6f9c404c8df 100644
--- a/nix/nix-daemon/guix-daemon.cc
+++ b/nix/nix-daemon/guix-daemon.cc
@@ -466,8 +466,7 @@ main (int argc, char *argv[])
466 { 466 {
467 settings.processEnvironment (); 467 settings.processEnvironment ();
468 468
469 /* Use our substituter by default. */ 469 /* Enable substitutes by default. */
470 settings.substituters.clear ();
471 settings.set ("build-use-substitutes", "true"); 470 settings.set ("build-use-substitutes", "true");
472 471
473 /* Use our substitute server by default. */ 472 /* Use our substitute server by default. */
@@ -490,14 +489,6 @@ main (int argc, char *argv[])
490 printMsg(lvlDebug, 489 printMsg(lvlDebug,
491 format ("build log compression: %1%") % settings.logCompression); 490 format ("build log compression: %1%") % settings.logCompression);
492 491
493 if (settings.useSubstitutes)
494 settings.substituters.push_back (settings.nixLibexecDir
495 + "/substitute");
496 else
497 /* Clear the substituter list to make sure nothing ever gets
498 substituted, regardless of the client's settings. */
499 settings.substituters.clear ();
500
501 if (geteuid () == 0 && settings.buildUsersGroup.empty ()) 492 if (geteuid () == 0 && settings.buildUsersGroup.empty ())
502 fprintf (stderr, _("warning: daemon is running as root, so \ 493 fprintf (stderr, _("warning: daemon is running as root, so \
503using `--build-users-group' is highly recommended\n")); 494using `--build-users-group' is highly recommended\n"));
diff --git a/nix/nix-daemon/nix-daemon.cc b/nix/nix-daemon/nix-daemon.cc
index f29bcd2eabc..ffac6cde34a 100644
--- a/nix/nix-daemon/nix-daemon.cc
+++ b/nix/nix-daemon/nix-daemon.cc
@@ -596,8 +596,12 @@ static void performOp(bool trusted, unsigned int clientVersion,
596 if (GET_PROTOCOL_MINOR(clientVersion) >= 6 596 if (GET_PROTOCOL_MINOR(clientVersion) >= 6
597 && GET_PROTOCOL_MINOR(clientVersion) < 0x61) 597 && GET_PROTOCOL_MINOR(clientVersion) < 0x61)
598 settings.set("build-cores", std::to_string(readInt(from))); 598 settings.set("build-cores", std::to_string(readInt(from)));
599 if (GET_PROTOCOL_MINOR(clientVersion) >= 10) 599 if (GET_PROTOCOL_MINOR(clientVersion) >= 10) {
600 settings.set("build-use-substitutes", readInt(from) ? "true" : "false"); 600 if (settings.useSubstitutes)
601 settings.set("build-use-substitutes", readInt(from) ? "true" : "false");
602 else
603 readInt(from); // substitutes remain disabled
604 }
601 if (GET_PROTOCOL_MINOR(clientVersion) >= 12) { 605 if (GET_PROTOCOL_MINOR(clientVersion) >= 12) {
602 unsigned int n = readInt(from); 606 unsigned int n = readInt(from);
603 for (unsigned int i = 0; i < n; i++) { 607 for (unsigned int i = 0; i < n; i++) {
diff --git a/nix/scripts/substitute.in b/nix/scripts/substitute.in
deleted file mode 100644
index 5a2eeb7259a..00000000000
--- a/nix/scripts/substitute.in
+++ /dev/null
@@ -1,11 +0,0 @@
1#!@SHELL@
2# A shorthand for "guix substitute", for use by the daemon.
3
4if test "x$GUIX_UNINSTALLED" = "x"
5then
6 prefix="@prefix@"
7 exec_prefix="@exec_prefix@"
8 exec "@bindir@/guix" substitute "$@"
9else
10 exec guix substitute "$@"
11fi