summaryrefslogtreecommitdiff
path: root/nix/libstore
diff options
context:
space:
mode:
Diffstat (limited to 'nix/libstore')
-rw-r--r--nix/libstore/build.cc433
-rw-r--r--nix/libstore/builtins.cc3
-rw-r--r--nix/libstore/builtins.hh1
-rw-r--r--nix/libstore/derivations.cc9
-rw-r--r--nix/libstore/gc.cc139
-rw-r--r--nix/libstore/globals.cc8
-rw-r--r--nix/libstore/local-store.cc162
-rw-r--r--nix/libstore/misc.cc17
-rw-r--r--nix/libstore/optimise-store.cc61
-rw-r--r--nix/libstore/pathlocks.cc20
-rw-r--r--nix/libstore/references.cc8
-rw-r--r--nix/libstore/sqlite.cc9
-rw-r--r--nix/libstore/sqlite.hh3
-rw-r--r--nix/libstore/store-api.cc15
14 files changed, 444 insertions, 444 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
diff --git a/nix/libstore/builtins.cc b/nix/libstore/builtins.cc
index 6bf467354a5..b1a32480b55 100644
--- a/nix/libstore/builtins.cc
+++ b/nix/libstore/builtins.cc
@@ -22,6 +22,7 @@
22 22
23#include <unistd.h> 23#include <unistd.h>
24#include <cstdlib> 24#include <cstdlib>
25#include <format>
25 26
26namespace nix { 27namespace nix {
27 28
@@ -53,7 +54,7 @@ static void builtinDownload(const Derivation &drv,
53 const string program = settings.guixProgram; 54 const string program = settings.guixProgram;
54 execv(program.c_str(), (char *const *) argv); 55 execv(program.c_str(), (char *const *) argv);
55 56
56 throw SysError(format("failed to run download program '%1%'") % program); 57 throw SysError(std::format("failed to run download program '{}'", program));
57} 58}
58 59
59static const std::map<std::string, derivationBuilder> builtins = 60static const std::map<std::string, derivationBuilder> builtins =
diff --git a/nix/libstore/builtins.hh b/nix/libstore/builtins.hh
index 396ea14ebc0..602a5a1c58d 100644
--- a/nix/libstore/builtins.hh
+++ b/nix/libstore/builtins.hh
@@ -21,7 +21,6 @@
21#pragma once 21#pragma once
22 22
23#include <derivations.hh> 23#include <derivations.hh>
24#include <map>
25#include <string> 24#include <string>
26 25
27namespace nix { 26namespace nix {
diff --git a/nix/libstore/derivations.cc b/nix/libstore/derivations.cc
index 0c3a249228d..c253a2a438a 100644
--- a/nix/libstore/derivations.cc
+++ b/nix/libstore/derivations.cc
@@ -4,6 +4,9 @@
4#include "util.hh" 4#include "util.hh"
5#include "misc.hh" 5#include "misc.hh"
6 6
7#include <format>
8
9#include <cassert>
7 10
8namespace nix { 11namespace nix {
9 12
@@ -20,7 +23,7 @@ void DerivationOutput::parseHashInfo(bool & recursive, HashType & hashType, Hash
20 23
21 hashType = parseHashType(algo); 24 hashType = parseHashType(algo);
22 if (hashType == htUnknown) 25 if (hashType == htUnknown)
23 throw Error(format("unknown hash algorithm `%1%'") % algo); 26 throw Error(std::format("unknown hash algorithm `{}'", algo));
24 27
25 hash = parseHash(hashType, this->hash); 28 hash = parseHash(hashType, this->hash);
26} 29}
@@ -48,7 +51,7 @@ static Path parsePath(std::istream & str)
48{ 51{
49 string s = parseString(str); 52 string s = parseString(str);
50 if (s.size() == 0 || s[0] != '/') 53 if (s.size() == 0 || s[0] != '/')
51 throw FormatError(format("bad path `%1%' in derivation") % s); 54 throw FormatError(std::format("bad path `{}' in derivation", s));
52 return s; 55 return s;
53} 56}
54 57
@@ -117,7 +120,7 @@ Derivation readDerivation(const Path & drvPath)
117 try { 120 try {
118 return parseDerivation(readFile(drvPath)); 121 return parseDerivation(readFile(drvPath));
119 } catch (FormatError & e) { 122 } catch (FormatError & e) {
120 throw Error(format("error parsing derivation `%1%': %2%") % drvPath % e.msg()); 123 throw Error(std::format("error parsing derivation `{}': {}", drvPath, e.msg()));
121 } 124 }
122} 125}
123 126
diff --git a/nix/libstore/gc.cc b/nix/libstore/gc.cc
index 610270f907e..96440077fb5 100644
--- a/nix/libstore/gc.cc
+++ b/nix/libstore/gc.cc
@@ -6,6 +6,7 @@
6#include <queue> 6#include <queue>
7#include <random> 7#include <random>
8#include <algorithm> 8#include <algorithm>
9#include <format>
9 10
10#include <sys/types.h> 11#include <sys/types.h>
11#include <sys/stat.h> 12#include <sys/stat.h>
@@ -30,18 +31,17 @@ static string gcRootsDir = "gcroots";
30 yielded the GC lock. */ 31 yielded the GC lock. */
31int LocalStore::openGCLock(LockType lockType) 32int LocalStore::openGCLock(LockType lockType)
32{ 33{
33 Path fnGCLock = (format("%1%/%2%") 34 Path fnGCLock = std::format("{}/{}", settings.nixStateDir, gcLockName);
34 % settings.nixStateDir % gcLockName).str();
35 35
36 debug(format("acquiring global GC lock `%1%'") % fnGCLock); 36 debug(std::format("acquiring global GC lock `{}'", fnGCLock));
37 37
38 AutoCloseFD fdGCLock = open(fnGCLock.c_str(), O_RDWR | O_CREAT, 0600); 38 AutoCloseFD fdGCLock = open(fnGCLock.c_str(), O_RDWR | O_CREAT, 0600);
39 if (fdGCLock == -1) 39 if (fdGCLock == -1)
40 throw SysError(format("opening global GC lock `%1%'") % fnGCLock); 40 throw SysError(std::format("opening global GC lock `{}'", fnGCLock));
41 closeOnExec(fdGCLock); 41 closeOnExec(fdGCLock);
42 42
43 if (!lockFile(fdGCLock, lockType, false)) { 43 if (!lockFile(fdGCLock, lockType, false)) {
44 printMsg(lvlError, format("waiting for the big garbage collector lock...")); 44 printMsg(lvlError, "waiting for the big garbage collector lock...");
45 lockFile(fdGCLock, lockType, true); 45 lockFile(fdGCLock, lockType, true);
46 } 46 }
47 47
@@ -59,14 +59,12 @@ static void makeSymlink(const Path & link, const Path & target)
59 createDirs(dirOf(link)); 59 createDirs(dirOf(link));
60 60
61 /* Create the new symlink. */ 61 /* Create the new symlink. */
62 Path tempLink = (format("%1%.tmp-%2%-%3%") 62 Path tempLink = std::format("{}.tmp-{}-{}", link, getpid(), rand());
63 % link % getpid() % rand()).str();
64 createSymlink(target, tempLink); 63 createSymlink(target, tempLink);
65 64
66 /* Atomically replace the old one. */ 65 /* Atomically replace the old one. */
67 if (rename(tempLink.c_str(), link.c_str()) == -1) 66 if (rename(tempLink.c_str(), link.c_str()) == -1)
68 throw SysError(format("cannot rename `%1%' to `%2%'") 67 throw SysError(std::format("cannot rename `{}' to `{}'", tempLink, link));
69 % tempLink % link);
70} 68}
71 69
72 70
@@ -79,8 +77,8 @@ void LocalStore::syncWithGC()
79void LocalStore::addIndirectRoot(const Path & path) 77void LocalStore::addIndirectRoot(const Path & path)
80{ 78{
81 string hash = printHash32(hashString(htSHA1, path)); 79 string hash = printHash32(hashString(htSHA1, path));
82 Path realRoot = canonPath((format("%1%/%2%/auto/%3%") 80 Path realRoot = canonPath(std::format("{}/{}/auto/{}",
83 % settings.nixStateDir % gcRootsDir % hash).str()); 81 settings.nixStateDir, gcRootsDir, hash));
84 makeSymlink(realRoot, path); 82 makeSymlink(realRoot, path);
85} 83}
86 84
@@ -93,28 +91,28 @@ Path addPermRoot(StoreAPI & store, const Path & _storePath,
93 assertStorePath(storePath); 91 assertStorePath(storePath);
94 92
95 if (isInStore(gcRoot)) 93 if (isInStore(gcRoot))
96 throw Error(format( 94 throw Error(std::format(
97 "creating a garbage collector root (%1%) in the store is forbidden " 95 "creating a garbage collector root ({}) in the store is forbidden "
98 "(are you running nix-build inside the store?)") % gcRoot); 96 "(are you running nix-build inside the store?)", gcRoot));
99 97
100 if (indirect) { 98 if (indirect) {
101 /* Don't clobber the link if it already exists and doesn't 99 /* Don't clobber the link if it already exists and doesn't
102 point to the store. */ 100 point to the store. */
103 if (pathExists(gcRoot) && (!isLink(gcRoot) || !isInStore(readLink(gcRoot)))) 101 if (pathExists(gcRoot) && (!isLink(gcRoot) || !isInStore(readLink(gcRoot))))
104 throw Error(format("cannot create symlink `%1%'; already exists") % gcRoot); 102 throw Error(std::format("cannot create symlink `{}'; already exists", gcRoot));
105 makeSymlink(gcRoot, storePath); 103 makeSymlink(gcRoot, storePath);
106 store.addIndirectRoot(gcRoot); 104 store.addIndirectRoot(gcRoot);
107 } 105 }
108 106
109 else { 107 else {
110 if (!allowOutsideRootsDir) { 108 if (!allowOutsideRootsDir) {
111 Path rootsDir = canonPath((format("%1%/%2%") % settings.nixStateDir % gcRootsDir).str()); 109 Path rootsDir = canonPath(std::format("{}/{}", settings.nixStateDir, gcRootsDir));
112 110
113 if (string(gcRoot, 0, rootsDir.size() + 1) != rootsDir + "/") 111 if (string(gcRoot, 0, rootsDir.size() + 1) != rootsDir + "/")
114 throw Error(format( 112 throw Error(std::format(
115 "path `%1%' is not a valid garbage collector root; " 113 "path `{}' is not a valid garbage collector root; "
116 "it's not in the directory `%2%'") 114 "it's not in the directory `{}'",
117 % gcRoot % rootsDir); 115 gcRoot, rootsDir));
118 } 116 }
119 117
120 if (baseNameOf(gcRoot) == baseNameOf(storePath)) 118 if (baseNameOf(gcRoot) == baseNameOf(storePath))
@@ -132,10 +130,10 @@ Path addPermRoot(StoreAPI & store, const Path & _storePath,
132 Roots roots = store.findRoots(); 130 Roots roots = store.findRoots();
133 if (roots.find(gcRoot) == roots.end()) 131 if (roots.find(gcRoot) == roots.end())
134 printMsg(lvlError, 132 printMsg(lvlError,
135 format( 133 std::format(
136 "warning: `%1%' is not in a directory where the garbage collector looks for roots; " 134 "warning: `{}' is not in a directory where the garbage collector looks for roots; "
137 "therefore, `%2%' might be removed by the garbage collector") 135 "therefore, `{}' might be removed by the garbage collector",
138 % gcRoot % storePath); 136 gcRoot, storePath));
139 } 137 }
140 138
141 /* Grab the global GC root, causing us to block while a GC is in 139 /* Grab the global GC root, causing us to block while a GC is in
@@ -153,11 +151,10 @@ void LocalStore::addTempRoot(const Path & path)
153 if (fdTempRoots == -1) { 151 if (fdTempRoots == -1) {
154 152
155 while (1) { 153 while (1) {
156 Path dir = (format("%1%/%2%") % settings.nixStateDir % tempRootsDir).str(); 154 Path dir = std::format("{}/{}", settings.nixStateDir, tempRootsDir);
157 createDirs(dir); 155 createDirs(dir);
158 156
159 fnTempRoots = (format("%1%/%2%") 157 fnTempRoots = std::format("{}/{}", dir, getpid());
160 % dir % getpid()).str();
161 158
162 AutoCloseFD fdGCLock = openGCLock(ltRead); 159 AutoCloseFD fdGCLock = openGCLock(ltRead);
163 160
@@ -170,14 +167,14 @@ void LocalStore::addTempRoot(const Path & path)
170 167
171 fdGCLock.close(); 168 fdGCLock.close();
172 169
173 debug(format("acquiring read lock on `%1%'") % fnTempRoots); 170 debug(std::format("acquiring read lock on `{}'", fnTempRoots));
174 lockFile(fdTempRoots, ltRead, true); 171 lockFile(fdTempRoots, ltRead, true);
175 172
176 /* Check whether the garbage collector didn't get in our 173 /* Check whether the garbage collector didn't get in our
177 way. */ 174 way. */
178 struct stat st; 175 struct stat st;
179 if (fstat(fdTempRoots, &st) == -1) 176 if (fstat(fdTempRoots, &st) == -1)
180 throw SysError(format("statting `%1%'") % fnTempRoots); 177 throw SysError(std::format("statting `{}'", fnTempRoots));
181 if (st.st_size == 0) break; 178 if (st.st_size == 0) break;
182 179
183 /* The garbage collector deleted this file before we could 180 /* The garbage collector deleted this file before we could
@@ -189,14 +186,14 @@ void LocalStore::addTempRoot(const Path & path)
189 186
190 /* Upgrade the lock to a write lock. This will cause us to block 187 /* Upgrade the lock to a write lock. This will cause us to block
191 if the garbage collector is holding our lock. */ 188 if the garbage collector is holding our lock. */
192 debug(format("acquiring write lock on `%1%'") % fnTempRoots); 189 debug(std::format("acquiring write lock on `{}'", fnTempRoots));
193 lockFile(fdTempRoots, ltWrite, true); 190 lockFile(fdTempRoots, ltWrite, true);
194 191
195 string s = path + '\0'; 192 string s = path + '\0';
196 writeFull(fdTempRoots, s); 193 writeFull(fdTempRoots, s);
197 194
198 /* Downgrade to a read lock. */ 195 /* Downgrade to a read lock. */
199 debug(format("downgrading to read lock on `%1%'") % fnTempRoots); 196 debug(std::format("downgrading to read lock on `{}'", fnTempRoots));
200 lockFile(fdTempRoots, ltRead, true); 197 lockFile(fdTempRoots, ltRead, true);
201} 198}
202 199
@@ -210,17 +207,17 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds)
210 /* Read the `temproots' directory for per-process temporary root 207 /* Read the `temproots' directory for per-process temporary root
211 files. */ 208 files. */
212 DirEntries tempRootFiles = readDirectory( 209 DirEntries tempRootFiles = readDirectory(
213 (format("%1%/%2%") % settings.nixStateDir % tempRootsDir).str()); 210 std::format("{}/{}", settings.nixStateDir, tempRootsDir));
214 211
215 for (auto & i : tempRootFiles) { 212 for (auto & i : tempRootFiles) {
216 Path path = (format("%1%/%2%/%3%") % settings.nixStateDir % tempRootsDir % i.name).str(); 213 Path path = std::format("{}/{}/{}", settings.nixStateDir, tempRootsDir, i.name);
217 214
218 debug(format("reading temporary root file `%1%'") % path); 215 debug(std::format("reading temporary root file `{}'", path));
219 FDPtr fd(new AutoCloseFD(open(path.c_str(), O_RDWR, 0666))); 216 FDPtr fd(new AutoCloseFD(open(path.c_str(), O_RDWR, 0666)));
220 if (*fd == -1) { 217 if (*fd == -1) {
221 /* It's okay if the file has disappeared. */ 218 /* It's okay if the file has disappeared. */
222 if (errno == ENOENT) continue; 219 if (errno == ENOENT) continue;
223 throw SysError(format("opening temporary roots file `%1%'") % path); 220 throw SysError(std::format("opening temporary roots file `{}'", path));
224 } 221 }
225 222
226 /* This should work, but doesn't, for some reason. */ 223 /* This should work, but doesn't, for some reason. */
@@ -231,7 +228,7 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds)
231 only succeed if the owning process has died. In that case 228 only succeed if the owning process has died. In that case
232 we don't care about its temporary roots. */ 229 we don't care about its temporary roots. */
233 if (lockFile(*fd, ltWrite, false)) { 230 if (lockFile(*fd, ltWrite, false)) {
234 printMsg(lvlError, format("removing stale temporary roots file `%1%'") % path); 231 printMsg(lvlError, std::format("removing stale temporary roots file `{}'", path));
235 unlink(path.c_str()); 232 unlink(path.c_str());
236 writeFull(*fd, "d"); 233 writeFull(*fd, "d");
237 continue; 234 continue;
@@ -240,7 +237,7 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds)
240 /* Acquire a read lock. This will prevent the owning process 237 /* Acquire a read lock. This will prevent the owning process
241 from upgrading to a write lock, therefore it will block in 238 from upgrading to a write lock, therefore it will block in
242 addTempRoot(). */ 239 addTempRoot(). */
243 debug(format("waiting for read lock on `%1%'") % path); 240 debug(std::format("waiting for read lock on `{}'", path));
244 lockFile(*fd, ltRead, true); 241 lockFile(*fd, ltRead, true);
245 242
246 /* Read the entire file. */ 243 /* Read the entire file. */
@@ -251,7 +248,7 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds)
251 248
252 while ((end = contents.find((char) 0, pos)) != string::npos) { 249 while ((end = contents.find((char) 0, pos)) != string::npos) {
253 Path root(contents, pos, end - pos); 250 Path root(contents, pos, end - pos);
254 debug(format("got temporary root `%1%'") % root); 251 debug(std::format("got temporary root `{}'", root));
255 assertStorePath(root); 252 assertStorePath(root);
256 tempRoots.insert(root); 253 tempRoots.insert(root);
257 pos = end + 1; 254 pos = end + 1;
@@ -269,7 +266,7 @@ static void foundRoot(StoreAPI & store,
269 if (store.isValidPath(storePath)) 266 if (store.isValidPath(storePath))
270 roots[path] = storePath; 267 roots[path] = storePath;
271 else 268 else
272 printMsg(lvlInfo, format("skipping invalid root from `%1%' to `%2%'") % path % storePath); 269 printMsg(lvlInfo, std::format("skipping invalid root from `{}' to `{}'", path, storePath));
273} 270}
274 271
275 272
@@ -295,7 +292,7 @@ static void findRoots(StoreAPI & store, const Path & path, unsigned char type, R
295 target = absPath(target, dirOf(path)); 292 target = absPath(target, dirOf(path));
296 if (!pathExists(target)) { 293 if (!pathExists(target)) {
297 if (isInDir(path, settings.nixStateDir + "/" + gcRootsDir + "/auto")) { 294 if (isInDir(path, settings.nixStateDir + "/" + gcRootsDir + "/auto")) {
298 printMsg(lvlInfo, format("removing stale link from `%1%' to `%2%'") % path % target); 295 printMsg(lvlInfo, std::format("removing stale link from `{}' to `{}'", path, target));
299 unlink(path.c_str()); 296 unlink(path.c_str());
300 } 297 }
301 } else { 298 } else {
@@ -318,8 +315,8 @@ static void findRoots(StoreAPI & store, const Path & path, unsigned char type, R
318 catch (SysError & e) { 315 catch (SysError & e) {
319 /* We only ignore permanent failures. */ 316 /* We only ignore permanent failures. */
320 if (e.errNo == EACCES || e.errNo == ENOENT || e.errNo == ENOTDIR) 317 if (e.errNo == EACCES || e.errNo == ENOENT || e.errNo == ENOTDIR)
321 printMsg(lvlInfo, format("cannot read potential root '%1%': %2%") 318 printMsg(lvlInfo, std::format("cannot read potential root '{}': {}",
322 % path % strerror(e.errNo)); 319 path, strerror(e.errNo)));
323 else 320 else
324 throw; 321 throw;
325 } 322 }
@@ -342,8 +339,8 @@ Roots LocalStore::findRoots()
342 339
343static void addAdditionalRoots(StoreAPI & store, PathSet & roots) 340static void addAdditionalRoots(StoreAPI & store, PathSet & roots)
344{ 341{
345 debug(format("executing `%1% gc --list-busy' to find additional roots") 342 debug(std::format("executing `{} gc --list-busy' to find additional roots",
346 % settings.guixProgram); 343 settings.guixProgram));
347 344
348 const Strings args = { "gc", "--list-busy" }; 345 const Strings args = { "gc", "--list-busy" };
349 string result = runProgram(settings.guixProgram, false, args); 346 string result = runProgram(settings.guixProgram, false, args);
@@ -354,7 +351,7 @@ static void addAdditionalRoots(StoreAPI & store, PathSet & roots)
354 if (isInStore(i)) { 351 if (isInStore(i)) {
355 Path path = toStorePath(i); 352 Path path = toStorePath(i);
356 if (roots.find(path) == roots.end() && store.isValidPath(path)) { 353 if (roots.find(path) == roots.end() && store.isValidPath(path)) {
357 debug(format("got additional root `%1%'") % path); 354 debug(std::format("got additional root `{}'", path));
358 roots.insert(path); 355 roots.insert(path);
359 } 356 }
360 } 357 }
@@ -424,17 +421,17 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path)
424 struct stat st; 421 struct stat st;
425 if (lstat(path.c_str(), &st)) { 422 if (lstat(path.c_str(), &st)) {
426 if (errno == ENOENT) return; 423 if (errno == ENOENT) return;
427 throw SysError(format("getting status of %1%") % path); 424 throw SysError(std::format("getting status of {}", path));
428 } 425 }
429 426
430 if (state.options.maxFreed != ULLONG_MAX) { 427 if (state.options.maxFreed != ULLONG_MAX) {
431 auto freed = state.results.bytesFreed + state.bytesInvalidated; 428 auto freed = state.results.bytesFreed + state.bytesInvalidated;
432 double fraction = ((double) freed) / (double) state.options.maxFreed; 429 double fraction = ((double) freed) / (double) state.options.maxFreed;
433 unsigned int percentage = (fraction > 1. ? 1. : fraction) * 100.; 430 unsigned int percentage = (fraction > 1. ? 1. : fraction) * 100.;
434 printMsg(lvlInfo, format("[%1%%%] deleting '%2%'") % percentage % path); 431 printMsg(lvlInfo, std::format("[{}%] deleting '{}'", percentage, path));
435 } else { 432 } else {
436 auto freed = state.results.bytesFreed + state.bytesInvalidated; 433 auto freed = state.results.bytesFreed + state.bytesInvalidated;
437 printMsg(lvlInfo, format("[%1%] deleting '%2%'") % showBytes(freed) % path); 434 printMsg(lvlInfo, std::format("[{}] deleting '{}'", showBytes(freed), path));
438 } 435 }
439 436
440 state.results.paths.insert(path); 437 state.results.paths.insert(path);
@@ -450,17 +447,17 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path)
450 // size. 447 // size.
451 try { 448 try {
452 if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1) 449 if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1)
453 throw SysError(format("making `%1%' writable") % path); 450 throw SysError(std::format("making `{}' writable", path));
454 Path tmp = state.trashDir + "/" + baseNameOf(path); 451 Path tmp = state.trashDir + "/" + baseNameOf(path);
455 if (rename(path.c_str(), tmp.c_str())) 452 if (rename(path.c_str(), tmp.c_str()))
456 throw SysError(format("unable to rename `%1%' to `%2%'") % path % tmp); 453 throw SysError(std::format("unable to rename `{}' to `{}'", path, tmp));
457 state.bytesInvalidated += size; 454 state.bytesInvalidated += size;
458 } catch (SysError & e) { 455 } catch (SysError & e) {
459 /* In a Docker container, rename(2) returns EXDEV when the source 456 /* In a Docker container, rename(2) returns EXDEV when the source
460 and destination are not both on the "top layer". See: 457 and destination are not both on the "top layer". See:
461 https://bugs.gnu.org/41607 */ 458 https://bugs.gnu.org/41607 */
462 if (e.errNo == ENOSPC || e.errNo == EXDEV) { 459 if (e.errNo == ENOSPC || e.errNo == EXDEV) {
463 printMsg(lvlInfo, format("note: can't create move `%1%': %2%") % path % e.msg()); 460 printMsg(lvlInfo, std::format("note: can't create move `{}': {}", path, e.msg()));
464 deleteGarbage(state, path); 461 deleteGarbage(state, path);
465 } 462 }
466 } 463 }
@@ -468,7 +465,7 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path)
468 deleteGarbage(state, path); 465 deleteGarbage(state, path);
469 466
470 if (state.results.bytesFreed + state.bytesInvalidated > state.options.maxFreed) { 467 if (state.results.bytesFreed + state.bytesInvalidated > state.options.maxFreed) {
471 printMsg(lvlInfo, format("deleted or invalidated more than %1% bytes; stopping") % state.options.maxFreed); 468 printMsg(lvlInfo, std::format("deleted or invalidated more than {} bytes; stopping", state.options.maxFreed));
472 throw GCLimitReached(); 469 throw GCLimitReached();
473 } 470 }
474} 471}
@@ -487,7 +484,7 @@ bool LocalStore::canReachRoot(GCState & state, PathSet & visited, const Path & p
487 } 484 }
488 485
489 if (state.roots.find(path) != state.roots.end()) { 486 if (state.roots.find(path) != state.roots.end()) {
490 printMsg(lvlDebug, format("cannot delete `%1%' because it's a root") % path); 487 printMsg(lvlDebug, std::format("cannot delete `{}' because it's a root", path));
491 state.alive.insert(path); 488 state.alive.insert(path);
492 return true; 489 return true;
493 } 490 }
@@ -535,7 +532,7 @@ void LocalStore::tryToDelete(GCState & state, const Path & path)
535 532
536 if (path == linksDir || path == state.trashDir) return; 533 if (path == linksDir || path == state.trashDir) return;
537 534
538 startNest(nest, lvlDebug, format("considering whether to delete `%1%'") % path); 535 startNest(nest, lvlDebug, std::format("considering whether to delete `{}'", path));
539 536
540 if (!isValidPath(path)) { 537 if (!isValidPath(path)) {
541 /* A lock file belonging to a path that we're building right 538 /* A lock file belonging to a path that we're building right
@@ -550,7 +547,7 @@ void LocalStore::tryToDelete(GCState & state, const Path & path)
550 PathSet visited; 547 PathSet visited;
551 548
552 if (canReachRoot(state, visited, path)) { 549 if (canReachRoot(state, visited, path)) {
553 printMsg(lvlDebug, format("cannot delete `%1%' because it's still reachable") % path); 550 printMsg(lvlDebug, std::format("cannot delete `{}' because it's still reachable", path));
554 } else { 551 } else {
555 /* No path we visited was a root, so everything is garbage. 552 /* No path we visited was a root, so everything is garbage.
556 But we only delete ‘path’ and its referrers here so that 553 But we only delete ‘path’ and its referrers here so that
@@ -571,7 +568,7 @@ void LocalStore::tryToDelete(GCState & state, const Path & path)
571void LocalStore::removeUnusedLinks(const GCState & state) 568void LocalStore::removeUnusedLinks(const GCState & state)
572{ 569{
573 AutoCloseDir dir = opendir(linksDir.c_str()); 570 AutoCloseDir dir = opendir(linksDir.c_str());
574 if (!dir) throw SysError(format("opening directory `%1%'") % linksDir); 571 if (!dir) throw SysError(std::format("opening directory `{}'", linksDir));
575 572
576 long long actualSize = 0, unsharedSize = 0; 573 long long actualSize = 0, unsharedSize = 0;
577 574
@@ -596,15 +593,15 @@ void LocalStore::removeUnusedLinks(const GCState & state)
596 statx_flags &= ~AT_STATX_DONT_SYNC; 593 statx_flags &= ~AT_STATX_DONT_SYNC;
597 if (statx(AT_FDCWD, path.c_str(), statx_flags, 594 if (statx(AT_FDCWD, path.c_str(), statx_flags,
598 STATX_SIZE | STATX_NLINK, &st) == -1) 595 STATX_SIZE | STATX_NLINK, &st) == -1)
599 throw SysError(format("statting `%1%'") % path); 596 throw SysError(std::format("statting `{}'", path));
600 } else { 597 } else {
601 throw SysError(format("statting `%1%'") % path); 598 throw SysError(std::format("statting `{}'", path));
602 } 599 }
603 } 600 }
604#else 601#else
605 struct stat st; 602 struct stat st;
606 if (lstat(path.c_str(), &st) == -1) 603 if (lstat(path.c_str(), &st) == -1)
607 throw SysError(format("statting `%1%'") % path); 604 throw SysError(std::format("statting `{}'", path));
608#endif 605#endif
609 606
610 /* Drop links for files smaller than 'deduplicationMinSize', even if 607 /* Drop links for files smaller than 'deduplicationMinSize', even if
@@ -616,10 +613,10 @@ void LocalStore::removeUnusedLinks(const GCState & state)
616 continue; 613 continue;
617 } 614 }
618 615
619 printMsg(lvlTalkative, format("deleting unused link `%1%'") % path); 616 printMsg(lvlTalkative, std::format("deleting unused link `{}'", path));
620 617
621 if (unlink(path.c_str()) == -1) 618 if (unlink(path.c_str()) == -1)
622 throw SysError(format("deleting `%1%'") % path); 619 throw SysError(std::format("deleting `{}'", path));
623 620
624 state.results.bytesFreed += st.st_size; 621 state.results.bytesFreed += st.st_size;
625#undef st_size 622#undef st_size
@@ -628,11 +625,11 @@ void LocalStore::removeUnusedLinks(const GCState & state)
628 625
629 struct stat st; 626 struct stat st;
630 if (stat(linksDir.c_str(), &st) == -1) 627 if (stat(linksDir.c_str(), &st) == -1)
631 throw SysError(format("statting `%1%'") % linksDir); 628 throw SysError(std::format("statting `{}'", linksDir));
632 long long overhead = st.st_size; 629 long long overhead = st.st_size;
633 long long freedbytes = (unsharedSize - actualSize - overhead); 630 long long freedbytes = (unsharedSize - actualSize - overhead);
634 631
635 printMsg(lvlInfo, format("note: currently hard linking saves %1%") % showBytes(freedbytes)); 632 printMsg(lvlInfo, std::format("note: currently hard linking saves {}", showBytes(freedbytes)));
636} 633}
637 634
638 635
@@ -662,7 +659,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
662 659
663 /* Find the roots. Since we've grabbed the GC lock, the set of 660 /* Find the roots. Since we've grabbed the GC lock, the set of
664 permanent roots cannot increase now. */ 661 permanent roots cannot increase now. */
665 printMsg(lvlError, format("finding garbage collector roots...")); 662 printMsg(lvlError, "finding garbage collector roots...");
666 Roots rootMap = options.ignoreLiveness ? Roots() : findRoots(); 663 Roots rootMap = options.ignoreLiveness ? Roots() : findRoots();
667 664
668 for (auto& i : rootMap) state.roots.insert(i.second); 665 for (auto& i : rootMap) state.roots.insert(i.second);
@@ -690,7 +687,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
690 createDirs(state.trashDir); 687 createDirs(state.trashDir);
691 } catch (SysError & e) { 688 } catch (SysError & e) {
692 if (e.errNo == ENOSPC) { 689 if (e.errNo == ENOSPC) {
693 printMsg(lvlInfo, format("note: can't create trash directory: %1%") % e.msg()); 690 printMsg(lvlInfo, std::format("note: can't create trash directory: {}", e.msg()));
694 state.moveToTrash = false; 691 state.moveToTrash = false;
695 } 692 }
696 } 693 }
@@ -705,20 +702,20 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
705 assertStorePath(i); 702 assertStorePath(i);
706 tryToDelete(state, i); 703 tryToDelete(state, i);
707 if (state.dead.find(i) == state.dead.end()) 704 if (state.dead.find(i) == state.dead.end())
708 throw Error(format("cannot delete path `%1%' since it is still alive") % i); 705 throw Error(std::format("cannot delete path `{}' since it is still alive", i));
709 } 706 }
710 707
711 } else if (options.maxFreed > 0) { 708 } else if (options.maxFreed > 0) {
712 709
713 if (state.shouldDelete) 710 if (state.shouldDelete)
714 printMsg(lvlError, format("deleting garbage...")); 711 printMsg(lvlError, "deleting garbage...");
715 else 712 else
716 printMsg(lvlError, format("determining live/dead paths...")); 713 printMsg(lvlError, "determining live/dead paths...");
717 714
718 try { 715 try {
719 716
720 AutoCloseDir dir = opendir(settings.nixStore.c_str()); 717 AutoCloseDir dir = opendir(settings.nixStore.c_str());
721 if (!dir) throw SysError(format("opening directory `%1%'") % settings.nixStore); 718 if (!dir) throw SysError(std::format("opening directory `{}'", settings.nixStore));
722 719
723 /* Read the store and immediately delete all paths that 720 /* Read the store and immediately delete all paths that
724 aren't valid. When using --max-freed etc., deleting 721 aren't valid. When using --max-freed etc., deleting
@@ -773,12 +770,12 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
773 fds.clear(); 770 fds.clear();
774 771
775 /* Delete the trash directory. */ 772 /* Delete the trash directory. */
776 printMsg(lvlInfo, format("deleting `%1%'") % state.trashDir); 773 printMsg(lvlInfo, std::format("deleting `{}'", state.trashDir));
777 deleteGarbage(state, state.trashDir); 774 deleteGarbage(state, state.trashDir);
778 775
779 /* Clean up the links directory. */ 776 /* Clean up the links directory. */
780 if (options.action == GCOptions::gcDeleteDead || options.action == GCOptions::gcDeleteSpecific) { 777 if (options.action == GCOptions::gcDeleteDead || options.action == GCOptions::gcDeleteSpecific) {
781 printMsg(lvlError, format("deleting unused links...")); 778 printMsg(lvlError, "deleting unused links...");
782 removeUnusedLinks(state); 779 removeUnusedLinks(state);
783 } 780 }
784 781
diff --git a/nix/libstore/globals.cc b/nix/libstore/globals.cc
index 31da8d4769d..16f43f6abcb 100644
--- a/nix/libstore/globals.cc
+++ b/nix/libstore/globals.cc
@@ -6,7 +6,7 @@
6 6
7#include <map> 7#include <map>
8#include <algorithm> 8#include <algorithm>
9 9#include <format>
10 10
11namespace nix { 11namespace nix {
12 12
@@ -156,8 +156,8 @@ void Settings::_get(bool & res, const string & name)
156 if (i == settings.end()) return; 156 if (i == settings.end()) return;
157 if (i->second == "true") res = true; 157 if (i->second == "true") res = true;
158 else if (i->second == "false") res = false; 158 else if (i->second == "false") res = false;
159 else throw Error(format("configuration option `%1%' should be either `true' or `false', not `%2%'") 159 else throw Error(std::format("configuration option `{}' should be either `true' or `false', not `{}'",
160 % name % i->second); 160 name, i->second));
161} 161}
162 162
163 163
@@ -183,7 +183,7 @@ template<class N> void Settings::_get(N & res, const string & name)
183 SettingsMap::iterator i = settings.find(name); 183 SettingsMap::iterator i = settings.find(name);
184 if (i == settings.end()) return; 184 if (i == settings.end()) return;
185 if (!string2Int(i->second, res)) 185 if (!string2Int(i->second, res))
186 throw Error(format("configuration setting `%1%' should have an integer value") % name); 186 throw Error(std::format("configuration setting `{}' should have an integer value", name));
187} 187}
188 188
189 189
diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc
index 50ef707fdf3..f11f48bcf07 100644
--- a/nix/libstore/local-store.cc
+++ b/nix/libstore/local-store.cc
@@ -9,7 +9,9 @@
9 9
10#include <iostream> 10#include <iostream>
11#include <algorithm> 11#include <algorithm>
12#include <format>
12#include <cstring> 13#include <cstring>
14#include <cassert>
13 15
14#include <sys/types.h> 16#include <sys/types.h>
15#include <sys/stat.h> 17#include <sys/stat.h>
@@ -45,12 +47,12 @@ void checkStoreNotSymlink()
45 struct stat st; 47 struct stat st;
46 while (path != "/") { 48 while (path != "/") {
47 if (lstat(path.c_str(), &st)) 49 if (lstat(path.c_str(), &st))
48 throw SysError(format("getting status of `%1%'") % path); 50 throw SysError(std::format("getting status of `{}'", path));
49 if (S_ISLNK(st.st_mode)) 51 if (S_ISLNK(st.st_mode))
50 throw Error(format( 52 throw Error(std::format(
51 "the path `%1%' is a symlink; " 53 "the path `{}' is a symlink; "
52 "this is not allowed for the store and its parent directories") 54 "this is not allowed for the store and its parent directories",
53 % path); 55 path));
54 path = dirOf(path); 56 path = dirOf(path);
55 } 57 }
56} 58}
@@ -86,25 +88,24 @@ LocalStore::LocalStore(bool reserveSpace)
86 if (getuid() == 0 && settings.buildUsersGroup != "") { 88 if (getuid() == 0 && settings.buildUsersGroup != "") {
87 89
88 if (chmod(perUserDir.c_str(), 0755) == -1) 90 if (chmod(perUserDir.c_str(), 0755) == -1)
89 throw SysError(format("could not set permissions on '%1%' to 755") 91 throw SysError(std::format("could not set permissions on '{}' to 755", perUserDir));
90 % perUserDir);
91 92
92 mode_t perm = 01775; 93 mode_t perm = 01775;
93 94
94 struct group * gr = getgrnam(settings.buildUsersGroup.c_str()); 95 struct group * gr = getgrnam(settings.buildUsersGroup.c_str());
95 if (!gr) 96 if (!gr)
96 throw Error(format("the group `%1%' specified in `build-users-group' does not exist") 97 throw Error(std::format("the group `{}' specified in `build-users-group' does not exist",
97 % settings.buildUsersGroup); 98 settings.buildUsersGroup));
98 else { 99 else {
99 struct stat st; 100 struct stat st;
100 if (stat(settings.nixStore.c_str(), &st)) 101 if (stat(settings.nixStore.c_str(), &st))
101 throw SysError(format("getting attributes of path '%1%'") % settings.nixStore); 102 throw SysError(std::format("getting attributes of path '{}'", settings.nixStore));
102 103
103 if (st.st_uid != 0 || st.st_gid != gr->gr_gid || (st.st_mode & ~S_IFMT) != perm) { 104 if (st.st_uid != 0 || st.st_gid != gr->gr_gid || (st.st_mode & ~S_IFMT) != perm) {
104 if (chown(settings.nixStore.c_str(), 0, gr->gr_gid) == -1) 105 if (chown(settings.nixStore.c_str(), 0, gr->gr_gid) == -1)
105 throw SysError(format("changing ownership of path '%1%'") % settings.nixStore); 106 throw SysError(std::format("changing ownership of path '{}'", settings.nixStore));
106 if (chmod(settings.nixStore.c_str(), perm) == -1) 107 if (chmod(settings.nixStore.c_str(), perm) == -1)
107 throw SysError(format("changing permissions on path '%1%'") % settings.nixStore); 108 throw SysError(std::format("changing permissions on path '{}'", settings.nixStore));
108 } 109 }
109 } 110 }
110 } 111 }
@@ -159,20 +160,20 @@ LocalStore::LocalStore(bool reserveSpace)
159 upgrade. */ 160 upgrade. */
160 int curSchema = getSchema(); 161 int curSchema = getSchema();
161 if (curSchema > nixSchemaVersion) 162 if (curSchema > nixSchemaVersion)
162 throw Error(format("current store schema is version %1%, but I only support %2%") 163 throw Error(std::format("current store schema is version {}, but I only support {}",
163 % curSchema % nixSchemaVersion); 164 curSchema, nixSchemaVersion));
164 165
165 else if (curSchema == 0) { /* new store */ 166 else if (curSchema == 0) { /* new store */
166 curSchema = nixSchemaVersion; 167 curSchema = nixSchemaVersion;
167 openDB(true); 168 openDB(true);
168 writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str()); 169 writeFile(schemaPath, std::format("{}", nixSchemaVersion));
169 } 170 }
170 171
171 else if (curSchema < nixSchemaVersion) { 172 else if (curSchema < nixSchemaVersion) {
172 /* Guix always used version 7 of the schema. */ 173 /* Guix always used version 7 of the schema. */
173 throw Error( 174 throw Error(
174 format("Your store database uses an implausibly old schema, version %1%.") 175 std::format("Your store database uses an implausibly old schema, version {}.",
175 % curSchema); 176 curSchema));
176 } 177 }
177 178
178 else openDB(false); 179 else openDB(false);
@@ -198,7 +199,7 @@ int LocalStore::getSchema()
198 if (pathExists(schemaPath)) { 199 if (pathExists(schemaPath)) {
199 string s = readFile(schemaPath); 200 string s = readFile(schemaPath);
200 if (!string2Int(s, curSchema)) 201 if (!string2Int(s, curSchema))
201 throw Error(format("`%1%' is corrupt") % schemaPath); 202 throw Error(std::format("`{}' is corrupt", schemaPath));
202 } 203 }
203 return curSchema; 204 return curSchema;
204} 205}
@@ -207,13 +208,13 @@ int LocalStore::getSchema()
207void LocalStore::openDB(bool create) 208void LocalStore::openDB(bool create)
208{ 209{
209 if (access(settings.nixDBPath.c_str(), R_OK | W_OK)) 210 if (access(settings.nixDBPath.c_str(), R_OK | W_OK))
210 throw SysError(format("store database directory `%1%' is not writable") % settings.nixDBPath); 211 throw SysError(std::format("store database directory `{}' is not writable", settings.nixDBPath));
211 212
212 /* Open the store database. */ 213 /* Open the store database. */
213 string dbPath = settings.nixDBPath + "/db.sqlite"; 214 string dbPath = settings.nixDBPath + "/db.sqlite";
214 if (sqlite3_open_v2(dbPath.c_str(), &db.db, 215 if (sqlite3_open_v2(dbPath.c_str(), &db.db,
215 SQLITE_OPEN_READWRITE | (create ? SQLITE_OPEN_CREATE : 0), 0) != SQLITE_OK) 216 SQLITE_OPEN_READWRITE | (create ? SQLITE_OPEN_CREATE : 0), 0) != SQLITE_OK)
216 throw Error(format("cannot open store database `%1%'") % dbPath); 217 throw Error(std::format("cannot open store database `{}'", dbPath));
217 218
218 if (sqlite3_busy_timeout(db, 60 * 60 * 1000) != SQLITE_OK) 219 if (sqlite3_busy_timeout(db, 60 * 60 * 1000) != SQLITE_OK)
219 throwSQLiteError(db, "setting timeout"); 220 throwSQLiteError(db, "setting timeout");
@@ -317,7 +318,7 @@ void LocalStore::makeStoreWritable()
317 throw SysError("setting up a private mount namespace"); 318 throw SysError("setting up a private mount namespace");
318 319
319 if (mount(0, settings.nixStore.c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1) 320 if (mount(0, settings.nixStore.c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1)
320 throw SysError(format("remounting %1% writable") % settings.nixStore); 321 throw SysError(std::format("remounting {} writable", settings.nixStore));
321 } 322 }
322#endif 323#endif
323} 324}
@@ -338,7 +339,7 @@ static void canonicaliseTimestampAndPermissions(const Path & path, const struct
338 | 0444 339 | 0444
339 | (st.st_mode & S_IXUSR ? 0111 : 0); 340 | (st.st_mode & S_IXUSR ? 0111 : 0);
340 if (chmod(path.c_str(), mode) == -1) 341 if (chmod(path.c_str(), mode) == -1)
341 throw SysError(format("changing mode of `%1%' to %2$o") % path % mode); 342 throw SysError(std::format("changing mode of `{}' to {:o}", path, mode));
342 } 343 }
343 344
344 } 345 }
@@ -356,7 +357,7 @@ static void canonicaliseTimestampAndPermissions(const Path & path, const struct
356#else 357#else
357 if (!S_ISLNK(st.st_mode) && utimes(path.c_str(), times) == -1) 358 if (!S_ISLNK(st.st_mode) && utimes(path.c_str(), times) == -1)
358#endif 359#endif
359 throw SysError(format("changing modification time of `%1%'") % path); 360 throw SysError(std::format("changing modification time of `{}'", path));
360 } 361 }
361} 362}
362 363
@@ -365,7 +366,7 @@ void canonicaliseTimestampAndPermissions(const Path & path)
365{ 366{
366 struct stat st; 367 struct stat st;
367 if (lstat(path.c_str(), &st)) 368 if (lstat(path.c_str(), &st))
368 throw SysError(format("getting attributes of path `%1%'") % path); 369 throw SysError(std::format("getting attributes of path `{}'", path));
369 canonicaliseTimestampAndPermissions(path, st); 370 canonicaliseTimestampAndPermissions(path, st);
370} 371}
371 372
@@ -376,11 +377,11 @@ static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSe
376 377
377 struct stat st; 378 struct stat st;
378 if (lstat(path.c_str(), &st)) 379 if (lstat(path.c_str(), &st))
379 throw SysError(format("getting attributes of path `%1%'") % path); 380 throw SysError(std::format("getting attributes of path `{}'", path));
380 381
381 /* Really make sure that the path is of a supported type. */ 382 /* Really make sure that the path is of a supported type. */
382 if (!(S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))) 383 if (!(S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode)))
383 throw Error(format("file ‘%1%’ has an unsupported type") % path); 384 throw Error(std::format("file `{}' has an unsupported type", path));
384 385
385 /* Fail if the file is not owned by the build user. This prevents 386 /* Fail if the file is not owned by the build user. This prevents
386 us from messing up the ownership/permissions of files 387 us from messing up the ownership/permissions of files
@@ -391,7 +392,7 @@ static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSe
391 if (fromUid != (uid_t) -1 && st.st_uid != fromUid) { 392 if (fromUid != (uid_t) -1 && st.st_uid != fromUid) {
392 assert(!S_ISDIR(st.st_mode)); 393 assert(!S_ISDIR(st.st_mode));
393 if (inodesSeen.find(Inode(st.st_dev, st.st_ino)) == inodesSeen.end()) 394 if (inodesSeen.find(Inode(st.st_dev, st.st_ino)) == inodesSeen.end())
394 throw BuildError(format("invalid ownership on file `%1%'") % path); 395 throw BuildError(std::format("invalid ownership on file `{}'", path));
395 mode_t mode = st.st_mode & ~S_IFMT; 396 mode_t mode = st.st_mode & ~S_IFMT;
396 assert(S_ISLNK(st.st_mode) || (st.st_uid == geteuid() && (mode == 0444 || mode == 0555) && st.st_mtime == mtimeStore)); 397 assert(S_ISLNK(st.st_mode) || (st.st_uid == geteuid() && (mode == 0444 || mode == 0555) && st.st_mtime == mtimeStore));
397 return; 398 return;
@@ -415,8 +416,8 @@ static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSe
415 if (!S_ISLNK(st.st_mode) && 416 if (!S_ISLNK(st.st_mode) &&
416 chown(path.c_str(), geteuid(), getegid()) == -1) 417 chown(path.c_str(), geteuid(), getegid()) == -1)
417#endif 418#endif
418 throw SysError(format("changing owner of `%1%' to %2%") 419 throw SysError(std::format("changing owner of `{}' to {}",
419 % path % geteuid()); 420 path, geteuid()));
420 } 421 }
421 422
422 if (S_ISDIR(st.st_mode)) { 423 if (S_ISDIR(st.st_mode)) {
@@ -435,11 +436,11 @@ void canonicalisePathMetaData(const Path & path, uid_t fromUid, InodesSeen & ino
435 be a symlink, since we can't change its ownership. */ 436 be a symlink, since we can't change its ownership. */
436 struct stat st; 437 struct stat st;
437 if (lstat(path.c_str(), &st)) 438 if (lstat(path.c_str(), &st))
438 throw SysError(format("getting attributes of path `%1%'") % path); 439 throw SysError(std::format("getting attributes of path `{}'", path));
439 440
440 if (st.st_uid != geteuid()) { 441 if (st.st_uid != geteuid()) {
441 assert(S_ISLNK(st.st_mode)); 442 assert(S_ISLNK(st.st_mode));
442 throw Error(format("wrong ownership of top-level store path `%1%'") % path); 443 throw Error(std::format("wrong ownership of top-level store path `{}'", path));
443 } 444 }
444} 445}
445 446
@@ -460,7 +461,7 @@ void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation &
460 if (isFixedOutputDrv(drv)) { 461 if (isFixedOutputDrv(drv)) {
461 DerivationOutputs::const_iterator out = drv.outputs.find("out"); 462 DerivationOutputs::const_iterator out = drv.outputs.find("out");
462 if (out == drv.outputs.end()) 463 if (out == drv.outputs.end())
463 throw Error(format("derivation `%1%' does not have an output named `out'") % drvPath); 464 throw Error(std::format("derivation `{}' does not have an output named `out'", drvPath));
464 465
465 bool recursive; HashType ht; Hash h; 466 bool recursive; HashType ht; Hash h;
466 out->second.parseHashInfo(recursive, ht, h); 467 out->second.parseHashInfo(recursive, ht, h);
@@ -468,8 +469,8 @@ void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation &
468 469
469 StringPairs::const_iterator j = drv.env.find("out"); 470 StringPairs::const_iterator j = drv.env.find("out");
470 if (out->second.path != outPath || j == drv.env.end() || j->second != outPath) 471 if (out->second.path != outPath || j == drv.env.end() || j->second != outPath)
471 throw Error(format("derivation `%1%' has incorrect output `%2%', should be `%3%'") 472 throw Error(std::format("derivation `{}' has incorrect output `{}', should be `{}'",
472 % drvPath % out->second.path % outPath); 473 drvPath, out->second.path, outPath));
473 } 474 }
474 475
475 else { 476 else {
@@ -485,8 +486,8 @@ void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation &
485 Path outPath = makeOutputPath(i.first, h, drvName); 486 Path outPath = makeOutputPath(i.first, h, drvName);
486 StringPairs::const_iterator j = drv.env.find(i.first); 487 StringPairs::const_iterator j = drv.env.find(i.first);
487 if (i.second.path != outPath || j == drv.env.end() || j->second != outPath) 488 if (i.second.path != outPath || j == drv.env.end() || j->second != outPath)
488 throw Error(format("derivation `%1%' has incorrect output `%2%', should be `%3%'") 489 throw Error(std::format("derivation `{}' has incorrect output `{}', should be `{}'",
489 % drvPath % i.second.path % outPath); 490 drvPath, i.second.path, outPath));
490 } 491 }
491 } 492 }
492} 493}
@@ -583,12 +584,12 @@ Hash parseHashField(const Path & path, const string & s)
583{ 584{
584 string::size_type colon = s.find(':'); 585 string::size_type colon = s.find(':');
585 if (colon == string::npos) 586 if (colon == string::npos)
586 throw Error(format("corrupt hash `%1%' in valid-path entry for `%2%'") 587 throw Error(std::format("corrupt hash `{}' in valid-path entry for `{}'",
587 % s % path); 588 s, path));
588 HashType ht = parseHashType(string(s, 0, colon)); 589 HashType ht = parseHashType(string(s, 0, colon));
589 if (ht == htUnknown) 590 if (ht == htUnknown)
590 throw Error(format("unknown hash type `%1%' in valid-path entry for `%2%'") 591 throw Error(std::format("unknown hash type `{}' in valid-path entry for `{}'",
591 % string(s, 0, colon) % path); 592 string(s, 0, colon), path));
592 return parseHash(ht, string(s, colon + 1)); 593 return parseHash(ht, string(s, colon + 1));
593} 594}
594 595
@@ -606,7 +607,7 @@ ValidPathInfo LocalStore::queryPathInfo(const Path & path)
606 auto useQueryPathInfo(stmtQueryPathInfo.use()(path)); 607 auto useQueryPathInfo(stmtQueryPathInfo.use()(path));
607 608
608 if (!useQueryPathInfo.next()) 609 if (!useQueryPathInfo.next())
609 throw Error(format("path `%1%' is not valid") % path); 610 throw Error(std::format("path `{}' is not valid", path));
610 611
611 info.id = useQueryPathInfo.getInt(0); 612 info.id = useQueryPathInfo.getInt(0);
612 613
@@ -647,7 +648,7 @@ uint64_t LocalStore::queryValidPathId(const Path & path)
647{ 648{
648 auto use(stmtQueryPathInfo.use()(path)); 649 auto use(stmtQueryPathInfo.use()(path));
649 if (!use.next()) 650 if (!use.next())
650 throw Error(format("path %1% is not valid") % path); 651 throw Error(std::format("path `%1%' is not valid", path));
651 return use.getInt(0); 652 return use.getInt(0);
652} 653}
653 654
@@ -809,8 +810,8 @@ string LocalStore::getLineFromSubstituter(Agent & run)
809 if (errno == EINTR) continue; 810 if (errno == EINTR) continue;
810 throw SysError("reading from substituter's stderr"); 811 throw SysError("reading from substituter's stderr");
811 } 812 }
812 if (n == 0) throw EndOfFile(format("`%1% substitute' died unexpectedly") 813 if (n == 0) throw EndOfFile(std::format("`{} substitute' died unexpectedly",
813 % settings.guixProgram); 814 settings.guixProgram));
814 err.append(buf, n); 815 err.append(buf, n);
815 string::size_type p; 816 string::size_type p;
816 while (((p = err.find('\n')) != string::npos) 817 while (((p = err.find('\n')) != string::npos)
@@ -840,7 +841,7 @@ template<class T> T LocalStore::getIntLineFromSubstituter(Agent & run)
840 string s = getLineFromSubstituter(run); 841 string s = getLineFromSubstituter(run);
841 T res; 842 T res;
842 if (!string2Int(s, res)) 843 if (!string2Int(s, res))
843 throw Error(format("integer expected from stream: %1%") % s); 844 throw Error(std::format("integer expected from stream: {}", s));
844 return res; 845 return res;
845} 846}
846 847
@@ -897,7 +898,7 @@ void LocalStore::querySubstitutablePathInfos(PathSet & paths, SubstitutablePathI
897 Path path = getLineFromSubstituter(run); 898 Path path = getLineFromSubstituter(run);
898 if (path == "") break; 899 if (path == "") break;
899 if (paths.find(path) == paths.end()) 900 if (paths.find(path) == paths.end())
900 throw Error(format("got unexpected path `%1%' from substituter") % path); 901 throw Error(std::format("got unexpected path `{}' from substituter", path));
901 paths.erase(path); 902 paths.erase(path);
902 SubstitutablePathInfo & info(infos[path]); 903 SubstitutablePathInfo & info(infos[path]);
903 info.deriver = getLineFromSubstituter(run); 904 info.deriver = getLineFromSubstituter(run);
@@ -990,7 +991,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
990 there are no referrers. */ 991 there are no referrers. */
991void LocalStore::invalidatePath(const Path & path) 992void LocalStore::invalidatePath(const Path & path)
992{ 993{
993 debug(format("invalidating path `%1%'") % path); 994 debug(std::format("invalidating path `{}'", path));
994 995
995 drvHashes.erase(path); 996 drvHashes.erase(path);
996 997
@@ -1060,7 +1061,7 @@ Path LocalStore::addToStore(const string & name, const Path & _srcPath,
1060 bool recursive, HashType hashAlgo, PathFilter & filter, bool repair) 1061 bool recursive, HashType hashAlgo, PathFilter & filter, bool repair)
1061{ 1062{
1062 Path srcPath(absPath(_srcPath)); 1063 Path srcPath(absPath(_srcPath));
1063 debug(format("adding `%1%' to the store") % srcPath); 1064 debug(std::format("adding `{}' to the store", srcPath));
1064 1065
1065 /* Read the whole path into memory. This is not a very scalable 1066 /* Read the whole path into memory. This is not a very scalable
1066 method for very large paths, but `copyPath' is mainly used for 1067 method for very large paths, but `copyPath' is mainly used for
@@ -1139,9 +1140,9 @@ static void checkSecrecy(const Path & path)
1139{ 1140{
1140 struct stat st; 1141 struct stat st;
1141 if (stat(path.c_str(), &st)) 1142 if (stat(path.c_str(), &st))
1142 throw SysError(format("getting status of `%1%'") % path); 1143 throw SysError(std::format("getting status of `{}'", path));
1143 if ((st.st_mode & (S_IRWXG | S_IRWXO)) != 0) 1144 if ((st.st_mode & (S_IRWXG | S_IRWXO)) != 0)
1144 throw Error(format("file `%1%' should be secret (inaccessible to everybody else)!") % path); 1145 throw Error(std::format("file `{}' should be secret (inaccessible to everybody else)!", path));
1145} 1146}
1146 1147
1147 1148
@@ -1212,9 +1213,9 @@ static std::string signHash(const string &secretKey, const Hash &hash)
1212 auto hexHash = printHash(hash); 1213 auto hexHash = printHash(hash);
1213 1214
1214 writeLine(agent->toAgent.writeSide, 1215 writeLine(agent->toAgent.writeSide,
1215 (format("sign %1%:%2% %3%:%4%") 1216 std::format("sign {}:{} {}:{}",
1216 % secretKey.size() % secretKey 1217 secretKey.size(), secretKey,
1217 % hexHash.size() % hexHash).str()); 1218 hexHash.size(), hexHash));
1218 1219
1219 return readAuthenticateReply(agent->fromAgent.readSide); 1220 return readAuthenticateReply(agent->fromAgent.readSide);
1220} 1221}
@@ -1226,8 +1227,7 @@ static std::string verifySignature(const string &signature)
1226 auto agent = authenticationAgent(); 1227 auto agent = authenticationAgent();
1227 1228
1228 writeLine(agent->toAgent.writeSide, 1229 writeLine(agent->toAgent.writeSide,
1229 (format("verify %1%:%2%") 1230 std::format("verify {}:{}", signature.size(), signature));
1230 % signature.size() % signature).str());
1231 1231
1232 return readAuthenticateReply(agent->fromAgent.readSide); 1232 return readAuthenticateReply(agent->fromAgent.readSide);
1233} 1233}
@@ -1237,10 +1237,10 @@ void LocalStore::exportPath(const Path & path, bool sign,
1237{ 1237{
1238 assertStorePath(path); 1238 assertStorePath(path);
1239 1239
1240 printMsg(lvlInfo, format("exporting path `%1%'") % path); 1240 printMsg(lvlInfo, std::format("exporting path `{}'", path));
1241 1241
1242 if (!isValidPath(path)) 1242 if (!isValidPath(path))
1243 throw Error(format("path `%1%' is not valid") % path); 1243 throw Error(std::format("path `{}' is not valid", path));
1244 1244
1245 HashAndWriteSink hashAndWriteSink(sink); 1245 HashAndWriteSink hashAndWriteSink(sink);
1246 1246
@@ -1252,8 +1252,8 @@ void LocalStore::exportPath(const Path & path, bool sign,
1252 Hash hash = hashAndWriteSink.currentHash(); 1252 Hash hash = hashAndWriteSink.currentHash();
1253 Hash storedHash = queryPathHash(path); 1253 Hash storedHash = queryPathHash(path);
1254 if (hash != storedHash && storedHash != Hash(storedHash.type)) 1254 if (hash != storedHash && storedHash != Hash(storedHash.type))
1255 throw Error(format("hash of path `%1%' has changed from `%2%' to `%3%'!") % path 1255 throw Error(std::format("hash of path `{}' has changed from `{}' to `{}'!",
1256 % printHash(storedHash) % printHash(hash)); 1256 path, printHash(storedHash), printHash(hash)));
1257 1257
1258 writeInt(EXPORT_MAGIC, hashAndWriteSink); 1258 writeInt(EXPORT_MAGIC, hashAndWriteSink);
1259 1259
@@ -1347,7 +1347,7 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
1347 bool haveSignature = readInt(hashAndReadSource) == 1; 1347 bool haveSignature = readInt(hashAndReadSource) == 1;
1348 1348
1349 if (requireSignature && !haveSignature) 1349 if (requireSignature && !haveSignature)
1350 throw Error(format("imported archive of `%1%' lacks a signature") % dstPath); 1350 throw Error(std::format("imported archive of `{}' lacks a signature", dstPath));
1351 1351
1352 if (haveSignature) { 1352 if (haveSignature) {
1353 string signature = readString(hashAndReadSource); 1353 string signature = readString(hashAndReadSource);
@@ -1387,8 +1387,8 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
1387 if (pathExists(dstPath)) deletePath(dstPath); 1387 if (pathExists(dstPath)) deletePath(dstPath);
1388 1388
1389 if (rename(unpacked.c_str(), dstPath.c_str()) == -1) 1389 if (rename(unpacked.c_str(), dstPath.c_str()) == -1)
1390 throw SysError(format("cannot move `%1%' to `%2%'") 1390 throw SysError(std::format("cannot move `{}' to `{}'",
1391 % unpacked % dstPath); 1391 unpacked, dstPath));
1392 1392
1393 canonicalisePathMetaData(dstPath, -1); 1393 canonicalisePathMetaData(dstPath, -1);
1394 1394
@@ -1438,8 +1438,8 @@ void LocalStore::invalidatePathChecked(const Path & path)
1438 PathSet referrers; queryReferrers_(path, referrers); 1438 PathSet referrers; queryReferrers_(path, referrers);
1439 referrers.erase(path); /* ignore self-references */ 1439 referrers.erase(path); /* ignore self-references */
1440 if (!referrers.empty()) 1440 if (!referrers.empty())
1441 throw PathInUse(format("cannot delete path `%1%' because it is in use by %2%") 1441 throw PathInUse(std::format("cannot delete path `{}' because it is in use by {}",
1442 % path % showPaths(referrers)); 1442 path, showPaths(referrers)));
1443 invalidatePath(path); 1443 invalidatePath(path);
1444 } 1444 }
1445 1445
@@ -1450,7 +1450,7 @@ void LocalStore::invalidatePathChecked(const Path & path)
1450 1450
1451bool LocalStore::verifyStore(bool checkContents, bool repair) 1451bool LocalStore::verifyStore(bool checkContents, bool repair)
1452{ 1452{
1453 printMsg(lvlError, format("reading the store...")); 1453 printMsg(lvlError, "reading the store...");
1454 1454
1455 bool errors = false; 1455 bool errors = false;
1456 1456
@@ -1483,13 +1483,13 @@ bool LocalStore::verifyStore(bool checkContents, bool repair)
1483 ValidPathInfo info = queryPathInfo(i); 1483 ValidPathInfo info = queryPathInfo(i);
1484 1484
1485 /* Check the content hash (optionally - slow). */ 1485 /* Check the content hash (optionally - slow). */
1486 printMsg(lvlTalkative, format("checking contents of `%1%'") % i); 1486 printMsg(lvlTalkative, std::format("checking contents of `{}'", i));
1487 HashResult current = hashPath(info.hash.type, i); 1487 HashResult current = hashPath(info.hash.type, i);
1488 1488
1489 if (info.hash != nullHash && info.hash != current.first) { 1489 if (info.hash != nullHash && info.hash != current.first) {
1490 printMsg(lvlError, format("path `%1%' was modified! " 1490 printMsg(lvlError, std::format("path `{}' was modified! "
1491 "expected hash `%2%', got `%3%'") 1491 "expected hash `{}', got `{}'",
1492 % i % printHash(info.hash) % printHash(current.first)); 1492 i, printHash(info.hash), printHash(current.first)));
1493 if (repair) repairPath(i); else errors = true; 1493 if (repair) repairPath(i); else errors = true;
1494 } else { 1494 } else {
1495 1495
@@ -1497,14 +1497,14 @@ bool LocalStore::verifyStore(bool checkContents, bool repair)
1497 1497
1498 /* Fill in missing hashes. */ 1498 /* Fill in missing hashes. */
1499 if (info.hash == nullHash) { 1499 if (info.hash == nullHash) {
1500 printMsg(lvlError, format("fixing missing hash on `%1%'") % i); 1500 printMsg(lvlError, std::format("fixing missing hash on `{}'", i));
1501 info.hash = current.first; 1501 info.hash = current.first;
1502 update = true; 1502 update = true;
1503 } 1503 }
1504 1504
1505 /* Fill in missing narSize fields (from old stores). */ 1505 /* Fill in missing narSize fields (from old stores). */
1506 if (info.narSize == 0) { 1506 if (info.narSize == 0) {
1507 printMsg(lvlError, format("updating size field on `%1%' to %2%") % i % current.second); 1507 printMsg(lvlError, std::format("updating size field on `{}' to {}", i, current.second));
1508 info.narSize = current.second; 1508 info.narSize = current.second;
1509 update = true; 1509 update = true;
1510 } 1510 }
@@ -1517,9 +1517,9 @@ bool LocalStore::verifyStore(bool checkContents, bool repair)
1517 /* It's possible that the path got GC'ed, so ignore 1517 /* It's possible that the path got GC'ed, so ignore
1518 errors on invalid paths. */ 1518 errors on invalid paths. */
1519 if (isValidPath(i)) 1519 if (isValidPath(i))
1520 printMsg(lvlError, format("error: %1%") % e.msg()); 1520 printMsg(lvlError, std::format("error: {}", e.msg()));
1521 else 1521 else
1522 printMsg(lvlError, format("warning: %1%") % e.msg()); 1522 printMsg(lvlError, std::format("warning: {}", e.msg()));
1523 errors = true; 1523 errors = true;
1524 } 1524 }
1525 } 1525 }
@@ -1538,7 +1538,7 @@ void LocalStore::verifyPath(const Path & path, const PathSet & store,
1538 done.insert(path); 1538 done.insert(path);
1539 1539
1540 if (!isStorePath(path)) { 1540 if (!isStorePath(path)) {
1541 printMsg(lvlError, format("path `%1%' is not in the store") % path); 1541 printMsg(lvlError, std::format("path `{}' is not in the store", path));
1542 invalidatePath(path); 1542 invalidatePath(path);
1543 return; 1543 return;
1544 } 1544 }
@@ -1556,15 +1556,15 @@ void LocalStore::verifyPath(const Path & path, const PathSet & store,
1556 } 1556 }
1557 1557
1558 if (canInvalidate) { 1558 if (canInvalidate) {
1559 printMsg(lvlError, format("path `%1%' disappeared, removing from database...") % path); 1559 printMsg(lvlError, std::format("path `{}' disappeared, removing from database...", path));
1560 invalidatePath(path); 1560 invalidatePath(path);
1561 } else { 1561 } else {
1562 printMsg(lvlError, format("path `%1%' disappeared, but it still has valid referrers!") % path); 1562 printMsg(lvlError, std::format("path `{}' disappeared, but it still has valid referrers!", path));
1563 if (repair) 1563 if (repair)
1564 try { 1564 try {
1565 repairPath(path); 1565 repairPath(path);
1566 } catch (Error & e) { 1566 } catch (Error & e) {
1567 printMsg(lvlError, format("warning: %1%") % e.msg()); 1567 printMsg(lvlError, std::format("warning: {}", e.msg()));
1568 errors = true; 1568 errors = true;
1569 } 1569 }
1570 else errors = true; 1570 else errors = true;
@@ -1581,7 +1581,7 @@ bool LocalStore::pathContentsGood(const Path & path)
1581{ 1581{
1582 std::map<Path, bool>::iterator i = pathContentsGoodCache.find(path); 1582 std::map<Path, bool>::iterator i = pathContentsGoodCache.find(path);
1583 if (i != pathContentsGoodCache.end()) return i->second; 1583 if (i != pathContentsGoodCache.end()) return i->second;
1584 printMsg(lvlInfo, format("checking path `%1%'...") % path); 1584 printMsg(lvlInfo, std::format("checking path `{}'...", path));
1585 ValidPathInfo info = queryPathInfo(path); 1585 ValidPathInfo info = queryPathInfo(path);
1586 bool res; 1586 bool res;
1587 if (!pathExists(path)) 1587 if (!pathExists(path))
@@ -1592,7 +1592,7 @@ bool LocalStore::pathContentsGood(const Path & path)
1592 res = info.hash == nullHash || info.hash == current.first; 1592 res = info.hash == nullHash || info.hash == current.first;
1593 } 1593 }
1594 pathContentsGoodCache[path] = res; 1594 pathContentsGoodCache[path] = res;
1595 if (!res) printMsg(lvlError, format("path `%1%' is corrupted or missing!") % path); 1595 if (!res) printMsg(lvlError, std::format("path `{}' is corrupted or missing!", path));
1596 return res; 1596 return res;
1597} 1597}
1598 1598
@@ -1617,14 +1617,14 @@ void LocalStore::createUser(const std::string & userName, uid_t userId)
1617 auto created = createDirs(dir); 1617 auto created = createDirs(dir);
1618 if (!created.empty()) { 1618 if (!created.empty()) {
1619 if (chmod(dir.c_str(), 0755) == -1) 1619 if (chmod(dir.c_str(), 0755) == -1)
1620 throw SysError(format("changing permissions of directory '%s'") % dir); 1620 throw SysError(std::format("changing permissions of directory '{}'", dir));
1621 1621
1622 /* The following operation requires CAP_CHOWN or can be handled 1622 /* The following operation requires CAP_CHOWN or can be handled
1623 manually by a user with CAP_CHOWN. */ 1623 manually by a user with CAP_CHOWN. */
1624 if (chown(dir.c_str(), userId, -1) == -1) { 1624 if (chown(dir.c_str(), userId, -1) == -1) {
1625 rmdir(dir.c_str()); 1625 rmdir(dir.c_str());
1626 string message = strerror(errno); 1626 string message = strerror(errno);
1627 printMsg(lvlInfo, format("failed to change owner of directory '%1%' to %2%: %3%") % dir % userId % message); 1627 printMsg(lvlInfo, std::format("failed to change owner of directory '{}' to {}: {}", dir, userId, message));
1628 } 1628 }
1629 } 1629 }
1630} 1630}
diff --git a/nix/libstore/misc.cc b/nix/libstore/misc.cc
index e9904f3c4f4..943fb9c9719 100644
--- a/nix/libstore/misc.cc
+++ b/nix/libstore/misc.cc
@@ -4,6 +4,7 @@
4#include "local-store.hh" 4#include "local-store.hh"
5#include "globals.hh" 5#include "globals.hh"
6 6
7#include <format>
7 8
8namespace nix { 9namespace nix {
9 10
@@ -65,7 +66,7 @@ static void dfsVisit(StoreAPI & store, const PathSet & paths,
65 PathSet & parents) 66 PathSet & parents)
66{ 67{
67 if (parents.find(path) != parents.end()) 68 if (parents.find(path) != parents.end())
68 throw BuildError(format("cycle detected in the references of `%1%'") % path); 69 throw BuildError(std::format("cycle detected in the references of `{}'", path));
69 70
70 if (visited.find(path) != visited.end()) return; 71 if (visited.find(path) != visited.end()) return;
71 visited.insert(path); 72 visited.insert(path);
@@ -99,19 +100,19 @@ Paths topoSortPaths(StoreAPI & store, const PathSet & paths)
99string showBytes(long long bytes) 100string showBytes(long long bytes)
100{ 101{
101 if (llabs(bytes > exp2l(60))) { 102 if (llabs(bytes > exp2l(60))) {
102 return (format("%7.2f EiB") % (bytes / exp2l(60))).str(); 103 return std::format("{:7.2f} EiB", bytes / exp2l(60));
103 } else if (llabs(bytes > exp2l(50))) { 104 } else if (llabs(bytes > exp2l(50))) {
104 return (format("%7.2f PiB") % (bytes / exp2l(50))).str(); 105 return std::format("{:7.2f} PiB", bytes / exp2l(50));
105 } else if (llabs(bytes > exp2l(40))) { 106 } else if (llabs(bytes > exp2l(40))) {
106 return (format("%7.2f TiB") % (bytes / exp2l(40))).str(); 107 return std::format("{:7.2f} TiB", bytes / exp2l(40));
107 } else if (llabs(bytes > exp2l(30))) { 108 } else if (llabs(bytes > exp2l(30))) {
108 return (format("%7.2f GiB") % (bytes / exp2l(30))).str(); 109 return std::format("{:7.2f} GiB", bytes / exp2l(30));
109 } else if (llabs(bytes > exp2l(20))) { 110 } else if (llabs(bytes > exp2l(20))) {
110 return (format("%7.2f MiB") % (bytes / exp2l(20))).str(); 111 return std::format("{:7.2f} MiB", bytes / exp2l(20));
111 } else if (llabs(bytes > exp2l(10))) { 112 } else if (llabs(bytes > exp2l(10))) {
112 return (format("%7.2f KiB") % (bytes / exp2l(10))).str(); 113 return std::format("{:7.2f} KiB", bytes / exp2l(10));
113 } else { 114 } else {
114 return (format("%4f bytes") % bytes).str(); 115 return std::format("{:4} bytes", bytes);
115 } 116 }
116} 117}
117 118
diff --git a/nix/libstore/optimise-store.cc b/nix/libstore/optimise-store.cc
index e17d9160d6c..d69c43e9978 100644
--- a/nix/libstore/optimise-store.cc
+++ b/nix/libstore/optimise-store.cc
@@ -12,7 +12,7 @@
12#include <unistd.h> 12#include <unistd.h>
13#include <errno.h> 13#include <errno.h>
14#include <stdio.h> 14#include <stdio.h>
15 15#include <format>
16 16
17namespace nix { 17namespace nix {
18 18
@@ -24,9 +24,9 @@ static void makeWritable(const Path & path)
24{ 24{
25 struct stat st; 25 struct stat st;
26 if (lstat(path.c_str(), &st)) 26 if (lstat(path.c_str(), &st))
27 throw SysError(format("getting attributes of path `%1%'") % path); 27 throw SysError(std::format("getting attributes of path `{}'", path));
28 if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1) 28 if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1)
29 throw SysError(format("changing writability of `%1%'") % path); 29 throw SysError(std::format("changing writability of `{}'", path));
30} 30}
31 31
32 32
@@ -52,7 +52,7 @@ LocalStore::InodeHash LocalStore::loadInodeHash()
52 InodeHash inodeHash; 52 InodeHash inodeHash;
53 53
54 AutoCloseDir dir = opendir(linksDir.c_str()); 54 AutoCloseDir dir = opendir(linksDir.c_str());
55 if (!dir) throw SysError(format("opening directory `%1%'") % linksDir); 55 if (!dir) throw SysError(std::format("opening directory `{}'", linksDir));
56 56
57 struct dirent * dirent; 57 struct dirent * dirent;
58 while (errno = 0, dirent = readdir(dir)) { /* sic */ 58 while (errno = 0, dirent = readdir(dir)) { /* sic */
@@ -60,9 +60,9 @@ LocalStore::InodeHash LocalStore::loadInodeHash()
60 // We don't care if we hit non-hash files, anything goes 60 // We don't care if we hit non-hash files, anything goes
61 inodeHash.insert(dirent->d_ino); 61 inodeHash.insert(dirent->d_ino);
62 } 62 }
63 if (errno) throw SysError(format("reading directory `%1%'") % linksDir); 63 if (errno) throw SysError(std::format("reading directory `{}'", linksDir));
64 64
65 printMsg(lvlTalkative, format("loaded %1% hash inodes") % inodeHash.size()); 65 printMsg(lvlTalkative, std::format("loaded {} hash inodes", inodeHash.size()));
66 66
67 return inodeHash; 67 return inodeHash;
68} 68}
@@ -73,14 +73,14 @@ Strings LocalStore::readDirectoryIgnoringInodes(const Path & path, const InodeHa
73 Strings names; 73 Strings names;
74 74
75 AutoCloseDir dir = opendir(path.c_str()); 75 AutoCloseDir dir = opendir(path.c_str());
76 if (!dir) throw SysError(format("opening directory `%1%'") % path); 76 if (!dir) throw SysError(std::format("opening directory `{}'", path));
77 77
78 struct dirent * dirent; 78 struct dirent * dirent;
79 while (errno = 0, dirent = readdir(dir)) { /* sic */ 79 while (errno = 0, dirent = readdir(dir)) { /* sic */
80 checkInterrupt(); 80 checkInterrupt();
81 81
82 if (inodeHash.count(dirent->d_ino)) { 82 if (inodeHash.count(dirent->d_ino)) {
83 printMsg(lvlDebug, format("`%1%' is already linked") % dirent->d_name); 83 printMsg(lvlDebug, std::format("`{}' is already linked", dirent->d_name));
84 continue; 84 continue;
85 } 85 }
86 86
@@ -88,7 +88,7 @@ Strings LocalStore::readDirectoryIgnoringInodes(const Path & path, const InodeHa
88 if (name == "." || name == "..") continue; 88 if (name == "." || name == "..") continue;
89 names.push_back(name); 89 names.push_back(name);
90 } 90 }
91 if (errno) throw SysError(format("reading directory `%1%'") % path); 91 if (errno) throw SysError(std::format("reading directory `{}'", path));
92 92
93 return names; 93 return names;
94} 94}
@@ -100,7 +100,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
100 100
101 struct stat st; 101 struct stat st;
102 if (lstat(path.c_str(), &st)) 102 if (lstat(path.c_str(), &st))
103 throw SysError(format("getting attributes of path `%1%'") % path); 103 throw SysError(std::format("getting attributes of path `{}'", path));
104 104
105 if (S_ISDIR(st.st_mode)) { 105 if (S_ISDIR(st.st_mode)) {
106 Strings names = readDirectoryIgnoringInodes(path, inodeHash); 106 Strings names = readDirectoryIgnoringInodes(path, inodeHash);
@@ -121,13 +121,13 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
121 Guix System (example: $fontconfig/var/cache being modified). Skip 121 Guix System (example: $fontconfig/var/cache being modified). Skip
122 those files. FIXME: check the modification time. */ 122 those files. FIXME: check the modification time. */
123 if (S_ISREG(st.st_mode) && (st.st_mode & S_IWUSR)) { 123 if (S_ISREG(st.st_mode) && (st.st_mode & S_IWUSR)) {
124 printMsg(lvlError, format("skipping suspicious writable file `%1%'") % path); 124 printMsg(lvlError, std::format("skipping suspicious writable file `{}'", path));
125 return; 125 return;
126 } 126 }
127 127
128 /* This can still happen on top-level files. */ 128 /* This can still happen on top-level files. */
129 if (st.st_nlink > 1 && inodeHash.count(st.st_ino)) { 129 if (st.st_nlink > 1 && inodeHash.count(st.st_ino)) {
130 printMsg(lvlDebug, format("`%1%' is already linked, with %2% other file(s).") % path % (st.st_nlink - 2)); 130 printMsg(lvlDebug, std::format("`{}' is already linked, with {} other file(s).", path, (st.st_nlink - 2)));
131 return; 131 return;
132 } 132 }
133 133
@@ -141,7 +141,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
141 contents of the symlink (i.e. the result of readlink()), not 141 contents of the symlink (i.e. the result of readlink()), not
142 the contents of the target (which may not even exist). */ 142 the contents of the target (which may not even exist). */
143 Hash hash = hashPath(htSHA256, path).first; 143 Hash hash = hashPath(htSHA256, path).first;
144 printMsg(lvlDebug, format("`%1%' has hash `%2%'") % path % printHash(hash)); 144 printMsg(lvlDebug, std::format("`{}' has hash `{}'", path, printHash(hash)));
145 145
146 /* Check if this is a known hash. */ 146 /* Check if this is a known hash. */
147 Path linkPath = linksDir + "/" + printHash32(hash); 147 Path linkPath = linksDir + "/" + printHash32(hash);
@@ -164,12 +164,12 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
164 /* On ext4, that probably means the directory index is full. When 164 /* On ext4, that probably means the directory index is full. When
165 that happens, it's fine to ignore it: we just effectively 165 that happens, it's fine to ignore it: we just effectively
166 disable deduplication of this file. */ 166 disable deduplication of this file. */
167 printMsg(lvlInfo, format("cannot link `%1%' to `%2%': %3%") 167 printMsg(lvlInfo, std::format("cannot link `{}' to `{}': {}",
168 % linkPath % path % strerror(ENOSPC)); 168 linkPath, path, strerror(ENOSPC)));
169 return; 169 return;
170 170
171 default: 171 default:
172 throw SysError(format("cannot link `%1%' to `%2%'") % linkPath % path); 172 throw SysError(std::format("cannot link `{}' to `{}'", linkPath, path));
173 } 173 }
174 } 174 }
175 175
@@ -177,20 +177,20 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
177 current file with a hard link to that file. */ 177 current file with a hard link to that file. */
178 struct stat stLink; 178 struct stat stLink;
179 if (lstat(linkPath.c_str(), &stLink)) 179 if (lstat(linkPath.c_str(), &stLink))
180 throw SysError(format("getting attributes of path `%1%'") % linkPath); 180 throw SysError(std::format("getting attributes of path `{}'", linkPath));
181 181
182 if (st.st_ino == stLink.st_ino) { 182 if (st.st_ino == stLink.st_ino) {
183 printMsg(lvlDebug, format("`%1%' is already linked to `%2%'") % path % linkPath); 183 printMsg(lvlDebug, std::format("`{}' is already linked to `{}'", path, linkPath));
184 return; 184 return;
185 } 185 }
186 186
187 if (st.st_size != stLink.st_size) { 187 if (st.st_size != stLink.st_size) {
188 printMsg(lvlError, format("removing corrupted link %1%") % linkPath); 188 printMsg(lvlError, std::format("removing corrupted link `%1%'", linkPath));
189 unlink(linkPath.c_str()); 189 unlink(linkPath.c_str());
190 goto retry; 190 goto retry;
191 } 191 }
192 192
193 printMsg(lvlTalkative, format("linking %1% to %2%") % path % linkPath); 193 printMsg(lvlTalkative, std::format("linking `%1%' to `%2%'", path, linkPath));
194 194
195 /* Make the containing directory writable, but only if it's not 195 /* Make the containing directory writable, but only if it's not
196 the store itself (we don't want or need to mess with its 196 the store itself (we don't want or need to mess with its
@@ -202,8 +202,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
202 its timestamp back to 0. */ 202 its timestamp back to 0. */
203 MakeReadOnly makeReadOnly(mustToggle ? dirOf(path) : ""); 203 MakeReadOnly makeReadOnly(mustToggle ? dirOf(path) : "");
204 204
205 Path tempLink = (format("%1%/.tmp-link-%2%-%3%") 205 Path tempLink = std::format("{}/.tmp-link-{}-{}", settings.nixStore, getpid(), rand());
206 % settings.nixStore % getpid() % rand()).str();
207 206
208 if (link(linkPath.c_str(), tempLink.c_str()) == -1) { 207 if (link(linkPath.c_str(), tempLink.c_str()) == -1) {
209 if (errno == EMLINK) { 208 if (errno == EMLINK) {
@@ -211,27 +210,27 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
211 systems). This is likely to happen with empty files. 210 systems). This is likely to happen with empty files.
212 Just shrug and ignore. */ 211 Just shrug and ignore. */
213 if (st.st_size) 212 if (st.st_size)
214 printMsg(lvlInfo, format("`%1%' has maximum number of links") % linkPath); 213 printMsg(lvlInfo, std::format("`{}' has maximum number of links", linkPath));
215 return; 214 return;
216 } 215 }
217 throw SysError(format("cannot link `%1%' to `%2%'") % tempLink % linkPath); 216 throw SysError(std::format("cannot link `{}' to `{}'", tempLink, linkPath));
218 } 217 }
219 218
220 /* Atomically replace the old file with the new hard link. */ 219 /* Atomically replace the old file with the new hard link. */
221 if (rename(tempLink.c_str(), path.c_str()) == -1) { 220 if (rename(tempLink.c_str(), path.c_str()) == -1) {
222 int renameErrno = errno; 221 int renameErrno = errno;
223 if (unlink(tempLink.c_str()) == -1) 222 if (unlink(tempLink.c_str()) == -1)
224 printMsg(lvlError, format("unable to unlink `%1%'") % tempLink); 223 printMsg(lvlError, std::format("unable to unlink `{}'", tempLink));
225 if (renameErrno == EMLINK) { 224 if (renameErrno == EMLINK) {
226 /* Some filesystems generate too many links on the rename, 225 /* Some filesystems generate too many links on the rename,
227 rather than on the original link. (Probably it 226 rather than on the original link. (Probably it
228 temporarily increases the st_nlink field before 227 temporarily increases the st_nlink field before
229 decreasing it again.) */ 228 decreasing it again.) */
230 if (st.st_size) 229 if (st.st_size)
231 printMsg(lvlInfo, format("`%1%' has maximum number of links") % linkPath); 230 printMsg(lvlInfo, std::format("`{}' has maximum number of links", linkPath));
232 return; 231 return;
233 } 232 }
234 throw SysError(format("cannot rename `%1%' to `%2%'") % tempLink % path); 233 throw SysError(std::format("cannot rename `{}' to `{}'", tempLink, path));
235 } 234 }
236 235
237 stats.filesLinked++; 236 stats.filesLinked++;
@@ -248,7 +247,7 @@ void LocalStore::optimiseStore(OptimiseStats & stats)
248 for (auto& i : paths) { 247 for (auto& i : paths) {
249 addTempRoot(i); 248 addTempRoot(i);
250 if (!isValidPath(i)) continue; /* path was GC'ed, probably */ 249 if (!isValidPath(i)) continue; /* path was GC'ed, probably */
251 startNest(nest, lvlChatty, format("hashing files in `%1%'") % i); 250 startNest(nest, lvlChatty, std::format("hashing files in `{}'", i));
252 optimisePath_(stats, i, inodeHash); 251 optimisePath_(stats, i, inodeHash);
253 } 252 }
254} 253}
@@ -260,9 +259,9 @@ void LocalStore::optimiseStore()
260 optimiseStore(stats); 259 optimiseStore(stats);
261 260
262 printMsg(lvlError, 261 printMsg(lvlError,
263 format("%1% freed by hard-linking %2% files") 262 std::format("{} freed by hard-linking {} files",
264 % showBytes(stats.bytesFreed) 263 showBytes(stats.bytesFreed),
265 % stats.filesLinked); 264 stats.filesLinked));
266} 265}
267 266
268void LocalStore::optimisePath(const Path & path) 267void LocalStore::optimisePath(const Path & path)
diff --git a/nix/libstore/pathlocks.cc b/nix/libstore/pathlocks.cc
index c07f047192c..ce4671e2097 100644
--- a/nix/libstore/pathlocks.cc
+++ b/nix/libstore/pathlocks.cc
@@ -3,6 +3,8 @@
3 3
4#include <cerrno> 4#include <cerrno>
5#include <cstdlib> 5#include <cstdlib>
6#include <cassert>
7#include <format>
6 8
7#include <sys/types.h> 9#include <sys/types.h>
8#include <sys/stat.h> 10#include <sys/stat.h>
@@ -18,7 +20,7 @@ int openLockFile(const Path & path, bool create)
18 20
19 fd = open(path.c_str(), O_RDWR | (create ? O_CREAT : 0), 0600); 21 fd = open(path.c_str(), O_RDWR | (create ? O_CREAT : 0), 0600);
20 if (fd == -1 && (create || errno != ENOENT)) 22 if (fd == -1 && (create || errno != ENOENT))
21 throw SysError(format("opening lock file `%1%'") % path); 23 throw SysError(std::format("opening lock file `{}'", path));
22 24
23 closeOnExec(fd); 25 closeOnExec(fd);
24 26
@@ -54,14 +56,14 @@ bool lockFile(int fd, LockType lockType, bool wait)
54 while (fcntl(fd, F_SETLKW, &lock) != 0) { 56 while (fcntl(fd, F_SETLKW, &lock) != 0) {
55 checkInterrupt(); 57 checkInterrupt();
56 if (errno != EINTR) 58 if (errno != EINTR)
57 throw SysError(format("acquiring/releasing lock")); 59 throw SysError("acquiring/releasing lock");
58 } 60 }
59 } else { 61 } else {
60 while (fcntl(fd, F_SETLK, &lock) != 0) { 62 while (fcntl(fd, F_SETLK, &lock) != 0) {
61 checkInterrupt(); 63 checkInterrupt();
62 if (errno == EACCES || errno == EAGAIN) return false; 64 if (errno == EACCES || errno == EAGAIN) return false;
63 if (errno != EINTR) 65 if (errno != EINTR)
64 throw SysError(format("acquiring/releasing lock")); 66 throw SysError("acquiring/releasing lock");
65 } 67 }
66 } 68 }
67 69
@@ -109,7 +111,7 @@ bool PathLocks::lockPaths(const PathSet & _paths,
109 Path path = i; 111 Path path = i;
110 Path lockPath = path + ".lock"; 112 Path lockPath = path + ".lock";
111 113
112 debug(format("locking path `%1%'") % path); 114 debug(std::format("locking path `{}'", path));
113 115
114 if (lockedPaths.find(lockPath) != lockedPaths.end()) 116 if (lockedPaths.find(lockPath) != lockedPaths.end())
115 throw Error("deadlock: trying to re-acquire self-held lock"); 117 throw Error("deadlock: trying to re-acquire self-held lock");
@@ -134,19 +136,19 @@ bool PathLocks::lockPaths(const PathSet & _paths,
134 } 136 }
135 } 137 }
136 138
137 debug(format("lock acquired on `%1%'") % lockPath); 139 debug(std::format("lock acquired on `{}'", lockPath));
138 140
139 /* Check that the lock file hasn't become stale (i.e., 141 /* Check that the lock file hasn't become stale (i.e.,
140 hasn't been unlinked). */ 142 hasn't been unlinked). */
141 struct stat st; 143 struct stat st;
142 if (fstat(fd, &st) == -1) 144 if (fstat(fd, &st) == -1)
143 throw SysError(format("statting lock file `%1%'") % lockPath); 145 throw SysError(std::format("statting lock file `{}'", lockPath));
144 if (st.st_size != 0) 146 if (st.st_size != 0)
145 /* This lock file has been unlinked, so we're holding 147 /* This lock file has been unlinked, so we're holding
146 a lock on a deleted file. This means that other 148 a lock on a deleted file. This means that other
147 processes may create and acquire a lock on 149 processes may create and acquire a lock on
148 `lockPath', and proceed. So we must retry. */ 150 `lockPath', and proceed. So we must retry. */
149 debug(format("open lock file `%1%' has become stale") % lockPath); 151 debug(std::format("open lock file `{}' has become stale", lockPath));
150 else 152 else
151 break; 153 break;
152 } 154 }
@@ -178,9 +180,9 @@ void PathLocks::unlock()
178 lockedPaths.erase(i.second); 180 lockedPaths.erase(i.second);
179 if (close(i.first) == -1) 181 if (close(i.first) == -1)
180 printMsg(lvlError, 182 printMsg(lvlError,
181 format("error (ignored): cannot close lock file on `%1%'") % i.second); 183 std::format("error (ignored): cannot close lock file on `{}'", i.second));
182 184
183 debug(format("lock released on `%1%'") % i.second); 185 debug(std::format("lock released on `{}'", i.second));
184 } 186 }
185 187
186 fds.clear(); 188 fds.clear();
diff --git a/nix/libstore/references.cc b/nix/libstore/references.cc
index d9c8a9fbe38..a8ec39ee34b 100644
--- a/nix/libstore/references.cc
+++ b/nix/libstore/references.cc
@@ -5,7 +5,8 @@
5 5
6#include <map> 6#include <map>
7#include <cstdlib> 7#include <cstdlib>
8 8#include <cassert>
9#include <format>
9 10
10namespace nix { 11namespace nix {
11 12
@@ -37,8 +38,7 @@ static void search(const unsigned char * s, unsigned int len,
37 if (!match) continue; 38 if (!match) continue;
38 string ref((const char *) s + i, refLength); 39 string ref((const char *) s + i, refLength);
39 if (hashes.find(ref) != hashes.end()) { 40 if (hashes.find(ref) != hashes.end()) {
40 debug(format("found reference to `%1%' at offset `%2%'") 41 debug(std::format("found reference to `{}' at offset `{}'", ref, i));
41 % ref % i);
42 seen.insert(ref); 42 seen.insert(ref);
43 hashes.erase(ref); 43 hashes.erase(ref);
44 } 44 }
@@ -93,7 +93,7 @@ PathSet scanForReferences(const string & path,
93 string baseName = baseNameOf(i); 93 string baseName = baseNameOf(i);
94 string::size_type pos = baseName.find('-'); 94 string::size_type pos = baseName.find('-');
95 if (pos == string::npos) 95 if (pos == string::npos)
96 throw Error(format("bad reference `%1%'") % i); 96 throw Error(std::format("bad reference `{}'", i));
97 string s = string(baseName, 0, pos); 97 string s = string(baseName, 0, pos);
98 assert(s.size() == refLength); 98 assert(s.size() == refLength);
99 assert(backMap.find(s) == backMap.end()); 99 assert(backMap.find(s) == backMap.end());
diff --git a/nix/libstore/sqlite.cc b/nix/libstore/sqlite.cc
index e08c67f40ed..cbd768155ec 100644
--- a/nix/libstore/sqlite.cc
+++ b/nix/libstore/sqlite.cc
@@ -1,11 +1,14 @@
1#include "sqlite.hh" 1#include "sqlite.hh"
2#include "util.hh" 2#include "util.hh"
3 3
4#include <format>
5#include <cassert>
6
4#include <sqlite3.h> 7#include <sqlite3.h>
5 8
6namespace nix { 9namespace nix {
7 10
8[[noreturn]] void throwSQLiteError(sqlite3 * db, const format & f) 11[[noreturn]] void throwSQLiteError(sqlite3 * db, std::string_view f)
9{ 12{
10 int err = sqlite3_errcode(db); 13 int err = sqlite3_errcode(db);
11 if (err == SQLITE_BUSY || err == SQLITE_PROTOCOL) { 14 if (err == SQLITE_BUSY || err == SQLITE_PROTOCOL) {
@@ -28,10 +31,10 @@ namespace nix {
28#else 31#else
29 sleep(1); 32 sleep(1);
30#endif 33#endif
31 throw SQLiteBusy(format("%1%: %2%") % f.str() % sqlite3_errmsg(db)); 34 throw SQLiteBusy(std::format("{}: {}", f, sqlite3_errmsg(db)));
32 } 35 }
33 else 36 else
34 throw SQLiteError(format("%1%: %2%") % f.str() % sqlite3_errmsg(db)); 37 throw SQLiteError(std::format("{}: {}", f, sqlite3_errmsg(db)));
35} 38}
36 39
37SQLite::~SQLite() 40SQLite::~SQLite()
diff --git a/nix/libstore/sqlite.hh b/nix/libstore/sqlite.hh
index 6cadba68490..0c0bc9e6f5a 100644
--- a/nix/libstore/sqlite.hh
+++ b/nix/libstore/sqlite.hh
@@ -3,6 +3,7 @@
3#include <functional> 3#include <functional>
4#include <string> 4#include <string>
5#include <cstdint> 5#include <cstdint>
6#include <string_view>
6 7
7#include "types.hh" 8#include "types.hh"
8 9
@@ -85,7 +86,7 @@ struct SQLiteTxn
85MakeError(SQLiteError, Error); 86MakeError(SQLiteError, Error);
86MakeError(SQLiteBusy, SQLiteError); 87MakeError(SQLiteBusy, SQLiteError);
87 88
88[[noreturn]] void throwSQLiteError(sqlite3 * db, const format & f); 89[[noreturn]] void throwSQLiteError(sqlite3 * db, std::string_view f);
89 90
90/* Convenience function for retrying a SQLite transaction when the 91/* Convenience function for retrying a SQLite transaction when the
91 database is busy. */ 92 database is busy. */
diff --git a/nix/libstore/store-api.cc b/nix/libstore/store-api.cc
index 7282188fb37..0596678b8b5 100644
--- a/nix/libstore/store-api.cc
+++ b/nix/libstore/store-api.cc
@@ -3,7 +3,7 @@
3#include "util.hh" 3#include "util.hh"
4 4
5#include <climits> 5#include <climits>
6 6#include <format>
7 7
8namespace nix { 8namespace nix {
9 9
@@ -32,14 +32,14 @@ bool isStorePath(const Path & path)
32void assertStorePath(const Path & path) 32void assertStorePath(const Path & path)
33{ 33{
34 if (!isStorePath(path)) 34 if (!isStorePath(path))
35 throw Error(format("path `%1%' is not in the store") % path); 35 throw Error(std::format("path `{}' is not in the store", path));
36} 36}
37 37
38 38
39Path toStorePath(const Path & path) 39Path toStorePath(const Path & path)
40{ 40{
41 if (!isInStore(path)) 41 if (!isInStore(path))
42 throw Error(format("path `%1%' is not in the store") % path); 42 throw Error(std::format("path `{}' is not in the store", path));
43 Path::size_type slash = path.find('/', settings.nixStore.size() + 1); 43 Path::size_type slash = path.find('/', settings.nixStore.size() + 1);
44 if (slash == Path::npos) 44 if (slash == Path::npos)
45 return path; 45 return path;
@@ -61,15 +61,14 @@ void checkStoreName(const string & name)
61 /* Disallow names starting with a dot for possible security 61 /* Disallow names starting with a dot for possible security
62 reasons (e.g., "." and ".."). */ 62 reasons (e.g., "." and ".."). */
63 if (string(name, 0, 1) == ".") 63 if (string(name, 0, 1) == ".")
64 throw Error(format("invalid name: `%1%' (can't begin with dot)") % name); 64 throw Error(std::format("invalid name: `{}' (can't begin with dot)", name));
65 for (const auto& i : name) 65 for (const auto& i : name)
66 if (!((i >= 'A' && i <= 'Z') || 66 if (!((i >= 'A' && i <= 'Z') ||
67 (i >= 'a' && i <= 'z') || 67 (i >= 'a' && i <= 'z') ||
68 (i >= '0' && i <= '9') || 68 (i >= '0' && i <= '9') ||
69 validChars.find(i) != string::npos)) 69 validChars.find(i) != string::npos))
70 { 70 {
71 throw Error(format("invalid character `%1%' in name `%2%'") 71 throw Error(std::format("invalid character `{}' in name `{}'", i, name));
72 % i % name);
73 } 72 }
74} 73}
75 74
@@ -211,13 +210,13 @@ string StoreAPI::makeValidityRegistration(const PathSet & paths,
211 210
212 if (showHash) { 211 if (showHash) {
213 s += printHash(info.hash) + "\n"; 212 s += printHash(info.hash) + "\n";
214 s += (format("%1%\n") % info.narSize).str(); 213 s += std::format("{}\n", info.narSize);
215 } 214 }
216 215
217 Path deriver = showDerivers ? info.deriver : ""; 216 Path deriver = showDerivers ? info.deriver : "";
218 s += deriver + "\n"; 217 s += deriver + "\n";
219 218
220 s += (format("%1%\n") % info.references.size()).str(); 219 s += std::format("{}\n", info.references.size());
221 220
222 for (auto& j : info.references) 221 for (auto& j : info.references)
223 s += j + "\n"; 222 s += j + "\n";