summaryrefslogtreecommitdiff
path: root/nix/libstore/build.cc
diff options
context:
space:
mode:
authorCongcong Kuo <congcong.kuo@gmail.com>2025-07-21 11:02:40 +0800
committerLudovic Courtès <ludo@gnu.org>2025-10-19 21:29:39 +0200
commit3af52f845fe2ceb448416ac7b9f48925673c594e (patch)
treec8623599d15363a8e760adf1ad9dd01477ceabd7 /nix/libstore/build.cc
parentcbda925613b2962db8c6dbb2ea3dda7e3b433611 (diff)
daemon: Bump to C++20 and use ‘std::format’ instead of ‘boost::format’.
* nix/boost: This directory and all files inside it are removed. * nix/libstore/build.cc (Goal::trace): Use ‘std::string’ instead of ‘const format &’. (DerivationGoal::startBuilder, ...): Use ‘std::format’ or ‘std::vformat’ instead of ‘boost::format’. * nix/libstore/builtins.cc (builtinDownload): Same. * nix/libstore/derivations.cc (DerivationOutput::parseHashInfo, ...): Same. * nix/libstore/gc.cc (LocalStore::openGCLock, ...): Same. * nix/libstore/globals.cc (Settings::_get): Same. * nix/libstore/local-store.cc: (checkStoreNotSymlink, ...): Same. * nix/libstore/misc.cc (dfsVisit, showBytes): Same * nix/libstore/optimise-store.cc (makeWritable, ...): Same. * nix/libstore/pathlocks.cc (openLockFile, ...): Same. * nix/libstore/references.cc (search, scanForReferences): Same. * nix/libstore/sqlite.hh (throwSQLiteError): Use ‘std::string’ instead of ‘const format &’. * nix/libstore/sqlite.cc (throwSQLiteError): Use ‘std::string’ instead of ‘const format &’. * nix/libstore/store-api.cc (assertStorePath, ...): Use ‘std::format’ instead of ‘boost::format’. * nix/libutil/affinity.cc (setAffinityTo): Same. * nix/libutil/archive.cc (dumpContents, ...): Same. * nix/libutil/hash.cc (parseHash, parseHash32, parseHash16or32, hashFile): Same. * nix/libutil/hash.hh (parseHash, parseHash32, parseHash16or32, isHash): Same. * nix/libutil/serialise.cc : Add ‘<cassert>’ header file. * nix/libutil/spawn.cc (addPhaseAfter, ...): Use ‘std::format’ instead of ‘boost::format’. * nix/libutil/types.hh (FormatOrString): Removed. (BaseError, BaseError::addPrefix, SysError, MakeError): Use ‘std::string or std::string_view’ instead of ‘FormatOrString’. * nix/libutil/util.hh (Nest::open, printMsg_, warnOnce, expect): Same. * nix/libutil/util.cc (BaseError::BaseError, ...): Same. (writeToStderr, _interrupted): Use std::uncaught_exceptions() instead of std::uncaught_exception() * nix/nix-daemon/nix-daemon.cc (performOp, ...): Same. * nix/nix-daemon/guix-daemon.cc (string_to_bool, ...): Same. * nix/local.mk: Remove ‘libformat.a’ from ‘noinst_LIBRARIES’, remove ‘libformat_a_SOURCES’ and ‘libformat_headers’, remove ‘libformat_a_CPPFLAGS’ from ‘libutil_a_CPPFLAGS’ and ‘guix_daemon_LDADD’, update ‘AM_CXXFLAGS’ to ‘-std=c++20’. Signed-off-by: Ludovic Courtès <ludo@gnu.org>
Diffstat (limited to 'nix/libstore/build.cc')
-rw-r--r--nix/libstore/build.cc433
1 files changed, 214 insertions, 219 deletions
diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc
index f455343c189..bf2e9150d6a 100644
--- a/nix/libstore/build.cc
+++ b/nix/libstore/build.cc
@@ -7,14 +7,14 @@
7#include "local-store.hh" 7#include "local-store.hh"
8#include "util.hh" 8#include "util.hh"
9#include "archive.hh" 9#include "archive.hh"
10#include "affinity.hh"
11#include "builtins.hh" 10#include "builtins.hh"
12#include "spawn.hh" 11#include "spawn.hh"
13 12
14#include <map> 13#include <map>
15#include <sstream>
16#include <algorithm> 14#include <algorithm>
17#include <regex> 15#include <regex>
16#include <format>
17#include <string_view>
18 18
19#include <limits.h> 19#include <limits.h>
20#include <time.h> 20#include <time.h>
@@ -29,7 +29,7 @@
29#include <errno.h> 29#include <errno.h>
30#include <stdio.h> 30#include <stdio.h>
31#include <cstring> 31#include <cstring>
32#include <stdint.h> 32#include <cassert>
33 33
34#include <pwd.h> 34#include <pwd.h>
35#include <grp.h> 35#include <grp.h>
@@ -195,7 +195,7 @@ public:
195 abort(); 195 abort();
196 } 196 }
197 197
198 void trace(const format & f); 198 void trace(std::string_view s);
199 199
200 string getName() 200 string getName()
201 { 201 {
@@ -372,8 +372,7 @@ void Goal::waiteeDone(GoalPtr waitee, ExitCode result)
372 assert(waitees.find(waitee) != waitees.end()); 372 assert(waitees.find(waitee) != waitees.end());
373 waitees.erase(waitee); 373 waitees.erase(waitee);
374 374
375 trace(format("waitee `%1%' done; %2% left") % 375 trace(std::format("waitee `{}' done; {} left", waitee->name, waitees.size()));
376 waitee->name % waitees.size());
377 376
378 if (result == ecFailed || result == ecNoSubstituters || result == ecIncompleteClosure) ++nrFailed; 377 if (result == ecFailed || result == ecNoSubstituters || result == ecIncompleteClosure) ++nrFailed;
379 378
@@ -414,9 +413,9 @@ void Goal::amDone(ExitCode result)
414} 413}
415 414
416 415
417void Goal::trace(const format & f) 416void Goal::trace(std::string_view f)
418{ 417{
419 debug(format("%1%: %2%") % name % f); 418 debug(std::format("{}: {}", name, f));
420} 419}
421 420
422 421
@@ -483,34 +482,34 @@ void UserLock::acquire()
483 /* Get the members of the build-users-group. */ 482 /* Get the members of the build-users-group. */
484 struct group * gr = getgrnam(settings.buildUsersGroup.c_str()); 483 struct group * gr = getgrnam(settings.buildUsersGroup.c_str());
485 if (!gr) 484 if (!gr)
486 throw Error(format("the group `%1%' specified in `build-users-group' does not exist") 485 throw Error(std::format("the group `{}' specified in `build-users-group' does not exist",
487 % settings.buildUsersGroup); 486 settings.buildUsersGroup));
488 gid = gr->gr_gid; 487 gid = gr->gr_gid;
489 488
490 /* Copy the result of getgrnam. */ 489 /* Copy the result of getgrnam. */
491 Strings users; 490 Strings users;
492 for (char * * p = gr->gr_mem; *p; ++p) { 491 for (char * * p = gr->gr_mem; *p; ++p) {
493 debug(format("found build user `%1%'") % *p); 492 debug(std::format("found build user `{}'", *p));
494 users.push_back(*p); 493 users.push_back(*p);
495 } 494 }
496 495
497 if (users.empty()) 496 if (users.empty())
498 throw Error(format("the build users group `%1%' has no members") 497 throw Error(std::format("the build users group `{}' has no members",
499 % settings.buildUsersGroup); 498 settings.buildUsersGroup));
500 499
501 /* Find a user account that isn't currently in use for another 500 /* Find a user account that isn't currently in use for another
502 build. */ 501 build. */
503 for (auto& i : users) { 502 for (auto& i : users) {
504 debug(format("trying user `%1%'") % i); 503 debug(std::format("trying user `{}'", i));
505 504
506 struct passwd * pw = getpwnam(i.c_str()); 505 struct passwd * pw = getpwnam(i.c_str());
507 if (!pw) 506 if (!pw)
508 throw Error(format("the user `%1%' in the group `%2%' does not exist") 507 throw Error(std::format("the user `{}' in the group `{}' does not exist",
509 % i % settings.buildUsersGroup); 508 i, settings.buildUsersGroup));
510 509
511 createDirs(settings.nixStateDir + "/userpool"); 510 createDirs(settings.nixStateDir + "/userpool");
512 511
513 fnUserLock = (format("%1%/userpool/%2%") % settings.nixStateDir % pw->pw_uid).str(); 512 fnUserLock = std::format("{}/userpool/{}", settings.nixStateDir, pw->pw_uid);
514 513
515 if (lockedPaths.find(fnUserLock) != lockedPaths.end()) 514 if (lockedPaths.find(fnUserLock) != lockedPaths.end())
516 /* We already have a lock on this one. */ 515 /* We already have a lock on this one. */
@@ -518,7 +517,7 @@ void UserLock::acquire()
518 517
519 AutoCloseFD fd = open(fnUserLock.c_str(), O_RDWR | O_CREAT, 0600); 518 AutoCloseFD fd = open(fnUserLock.c_str(), O_RDWR | O_CREAT, 0600);
520 if (fd == -1) 519 if (fd == -1)
521 throw SysError(format("opening user lock `%1%'") % fnUserLock); 520 throw SysError(std::format("opening user lock `{}'", fnUserLock));
522 closeOnExec(fd); 521 closeOnExec(fd);
523 522
524 if (lockFile(fd, ltWrite, false)) { 523 if (lockFile(fd, ltWrite, false)) {
@@ -529,8 +528,8 @@ void UserLock::acquire()
529 528
530 /* Sanity check... */ 529 /* Sanity check... */
531 if (uid == getuid() || uid == geteuid()) 530 if (uid == getuid() || uid == geteuid())
532 throw Error(format("the build user should not be a member of `%1%'") 531 throw Error(std::format("the build user should not be a member of `{}'",
533 % settings.buildUsersGroup); 532 settings.buildUsersGroup));
534 533
535 /* Get the list of supplementary groups of this build user. This 534 /* Get the list of supplementary groups of this build user. This
536 is usually either empty or contains a group such as "kvm". */ 535 is usually either empty or contains a group such as "kvm". */
@@ -539,7 +538,7 @@ void UserLock::acquire()
539 int err = getgrouplist(pw->pw_name, pw->pw_gid, 538 int err = getgrouplist(pw->pw_name, pw->pw_gid,
540 supplementaryGIDs.data(), &ngroups); 539 supplementaryGIDs.data(), &ngroups);
541 if (err == -1) 540 if (err == -1)
542 throw Error(format("failed to get list of supplementary groups for ‘%1%’") % pw->pw_name); 541 throw Error(std::format("failed to get list of supplementary groups for `{}'", pw->pw_name));
543 542
544 supplementaryGIDs.resize(ngroups); 543 supplementaryGIDs.resize(ngroups);
545 544
@@ -547,9 +546,9 @@ void UserLock::acquire()
547 } 546 }
548 } 547 }
549 548
550 throw Error(format("all build users are currently in use; " 549 throw Error(std::format("all build users are currently in use; "
551 "consider creating additional users and adding them to the `%1%' group") 550 "consider creating additional users and adding them to the `{}' group",
552 % settings.buildUsersGroup); 551 settings.buildUsersGroup));
553} 552}
554 553
555 554
@@ -582,7 +581,7 @@ string rewriteHashes(string s, const HashRewrites & rewrites)
582 assert(i.first.size() == i.second.size()); 581 assert(i.first.size() == i.second.size());
583 size_t j = 0; 582 size_t j = 0;
584 while ((j = s.find(i.first, j)) != string::npos) { 583 while ((j = s.find(i.first, j)) != string::npos) {
585 debug(format("rewriting @ %1%") % j); 584 debug(std::format("rewriting @ {}", j));
586 s.replace(j, i.second.size(), i.second); 585 s.replace(j, i.second.size(), i.second);
587 } 586 }
588 } 587 }
@@ -716,7 +715,7 @@ public:
716 715
717 void timedOut() override; 716 void timedOut() override;
718 717
719 string key() 718 string key() override
720 { 719 {
721 /* Ensure that derivations get built in order of their name, 720 /* Ensure that derivations get built in order of their name,
722 i.e. a derivation named "aardvark" always comes before 721 i.e. a derivation named "aardvark" always comes before
@@ -725,7 +724,7 @@ public:
725 return "b$" + storePathToName(drvPath) + "$" + drvPath; 724 return "b$" + storePathToName(drvPath) + "$" + drvPath;
726 } 725 }
727 726
728 void work(); 727 void work() override;
729 728
730 Path getDrvPath() 729 Path getDrvPath()
731 { 730 {
@@ -771,8 +770,8 @@ private:
771 void deleteTmpDir(bool force); 770 void deleteTmpDir(bool force);
772 771
773 /* Callback used by the worker to write to the log. */ 772 /* Callback used by the worker to write to the log. */
774 void handleChildOutput(int fd, const string & data); 773 void handleChildOutput(int fd, const string & data) override;
775 void handleEOF(int fd); 774 void handleEOF(int fd) override;
776 775
777 /* Return the set of (in)valid paths. */ 776 /* Return the set of (in)valid paths. */
778 PathSet checkPathValidity(bool returnValid, bool checkHash); 777 PathSet checkPathValidity(bool returnValid, bool checkHash);
@@ -806,7 +805,7 @@ DerivationGoal::DerivationGoal(const Path & drvPath, const StringSet & wantedOut
806{ 805{
807 this->drvPath = drvPath; 806 this->drvPath = drvPath;
808 state = &DerivationGoal::init; 807 state = &DerivationGoal::init;
809 name = (format("building of `%1%'") % drvPath).str(); 808 name = std::format("building of `{}'", drvPath);
810 trace("created"); 809 trace("created");
811 810
812 /* Prevent the .chroot directory from being 811 /* Prevent the .chroot directory from being
@@ -862,7 +861,7 @@ void DerivationGoal::killChild()
862void DerivationGoal::timedOut() 861void DerivationGoal::timedOut()
863{ 862{
864 if (settings.printBuildTrace) 863 if (settings.printBuildTrace)
865 printMsg(lvlError, format("@ build-failed %1% - timeout") % drvPath); 864 printMsg(lvlError, std::format("@ build-failed {} - timeout", drvPath));
866 killChild(); 865 killChild();
867 done(BuildResult::TimedOut); 866 done(BuildResult::TimedOut);
868} 867}
@@ -896,7 +895,7 @@ void DerivationGoal::init()
896 trace("init"); 895 trace("init");
897 896
898 if (settings.readOnlyMode) 897 if (settings.readOnlyMode)
899 throw Error(format("cannot build derivation `%1%' - no write access to the store") % drvPath); 898 throw Error(std::format("cannot build derivation `{}' - no write access to the store", drvPath));
900 899
901 /* The first thing to do is to make sure that the derivation 900 /* The first thing to do is to make sure that the derivation
902 exists. If it doesn't, it may be created through a 901 exists. If it doesn't, it may be created through a
@@ -917,7 +916,7 @@ void DerivationGoal::haveDerivation()
917 trace("loading derivation"); 916 trace("loading derivation");
918 917
919 if (nrFailed != 0) { 918 if (nrFailed != 0) {
920 printMsg(lvlError, format("cannot build missing derivation ‘%1%’") % drvPath); 919 printMsg(lvlError, std::format("cannot build missing derivation `{}'", drvPath));
921 done(BuildResult::MiscFailure); 920 done(BuildResult::MiscFailure);
922 return; 921 return;
923 } 922 }
@@ -968,7 +967,7 @@ void DerivationGoal::outputsSubstituted()
968 trace("all outputs substituted (maybe)"); 967 trace("all outputs substituted (maybe)");
969 968
970 if (nrFailed > 0 && nrFailed > nrNoSubstituters + nrIncompleteClosure && !settings.tryFallback) 969 if (nrFailed > 0 && nrFailed > nrNoSubstituters + nrIncompleteClosure && !settings.tryFallback)
971 throw Error(format("some substitutes for the outputs of derivation `%1%' failed (usually happens due to networking issues); try `--fallback' to build derivation from source ") % drvPath); 970 throw Error(std::format("some substitutes for the outputs of derivation `{}' failed (usually happens due to networking issues); try `--fallback' to build derivation from source ", drvPath));
972 971
973 /* If the substitutes form an incomplete closure, then we should 972 /* If the substitutes form an incomplete closure, then we should
974 build the dependencies of this derivation, but after that, we 973 build the dependencies of this derivation, but after that, we
@@ -993,7 +992,7 @@ void DerivationGoal::outputsSubstituted()
993 return; 992 return;
994 } 993 }
995 if (buildMode == bmCheck && nrInvalid > 0) 994 if (buildMode == bmCheck && nrInvalid > 0)
996 throw Error(format("`%1%' is missing outputs; build it normally before using `--check'") % drvPath); 995 throw Error(std::format("`{}' is missing outputs; build it normally before using `--check'", drvPath));
997 996
998 /* Otherwise, at least one of the output paths could not be 997 /* Otherwise, at least one of the output paths could not be
999 produced using a substitute. So we have to build instead. */ 998 produced using a substitute. So we have to build instead. */
@@ -1051,7 +1050,7 @@ void DerivationGoal::repairClosure()
1051 PathSet broken; 1050 PathSet broken;
1052 for (auto& i : outputClosure) { 1051 for (auto& i : outputClosure) {
1053 if (worker.store.pathContentsGood(i)) continue; 1052 if (worker.store.pathContentsGood(i)) continue;
1054 printMsg(lvlError, format("found corrupted or missing path `%1%' in the output closure of `%2%'") % i % drvPath); 1053 printMsg(lvlError, std::format("found corrupted or missing path `{}' in the output closure of `{}'", i, drvPath));
1055 Path drvPath2 = outputsToDrv[i]; 1054 Path drvPath2 = outputsToDrv[i];
1056 if (drvPath2 == "") 1055 if (drvPath2 == "")
1057 addWaitee(worker.makeSubstitutionGoal(i, true)); 1056 addWaitee(worker.makeSubstitutionGoal(i, true));
@@ -1072,7 +1071,7 @@ void DerivationGoal::closureRepaired()
1072{ 1071{
1073 trace("closure repaired"); 1072 trace("closure repaired");
1074 if (nrFailed > 0) 1073 if (nrFailed > 0)
1075 throw Error(format("some paths in the output closure of derivation ‘%1%’ could not be repaired") % drvPath); 1074 throw Error(std::format("some paths in the output closure of derivation `{}' could not be repaired", drvPath));
1076 done(BuildResult::AlreadyValid); 1075 done(BuildResult::AlreadyValid);
1077} 1076}
1078 1077
@@ -1083,8 +1082,8 @@ void DerivationGoal::inputsRealised()
1083 1082
1084 if (nrFailed != 0) { 1083 if (nrFailed != 0) {
1085 printMsg(lvlError, 1084 printMsg(lvlError,
1086 format("cannot build derivation `%1%': %2% dependencies couldn't be built") 1085 std::format("cannot build derivation `{}': {} dependencies couldn't be built",
1087 % drvPath % nrFailed); 1086 drvPath, nrFailed));
1088 done(BuildResult::DependencyFailed); 1087 done(BuildResult::DependencyFailed);
1089 return; 1088 return;
1090 } 1089 }
@@ -1099,7 +1098,7 @@ void DerivationGoal::inputsRealised()
1099 1098
1100 /* The outputs are referenceable paths. */ 1099 /* The outputs are referenceable paths. */
1101 for (auto& i : drv.outputs) { 1100 for (auto& i : drv.outputs) {
1102 debug(format("building path `%1%'") % i.second.path); 1101 debug(std::format("building path `{}'", i.second.path));
1103 allPaths.insert(i.second.path); 1102 allPaths.insert(i.second.path);
1104 } 1103 }
1105 1104
@@ -1117,15 +1116,15 @@ void DerivationGoal::inputsRealised()
1117 computeFSClosure(worker.store, inDrv.outputs[j].path, inputPaths); 1116 computeFSClosure(worker.store, inDrv.outputs[j].path, inputPaths);
1118 else 1117 else
1119 throw Error( 1118 throw Error(
1120 format("derivation `%1%' requires non-existent output `%2%' from input derivation `%3%'") 1119 std::format("derivation `{}' requires non-existent output `{}' from input derivation `{}'",
1121 % drvPath % j % i.first); 1120 drvPath, j, i.first));
1122 } 1121 }
1123 1122
1124 /* Second, the input sources. */ 1123 /* Second, the input sources. */
1125 for (auto& i : drv.inputSrcs) 1124 for (auto& i : drv.inputSrcs)
1126 computeFSClosure(worker.store, i, inputPaths); 1125 computeFSClosure(worker.store, i, inputPaths);
1127 1126
1128 debug(format("added input paths %1%") % showPaths(inputPaths)); 1127 debug(std::format("added input paths {}", showPaths(inputPaths)));
1129 1128
1130 allPaths.insert(inputPaths.begin(), inputPaths.end()); 1129 allPaths.insert(inputPaths.begin(), inputPaths.end());
1131 1130
@@ -1187,8 +1186,8 @@ void DerivationGoal::tryToBuild()
1187 goal to sleep until another goal finishes, then try again. */ 1186 goal to sleep until another goal finishes, then try again. */
1188 for (auto& i : drv.outputs) 1187 for (auto& i : drv.outputs)
1189 if (pathIsLockedByMe(i.second.path)) { 1188 if (pathIsLockedByMe(i.second.path)) {
1190 debug(format("putting derivation `%1%' to sleep because `%2%' is locked by another goal") 1189 debug(std::format("putting derivation `{}' to sleep because `{}' is locked by another goal",
1191 % drvPath % i.second.path); 1190 drvPath, i.second.path));
1192 worker.waitForAnyGoal(shared_from_this()); 1191 worker.waitForAnyGoal(shared_from_this());
1193 return; 1192 return;
1194 } 1193 }
@@ -1212,7 +1211,7 @@ void DerivationGoal::tryToBuild()
1212 build this derivation, so no further checks are necessary. */ 1211 build this derivation, so no further checks are necessary. */
1213 validPaths = checkPathValidity(true, buildMode == bmRepair); 1212 validPaths = checkPathValidity(true, buildMode == bmRepair);
1214 if (buildMode != bmCheck && validPaths.size() == drv.outputs.size()) { 1213 if (buildMode != bmCheck && validPaths.size() == drv.outputs.size()) {
1215 debug(format("skipping build of derivation `%1%', someone beat us to it") % drvPath); 1214 debug(std::format("skipping build of derivation `{}', someone beat us to it", drvPath));
1216 outputLocks.setDeletion(true); 1215 outputLocks.setDeletion(true);
1217 outputLocks.unlock(); 1216 outputLocks.unlock();
1218 done(BuildResult::AlreadyValid); 1217 done(BuildResult::AlreadyValid);
@@ -1229,7 +1228,7 @@ void DerivationGoal::tryToBuild()
1229 Path path = i.second.path; 1228 Path path = i.second.path;
1230 if (worker.store.isValidPath(path)) continue; 1229 if (worker.store.isValidPath(path)) continue;
1231 if (!pathExists(path)) continue; 1230 if (!pathExists(path)) continue;
1232 debug(format("removing invalid path `%1%'") % path); 1231 debug(std::format("removing invalid path `{}'", path));
1233 deletePath(path); 1232 deletePath(path);
1234 } 1233 }
1235 1234
@@ -1284,8 +1283,8 @@ void DerivationGoal::tryToBuild()
1284 outputLocks.unlock(); 1283 outputLocks.unlock();
1285 buildUser.release(); 1284 buildUser.release();
1286 if (settings.printBuildTrace) 1285 if (settings.printBuildTrace)
1287 printMsg(lvlError, format("@ build-failed %1% - %2% %3%") 1286 printMsg(lvlError, std::format("@ build-failed {} - {} {}",
1288 % drvPath % 0 % e.msg()); 1287 drvPath, 0, e.msg()));
1289 worker.permanentFailure = true; 1288 worker.permanentFailure = true;
1290 done(BuildResult::InputRejected, e.msg()); 1289 done(BuildResult::InputRejected, e.msg());
1291 return; 1290 return;
@@ -1303,11 +1302,11 @@ void replaceValidPath(const Path & storePath, const Path tmpPath)
1303 tmpPath (the replacement), so we have to move it out of the 1302 tmpPath (the replacement), so we have to move it out of the
1304 way first. We'd better not be interrupted here, because if 1303 way first. We'd better not be interrupted here, because if
1305 we're repairing (say) Glibc, we end up with a broken system. */ 1304 we're repairing (say) Glibc, we end up with a broken system. */
1306 Path oldPath = (format("%1%.old-%2%-%3%") % storePath % getpid() % rand()).str(); 1305 Path oldPath = std::format("{}.old-{}-{}", storePath, getpid(), rand());
1307 if (pathExists(storePath)) 1306 if (pathExists(storePath))
1308 rename(storePath.c_str(), oldPath.c_str()); 1307 rename(storePath.c_str(), oldPath.c_str());
1309 if (rename(tmpPath.c_str(), storePath.c_str()) == -1) 1308 if (rename(tmpPath.c_str(), storePath.c_str()) == -1)
1310 throw SysError(format("moving `%1%' to `%2%'") % tmpPath % storePath); 1309 throw SysError(std::format("moving `{}' to `{}'", tmpPath, storePath));
1311 if (pathExists(oldPath)) 1310 if (pathExists(oldPath))
1312 deletePath(oldPath); 1311 deletePath(oldPath);
1313} 1312}
@@ -1349,7 +1348,7 @@ static void secureFilePerms(Path path, bool allowSpecialFiles = false)
1349 /* FALLTHROUGH */ 1348 /* FALLTHROUGH */
1350 1349
1351 default: 1350 default:
1352 throw Error(format("file `%1%' has an unsupported type") % path); 1351 throw Error(std::format("file `{}' has an unsupported type", path));
1353 } 1352 }
1354} 1353}
1355 1354
@@ -1373,7 +1372,7 @@ void DerivationGoal::buildDone()
1373 status = pid.wait(true); 1372 status = pid.wait(true);
1374 } 1373 }
1375 1374
1376 debug(format("builder process for `%1%' finished") % drvPath); 1375 debug(std::format("builder process for `{}' finished", drvPath));
1377 1376
1378 /* So the child is gone now. */ 1377 /* So the child is gone now. */
1379 worker.childTerminated(savedPid); 1378 worker.childTerminated(savedPid);
@@ -1436,8 +1435,8 @@ void DerivationGoal::buildDone()
1436 if (diskFull) 1435 if (diskFull)
1437 printMsg(lvlError, "note: build failure may have been caused by lack of free disk space"); 1436 printMsg(lvlError, "note: build failure may have been caused by lack of free disk space");
1438 1437
1439 throw BuildError(format("builder for `%1%' %2%") 1438 throw BuildError(std::format("builder for `{}' {}",
1440 % drvPath % statusToString(status)); 1439 drvPath, statusToString(status)));
1441 } 1440 }
1442 1441
1443 if (fixedOutput) { 1442 if (fixedOutput) {
@@ -1451,8 +1450,8 @@ void DerivationGoal::buildDone()
1451 copyFileRecursively(output, pivot, true); 1450 copyFileRecursively(output, pivot, true);
1452 int err = rename(pivot.c_str(), output.c_str()); 1451 int err = rename(pivot.c_str(), output.c_str());
1453 if (err != 0) 1452 if (err != 0)
1454 throw SysError(format("renaming `%1%' to `%2%'") 1453 throw SysError(std::format("renaming `{}' to `{}'",
1455 % pivot % output); 1454 pivot, output));
1456 } 1455 }
1457 } 1456 }
1458 } 1457 }
@@ -1496,20 +1495,20 @@ void DerivationGoal::buildDone()
1496 1495
1497 if (hook && WIFEXITED(status) && WEXITSTATUS(status) == 101) { 1496 if (hook && WIFEXITED(status) && WEXITSTATUS(status) == 101) {
1498 if (settings.printBuildTrace) 1497 if (settings.printBuildTrace)
1499 printMsg(lvlError, format("@ build-failed %1% - timeout") % drvPath); 1498 printMsg(lvlError, std::format("@ build-failed {} - timeout", drvPath));
1500 st = BuildResult::TimedOut; 1499 st = BuildResult::TimedOut;
1501 } 1500 }
1502 1501
1503 else if (hook && (!WIFEXITED(status) || WEXITSTATUS(status) != 100)) { 1502 else if (hook && (!WIFEXITED(status) || WEXITSTATUS(status) != 100)) {
1504 if (settings.printBuildTrace) 1503 if (settings.printBuildTrace)
1505 printMsg(lvlError, format("@ hook-failed %1% - %2% %3%") 1504 printMsg(lvlError, std::format("@ hook-failed {} - {} {}",
1506 % drvPath % status % e.msg()); 1505 drvPath, status, e.msg()));
1507 } 1506 }
1508 1507
1509 else { 1508 else {
1510 if (settings.printBuildTrace) 1509 if (settings.printBuildTrace)
1511 printMsg(lvlError, format("@ build-failed %1% - %2% %3%") 1510 printMsg(lvlError, std::format("@ build-failed {} - {} {}",
1512 % drvPath % 1 % e.msg()); 1511 drvPath, 1, e.msg()));
1513 1512
1514 st = 1513 st =
1515 statusOk(status) ? BuildResult::OutputRejected : 1514 statusOk(status) ? BuildResult::OutputRejected :
@@ -1536,7 +1535,7 @@ void DerivationGoal::buildDone()
1536 buildUser.release(); 1535 buildUser.release();
1537 1536
1538 if (settings.printBuildTrace) 1537 if (settings.printBuildTrace)
1539 printMsg(lvlError, format("@ build-succeeded %1% -") % drvPath); 1538 printMsg(lvlError, std::format("@ build-succeeded {} -", drvPath));
1540 1539
1541 done(BuildResult::Built); 1540 done(BuildResult::Built);
1542} 1541}
@@ -1549,10 +1548,10 @@ HookReply DerivationGoal::tryBuildHook()
1549 if (!worker.hook) { 1548 if (!worker.hook) {
1550 Strings args = { 1549 Strings args = {
1551 "offload", 1550 "offload",
1552 settings.thisSystem.c_str(), 1551 settings.thisSystem,
1553 (format("%1%") % settings.maxSilentTime).str().c_str(), 1552 std::format("{}", settings.maxSilentTime),
1554 (format("%1%") % settings.printBuildTrace).str().c_str(), 1553 std::format("{}", settings.printBuildTrace),
1555 (format("%1%") % settings.buildTimeout).str().c_str() 1554 std::format("{}", settings.buildTimeout)
1556 }; 1555 };
1557 1556
1558 worker.hook = std::make_shared<Agent>(settings.guixProgram, args); 1557 worker.hook = std::make_shared<Agent>(settings.guixProgram, args);
@@ -1565,9 +1564,9 @@ HookReply DerivationGoal::tryBuildHook()
1565 for (auto& i : features) checkStoreName(i); /* !!! abuse */ 1564 for (auto& i : features) checkStoreName(i); /* !!! abuse */
1566 1565
1567 /* Send the request to the hook. */ 1566 /* Send the request to the hook. */
1568 writeLine(worker.hook->toAgent.writeSide, (format("%1% %2% %3% %4%") 1567 writeLine(worker.hook->toAgent.writeSide, std::format("{} {} {} {}",
1569 % (worker.getNrLocalBuilds() < settings.maxBuildJobs ? "1" : "0") 1568 (worker.getNrLocalBuilds() < settings.maxBuildJobs ? "1" : "0"),
1570 % drv.platform % drvPath % concatStringsSep(",", features)).str()); 1569 drv.platform, drvPath, concatStringsSep(",", features)));
1571 1570
1572 /* Read the first line of input, which should be a word indicating 1571 /* Read the first line of input, which should be a word indicating
1573 whether the hook wishes to perform the build. */ 1572 whether the hook wishes to perform the build. */
@@ -1582,14 +1581,14 @@ HookReply DerivationGoal::tryBuildHook()
1582 writeToStderr(s); 1581 writeToStderr(s);
1583 } 1582 }
1584 1583
1585 debug(format("hook reply is `%1%'") % reply); 1584 debug(std::format("hook reply is `{}'", reply));
1586 1585
1587 if (reply == "decline" || reply == "postpone") 1586 if (reply == "decline" || reply == "postpone")
1588 return reply == "decline" ? rpDecline : rpPostpone; 1587 return reply == "decline" ? rpDecline : rpPostpone;
1589 else if (reply != "accept") 1588 else if (reply != "accept")
1590 throw Error(format("bad hook reply `%1%'") % reply); 1589 throw Error(std::format("bad hook reply `{}'", reply));
1591 1590
1592 printMsg(lvlTalkative, format("using hook to build path(s) %1%") % showPaths(missingPaths)); 1591 printMsg(lvlTalkative, std::format("using hook to build path(s) {}", showPaths(missingPaths)));
1593 1592
1594 hook = worker.hook; 1593 hook = worker.hook;
1595 worker.hook.reset(); 1594 worker.hook.reset();
@@ -1624,8 +1623,8 @@ HookReply DerivationGoal::tryBuildHook()
1624 worker.childStarted(shared_from_this(), hook->pid, fds, false, true); 1623 worker.childStarted(shared_from_this(), hook->pid, fds, false, true);
1625 1624
1626 if (settings.printBuildTrace) 1625 if (settings.printBuildTrace)
1627 printMsg(lvlError, format("@ build-started %1% - %2% %3% %4%") 1626 printMsg(lvlError, std::format("@ build-started {} - {} {} {}",
1628 % drvPath % drv.platform % logFile % hook->pid); 1627 drvPath, drv.platform, logFile, pid_t(hook->pid)));
1629 1628
1630 return rpAccept; 1629 return rpAccept;
1631} 1630}
@@ -1634,7 +1633,7 @@ HookReply DerivationGoal::tryBuildHook()
1634void chmod_(const Path & path, mode_t mode) 1633void chmod_(const Path & path, mode_t mode)
1635{ 1634{
1636 if (chmod(path.c_str(), mode) == -1) 1635 if (chmod(path.c_str(), mode) == -1)
1637 throw SysError(format("setting permissions on `%1%'") % path); 1636 throw SysError(std::format("setting permissions on `{}'", path));
1638} 1637}
1639 1638
1640 1639
@@ -1652,7 +1651,7 @@ static void initializeUserNamespace(pid_t child,
1652 bool haveCapSetGID = false) 1651 bool haveCapSetGID = false)
1653{ 1652{
1654 writeFile("/proc/" + std::to_string(child) + "/uid_map", 1653 writeFile("/proc/" + std::to_string(child) + "/uid_map",
1655 (format("%d %d 1") % guestUID % hostUID).str()); 1654 std::format("{} {} 1", guestUID, hostUID));
1656 1655
1657 if (!haveCapSetGID && !extraGIDs.empty()) { 1656 if (!haveCapSetGID && !extraGIDs.empty()) {
1658 try { 1657 try {
@@ -1668,8 +1667,8 @@ static void initializeUserNamespace(pid_t child,
1668 1667
1669 runProgram("newgidmap", true, args); 1668 runProgram("newgidmap", true, args);
1670 printMsg(lvlChatty, 1669 printMsg(lvlChatty,
1671 format("mapped %1% extra GIDs into namespace of PID %2%") 1670 std::format("mapped {} extra GIDs into namespace of PID {}",
1672 % extraGIDs.size() % child); 1671 extraGIDs.size(), child));
1673 1672
1674 return; 1673 return;
1675 } catch (const ExecError &e) { 1674 } catch (const ExecError &e) {
@@ -1680,10 +1679,10 @@ static void initializeUserNamespace(pid_t child,
1680 if (!haveCapSetGID) 1679 if (!haveCapSetGID)
1681 writeFile("/proc/" + std::to_string(child) + "/setgroups", "deny"); 1680 writeFile("/proc/" + std::to_string(child) + "/setgroups", "deny");
1682 1681
1683 auto content = (format("%d %d 1\n") % guestGID % hostGID).str(); 1682 auto content = std::format("{} {} 1\n", guestGID, hostGID);
1684 if (haveCapSetGID) { 1683 if (haveCapSetGID) {
1685 for (auto &mapping: extraGIDs) { 1684 for (auto &mapping: extraGIDs) {
1686 content += (format("%d %d 1\n") % mapping.second % mapping.first).str(); 1685 content += std::format("{} {} 1\n", mapping.second, mapping.first);
1687 } 1686 }
1688 } 1687 }
1689 writeFile("/proc/" + std::to_string(child) + "/gid_map", content); 1688 writeFile("/proc/" + std::to_string(child) + "/gid_map", content);
@@ -1963,7 +1962,7 @@ static void prepareSlirpChrootAction(SpawnContext & sctx)
1963 struct stat st; 1962 struct stat st;
1964 if(stat(fs.c_str(), &st) != 0) { 1963 if(stat(fs.c_str(), &st) != 0) {
1965 if(errno == EACCES) continue; /* Not accessible anyway */ 1964 if(errno == EACCES) continue; /* Not accessible anyway */
1966 else throw SysError(format("stat of `%1%'") % fs); 1965 else throw SysError(std::format("stat of `{}'", fs));
1967 } 1966 }
1968 1967
1969 ctx.readOnlyFilesInChroot.insert(fs); 1968 ctx.readOnlyFilesInChroot.insert(fs);
@@ -2408,7 +2407,7 @@ void DerivationGoal::execBuilderOrBuiltin(SpawnContext & ctx)
2408 buildDrv(drv, drvPath, output); 2407 buildDrv(drv, drvPath, output);
2409 } 2408 }
2410 else 2409 else
2411 throw Error(format("unsupported builtin function '%1%'") % string(drv.builder, 8)); 2410 throw Error(std::format("unsupported builtin function '{}'", string(drv.builder, 8)));
2412 _exit(0); 2411 _exit(0);
2413 } catch (std::exception & e) { 2412 } catch (std::exception & e) {
2414 writeFull(STDERR_FILENO, "error: " + string(e.what()) + "\n"); 2413 writeFull(STDERR_FILENO, "error: " + string(e.what()) + "\n");
@@ -2427,7 +2426,7 @@ void DerivationGoal::execBuilderOrBuiltin(SpawnContext & ctx)
2427 chroot. */ 2426 chroot. */
2428 ctx.program = canonPath(ctx.program, true); 2427 ctx.program = canonPath(ctx.program, true);
2429 if(!isInStore(ctx.program)) 2428 if(!isInStore(ctx.program))
2430 throw Error(format("derivation builder `%1' is outside the store") % ctx.program); 2429 throw Error(std::format("derivation builder `{}' is outside the store", ctx.program));
2431 /* If DRV targets the same operating system kernel, try to execute it: 2430 /* If DRV targets the same operating system kernel, try to execute it:
2432 there might be binfmt_misc set up for user-land emulation of other 2431 there might be binfmt_misc set up for user-land emulation of other
2433 architectures. However, if it targets a different operating 2432 architectures. However, if it targets a different operating
@@ -2450,13 +2449,13 @@ void DerivationGoal::execBuilderOrBuiltin(SpawnContext & ctx)
2450 that invoke QEMU. */ 2449 that invoke QEMU. */
2451 if (error == ENOEXEC && !canBuildLocally(drv.platform)) { 2450 if (error == ENOEXEC && !canBuildLocally(drv.platform)) {
2452 if (settings.printBuildTrace) 2451 if (settings.printBuildTrace)
2453 printMsg(lvlError, format("@ unsupported-platform %1% %2%") % drvPath % drv.platform); 2452 printMsg(lvlError, std::format("@ unsupported-platform {} {}", drvPath, drv.platform));
2454 throw Error(format("a `%1%' is required to build `%3%', but I am a `%2%'") 2453 throw Error(std::format("a `{}' is required to build `{}', but I am a `{}'",
2455 % drv.platform % settings.thisSystem % drvPath); 2454 drv.platform, settings.thisSystem, drvPath));
2456 } 2455 }
2457 2456
2458 errno = error; 2457 errno = error;
2459 throw SysError(format("executing `%1%'") % drv.builder); 2458 throw SysError(std::format("executing `{}'", drv.builder));
2460} 2459}
2461 2460
2462 2461
@@ -2468,13 +2467,14 @@ void execBuilderOrBuiltinAction(SpawnContext & ctx)
2468 2467
2469void DerivationGoal::startBuilder() 2468void DerivationGoal::startBuilder()
2470{ 2469{
2471 auto f = format( 2470 auto path = showPaths(missingPaths);
2472 buildMode == bmRepair ? "repairing path(s) %1%" : 2471 auto f = std::vformat(
2473 buildMode == bmCheck ? "checking path(s) %1%" : 2472 buildMode == bmRepair ? "repairing path(s) {0}" :
2474 nrRounds > 1 ? "building path(s) %1% (round %2%/%3%)" : 2473 buildMode == bmCheck ? "checking path(s) {0}" :
2475 "building path(s) %1%"); 2474 nrRounds > 1 ? "building path(s) {0} (round {1}/{2})" :
2476 f.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit); 2475 "building path(s) {0}",
2477 startNest(nest, lvlInfo, f % showPaths(missingPaths) % curRound % nrRounds); 2476 std::make_format_args(path, curRound, nrRounds));
2477 startNest(nest, lvlInfo, f);
2478 2478
2479 /* A ChrootBuildSpawnContext reference can be passed to procedures 2479 /* A ChrootBuildSpawnContext reference can be passed to procedures
2480 expecting a SpawnContext reference */ 2480 expecting a SpawnContext reference */
@@ -2558,7 +2558,7 @@ void DerivationGoal::startBuilder()
2558 ctx.env["NIX_STORE"] = settings.nixStore; 2558 ctx.env["NIX_STORE"] = settings.nixStore;
2559 2559
2560 /* The maximum number of cores to utilize for parallel building. */ 2560 /* The maximum number of cores to utilize for parallel building. */
2561 ctx.env["NIX_BUILD_CORES"] = (format("%d") % settings.buildCores).str(); 2561 ctx.env["NIX_BUILD_CORES"] = std::format("{}", settings.buildCores);
2562 2562
2563 /* Add all bindings specified in the derivation. */ 2563 /* Add all bindings specified in the derivation. */
2564 for (auto& i : drv.env) 2564 for (auto& i : drv.env)
@@ -2630,7 +2630,7 @@ void DerivationGoal::startBuilder()
2630 string s = get(drv.env, "exportReferencesGraph"); 2630 string s = get(drv.env, "exportReferencesGraph");
2631 Strings ss = tokenizeString<Strings>(s); 2631 Strings ss = tokenizeString<Strings>(s);
2632 if (ss.size() % 2 != 0) 2632 if (ss.size() % 2 != 0)
2633 throw BuildError(format("odd number of tokens in `exportReferencesGraph': `%1%'") % s); 2633 throw BuildError(std::format("odd number of tokens in `exportReferencesGraph': `{}'", s));
2634 for (Strings::iterator i = ss.begin(); i != ss.end(); ) { 2634 for (Strings::iterator i = ss.begin(); i != ss.end(); ) {
2635 string fileName = *i++; 2635 string fileName = *i++;
2636 checkStoreName(fileName); /* !!! abuse of this function */ 2636 checkStoreName(fileName); /* !!! abuse of this function */
@@ -2638,12 +2638,12 @@ void DerivationGoal::startBuilder()
2638 /* Check that the store path is valid. */ 2638 /* Check that the store path is valid. */
2639 Path storePath = *i++; 2639 Path storePath = *i++;
2640 if (!isInStore(storePath)) 2640 if (!isInStore(storePath))
2641 throw BuildError(format("`exportReferencesGraph' contains a non-store path `%1%'") 2641 throw BuildError(std::format("`exportReferencesGraph' contains a non-store path `{}'",
2642 % storePath); 2642 storePath));
2643 storePath = toStorePath(storePath); 2643 storePath = toStorePath(storePath);
2644 if (!worker.store.isValidPath(storePath)) 2644 if (!worker.store.isValidPath(storePath))
2645 throw BuildError(format("`exportReferencesGraph' contains an invalid path `%1%'") 2645 throw BuildError(std::format("`exportReferencesGraph' contains an invalid path `{}'",
2646 % storePath); 2646 storePath));
2647 2647
2648 /* If there are derivations in the graph, then include their 2648 /* If there are derivations in the graph, then include their
2649 outputs as well. This is useful if you want to do things 2649 outputs as well. This is useful if you want to do things
@@ -2680,7 +2680,7 @@ void DerivationGoal::startBuilder()
2680 2680
2681 /* Change ownership of the temporary build directory. */ 2681 /* Change ownership of the temporary build directory. */
2682 if (chown(tmpDir.c_str(), buildUser.getUID(), buildUser.getGID()) == -1) 2682 if (chown(tmpDir.c_str(), buildUser.getUID(), buildUser.getGID()) == -1)
2683 throw SysError(format("cannot change ownership of '%1%'") % tmpDir); 2683 throw SysError(std::format("cannot change ownership of '{}'", tmpDir));
2684 2684
2685 ctx.setuid = true; 2685 ctx.setuid = true;
2686 ctx.user = buildUser.getUID(); 2686 ctx.user = buildUser.getUID();
@@ -2711,7 +2711,7 @@ void DerivationGoal::startBuilder()
2711 2711
2712 if(fixedOutput) { 2712 if(fixedOutput) {
2713 if(findProgram(settings.slirp4netns) == "") 2713 if(findProgram(settings.slirp4netns) == "")
2714 printMsg(lvlError, format("`%1%' can't be found in PATH, network access disabled") % settings.slirp4netns); 2714 printMsg(lvlError, std::format("`{}' can't be found in PATH, network access disabled", settings.slirp4netns));
2715 else { 2715 else {
2716 if(!pathExists("/dev/net/tun")) 2716 if(!pathExists("/dev/net/tun"))
2717 printMsg(lvlError, "`/dev/net/tun' is missing, network access disabled"); 2717 printMsg(lvlError, "`/dev/net/tun' is missing, network access disabled");
@@ -2737,15 +2737,15 @@ void DerivationGoal::startBuilder()
2737 ctx.hostname = "localhost"; 2737 ctx.hostname = "localhost";
2738 ctx.domainname = "(none)"; /* kernel default */ 2738 ctx.domainname = "(none)"; /* kernel default */
2739 2739
2740 printMsg(lvlChatty, format("setting up chroot environment in `%1%'") % chrootRootDir); 2740 printMsg(lvlChatty, std::format("setting up chroot environment in `{}'", chrootRootDir));
2741 2741
2742 if (mkdir(chrootRootTop.c_str(), 0750) == -1) 2742 if (mkdir(chrootRootTop.c_str(), 0750) == -1)
2743 throw SysError(format("cannot create build root container '%1%'") % chrootRootTop); 2743 throw SysError(std::format("cannot create build root container '{}'", chrootRootTop));
2744 if (mkdir(chrootRootDir.c_str(), 0750) == -1) 2744 if (mkdir(chrootRootDir.c_str(), 0750) == -1)
2745 throw SysError(format("cannot create build root '%1%'") % chrootRootDir); 2745 throw SysError(std::format("cannot create build root '{}'", chrootRootDir));
2746 2746
2747 if (buildUser.enabled() && chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1) 2747 if (buildUser.enabled() && chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1)
2748 throw SysError(format("cannot change ownership of ‘%1%’") % chrootRootDir); 2748 throw SysError(std::format("cannot change ownership of `{}'", chrootRootDir));
2749 2749
2750 /* Create a writable /tmp in the chroot. Many builders need 2750 /* Create a writable /tmp in the chroot. Many builders need
2751 this. (Of course they should really respect $TMPDIR 2751 this. (Of course they should really respect $TMPDIR
@@ -2760,17 +2760,17 @@ void DerivationGoal::startBuilder()
2760 createDirs(chrootRootDir + "/etc"); 2760 createDirs(chrootRootDir + "/etc");
2761 2761
2762 writeFile(chrootRootDir + "/etc/passwd", 2762 writeFile(chrootRootDir + "/etc/passwd",
2763 (format( 2763 std::format(
2764 "nixbld:x:%1%:%2%:Nix build user:/:/noshell\n" 2764 "nixbld:x:{}:{}:Nix build user:/:/noshell\n"
2765 "nobody:x:65534:65534:Nobody:/:/noshell\n") 2765 "nobody:x:65534:65534:Nobody:/:/noshell\n",
2766 % (buildUser.enabled() ? buildUser.getUID() : guestUID) 2766 buildUser.enabled() ? buildUser.getUID() : guestUID,
2767 % (buildUser.enabled() ? buildUser.getGID() : guestGID)).str()); 2767 buildUser.enabled() ? buildUser.getGID() : guestGID));
2768 2768
2769 /* Declare the build user's group so that programs get a consistent 2769 /* Declare the build user's group so that programs get a consistent
2770 view of the system (e.g., "id -gn"). */ 2770 view of the system (e.g., "id -gn"). */
2771 writeFile(chrootRootDir + "/etc/group", 2771 writeFile(chrootRootDir + "/etc/group",
2772 (format("nixbld:!:%1%:\n") 2772 std::format("nixbld:!:{}:\n",
2773 % (buildUser.enabled() ? buildUser.getGID() : guestGID)).str()); 2773 buildUser.enabled() ? buildUser.getGID() : guestGID));
2774 2774
2775 if (fixedOutput) { 2775 if (fixedOutput) {
2776 /* Fixed-output derivations typically need to access the network, 2776 /* Fixed-output derivations typically need to access the network,
@@ -2834,7 +2834,7 @@ void DerivationGoal::startBuilder()
2834 if (buildUser.enabled() && chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) 2834 if (buildUser.enabled() && chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1)
2835 /* As an extra security precaution, make the fake store only 2835 /* As an extra security precaution, make the fake store only
2836 writable by the build user. */ 2836 writable by the build user. */
2837 throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); 2837 throw SysError(std::format("cannot change ownership of `{}'", chrootStoreDir));
2838 2838
2839 /* Make the closure of the inputs available in the chroot, rather than 2839 /* Make the closure of the inputs available in the chroot, rather than
2840 the whole store. This prevents any access to undeclared 2840 the whole store. This prevents any access to undeclared
@@ -2902,7 +2902,7 @@ void DerivationGoal::startBuilder()
2902 ctx.phases = getBasicSpawnPhases(); 2902 ctx.phases = getBasicSpawnPhases();
2903 2903
2904 if (pathExists(homeDir)) 2904 if (pathExists(homeDir))
2905 throw Error(format("directory `%1%' exists; please remove it") % homeDir); 2905 throw Error(std::format("directory `{}' exists; please remove it", homeDir));
2906 2906
2907 /* We're not doing a chroot build, but we have some valid 2907 /* We're not doing a chroot build, but we have some valid
2908 output paths. Since we can't just overwrite or delete 2908 output paths. Since we can't just overwrite or delete
@@ -2930,7 +2930,7 @@ void DerivationGoal::startBuilder()
2930 replacePhase(ctx.phases, "exec", execBuilderOrBuiltinAction); 2930 replacePhase(ctx.phases, "exec", execBuilderOrBuiltinAction);
2931 2931
2932 /* Run the builder. */ 2932 /* Run the builder. */
2933 printMsg(lvlChatty, format("executing builder `%1%'") % drv.builder); 2933 printMsg(lvlChatty, std::format("executing builder `{}'", drv.builder));
2934 2934
2935 /* Create the log file. */ 2935 /* Create the log file. */
2936 Path logFile = openLogFile(); 2936 Path logFile = openLogFile();
@@ -3070,8 +3070,8 @@ void DerivationGoal::startBuilder()
3070 if (!msg.empty()) throw Error(msg); 3070 if (!msg.empty()) throw Error(msg);
3071 3071
3072 if (settings.printBuildTrace) { 3072 if (settings.printBuildTrace) {
3073 printMsg(lvlError, format("@ build-started %1% - %2% %3% %4%") 3073 printMsg(lvlError, std::format("@ build-started {} - {} {} {}",
3074 % drvPath % drv.platform % logFile % pid); 3074 drvPath, drv.platform, logFile, pid_t(pid)));
3075 } 3075 }
3076 3076
3077} 3077}
@@ -3090,8 +3090,7 @@ PathSet parseReferenceSpecifiers(const Derivation & drv, string attr)
3090 else if (drv.outputs.find(i) != drv.outputs.end()) 3090 else if (drv.outputs.find(i) != drv.outputs.end())
3091 result.insert(drv.outputs.find(i)->second.path); 3091 result.insert(drv.outputs.find(i)->second.path);
3092 else throw BuildError( 3092 else throw BuildError(
3093 format("derivation contains an invalid reference specifier `%1%'") 3093 std::format("derivation contains an invalid reference specifier `{}'", i));
3094 % i);
3095 } 3094 }
3096 return result; 3095 return result;
3097} 3096}
@@ -3142,9 +3141,9 @@ void DerivationGoal::registerOutputs()
3142 if (lstat(actualPath.c_str(), &st) == -1) { 3141 if (lstat(actualPath.c_str(), &st) == -1) {
3143 if (errno == ENOENT) 3142 if (errno == ENOENT)
3144 throw BuildError( 3143 throw BuildError(
3145 format("builder for `%1%' failed to produce output path `%2%'") 3144 std::format("builder for `{}' failed to produce output path `{}'",
3146 % drvPath % path); 3145 drvPath, path));
3147 throw SysError(format("getting attributes of path `%1%'") % actualPath); 3146 throw SysError(std::format("getting attributes of path `{}'", actualPath));
3148 } 3147 }
3149 3148
3150#ifndef __CYGWIN__ 3149#ifndef __CYGWIN__
@@ -3154,13 +3153,13 @@ void DerivationGoal::registerOutputs()
3154 user. */ 3153 user. */
3155 if ((!S_ISLNK(st.st_mode) && (st.st_mode & (S_IWGRP | S_IWOTH))) || 3154 if ((!S_ISLNK(st.st_mode) && (st.st_mode & (S_IWGRP | S_IWOTH))) ||
3156 (buildUser.enabled() && st.st_uid != buildUser.getUID())) 3155 (buildUser.enabled() && st.st_uid != buildUser.getUID()))
3157 throw BuildError(format("suspicious ownership or permission on `%1%'; rejecting this build output") % path); 3156 throw BuildError(std::format("suspicious ownership or permission on `{}'; rejecting this build output", path));
3158#endif 3157#endif
3159 3158
3160 /* Apply hash rewriting if necessary. */ 3159 /* Apply hash rewriting if necessary. */
3161 bool rewritten = false; 3160 bool rewritten = false;
3162 if (!rewritesFromTmp.empty()) { 3161 if (!rewritesFromTmp.empty()) {
3163 printMsg(lvlError, format("warning: rewriting hashes in `%1%'; cross fingers") % path); 3162 printMsg(lvlError, std::format("warning: rewriting hashes in `{}'; cross fingers", path));
3164 3163
3165 /* Canonicalise first. This ensures that the path we're 3164 /* Canonicalise first. This ensures that the path we're
3166 rewriting doesn't contain a hard link to /etc/shadow or 3165 rewriting doesn't contain a hard link to /etc/shadow or
@@ -3179,7 +3178,7 @@ void DerivationGoal::registerOutputs()
3179 } 3178 }
3180 3179
3181 startNest(nest, lvlTalkative, 3180 startNest(nest, lvlTalkative,
3182 format("scanning for references inside `%1%'") % path); 3181 std::format("scanning for references inside `{}'", path));
3183 3182
3184 /* Check that fixed-output derivations produced the right 3183 /* Check that fixed-output derivations produced the right
3185 outputs (i.e., the content hash should match the specified 3184 outputs (i.e., the content hash should match the specified
@@ -3194,17 +3193,17 @@ void DerivationGoal::registerOutputs()
3194 execute permission. */ 3193 execute permission. */
3195 if (!S_ISREG(st.st_mode) || (st.st_mode & S_IXUSR) != 0) 3194 if (!S_ISREG(st.st_mode) || (st.st_mode & S_IXUSR) != 0)
3196 throw BuildError( 3195 throw BuildError(
3197 format("output path `%1% should be a non-executable regular file") % path); 3196 std::format("output path `{}' should be a non-executable regular file", path));
3198 } 3197 }
3199 3198
3200 /* Check the hash. */ 3199 /* Check the hash. */
3201 Hash h2 = recursive ? hashPath(ht, actualPath).first : hashFile(ht, actualPath); 3200 Hash h2 = recursive ? hashPath(ht, actualPath).first : hashFile(ht, actualPath);
3202 if (h != h2) { 3201 if (h != h2) {
3203 if (settings.printBuildTrace) 3202 if (settings.printBuildTrace)
3204 printMsg(lvlError, format("@ hash-mismatch %1% %2% %3% %4%") 3203 printMsg(lvlError, std::format("@ hash-mismatch {} {} {} {}",
3205 % path % i.second.hashAlgo 3204 path, i.second.hashAlgo,
3206 % printHash16or32(h) % printHash16or32(h2)); 3205 printHash16or32(h), printHash16or32(h2)));
3207 throw BuildError(format("hash mismatch for store item '%1%'") % path); 3206 throw BuildError(std::format("hash mismatch for store item '{}'", path));
3208 } 3207 }
3209 } 3208 }
3210 3209
@@ -3224,16 +3223,16 @@ void DerivationGoal::registerOutputs()
3224 if (buildMode != bmCheck) { 3223 if (buildMode != bmCheck) {
3225 if (S_ISDIR(st.st_mode)) { 3224 if (S_ISDIR(st.st_mode)) {
3226 if (lstat(actualPath.c_str(), &st) == -1) 3225 if (lstat(actualPath.c_str(), &st) == -1)
3227 throw SysError(format("getting canonicalized permissions of directory `%1%'") % actualPath); 3226 throw SysError(std::format("getting canonicalized permissions of directory `{}'", actualPath));
3228 /* Change mode on the directory to allow for 3227 /* Change mode on the directory to allow for
3229 rename(2). */ 3228 rename(2). */
3230 if (chmod(actualPath.c_str(), st.st_mode | 0700) == -1) 3229 if (chmod(actualPath.c_str(), st.st_mode | 0700) == -1)
3231 throw SysError(format("making `%1%' writable for move from chroot to store") % actualPath); 3230 throw SysError(std::format("making `{}' writable for move from chroot to store", actualPath));
3232 } 3231 }
3233 if (rename(actualPath.c_str(), path.c_str()) == -1) 3232 if (rename(actualPath.c_str(), path.c_str()) == -1)
3234 throw SysError(format("moving build output `%1%' from the chroot to the store") % path); 3233 throw SysError(std::format("moving build output `{}' from the chroot to the store", path));
3235 if (S_ISDIR(st.st_mode) && chmod(path.c_str(), st.st_mode) == -1) 3234 if (S_ISDIR(st.st_mode) && chmod(path.c_str(), st.st_mode) == -1)
3236 throw SysError(format("restoring permissions on directory `%1%'") % actualPath); 3235 throw SysError(std::format("restoring permissions on directory `{}'", actualPath));
3237 } 3236 }
3238 } 3237 }
3239 if (buildMode != bmCheck) actualPath = path; 3238 if (buildMode != bmCheck) actualPath = path;
@@ -3254,16 +3253,16 @@ void DerivationGoal::registerOutputs()
3254 Path dst = path + checkSuffix; 3253 Path dst = path + checkSuffix;
3255 if (pathExists(dst)) deletePath(dst); 3254 if (pathExists(dst)) deletePath(dst);
3256 if (rename(actualPath.c_str(), dst.c_str())) 3255 if (rename(actualPath.c_str(), dst.c_str()))
3257 throw SysError(format("renaming `%1%' to `%2%'") % actualPath % dst); 3256 throw SysError(std::format("renaming `{}' to `{}'", actualPath, dst));
3258 throw Error(format("derivation `%1%' may not be deterministic: output `%2%' differs from `%3%'") 3257 throw Error(std::format("derivation `{}' may not be deterministic: output `{}' differs from `{}'",
3259 % drvPath % path % dst); 3258 drvPath, path, dst));
3260 } else 3259 } else
3261 throw Error(format("derivation `%1%' may not be deterministic: output `%2%' differs") 3260 throw Error(std::format("derivation `{}' may not be deterministic: output `{}' differs",
3262 % drvPath % path); 3261 drvPath, path));
3263 } 3262 }
3264 3263
3265 if (settings.printBuildTrace) 3264 if (settings.printBuildTrace)
3266 printMsg(lvlError, format("@ build-succeeded %1% -") % drvPath); 3265 printMsg(lvlError, std::format("@ build-succeeded {} -", drvPath));
3267 3266
3268 continue; 3267 continue;
3269 } 3268 }
@@ -3273,9 +3272,9 @@ void DerivationGoal::registerOutputs()
3273 for (auto& i : inputPaths) { 3272 for (auto& i : inputPaths) {
3274 PathSet::iterator j = references.find(i); 3273 PathSet::iterator j = references.find(i);
3275 if (j == references.end()) 3274 if (j == references.end())
3276 debug(format("unreferenced input: `%1%'") % i); 3275 debug(std::format("unreferenced input: `{}'", i));
3277 else 3276 else
3278 debug(format("referenced input: `%1%'") % i); 3277 debug(std::format("referenced input: `{}'", i));
3279 } 3278 }
3280 3279
3281 /* Enforce `allowedReferences' and friends. */ 3280 /* Enforce `allowedReferences' and friends. */
@@ -3297,10 +3296,10 @@ void DerivationGoal::registerOutputs()
3297 for (auto & i : used) 3296 for (auto & i : used)
3298 if (allowed) { 3297 if (allowed) {
3299 if (spec.find(i) == spec.end()) 3298 if (spec.find(i) == spec.end())
3300 throw BuildError(format("output (`%1%') is not allowed to refer to path `%2%'") % actualPath % i); 3299 throw BuildError(std::format("output (`{}') is not allowed to refer to path `{}'", actualPath, i));
3301 } else { 3300 } else {
3302 if (spec.find(i) != spec.end()) 3301 if (spec.find(i) != spec.end())
3303 throw BuildError(format("output (`%1%') is not allowed to refer to path `%2%'") % actualPath % i); 3302 throw BuildError(std::format("output (`{}') is not allowed to refer to path `{}'", actualPath, i));
3304 } 3303 }
3305 }; 3304 };
3306 3305
@@ -3333,12 +3332,12 @@ void DerivationGoal::registerOutputs()
3333 Path prev = i->path + checkSuffix; 3332 Path prev = i->path + checkSuffix;
3334 if (pathExists(prev)) 3333 if (pathExists(prev))
3335 throw NotDeterministic( 3334 throw NotDeterministic(
3336 format("output ‘%1%’ of ‘%2%’ differs from ‘%3%’ from previous round") 3335 std::format("output `{}' of `{}' differs from `{}' from previous round",
3337 % i->path % drvPath % prev); 3336 i->path, drvPath, prev));
3338 else 3337 else
3339 throw NotDeterministic( 3338 throw NotDeterministic(
3340 format("output ‘%1%’ of ‘%2%’ differs from previous round") 3339 std::format("output `{}' of `{}' differs from previous round",
3341 % i->path % drvPath); 3340 i->path, drvPath));
3342 } 3341 }
3343 assert(false); // shouldn't happen 3342 assert(false); // shouldn't happen
3344 } 3343 }
@@ -3350,7 +3349,7 @@ void DerivationGoal::registerOutputs()
3350 if (curRound < nrRounds) { 3349 if (curRound < nrRounds) {
3351 Path dst = i.second.path + checkSuffix; 3350 Path dst = i.second.path + checkSuffix;
3352 if (rename(i.second.path.c_str(), dst.c_str())) 3351 if (rename(i.second.path.c_str(), dst.c_str()))
3353 throw SysError(format("renaming ‘%1%’ to ‘%2%’") % i.second.path % dst); 3352 throw SysError(std::format("renaming `{}' to `{}'", i.second.path, dst));
3354 } 3353 }
3355 } 3354 }
3356 3355
@@ -3380,20 +3379,20 @@ Path DerivationGoal::openLogFile()
3380 string baseName = baseNameOf(drvPath); 3379 string baseName = baseNameOf(drvPath);
3381 3380
3382 /* Create a log file. */ 3381 /* Create a log file. */
3383 Path dir = (format("%1%/%2%/%3%/") % settings.nixLogDir % drvsLogDir % string(baseName, 0, 2)).str(); 3382 Path dir = std::format("{}/{}/{}/", settings.nixLogDir, drvsLogDir, string(baseName, 0, 2));
3384 createDirs(dir); 3383 createDirs(dir);
3385 3384
3386 switch (settings.logCompression) 3385 switch (settings.logCompression)
3387 { 3386 {
3388 case COMPRESSION_GZIP: { 3387 case COMPRESSION_GZIP: {
3389 Path logFileName = (format("%1%/%2%.gz") % dir % string(baseName, 2)).str(); 3388 Path logFileName = std::format("{}/{}.gz", dir, string(baseName, 2));
3390 AutoCloseFD fd = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666); 3389 AutoCloseFD fd = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666);
3391 if (fd == -1) throw SysError(format("creating log file `%1%'") % logFileName); 3390 if (fd == -1) throw SysError(std::format("creating log file `{}'", logFileName));
3392 closeOnExec(fd); 3391 closeOnExec(fd);
3393 3392
3394 /* Note: FD will be closed by 'gzclose'. */ 3393 /* Note: FD will be closed by 'gzclose'. */
3395 if (!(gzLogFile = gzdopen(fd.borrow(), "w"))) 3394 if (!(gzLogFile = gzdopen(fd.borrow(), "w")))
3396 throw Error(format("cannot open compressed log file `%1%'") % logFileName); 3395 throw Error(std::format("cannot open compressed log file `{}'", logFileName));
3397 3396
3398 gzbuffer(gzLogFile, 32768); 3397 gzbuffer(gzLogFile, 32768);
3399 gzsetparams(gzLogFile, Z_BEST_COMPRESSION, Z_DEFAULT_STRATEGY); 3398 gzsetparams(gzLogFile, Z_BEST_COMPRESSION, Z_DEFAULT_STRATEGY);
@@ -3403,26 +3402,26 @@ Path DerivationGoal::openLogFile()
3403 3402
3404#if HAVE_BZLIB_H 3403#if HAVE_BZLIB_H
3405 case COMPRESSION_BZIP2: { 3404 case COMPRESSION_BZIP2: {
3406 Path logFileName = (format("%1%/%2%.bz2") % dir % string(baseName, 2)).str(); 3405 Path logFileName = std::format("{}/{}.bz2", dir, string(baseName, 2));
3407 AutoCloseFD fd = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666); 3406 AutoCloseFD fd = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666);
3408 if (fd == -1) throw SysError(format("creating log file `%1%'") % logFileName); 3407 if (fd == -1) throw SysError(std::format("creating log file `{}'", logFileName));
3409 closeOnExec(fd); 3408 closeOnExec(fd);
3410 3409
3411 if (!(fLogFile = fdopen(fd.borrow(), "w"))) 3410 if (!(fLogFile = fdopen(fd.borrow(), "w")))
3412 throw SysError(format("opening log file `%1%'") % logFileName); 3411 throw SysError(std::format("opening log file `{}'", logFileName));
3413 3412
3414 int err; 3413 int err;
3415 if (!(bzLogFile = BZ2_bzWriteOpen(&err, fLogFile, 9, 0, 0))) 3414 if (!(bzLogFile = BZ2_bzWriteOpen(&err, fLogFile, 9, 0, 0)))
3416 throw Error(format("cannot open compressed log file `%1%'") % logFileName); 3415 throw Error(std::format("cannot open compressed log file `{}'", logFileName));
3417 3416
3418 return logFileName; 3417 return logFileName;
3419 } 3418 }
3420#endif 3419#endif
3421 3420
3422 case COMPRESSION_NONE: { 3421 case COMPRESSION_NONE: {
3423 Path logFileName = (format("%1%/%2%") % dir % string(baseName, 2)).str(); 3422 Path logFileName = std::format("{}/{}", dir, string(baseName, 2));
3424 fdLogFile = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666); 3423 fdLogFile = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666);
3425 if (fdLogFile == -1) throw SysError(format("creating log file `%1%'") % logFileName); 3424 if (fdLogFile == -1) throw SysError(std::format("creating log file `{}'", logFileName));
3426 closeOnExec(fdLogFile); 3425 closeOnExec(fdLogFile);
3427 return logFileName; 3426 return logFileName;
3428 } 3427 }
@@ -3438,14 +3437,14 @@ void DerivationGoal::closeLogFile()
3438 int err; 3437 int err;
3439 err = gzclose(gzLogFile); 3438 err = gzclose(gzLogFile);
3440 gzLogFile = NULL; 3439 gzLogFile = NULL;
3441 if (err != Z_OK) throw Error(format("cannot close compressed log file (gzip error = %1%)") % err); 3440 if (err != Z_OK) throw Error(std::format("cannot close compressed log file (gzip error = {})", err));
3442 } 3441 }
3443#if HAVE_BZLIB_H 3442#if HAVE_BZLIB_H
3444 else if (bzLogFile) { 3443 else if (bzLogFile) {
3445 int err; 3444 int err;
3446 BZ2_bzWriteClose(&err, bzLogFile, 0, 0, 0); 3445 BZ2_bzWriteClose(&err, bzLogFile, 0, 0, 0);
3447 bzLogFile = 0; 3446 bzLogFile = 0;
3448 if (err != BZ_OK) throw Error(format("cannot close compressed log file (BZip2 error = %1%)") % err); 3447 if (err != BZ_OK) throw Error(std::format("cannot close compressed log file (BZip2 error = {})", err));
3449 } 3448 }
3450#endif 3449#endif
3451 3450
@@ -3463,7 +3462,7 @@ static void _chown(const Path & path, uid_t uid, gid_t gid)
3463 checkInterrupt(); 3462 checkInterrupt();
3464 3463
3465 if (lchown(path.c_str(), uid, gid) == -1) { 3464 if (lchown(path.c_str(), uid, gid) == -1) {
3466 throw SysError(format("change owner and group of `%1%'") % path); 3465 throw SysError(std::format("change owner and group of `{}'", path));
3467 } 3466 }
3468 struct stat st = lstat(path); 3467 struct stat st = lstat(path);
3469 if (S_ISDIR(st.st_mode)) { 3468 if (S_ISDIR(st.st_mode)) {
@@ -3486,8 +3485,7 @@ void DerivationGoal::deleteTmpDir(bool force)
3486 3485
3487 if (settings.keepFailed && !force) { 3486 if (settings.keepFailed && !force) {
3488 printMsg(lvlError, 3487 printMsg(lvlError,
3489 format("note: keeping build directory `%2%'") 3488 std::format("note: keeping build directory `{}'", top));
3490 % drvPath % top);
3491 chmod(tmpDir.c_str(), 0755); 3489 chmod(tmpDir.c_str(), 0755);
3492 3490
3493 // Change the ownership if clientUid is set. Never change the 3491 // Change the ownership if clientUid is set. Never change the
@@ -3516,8 +3514,8 @@ void DerivationGoal::deleteTmpDir(bool force)
3516 /* When running as an unprivileged user and without 3514 /* When running as an unprivileged user and without
3517 CAP_CHOWN, we cannot chown the build tree. Print a 3515 CAP_CHOWN, we cannot chown the build tree. Print a
3518 message and keep going. */ 3516 message and keep going. */
3519 printMsg(lvlInfo, format("cannot change ownership of build directory '%1%': %2%") 3517 printMsg(lvlInfo, std::format("cannot change ownership of build directory '{}': {}",
3520 % tmpDir % strerror(e.errNo)); 3518 tmpDir, strerror(e.errNo)));
3521 } 3519 }
3522 3520
3523 if (top != tmpDir) { 3521 if (top != tmpDir) {
@@ -3568,8 +3566,8 @@ void DerivationGoal::handleChildOutput(int fd, const string & data)
3568 logSize += data.size(); 3566 logSize += data.size();
3569 if (settings.maxLogSize && logSize > settings.maxLogSize) { 3567 if (settings.maxLogSize && logSize > settings.maxLogSize) {
3570 printMsg(lvlError, 3568 printMsg(lvlError,
3571 format("%1% killed after writing more than %2% bytes of log output") 3569 std::format("{} killed after writing more than {} bytes of log output",
3572 % getName() % settings.maxLogSize); 3570 getName(), settings.maxLogSize));
3573 timedOut(); // not really a timeout, but close enough 3571 timedOut(); // not really a timeout, but close enough
3574 return; 3572 return;
3575 } 3573 }
@@ -3580,13 +3578,13 @@ void DerivationGoal::handleChildOutput(int fd, const string & data)
3580 if (data.size() > 0) { 3578 if (data.size() > 0) {
3581 int count, err; 3579 int count, err;
3582 count = gzwrite(gzLogFile, data.data(), data.size()); 3580 count = gzwrite(gzLogFile, data.data(), data.size());
3583 if (count == 0) throw Error(format("cannot write to compressed log file (gzip error = %1%)") % gzerror(gzLogFile, &err)); 3581 if (count == 0) throw Error(std::format("cannot write to compressed log file (gzip error = {})", gzerror(gzLogFile, &err)));
3584 } 3582 }
3585#if HAVE_BZLIB_H 3583#if HAVE_BZLIB_H
3586 } else if (bzLogFile) { 3584 } else if (bzLogFile) {
3587 int err; 3585 int err;
3588 BZ2_bzWrite(&err, bzLogFile, (unsigned char *) data.data(), data.size()); 3586 BZ2_bzWrite(&err, bzLogFile, (unsigned char *) data.data(), data.size());
3589 if (err != BZ_OK) throw Error(format("cannot write to compressed log file (BZip2 error = %1%)") % err); 3587 if (err != BZ_OK) throw Error(std::format("cannot write to compressed log file (BZip2 error = {})", err));
3590#endif 3588#endif
3591 } else if (fdLogFile != -1) 3589 } else if (fdLogFile != -1)
3592 writeFull(fdLogFile, data); 3590 writeFull(fdLogFile, data);
@@ -3623,10 +3621,10 @@ bool DerivationGoal::pathFailed(const Path & path)
3623 3621
3624 if (!worker.store.hasPathFailed(path)) return false; 3622 if (!worker.store.hasPathFailed(path)) return false;
3625 3623
3626 printMsg(lvlError, format("builder for `%1%' failed previously (cached)") % path); 3624 printMsg(lvlError, std::format("builder for `{}' failed previously (cached)", path));
3627 3625
3628 if (settings.printBuildTrace) 3626 if (settings.printBuildTrace)
3629 printMsg(lvlError, format("@ build-failed %1% - cached") % drvPath); 3627 printMsg(lvlError, std::format("@ build-failed {} - cached", drvPath));
3630 3628
3631 done(BuildResult::CachedFailure); 3629 done(BuildResult::CachedFailure);
3632 3630
@@ -3644,8 +3642,8 @@ Path DerivationGoal::addHashRewrite(const Path & path)
3644 rewritesToTmp[h1] = h2; 3642 rewritesToTmp[h1] = h2;
3645 rewritesFromTmp[h2] = h1; 3643 rewritesFromTmp[h2] = h1;
3646 redirectedOutputs[path] = p; 3644 redirectedOutputs[path] = p;
3647 printMsg(lvlChatty, format("output '%1%' redirected to '%2%'") 3645 printMsg(lvlChatty, std::format("output '{}' redirected to '{}'",
3648 % path % p); 3646 path, p));
3649 return p; 3647 return p;
3650} 3648}
3651 3649
@@ -3734,7 +3732,7 @@ SubstitutionGoal::SubstitutionGoal(const Path & storePath, Worker & worker, bool
3734{ 3732{
3735 this->storePath = storePath; 3733 this->storePath = storePath;
3736 state = &SubstitutionGoal::init; 3734 state = &SubstitutionGoal::init;
3737 name = (format("substitution of `%1%'") % storePath).str(); 3735 name = std::format("substitution of `{}'", storePath);
3738 trace("created"); 3736 trace("created");
3739} 3737}
3740 3738
@@ -3748,7 +3746,7 @@ SubstitutionGoal::~SubstitutionGoal()
3748void SubstitutionGoal::timedOut() 3746void SubstitutionGoal::timedOut()
3749{ 3747{
3750 if (settings.printBuildTrace) 3748 if (settings.printBuildTrace)
3751 printMsg(lvlError, format("@ substituter-failed %1% timeout") % storePath); 3749 printMsg(lvlError, std::format("@ substituter-failed {} timeout", storePath));
3752 if (substituter) { 3750 if (substituter) {
3753 pid_t savedPid = substituter->pid; 3751 pid_t savedPid = substituter->pid;
3754 substituter.reset(); 3752 substituter.reset();
@@ -3777,7 +3775,7 @@ void SubstitutionGoal::init()
3777 } 3775 }
3778 3776
3779 if (settings.readOnlyMode) 3777 if (settings.readOnlyMode)
3780 throw Error(format("cannot substitute path `%1%' - no write access to the store") % storePath); 3778 throw Error(std::format("cannot substitute path `{}' - no write access to the store", storePath));
3781 3779
3782 tryNext(); 3780 tryNext();
3783} 3781}
@@ -3794,7 +3792,7 @@ void SubstitutionGoal::tryNext()
3794 if (k == infos.end()) { 3792 if (k == infos.end()) {
3795 /* None left. Terminate this goal and let someone else deal 3793 /* None left. Terminate this goal and let someone else deal
3796 with it. */ 3794 with it. */
3797 debug(format("path `%1%' is required, but there is no substituter that can build it") % storePath); 3795 debug(std::format("path `{}' is required, but there is no substituter that can build it", storePath));
3798 /* Hack: don't indicate failure if there were no substituters. 3796 /* Hack: don't indicate failure if there were no substituters.
3799 In that case the calling derivation should just do a 3797 In that case the calling derivation should just do a
3800 build. */ 3798 build. */
@@ -3823,7 +3821,7 @@ void SubstitutionGoal::referencesValid()
3823 trace("all references realised"); 3821 trace("all references realised");
3824 3822
3825 if (nrFailed > 0) { 3823 if (nrFailed > 0) {
3826 debug(format("some references of path `%1%' could not be realised") % storePath); 3824 debug(std::format("some references of path `{}' could not be realised", storePath));
3827 amDone(nrNoSubstituters > 0 || nrIncompleteClosure > 0 ? ecIncompleteClosure : ecFailed); 3825 amDone(nrNoSubstituters > 0 || nrIncompleteClosure > 0 ? ecIncompleteClosure : ecFailed);
3828 return; 3826 return;
3829 } 3827 }
@@ -3855,8 +3853,8 @@ void SubstitutionGoal::tryToRun()
3855 first, but let's be defensive). */ 3853 first, but let's be defensive). */
3856 outputLock.reset(); // make sure this goal's lock is gone 3854 outputLock.reset(); // make sure this goal's lock is gone
3857 if (pathIsLockedByMe(storePath)) { 3855 if (pathIsLockedByMe(storePath)) {
3858 debug(format("restarting substitution of `%1%' because it's locked by another goal") 3856 debug(std::format("restarting substitution of `{}' because it's locked by another goal",
3859 % storePath); 3857 storePath));
3860 worker.waitForAnyGoal(shared_from_this()); 3858 worker.waitForAnyGoal(shared_from_this());
3861 return; /* restart in the tryToRun() state when another goal finishes */ 3859 return; /* restart in the tryToRun() state when another goal finishes */
3862 } 3860 }
@@ -3870,14 +3868,14 @@ void SubstitutionGoal::tryToRun()
3870 3868
3871 /* Check again whether the path is invalid. */ 3869 /* Check again whether the path is invalid. */
3872 if (!repair && worker.store.isValidPath(storePath)) { 3870 if (!repair && worker.store.isValidPath(storePath)) {
3873 debug(format("store path `%1%' has become valid") % storePath); 3871 debug(std::format("store path `{}' has become valid", storePath));
3874 outputLock->setDeletion(true); 3872 outputLock->setDeletion(true);
3875 outputLock.reset(); 3873 outputLock.reset();
3876 amDone(ecSuccess); 3874 amDone(ecSuccess);
3877 return; 3875 return;
3878 } 3876 }
3879 3877
3880 printMsg(lvlInfo, format("fetching path `%1%'...") % storePath); 3878 printMsg(lvlInfo, std::format("fetching path `{}'...", storePath));
3881 3879
3882 destPath = repair ? storePath + ".tmp" : storePath; 3880 destPath = repair ? storePath + ".tmp" : storePath;
3883 3881
@@ -3901,7 +3899,7 @@ void SubstitutionGoal::tryToRun()
3901 3899
3902 /* Send the request to the substituter. */ 3900 /* Send the request to the substituter. */
3903 writeLine(substituter->toAgent.writeSide, 3901 writeLine(substituter->toAgent.writeSide,
3904 (format("substitute %1% %2%") % storePath % destPath).str()); 3902 std::format("substitute {} {}", storePath, destPath));
3905 3903
3906 set<int> fds; 3904 set<int> fds;
3907 fds.insert(substituter->fromAgent.readSide); 3905 fds.insert(substituter->fromAgent.readSide);
@@ -3913,7 +3911,7 @@ void SubstitutionGoal::tryToRun()
3913 if (settings.printBuildTrace) 3911 if (settings.printBuildTrace)
3914 /* The second element in the message used to be the name of the 3912 /* The second element in the message used to be the name of the
3915 substituter but we're left with only one. */ 3913 substituter but we're left with only one. */
3916 printMsg(lvlError, format("@ substituter-started %1% substitute") % storePath); 3914 printMsg(lvlError, std::format("@ substituter-started {} substitute", storePath));
3917} 3915}
3918 3916
3919 3917
@@ -3939,35 +3937,33 @@ void SubstitutionGoal::finished()
3939 auto statusList = tokenizeString<vector<string> >(status); 3937 auto statusList = tokenizeString<vector<string> >(status);
3940 3938
3941 if (statusList.empty()) { 3939 if (statusList.empty()) {
3942 throw SubstError(format("fetching path `%1%' (empty status)") 3940 throw SubstError(std::format("fetching path `{}' (empty status)", storePath));
3943 % storePath);
3944 } else if (statusList[0] == "hash-mismatch") { 3941 } else if (statusList[0] == "hash-mismatch") {
3945 if (settings.printBuildTrace) { 3942 if (settings.printBuildTrace) {
3946 auto hashType = statusList[1]; 3943 auto hashType = statusList[1];
3947 auto expectedHash = statusList[2]; 3944 auto expectedHash = statusList[2];
3948 auto actualHash = statusList[3]; 3945 auto actualHash = statusList[3];
3949 printMsg(lvlError, format("@ hash-mismatch %1% %2% %3% %4%") 3946 printMsg(lvlError, std::format("@ hash-mismatch {} {} {} {}",
3950 % storePath 3947 storePath, hashType, expectedHash, actualHash));
3951 % hashType % expectedHash % actualHash);
3952 } 3948 }
3953 throw SubstError(format("hash mismatch for substituted item `%1%'") % storePath); 3949 throw SubstError(std::format("hash mismatch for substituted item `{}'", storePath));
3954 } else if (statusList[0] == "success") { 3950 } else if (statusList[0] == "success") {
3955 if (!pathExists(destPath)) 3951 if (!pathExists(destPath))
3956 throw SubstError(format("substitute did not produce path `%1%'") % destPath); 3952 throw SubstError(std::format("substitute did not produce path `{}'", destPath));
3957 3953
3958 std::string hashStr = statusList[1]; 3954 std::string hashStr = statusList[1];
3959 size_t n = hashStr.find(':'); 3955 size_t n = hashStr.find(':');
3960 if (n == string::npos) 3956 if (n == string::npos)
3961 throw Error(format("bad hash from substituter: %1%") % hashStr); 3957 throw Error(std::format("bad hash from substituter: {}", hashStr));
3962 3958
3963 HashType hashType = parseHashType(string(hashStr, 0, n)); 3959 HashType hashType = parseHashType(string(hashStr, 0, n));
3964 switch (hashType) { 3960 switch (hashType) {
3965 case htUnknown: 3961 case htUnknown:
3966 throw Error(format("unknown hash algorithm in `%1%'") % hashStr); 3962 throw Error(std::format("unknown hash algorithm in `{}'", hashStr));
3967 case htSHA256: 3963 case htSHA256:
3968 hash.first = parseHash16or32(hashType, string(hashStr, n + 1)); 3964 hash.first = parseHash16or32(hashType, string(hashStr, n + 1));
3969 if (!string2Int(statusList[2], hash.second)) 3965 if (!string2Int(statusList[2], hash.second))
3970 throw Error(format("invalid nar size for '%1%' substitute") % storePath); 3966 throw Error(std::format("invalid nar size for '{}' substitute", storePath));
3971 break; 3967 break;
3972 default: 3968 default:
3973 /* The database only stores SHA256 hashes, so compute it. */ 3969 /* The database only stores SHA256 hashes, so compute it. */
@@ -3976,16 +3972,16 @@ void SubstitutionGoal::finished()
3976 } 3972 }
3977 } 3973 }
3978 else 3974 else
3979 throw SubstError(format("fetching path `%1%' (status: '%2%')") 3975 throw SubstError(std::format("fetching path `{}' (status: '{}')",
3980 % storePath % status); 3976 storePath, status));
3981 3977
3982 } catch (SubstError & e) { 3978 } catch (SubstError & e) {
3983 3979
3984 printMsg(lvlInfo, e.msg()); 3980 printMsg(lvlInfo, e.msg());
3985 3981
3986 if (settings.printBuildTrace) { 3982 if (settings.printBuildTrace) {
3987 printMsg(lvlError, format("@ substituter-failed %1% %2% %3%") 3983 printMsg(lvlError, std::format("@ substituter-failed {} {} {}",
3988 % storePath % status % e.msg()); 3984 storePath, status, e.msg()));
3989 } 3985 }
3990 3986
3991 amDone(ecFailed); 3987 amDone(ecFailed);
@@ -4011,10 +4007,10 @@ void SubstitutionGoal::finished()
4011 worker.store.markContentsGood(storePath); 4007 worker.store.markContentsGood(storePath);
4012 4008
4013 printMsg(lvlChatty, 4009 printMsg(lvlChatty,
4014 format("substitution of path `%1%' succeeded") % storePath); 4010 std::format("substitution of path `{}' succeeded", storePath));
4015 4011
4016 if (settings.printBuildTrace) 4012 if (settings.printBuildTrace)
4017 printMsg(lvlError, format("@ substituter-succeeded %1%") % storePath); 4013 printMsg(lvlError, std::format("@ substituter-succeeded {}", storePath));
4018 4014
4019 amDone(ecSuccess); 4015 amDone(ecSuccess);
4020} 4016}
@@ -4042,7 +4038,7 @@ void SubstitutionGoal::handleChildOutput(int fd, const string & data)
4042 status = trimmed; 4038 status = trimmed;
4043 worker.wakeUp(shared_from_this()); 4039 worker.wakeUp(shared_from_this());
4044 } else { 4040 } else {
4045 printMsg(lvlError, format("unexpected substituter message '%1%'") % input); 4041 printMsg(lvlError, std::format("unexpected substituter message '{}'", input));
4046 } 4042 }
4047 4043
4048 input = (end != string::npos) ? input.substr(end + 1) : ""; 4044 input = (end != string::npos) ? input.substr(end + 1) : "";
@@ -4234,7 +4230,7 @@ void Worker::run(const Goals & _topGoals)
4234{ 4230{
4235 for (auto& i : _topGoals) topGoals.insert(i); 4231 for (auto& i : _topGoals) topGoals.insert(i);
4236 4232
4237 startNest(nest, lvlDebug, format("entered goal loop")); 4233 startNest(nest, lvlDebug, "entered goal loop");
4238 4234
4239 while (1) { 4235 while (1) {
4240 4236
@@ -4308,7 +4304,7 @@ void Worker::waitForInput()
4308 if (nearest != LONG_MAX) { 4304 if (nearest != LONG_MAX) {
4309 timeout.tv_sec = std::max((time_t) 1, nearest - before); 4305 timeout.tv_sec = std::max((time_t) 1, nearest - before);
4310 useTimeout = true; 4306 useTimeout = true;
4311 printMsg(lvlVomit, format("sleeping %1% seconds") % timeout.tv_sec); 4307 printMsg(lvlVomit, std::format("sleeping {} seconds", timeout.tv_sec));
4312 } 4308 }
4313 4309
4314 /* If we are polling goals that are waiting for a lock, then wake 4310 /* If we are polling goals that are waiting for a lock, then wake
@@ -4365,15 +4361,14 @@ void Worker::waitForInput()
4365 ssize_t rd = read(k, buffer, sizeof(buffer)); 4361 ssize_t rd = read(k, buffer, sizeof(buffer));
4366 if (rd == -1) { 4362 if (rd == -1) {
4367 if (errno != EINTR) 4363 if (errno != EINTR)
4368 throw SysError(format("reading from %1%") 4364 throw SysError(std::format("reading from {}", goal->getName()));
4369 % goal->getName());
4370 } else if (rd == 0) { 4365 } else if (rd == 0) {
4371 debug(format("%1%: got EOF") % goal->getName()); 4366 debug(std::format("{}: got EOF", goal->getName()));
4372 goal->handleEOF(k); 4367 goal->handleEOF(k);
4373 j->second.fds.erase(k); 4368 j->second.fds.erase(k);
4374 } else { 4369 } else {
4375 printMsg(lvlVomit, format("%1%: read %2% bytes") 4370 printMsg(lvlVomit, std::format("{}: read {} bytes",
4376 % goal->getName() % rd); 4371 goal->getName(), rd));
4377 string data((char *) buffer, rd); 4372 string data((char *) buffer, rd);
4378 j->second.lastOutput = after; 4373 j->second.lastOutput = after;
4379 goal->handleChildOutput(k, data); 4374 goal->handleChildOutput(k, data);
@@ -4387,8 +4382,8 @@ void Worker::waitForInput()
4387 after - j->second.lastOutput >= (time_t) settings.maxSilentTime) 4382 after - j->second.lastOutput >= (time_t) settings.maxSilentTime)
4388 { 4383 {
4389 printMsg(lvlError, 4384 printMsg(lvlError,
4390 format("%1% timed out after %2% seconds of silence") 4385 std::format("{} timed out after {} seconds of silence",
4391 % goal->getName() % settings.maxSilentTime); 4386 goal->getName(), settings.maxSilentTime));
4392 goal->timedOut(); 4387 goal->timedOut();
4393 } 4388 }
4394 4389
@@ -4398,8 +4393,8 @@ void Worker::waitForInput()
4398 after - j->second.timeStarted >= (time_t) settings.buildTimeout) 4393 after - j->second.timeStarted >= (time_t) settings.buildTimeout)
4399 { 4394 {
4400 printMsg(lvlError, 4395 printMsg(lvlError,
4401 format("%1% timed out after %2% seconds") 4396 std::format("{} timed out after %2% seconds",
4402 % goal->getName() % settings.buildTimeout); 4397 goal->getName(), settings.buildTimeout));
4403 goal->timedOut(); 4398 goal->timedOut();
4404 } 4399 }
4405 } 4400 }
@@ -4427,7 +4422,7 @@ unsigned int Worker::exitStatus()
4427void LocalStore::buildPaths(const PathSet & drvPaths, BuildMode buildMode) 4422void LocalStore::buildPaths(const PathSet & drvPaths, BuildMode buildMode)
4428{ 4423{
4429 startNest(nest, lvlDebug, 4424 startNest(nest, lvlDebug,
4430 format("building %1%") % showPaths(drvPaths)); 4425 std::format("building {}", showPaths(drvPaths)));
4431 4426
4432 Worker worker(*this); 4427 Worker worker(*this);
4433 4428
@@ -4451,7 +4446,7 @@ void LocalStore::buildPaths(const PathSet & drvPaths, BuildMode buildMode)
4451 } 4446 }
4452 4447
4453 if (!failed.empty()) 4448 if (!failed.empty())
4454 throw Error(format("build of %1% failed") % showPaths(failed), worker.exitStatus()); 4449 throw Error(std::format("build of {} failed", showPaths(failed)), worker.exitStatus());
4455} 4450}
4456 4451
4457 4452
@@ -4467,7 +4462,7 @@ void LocalStore::ensurePath(const Path & path)
4467 worker.run(goals); 4462 worker.run(goals);
4468 4463
4469 if (goal->getExitCode() != Goal::ecSuccess) 4464 if (goal->getExitCode() != Goal::ecSuccess)
4470 throw Error(format("path `%1%' does not exist and cannot be created") % path, worker.exitStatus()); 4465 throw Error(std::format("path `{}' does not exist and cannot be created", path), worker.exitStatus());
4471} 4466}
4472 4467
4473 4468
@@ -4488,7 +4483,7 @@ void LocalStore::repairPath(const Path & path)
4488 goals.insert(worker.makeDerivationGoal(deriver, StringSet(), bmRepair)); 4483 goals.insert(worker.makeDerivationGoal(deriver, StringSet(), bmRepair));
4489 worker.run(goals); 4484 worker.run(goals);
4490 } else 4485 } else
4491 throw Error(format("cannot repair path `%1%'") % path, worker.exitStatus()); 4486 throw Error(std::format("cannot repair path `{}'", path), worker.exitStatus());
4492 } 4487 }
4493} 4488}
4494 4489