mirror of
https://github.com/NixOS/nix.git
synced 2025-11-13 14:02:42 +01:00
Merge branch 'errors-phase-2' of https://github.com/bburdette/nix
This commit is contained in:
commit
7a77762961
81 changed files with 1857 additions and 1010 deletions
|
|
@ -40,14 +40,14 @@ void BinaryCacheStore::init()
|
|||
upsertFile(cacheInfoFile, "StoreDir: " + storeDir + "\n", "text/x-nix-cache-info");
|
||||
} else {
|
||||
for (auto & line : tokenizeString<Strings>(*cacheInfo, "\n")) {
|
||||
size_t colon = line.find(':');
|
||||
if (colon == std::string::npos) continue;
|
||||
size_t colon= line.find(':');
|
||||
if (colon ==std::string::npos) continue;
|
||||
auto name = line.substr(0, colon);
|
||||
auto value = trim(line.substr(colon + 1, std::string::npos));
|
||||
if (name == "StoreDir") {
|
||||
if (value != storeDir)
|
||||
throw Error(format("binary cache '%s' is for Nix stores with prefix '%s', not '%s'")
|
||||
% getUri() % value % storeDir);
|
||||
throw Error("binary cache '%s' is for Nix stores with prefix '%s', not '%s'",
|
||||
getUri(), value, storeDir);
|
||||
} else if (name == "WantMassQuery") {
|
||||
wantMassQuery.setDefault(value == "1" ? "true" : "false");
|
||||
} else if (name == "Priority") {
|
||||
|
|
@ -287,7 +287,7 @@ void BinaryCacheStore::narFromPath(const StorePath & storePath, Sink & sink)
|
|||
try {
|
||||
getFile(info->url, *decompressor);
|
||||
} catch (NoSuchBinaryCacheFile & e) {
|
||||
throw SubstituteGone(e.what());
|
||||
throw SubstituteGone(e.info());
|
||||
}
|
||||
|
||||
decompressor->finish();
|
||||
|
|
|
|||
|
|
@ -453,7 +453,7 @@ static void commonChildInit(Pipe & logPipe)
|
|||
that e.g. ssh cannot open /dev/tty) and it doesn't receive
|
||||
terminal signals. */
|
||||
if (setsid() == -1)
|
||||
throw SysError(format("creating a new session"));
|
||||
throw SysError("creating a new session");
|
||||
|
||||
/* Dup the write side of the logger pipe into stderr. */
|
||||
if (dup2(logPipe.writeSide.get(), STDERR_FILENO) == -1)
|
||||
|
|
@ -466,7 +466,7 @@ static void commonChildInit(Pipe & logPipe)
|
|||
/* Reroute stdin to /dev/null. */
|
||||
int fdDevNull = open(pathNullDevice.c_str(), O_RDWR);
|
||||
if (fdDevNull == -1)
|
||||
throw SysError(format("cannot open '%1%'") % pathNullDevice);
|
||||
throw SysError("cannot open '%1%'", pathNullDevice);
|
||||
if (dup2(fdDevNull, STDIN_FILENO) == -1)
|
||||
throw SysError("cannot dup null device into stdin");
|
||||
close(fdDevNull);
|
||||
|
|
@ -488,12 +488,18 @@ void handleDiffHook(
|
|||
|
||||
auto diffRes = runProgram(diffHookOptions);
|
||||
if (!statusOk(diffRes.first))
|
||||
throw ExecError(diffRes.first, fmt("diff-hook program '%1%' %2%", diffHook, statusToString(diffRes.first)));
|
||||
throw ExecError(diffRes.first,
|
||||
"diff-hook program '%1%' %2%",
|
||||
diffHook,
|
||||
statusToString(diffRes.first));
|
||||
|
||||
if (diffRes.second != "")
|
||||
printError(chomp(diffRes.second));
|
||||
} catch (Error & error) {
|
||||
printError("diff hook execution failed: %s", error.what());
|
||||
ErrorInfo ei = error.info();
|
||||
ei.hint = hintfmt("diff hook execution failed: %s",
|
||||
(error.info().hint.has_value() ? error.info().hint->str() : ""));
|
||||
logError(ei);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -542,37 +548,37 @@ bool UserLock::findFreeUser() {
|
|||
/* Get the members of the build-users-group. */
|
||||
struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str());
|
||||
if (!gr)
|
||||
throw Error(format("the group '%1%' specified in 'build-users-group' does not exist")
|
||||
% settings.buildUsersGroup);
|
||||
throw Error("the group '%1%' specified in 'build-users-group' does not exist",
|
||||
settings.buildUsersGroup);
|
||||
gid = gr->gr_gid;
|
||||
|
||||
/* Copy the result of getgrnam. */
|
||||
Strings users;
|
||||
for (char * * p = gr->gr_mem; *p; ++p) {
|
||||
debug(format("found build user '%1%'") % *p);
|
||||
debug("found build user '%1%'", *p);
|
||||
users.push_back(*p);
|
||||
}
|
||||
|
||||
if (users.empty())
|
||||
throw Error(format("the build users group '%1%' has no members")
|
||||
% settings.buildUsersGroup);
|
||||
throw Error("the build users group '%1%' has no members",
|
||||
settings.buildUsersGroup);
|
||||
|
||||
/* Find a user account that isn't currently in use for another
|
||||
build. */
|
||||
for (auto & i : users) {
|
||||
debug(format("trying user '%1%'") % i);
|
||||
debug("trying user '%1%'", i);
|
||||
|
||||
struct passwd * pw = getpwnam(i.c_str());
|
||||
if (!pw)
|
||||
throw Error(format("the user '%1%' in the group '%2%' does not exist")
|
||||
% i % settings.buildUsersGroup);
|
||||
throw Error("the user '%1%' in the group '%2%' does not exist",
|
||||
i, settings.buildUsersGroup);
|
||||
|
||||
|
||||
fnUserLock = (format("%1%/userpool/%2%") % settings.nixStateDir % pw->pw_uid).str();
|
||||
|
||||
AutoCloseFD fd = open(fnUserLock.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600);
|
||||
if (!fd)
|
||||
throw SysError(format("opening user lock '%1%'") % fnUserLock);
|
||||
throw SysError("opening user lock '%1%'", fnUserLock);
|
||||
|
||||
if (lockFile(fd.get(), ltWrite, false)) {
|
||||
fdUserLock = std::move(fd);
|
||||
|
|
@ -581,8 +587,8 @@ bool UserLock::findFreeUser() {
|
|||
|
||||
/* Sanity check... */
|
||||
if (uid == getuid() || uid == geteuid())
|
||||
throw Error(format("the Nix user should not be a member of '%1%'")
|
||||
% settings.buildUsersGroup);
|
||||
throw Error("the Nix user should not be a member of '%1%'",
|
||||
settings.buildUsersGroup);
|
||||
|
||||
#if __linux__
|
||||
/* Get the list of supplementary groups of this build user. This
|
||||
|
|
@ -592,7 +598,7 @@ bool UserLock::findFreeUser() {
|
|||
int err = getgrouplist(pw->pw_name, pw->pw_gid,
|
||||
supplementaryGIDs.data(), &ngroups);
|
||||
if (err == -1)
|
||||
throw Error(format("failed to get list of supplementary groups for '%1%'") % pw->pw_name);
|
||||
throw Error("failed to get list of supplementary groups for '%1%'", pw->pw_name);
|
||||
|
||||
supplementaryGIDs.resize(ngroups);
|
||||
#endif
|
||||
|
|
@ -601,6 +607,7 @@ bool UserLock::findFreeUser() {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1151,7 +1158,10 @@ void DerivationGoal::loadDerivation()
|
|||
trace("loading derivation");
|
||||
|
||||
if (nrFailed != 0) {
|
||||
printError("cannot build missing derivation '%s'", worker.store.printStorePath(drvPath));
|
||||
logError({
|
||||
.name = "missing derivation during build",
|
||||
.hint = hintfmt("cannot build missing derivation '%s'", worker.store.printStorePath(drvPath))
|
||||
});
|
||||
done(BuildResult::MiscFailure);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1302,8 +1312,12 @@ void DerivationGoal::repairClosure()
|
|||
/* Check each path (slow!). */
|
||||
for (auto & i : outputClosure) {
|
||||
if (worker.pathContentsGood(i)) continue;
|
||||
printError("found corrupted or missing path '%s' in the output closure of '%s'",
|
||||
worker.store.printStorePath(i), worker.store.printStorePath(drvPath));
|
||||
logError({
|
||||
.name = "Corrupt path in closure",
|
||||
.hint = hintfmt(
|
||||
"found corrupted or missing path '%s' in the output closure of '%s'",
|
||||
worker.store.printStorePath(i), worker.store.printStorePath(drvPath))
|
||||
});
|
||||
auto drvPath2 = outputsToDrv.find(i);
|
||||
if (drvPath2 == outputsToDrv.end())
|
||||
addWaitee(worker.makeSubstitutionGoal(i, Repair));
|
||||
|
|
@ -1337,8 +1351,12 @@ void DerivationGoal::inputsRealised()
|
|||
if (nrFailed != 0) {
|
||||
if (!useDerivation)
|
||||
throw Error("some dependencies of '%s' are missing", worker.store.printStorePath(drvPath));
|
||||
printError("cannot build derivation '%s': %s dependencies couldn't be built",
|
||||
worker.store.printStorePath(drvPath), nrFailed);
|
||||
logError({
|
||||
.name = "Dependencies could not be built",
|
||||
.hint = hintfmt(
|
||||
"cannot build derivation '%s': %s dependencies couldn't be built",
|
||||
worker.store.printStorePath(drvPath), nrFailed)
|
||||
});
|
||||
done(BuildResult::DependencyFailed);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1523,7 +1541,7 @@ void DerivationGoal::tryLocalBuild() {
|
|||
startBuilder();
|
||||
|
||||
} catch (BuildError & e) {
|
||||
printError(e.msg());
|
||||
logError(e.info());
|
||||
outputLocks.unlock();
|
||||
buildUser.reset();
|
||||
worker.permanentFailure = true;
|
||||
|
|
@ -1740,7 +1758,7 @@ void DerivationGoal::buildDone()
|
|||
outputLocks.unlock();
|
||||
|
||||
} catch (BuildError & e) {
|
||||
printError(e.msg());
|
||||
logError(e.info());
|
||||
|
||||
outputLocks.unlock();
|
||||
|
||||
|
|
@ -1803,7 +1821,7 @@ HookReply DerivationGoal::tryBuildHook()
|
|||
}
|
||||
}
|
||||
|
||||
debug(format("hook reply is '%1%'") % reply);
|
||||
debug("hook reply is '%1%'", reply);
|
||||
|
||||
if (reply == "decline")
|
||||
return rpDecline;
|
||||
|
|
@ -1819,8 +1837,12 @@ HookReply DerivationGoal::tryBuildHook()
|
|||
|
||||
} catch (SysError & e) {
|
||||
if (e.errNo == EPIPE) {
|
||||
printError("build hook died unexpectedly: %s",
|
||||
chomp(drainFD(worker.hook->fromHook.readSide.get())));
|
||||
logError({
|
||||
.name = "Build hook died",
|
||||
.hint = hintfmt(
|
||||
"build hook died unexpectedly: %s",
|
||||
chomp(drainFD(worker.hook->fromHook.readSide.get())))
|
||||
});
|
||||
worker.hook = 0;
|
||||
return rpDecline;
|
||||
} else
|
||||
|
|
@ -2000,7 +2022,7 @@ void DerivationGoal::startBuilder()
|
|||
string s = get(drv->env, "exportReferencesGraph").value_or("");
|
||||
Strings ss = tokenizeString<Strings>(s);
|
||||
if (ss.size() % 2 != 0)
|
||||
throw BuildError(format("odd number of tokens in 'exportReferencesGraph': '%1%'") % s);
|
||||
throw BuildError("odd number of tokens in 'exportReferencesGraph': '%1%'", s);
|
||||
for (Strings::iterator i = ss.begin(); i != ss.end(); ) {
|
||||
string fileName = *i++;
|
||||
static std::regex regex("[A-Za-z_][A-Za-z0-9_.-]*");
|
||||
|
|
@ -2049,7 +2071,7 @@ void DerivationGoal::startBuilder()
|
|||
worker.store.computeFSClosure(worker.store.parseStorePath(worker.store.toStorePath(i.second.source)), closure);
|
||||
} catch (InvalidPath & e) {
|
||||
} catch (Error & e) {
|
||||
throw Error(format("while processing 'sandbox-paths': %s") % e.what());
|
||||
throw Error("while processing 'sandbox-paths': %s", e.what());
|
||||
}
|
||||
for (auto & i : closure) {
|
||||
auto p = worker.store.printStorePath(i);
|
||||
|
|
@ -2096,10 +2118,10 @@ void DerivationGoal::startBuilder()
|
|||
printMsg(lvlChatty, format("setting up chroot environment in '%1%'") % chrootRootDir);
|
||||
|
||||
if (mkdir(chrootRootDir.c_str(), 0750) == -1)
|
||||
throw SysError(format("cannot create '%1%'") % chrootRootDir);
|
||||
throw SysError("cannot create '%1%'", chrootRootDir);
|
||||
|
||||
if (buildUser && chown(chrootRootDir.c_str(), 0, buildUser->getGID()) == -1)
|
||||
throw SysError(format("cannot change ownership of '%1%'") % chrootRootDir);
|
||||
throw SysError("cannot change ownership of '%1%'", chrootRootDir);
|
||||
|
||||
/* Create a writable /tmp in the chroot. Many builders need
|
||||
this. (Of course they should really respect $TMPDIR
|
||||
|
|
@ -2143,7 +2165,7 @@ void DerivationGoal::startBuilder()
|
|||
chmod_(chrootStoreDir, 01775);
|
||||
|
||||
if (buildUser && chown(chrootStoreDir.c_str(), 0, buildUser->getGID()) == -1)
|
||||
throw SysError(format("cannot change ownership of '%1%'") % chrootStoreDir);
|
||||
throw SysError("cannot change ownership of '%1%'", chrootStoreDir);
|
||||
|
||||
for (auto & i : inputPaths) {
|
||||
auto p = worker.store.printStorePath(i);
|
||||
|
|
@ -2176,7 +2198,7 @@ void DerivationGoal::startBuilder()
|
|||
if (needsHashRewrite()) {
|
||||
|
||||
if (pathExists(homeDir))
|
||||
throw Error(format("home directory '%1%' exists; please remove it to assure purity of builds without sandboxing") % homeDir);
|
||||
throw Error("home directory '%1%' exists; please remove it to assure purity of builds without sandboxing", homeDir);
|
||||
|
||||
/* We're not doing a chroot build, but we have some valid
|
||||
output paths. Since we can't just overwrite or delete
|
||||
|
|
@ -2221,8 +2243,7 @@ void DerivationGoal::startBuilder()
|
|||
if (line == "extra-sandbox-paths" || line == "extra-chroot-dirs") {
|
||||
state = stExtraChrootDirs;
|
||||
} else {
|
||||
throw Error(format("unknown pre-build hook command '%1%'")
|
||||
% line);
|
||||
throw Error("unknown pre-build hook command '%1%'", line);
|
||||
}
|
||||
} else if (state == stExtraChrootDirs) {
|
||||
if (line == "") {
|
||||
|
|
@ -2244,7 +2265,7 @@ void DerivationGoal::startBuilder()
|
|||
startDaemon();
|
||||
|
||||
/* Run the builder. */
|
||||
printMsg(lvlChatty, format("executing builder '%1%'") % drv->builder);
|
||||
printMsg(lvlChatty, "executing builder '%1%'", drv->builder);
|
||||
|
||||
/* Create the log file. */
|
||||
Path logFile = openLogFile();
|
||||
|
|
@ -2982,7 +3003,7 @@ void DerivationGoal::chownToBuilder(const Path & path)
|
|||
{
|
||||
if (!buildUser) return;
|
||||
if (chown(path.c_str(), buildUser->getUID(), buildUser->getGID()) == -1)
|
||||
throw SysError(format("cannot change ownership of '%1%'") % path);
|
||||
throw SysError("cannot change ownership of '%1%'", path);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -3119,7 +3140,7 @@ void DerivationGoal::runChild()
|
|||
/* Bind-mount chroot directory to itself, to treat it as a
|
||||
different filesystem from /, as needed for pivot_root. */
|
||||
if (mount(chrootRootDir.c_str(), chrootRootDir.c_str(), 0, MS_BIND, 0) == -1)
|
||||
throw SysError(format("unable to bind mount '%1%'") % chrootRootDir);
|
||||
throw SysError("unable to bind mount '%1%'", chrootRootDir);
|
||||
|
||||
/* Bind-mount the sandbox's Nix store onto itself so that
|
||||
we can mark it as a "shared" subtree, allowing bind
|
||||
|
|
@ -3181,7 +3202,7 @@ void DerivationGoal::runChild()
|
|||
filesystem that we want in the chroot
|
||||
environment. */
|
||||
auto doBind = [&](const Path & source, const Path & target, bool optional = false) {
|
||||
debug(format("bind mounting '%1%' to '%2%'") % source % target);
|
||||
debug("bind mounting '%1%' to '%2%'", source, target);
|
||||
struct stat st;
|
||||
if (stat(source.c_str(), &st) == -1) {
|
||||
if (optional && errno == ENOENT)
|
||||
|
|
@ -3253,16 +3274,16 @@ void DerivationGoal::runChild()
|
|||
|
||||
/* Do the chroot(). */
|
||||
if (chdir(chrootRootDir.c_str()) == -1)
|
||||
throw SysError(format("cannot change directory to '%1%'") % chrootRootDir);
|
||||
throw SysError("cannot change directory to '%1%'", chrootRootDir);
|
||||
|
||||
if (mkdir("real-root", 0) == -1)
|
||||
throw SysError("cannot create real-root directory");
|
||||
|
||||
if (pivot_root(".", "real-root") == -1)
|
||||
throw SysError(format("cannot pivot old root directory onto '%1%'") % (chrootRootDir + "/real-root"));
|
||||
throw SysError("cannot pivot old root directory onto '%1%'", (chrootRootDir + "/real-root"));
|
||||
|
||||
if (chroot(".") == -1)
|
||||
throw SysError(format("cannot change root directory to '%1%'") % chrootRootDir);
|
||||
throw SysError("cannot change root directory to '%1%'", chrootRootDir);
|
||||
|
||||
if (umount2("real-root", MNT_DETACH) == -1)
|
||||
throw SysError("cannot unmount real root filesystem");
|
||||
|
|
@ -3283,7 +3304,7 @@ void DerivationGoal::runChild()
|
|||
#endif
|
||||
|
||||
if (chdir(tmpDirInSandbox.c_str()) == -1)
|
||||
throw SysError(format("changing into '%1%'") % tmpDir);
|
||||
throw SysError("changing into '%1%'", tmpDir);
|
||||
|
||||
/* Close all other file descriptors. */
|
||||
closeMostFDs({STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO});
|
||||
|
|
@ -3422,9 +3443,9 @@ void DerivationGoal::runChild()
|
|||
sandboxProfile += "(allow file-read* file-write* process-exec\n";
|
||||
for (auto & i : dirsInChroot) {
|
||||
if (i.first != i.second.source)
|
||||
throw Error(format(
|
||||
"can't map '%1%' to '%2%': mismatched impure paths not supported on Darwin")
|
||||
% i.first % i.second.source);
|
||||
throw Error(
|
||||
"can't map '%1%' to '%2%': mismatched impure paths not supported on Darwin",
|
||||
i.first, i.second.source);
|
||||
|
||||
string path = i.first;
|
||||
struct stat st;
|
||||
|
|
@ -3515,7 +3536,7 @@ void DerivationGoal::runChild()
|
|||
else if (drv->builder == "builtin:unpack-channel")
|
||||
builtinUnpackChannel(drv2);
|
||||
else
|
||||
throw Error(format("unsupported builtin function '%1%'") % string(drv->builder, 8));
|
||||
throw Error("unsupported builtin function '%1%'", string(drv->builder, 8));
|
||||
_exit(0);
|
||||
} catch (std::exception & e) {
|
||||
writeFull(STDERR_FILENO, "error: " + string(e.what()) + "\n");
|
||||
|
|
@ -3525,7 +3546,7 @@ void DerivationGoal::runChild()
|
|||
|
||||
execve(builder, stringsToCharPtrs(args).data(), stringsToCharPtrs(envStrs).data());
|
||||
|
||||
throw SysError(format("executing '%1%'") % drv->builder);
|
||||
throw SysError("executing '%1%'", drv->builder);
|
||||
|
||||
} catch (std::exception & e) {
|
||||
writeFull(STDERR_FILENO, "\1while setting up the build environment: " + string(e.what()) + "\n");
|
||||
|
|
@ -3558,7 +3579,7 @@ static void moveCheckToStore(const Path & src, const Path & dst)
|
|||
directory's parent link ".."). */
|
||||
struct stat st;
|
||||
if (lstat(src.c_str(), &st) == -1) {
|
||||
throw SysError(format("getting attributes of path '%1%'") % src);
|
||||
throw SysError("getting attributes of path '%1%'", src);
|
||||
}
|
||||
|
||||
bool changePerm = (geteuid() && S_ISDIR(st.st_mode) && !(st.st_mode & S_IWUSR));
|
||||
|
|
@ -3567,7 +3588,7 @@ static void moveCheckToStore(const Path & src, const Path & dst)
|
|||
chmod_(src, st.st_mode | S_IWUSR);
|
||||
|
||||
if (rename(src.c_str(), dst.c_str()))
|
||||
throw SysError(format("renaming '%1%' to '%2%'") % src % dst);
|
||||
throw SysError("renaming '%1%' to '%2%'", src, dst);
|
||||
|
||||
if (changePerm)
|
||||
chmod_(dst, st.st_mode);
|
||||
|
|
@ -3633,7 +3654,7 @@ void DerivationGoal::registerOutputs()
|
|||
replaceValidPath(path, actualPath);
|
||||
else
|
||||
if (buildMode != bmCheck && rename(actualPath.c_str(), worker.store.toRealPath(path).c_str()) == -1)
|
||||
throw SysError(format("moving build output '%1%' from the sandbox to the Nix store") % path);
|
||||
throw SysError("moving build output '%1%' from the sandbox to the Nix store", path);
|
||||
}
|
||||
if (buildMode != bmCheck) actualPath = worker.store.toRealPath(path);
|
||||
}
|
||||
|
|
@ -3654,13 +3675,16 @@ void DerivationGoal::registerOutputs()
|
|||
user. */
|
||||
if ((!S_ISLNK(st.st_mode) && (st.st_mode & (S_IWGRP | S_IWOTH))) ||
|
||||
(buildUser && st.st_uid != buildUser->getUID()))
|
||||
throw BuildError(format("suspicious ownership or permission on '%1%'; rejecting this build output") % path);
|
||||
throw BuildError("suspicious ownership or permission on '%1%'; rejecting this build output", path);
|
||||
#endif
|
||||
|
||||
/* Apply hash rewriting if necessary. */
|
||||
bool rewritten = false;
|
||||
if (!outputRewrites.empty()) {
|
||||
printError(format("warning: rewriting hashes in '%1%'; cross fingers") % path);
|
||||
logWarning({
|
||||
.name = "Rewriting hashes",
|
||||
.hint = hintfmt("rewriting hashes in '%1%'; cross fingers", path)
|
||||
});
|
||||
|
||||
/* Canonicalise first. This ensures that the path we're
|
||||
rewriting doesn't contain a hard link to /etc/shadow or
|
||||
|
|
@ -3692,8 +3716,9 @@ void DerivationGoal::registerOutputs()
|
|||
/* The output path should be a regular file without execute permission. */
|
||||
if (!S_ISREG(st.st_mode) || (st.st_mode & S_IXUSR) != 0)
|
||||
throw BuildError(
|
||||
format("output path '%1%' should be a non-executable regular file "
|
||||
"since recursive hashing is not enabled (outputHashMode=flat)") % path);
|
||||
"output path '%1%' should be a non-executable regular file "
|
||||
"since recursive hashing is not enabled (outputHashMode=flat)",
|
||||
path);
|
||||
}
|
||||
|
||||
/* Check the hash. In hash mode, move the path produced by
|
||||
|
|
@ -3823,10 +3848,10 @@ void DerivationGoal::registerOutputs()
|
|||
result.isNonDeterministic = true;
|
||||
Path prev = worker.store.printStorePath(i->second.path) + checkSuffix;
|
||||
bool prevExists = keepPreviousRound && pathExists(prev);
|
||||
auto msg = prevExists
|
||||
? fmt("output '%s' of '%s' differs from '%s' from previous round",
|
||||
hintformat hint = prevExists
|
||||
? hintfmt("output '%s' of '%s' differs from '%s' from previous round",
|
||||
worker.store.printStorePath(i->second.path), worker.store.printStorePath(drvPath), prev)
|
||||
: fmt("output '%s' of '%s' differs from previous round",
|
||||
: hintfmt("output '%s' of '%s' differs from previous round",
|
||||
worker.store.printStorePath(i->second.path), worker.store.printStorePath(drvPath));
|
||||
|
||||
handleDiffHook(
|
||||
|
|
@ -3836,9 +3861,14 @@ void DerivationGoal::registerOutputs()
|
|||
worker.store.printStorePath(drvPath), tmpDir);
|
||||
|
||||
if (settings.enforceDeterminism)
|
||||
throw NotDeterministic(msg);
|
||||
throw NotDeterministic(hint);
|
||||
|
||||
logError({
|
||||
.name = "Output determinism error",
|
||||
.hint = hint
|
||||
});
|
||||
|
||||
|
||||
printError(msg);
|
||||
curRound = nrRounds; // we know enough, bail out early
|
||||
}
|
||||
}
|
||||
|
|
@ -4056,7 +4086,7 @@ Path DerivationGoal::openLogFile()
|
|||
settings.compressLog ? ".bz2" : "");
|
||||
|
||||
fdLogFile = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0666);
|
||||
if (!fdLogFile) throw SysError(format("creating log file '%1%'") % logFileName);
|
||||
if (!fdLogFile) throw SysError("creating log file '%1%'", logFileName);
|
||||
|
||||
logFileSink = std::make_shared<FdSink>(fdLogFile.get());
|
||||
|
||||
|
|
@ -4102,9 +4132,12 @@ void DerivationGoal::handleChildOutput(int fd, const string & data)
|
|||
{
|
||||
logSize += data.size();
|
||||
if (settings.maxLogSize && logSize > settings.maxLogSize) {
|
||||
printError(
|
||||
format("%1% killed after writing more than %2% bytes of log output")
|
||||
% getName() % settings.maxLogSize);
|
||||
logError({
|
||||
.name = "Max log size exceeded",
|
||||
.hint = hintfmt(
|
||||
"%1% killed after writing more than %2% bytes of log output",
|
||||
getName(), settings.maxLogSize)
|
||||
});
|
||||
killChild();
|
||||
done(BuildResult::LogLimitExceeded);
|
||||
return;
|
||||
|
|
@ -4389,7 +4422,7 @@ void SubstitutionGoal::tryNext()
|
|||
throw;
|
||||
} catch (Error & e) {
|
||||
if (settings.tryFallback) {
|
||||
printError(e.what());
|
||||
logError(e.info());
|
||||
tryNext();
|
||||
return;
|
||||
}
|
||||
|
|
@ -4415,8 +4448,11 @@ void SubstitutionGoal::tryNext()
|
|||
&& !sub->isTrusted
|
||||
&& !info->checkSignatures(worker.store, worker.store.getPublicKeys()))
|
||||
{
|
||||
printError("warning: substituter '%s' does not have a valid signature for path '%s'",
|
||||
sub->getUri(), worker.store.printStorePath(storePath));
|
||||
logWarning({
|
||||
.name = "Invalid path signature",
|
||||
.hint = hintfmt("substituter '%s' does not have a valid signature for path '%s'",
|
||||
sub->getUri(), worker.store.printStorePath(storePath))
|
||||
});
|
||||
tryNext();
|
||||
return;
|
||||
}
|
||||
|
|
@ -4559,7 +4595,6 @@ void SubstitutionGoal::handleEOF(int fd)
|
|||
if (fd == outPipe.readSide.get()) worker.wakeUp(shared_from_this());
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
|
@ -4776,9 +4811,9 @@ void Worker::run(const Goals & _topGoals)
|
|||
if (!children.empty() || !waitingForAWhile.empty())
|
||||
waitForInput();
|
||||
else {
|
||||
if (awake.empty() && 0 == settings.maxBuildJobs) throw Error(
|
||||
"unable to start any build; either increase '--max-jobs' "
|
||||
"or enable remote builds");
|
||||
if (awake.empty() && 0 == settings.maxBuildJobs)
|
||||
throw Error("unable to start any build; either increase '--max-jobs' "
|
||||
"or enable remote builds");
|
||||
assert(!awake.empty());
|
||||
}
|
||||
}
|
||||
|
|
@ -4791,7 +4826,6 @@ void Worker::run(const Goals & _topGoals)
|
|||
assert(!settings.keepGoing || children.empty());
|
||||
}
|
||||
|
||||
|
||||
void Worker::waitForInput()
|
||||
{
|
||||
printMsg(lvlVomit, "waiting for children");
|
||||
|
|
@ -4830,7 +4864,7 @@ void Worker::waitForInput()
|
|||
if (!waitingForAWhile.empty()) {
|
||||
useTimeout = true;
|
||||
if (lastWokenUp == steady_time_point::min())
|
||||
printError("waiting for locks, build slots or build users...");
|
||||
printInfo("waiting for locks, build slots or build users...");
|
||||
if (lastWokenUp == steady_time_point::min() || lastWokenUp > before) lastWokenUp = before;
|
||||
timeout = std::max(1L,
|
||||
(long) std::chrono::duration_cast<std::chrono::seconds>(
|
||||
|
|
@ -4879,15 +4913,15 @@ void Worker::waitForInput()
|
|||
// FIXME: is there a cleaner way to handle pt close
|
||||
// than EIO? Is this even standard?
|
||||
if (rd == 0 || (rd == -1 && errno == EIO)) {
|
||||
debug(format("%1%: got EOF") % goal->getName());
|
||||
debug("%1%: got EOF", goal->getName());
|
||||
goal->handleEOF(k);
|
||||
j->fds.erase(k);
|
||||
} else if (rd == -1) {
|
||||
if (errno != EINTR)
|
||||
throw SysError("%s: read failed", goal->getName());
|
||||
} else {
|
||||
printMsg(lvlVomit, format("%1%: read %2% bytes")
|
||||
% goal->getName() % rd);
|
||||
printMsg(lvlVomit, "%1%: read %2% bytes",
|
||||
goal->getName(), rd);
|
||||
string data((char *) buffer.data(), rd);
|
||||
j->lastOutput = after;
|
||||
goal->handleChildOutput(k, data);
|
||||
|
|
@ -4900,9 +4934,12 @@ void Worker::waitForInput()
|
|||
j->respectTimeouts &&
|
||||
after - j->lastOutput >= std::chrono::seconds(settings.maxSilentTime))
|
||||
{
|
||||
printError(
|
||||
format("%1% timed out after %2% seconds of silence")
|
||||
% goal->getName() % settings.maxSilentTime);
|
||||
logError({
|
||||
.name = "Silent build timeout",
|
||||
.hint = hintfmt(
|
||||
"%1% timed out after %2% seconds of silence",
|
||||
goal->getName(), settings.maxSilentTime)
|
||||
});
|
||||
goal->timedOut();
|
||||
}
|
||||
|
||||
|
|
@ -4911,9 +4948,12 @@ void Worker::waitForInput()
|
|||
j->respectTimeouts &&
|
||||
after - j->timeStarted >= std::chrono::seconds(settings.buildTimeout))
|
||||
{
|
||||
printError(
|
||||
format("%1% timed out after %2% seconds")
|
||||
% goal->getName() % settings.buildTimeout);
|
||||
logError({
|
||||
.name = "Build timeout",
|
||||
.hint = hintfmt(
|
||||
"%1% timed out after %2% seconds",
|
||||
goal->getName(), settings.buildTimeout)
|
||||
});
|
||||
goal->timedOut();
|
||||
}
|
||||
}
|
||||
|
|
@ -4972,7 +5012,11 @@ bool Worker::pathContentsGood(const StorePath & path)
|
|||
res = info->narHash == nullHash || info->narHash == current.first;
|
||||
}
|
||||
pathContentsGoodCache.insert_or_assign(path.clone(), res);
|
||||
if (!res) printError("path '%s' is corrupted or missing!", store.printStorePath(path));
|
||||
if (!res)
|
||||
logError({
|
||||
.name = "Corrupted path",
|
||||
.hint = hintfmt("path '%s' is corrupted or missing!", store.printStorePath(path))
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -5028,7 +5072,6 @@ void LocalStore::buildPaths(const std::vector<StorePathWithOutputs> & drvPaths,
|
|||
throw Error(worker.exitStatus(), "build of %s failed", showPaths(failed));
|
||||
}
|
||||
|
||||
|
||||
BuildResult LocalStore::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv,
|
||||
BuildMode buildMode)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,7 +22,11 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
|
|||
srcFiles = readDirectory(srcDir);
|
||||
} catch (SysError & e) {
|
||||
if (e.errNo == ENOTDIR) {
|
||||
printError("warning: not including '%s' in the user environment because it's not a directory", srcDir);
|
||||
logWarning(
|
||||
ErrorInfo {
|
||||
.name = "Create links - directory",
|
||||
.hint = hintfmt("not including '%s' in the user environment because it's not a directory", srcDir)
|
||||
});
|
||||
return;
|
||||
}
|
||||
throw;
|
||||
|
|
@ -41,7 +45,11 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
|
|||
throw SysError("getting status of '%1%'", srcFile);
|
||||
} catch (SysError & e) {
|
||||
if (e.errNo == ENOENT || e.errNo == ENOTDIR) {
|
||||
printError("warning: skipping dangling symlink '%s'", dstFile);
|
||||
logWarning(
|
||||
ErrorInfo {
|
||||
.name = "Create links - skipping symlink",
|
||||
.hint = hintfmt("skipping dangling symlink '%s'", dstFile)
|
||||
});
|
||||
continue;
|
||||
}
|
||||
throw;
|
||||
|
|
@ -72,15 +80,15 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
|
|||
if (!S_ISDIR(lstat(target).st_mode))
|
||||
throw Error("collision between '%1%' and non-directory '%2%'", srcFile, target);
|
||||
if (unlink(dstFile.c_str()) == -1)
|
||||
throw SysError(format("unlinking '%1%'") % dstFile);
|
||||
throw SysError("unlinking '%1%'", dstFile);
|
||||
if (mkdir(dstFile.c_str(), 0755) == -1)
|
||||
throw SysError(format("creating directory '%1%'"));
|
||||
throw SysError("creating directory '%1%'", dstFile);
|
||||
createLinks(state, target, dstFile, state.priorities[dstFile]);
|
||||
createLinks(state, srcFile, dstFile, priority);
|
||||
continue;
|
||||
}
|
||||
} else if (errno != ENOENT)
|
||||
throw SysError(format("getting status of '%1%'") % dstFile);
|
||||
throw SysError("getting status of '%1%'", dstFile);
|
||||
}
|
||||
|
||||
else {
|
||||
|
|
@ -99,11 +107,11 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
|
|||
if (prevPriority < priority)
|
||||
continue;
|
||||
if (unlink(dstFile.c_str()) == -1)
|
||||
throw SysError(format("unlinking '%1%'") % dstFile);
|
||||
throw SysError("unlinking '%1%'", dstFile);
|
||||
} else if (S_ISDIR(dstSt.st_mode))
|
||||
throw Error("collision between non-directory '%1%' and directory '%2%'", srcFile, dstFile);
|
||||
} else if (errno != ENOENT)
|
||||
throw SysError(format("getting status of '%1%'") % dstFile);
|
||||
throw SysError("getting status of '%1%'", dstFile);
|
||||
}
|
||||
|
||||
createSymlink(srcFile, dstFile);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData)
|
|||
|
||||
auto getAttr = [&](const string & name) {
|
||||
auto i = drv.env.find(name);
|
||||
if (i == drv.env.end()) throw Error(format("attribute '%s' missing") % name);
|
||||
if (i == drv.env.end()) throw Error("attribute '%s' missing", name);
|
||||
return i->second;
|
||||
};
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData)
|
|||
auto executable = drv.env.find("executable");
|
||||
if (executable != drv.env.end() && executable->second == "1") {
|
||||
if (chmod(storePath.c_str(), 0755) == -1)
|
||||
throw SysError(format("making '%1%' executable") % storePath);
|
||||
throw SysError("making '%1%' executable", storePath);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,18 @@ struct TunnelLogger : public Logger
|
|||
enqueueMsg(*buf.s);
|
||||
}
|
||||
|
||||
void logEI(const ErrorInfo & ei) override
|
||||
{
|
||||
if (ei.level > verbosity) return;
|
||||
|
||||
std::stringstream oss;
|
||||
oss << ei;
|
||||
|
||||
StringSink buf;
|
||||
buf << STDERR_NEXT << oss.str() << "\n"; // (fs.s + "\n");
|
||||
enqueueMsg(*buf.s);
|
||||
}
|
||||
|
||||
/* startWork() means that we're starting an operation for which we
|
||||
want to send out stderr to the client. */
|
||||
void startWork()
|
||||
|
|
@ -744,7 +756,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
|
|||
}
|
||||
|
||||
default:
|
||||
throw Error(format("invalid operation %1%") % op);
|
||||
throw Error("invalid operation %1%", op);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ static void expect(std::istream & str, const string & s)
|
|||
char s2[s.size()];
|
||||
str.read(s2, s.size());
|
||||
if (string(s2, s.size()) != s)
|
||||
throw FormatError(format("expected string '%1%'") % s);
|
||||
throw FormatError("expected string '%1%'", s);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ static Path parsePath(std::istream & str)
|
|||
{
|
||||
string s = parseString(str);
|
||||
if (s.size() == 0 || s[0] != '/')
|
||||
throw FormatError(format("bad path '%1%' in derivation") % s);
|
||||
throw FormatError("bad path '%1%' in derivation", s);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
@ -196,7 +196,7 @@ Derivation readDerivation(const Store & store, const Path & drvPath)
|
|||
try {
|
||||
return parseDerivation(store, readFile(drvPath));
|
||||
} catch (FormatError & e) {
|
||||
throw Error(format("error parsing derivation '%1%': %2%") % drvPath % e.msg());
|
||||
throw Error("error parsing derivation '%1%': %2%", drvPath, e.msg());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ struct curlFileTransfer : public FileTransfer
|
|||
if (requestHeaders) curl_slist_free_all(requestHeaders);
|
||||
try {
|
||||
if (!done)
|
||||
fail(FileTransferError(Interrupted, format("download of '%s' was interrupted") % request.uri));
|
||||
fail(FileTransferError(Interrupted, "download of '%s' was interrupted", request.uri));
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
|
|
@ -517,7 +517,7 @@ struct curlFileTransfer : public FileTransfer
|
|||
int running;
|
||||
CURLMcode mc = curl_multi_perform(curlm, &running);
|
||||
if (mc != CURLM_OK)
|
||||
throw nix::Error(format("unexpected error from curl_multi_perform(): %s") % curl_multi_strerror(mc));
|
||||
throw nix::Error("unexpected error from curl_multi_perform(): %s", curl_multi_strerror(mc));
|
||||
|
||||
/* Set the promises of any finished requests. */
|
||||
CURLMsg * msg;
|
||||
|
|
@ -547,7 +547,7 @@ struct curlFileTransfer : public FileTransfer
|
|||
vomit("download thread waiting for %d ms", sleepTimeMs);
|
||||
mc = curl_multi_wait(curlm, extraFDs, 1, sleepTimeMs, &numfds);
|
||||
if (mc != CURLM_OK)
|
||||
throw nix::Error(format("unexpected error from curl_multi_wait(): %s") % curl_multi_strerror(mc));
|
||||
throw nix::Error("unexpected error from curl_multi_wait(): %s", curl_multi_strerror(mc));
|
||||
|
||||
nextWakeup = std::chrono::steady_clock::time_point();
|
||||
|
||||
|
|
@ -599,7 +599,11 @@ struct curlFileTransfer : public FileTransfer
|
|||
workerThreadMain();
|
||||
} catch (nix::Interrupted & e) {
|
||||
} catch (std::exception & e) {
|
||||
printError("unexpected error in download thread: %s", e.what());
|
||||
logError({
|
||||
.name = "File transfer",
|
||||
.hint = hintfmt("unexpected error in download thread: %s",
|
||||
e.what())
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -103,8 +103,9 @@ class FileTransferError : public Error
|
|||
{
|
||||
public:
|
||||
FileTransfer::Error error;
|
||||
FileTransferError(FileTransfer::Error error, const FormatOrString & fs)
|
||||
: Error(fs), error(error)
|
||||
template<typename... Args>
|
||||
FileTransferError(FileTransfer::Error error, const Args & ... args)
|
||||
: Error(args...), error(error)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -38,10 +38,10 @@ AutoCloseFD LocalStore::openGCLock(LockType lockType)
|
|||
|
||||
AutoCloseFD fdGCLock = open(fnGCLock.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600);
|
||||
if (!fdGCLock)
|
||||
throw SysError(format("opening global GC lock '%1%'") % fnGCLock);
|
||||
throw SysError("opening global GC lock '%1%'", fnGCLock);
|
||||
|
||||
if (!lockFile(fdGCLock.get(), lockType, false)) {
|
||||
printError(format("waiting for the big garbage collector lock..."));
|
||||
printInfo("waiting for the big garbage collector lock...");
|
||||
lockFile(fdGCLock.get(), lockType, true);
|
||||
}
|
||||
|
||||
|
|
@ -65,8 +65,8 @@ static void makeSymlink(const Path & link, const Path & target)
|
|||
|
||||
/* Atomically replace the old one. */
|
||||
if (rename(tempLink.c_str(), link.c_str()) == -1)
|
||||
throw SysError(format("cannot rename '%1%' to '%2%'")
|
||||
% tempLink % link);
|
||||
throw SysError("cannot rename '%1%' to '%2%'",
|
||||
tempLink , link);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -91,15 +91,15 @@ Path LocalFSStore::addPermRoot(const StorePath & storePath,
|
|||
Path gcRoot(canonPath(_gcRoot));
|
||||
|
||||
if (isInStore(gcRoot))
|
||||
throw Error(format(
|
||||
throw Error(
|
||||
"creating a garbage collector root (%1%) in the Nix store is forbidden "
|
||||
"(are you running nix-build inside the store?)") % gcRoot);
|
||||
"(are you running nix-build inside the store?)", gcRoot);
|
||||
|
||||
if (indirect) {
|
||||
/* Don't clobber the link if it already exists and doesn't
|
||||
point to the Nix store. */
|
||||
if (pathExists(gcRoot) && (!isLink(gcRoot) || !isInStore(readLink(gcRoot))))
|
||||
throw Error(format("cannot create symlink '%1%'; already exists") % gcRoot);
|
||||
throw Error("cannot create symlink '%1%'; already exists", gcRoot);
|
||||
makeSymlink(gcRoot, printStorePath(storePath));
|
||||
addIndirectRoot(gcRoot);
|
||||
}
|
||||
|
|
@ -109,10 +109,10 @@ Path LocalFSStore::addPermRoot(const StorePath & storePath,
|
|||
Path rootsDir = canonPath((format("%1%/%2%") % stateDir % gcRootsDir).str());
|
||||
|
||||
if (string(gcRoot, 0, rootsDir.size() + 1) != rootsDir + "/")
|
||||
throw Error(format(
|
||||
throw Error(
|
||||
"path '%1%' is not a valid garbage collector root; "
|
||||
"it's not in the directory '%2%'")
|
||||
% gcRoot % rootsDir);
|
||||
"it's not in the directory '%2%'",
|
||||
gcRoot, rootsDir);
|
||||
}
|
||||
|
||||
if (baseNameOf(gcRoot) == std::string(storePath.to_string()))
|
||||
|
|
@ -129,10 +129,13 @@ Path LocalFSStore::addPermRoot(const StorePath & storePath,
|
|||
if (settings.checkRootReachability) {
|
||||
auto roots = findRoots(false);
|
||||
if (roots[storePath.clone()].count(gcRoot) == 0)
|
||||
printError(
|
||||
"warning: '%1%' is not in a directory where the garbage collector looks for roots; "
|
||||
logWarning(
|
||||
ErrorInfo {
|
||||
.name = "GC root",
|
||||
.hint = hintfmt("warning: '%1%' is not in a directory where the garbage collector looks for roots; "
|
||||
"therefore, '%2%' might be removed by the garbage collector",
|
||||
gcRoot, printStorePath(storePath));
|
||||
gcRoot, printStorePath(storePath))
|
||||
});
|
||||
}
|
||||
|
||||
/* Grab the global GC root, causing us to block while a GC is in
|
||||
|
|
@ -170,7 +173,7 @@ void LocalStore::addTempRoot(const StorePath & path)
|
|||
way. */
|
||||
struct stat st;
|
||||
if (fstat(state->fdTempRoots.get(), &st) == -1)
|
||||
throw SysError(format("statting '%1%'") % fnTempRoots);
|
||||
throw SysError("statting '%1%'", fnTempRoots);
|
||||
if (st.st_size == 0) break;
|
||||
|
||||
/* The garbage collector deleted this file before we could
|
||||
|
|
@ -216,7 +219,7 @@ void LocalStore::findTempRoots(FDs & fds, Roots & tempRoots, bool censor)
|
|||
if (!*fd) {
|
||||
/* It's okay if the file has disappeared. */
|
||||
if (errno == ENOENT) continue;
|
||||
throw SysError(format("opening temporary roots file '%1%'") % path);
|
||||
throw SysError("opening temporary roots file '%1%'", path);
|
||||
}
|
||||
|
||||
/* This should work, but doesn't, for some reason. */
|
||||
|
|
@ -227,7 +230,7 @@ void LocalStore::findTempRoots(FDs & fds, Roots & tempRoots, bool censor)
|
|||
only succeed if the owning process has died. In that case
|
||||
we don't care about its temporary roots. */
|
||||
if (lockFile(fd->get(), ltWrite, false)) {
|
||||
printError(format("removing stale temporary roots file '%1%'") % path);
|
||||
printInfo("removing stale temporary roots file '%1%'", path);
|
||||
unlink(path.c_str());
|
||||
writeFull(fd->get(), "d");
|
||||
continue;
|
||||
|
|
@ -403,7 +406,7 @@ void LocalStore::findRuntimeRoots(Roots & roots, bool censor)
|
|||
if (!fdDir) {
|
||||
if (errno == ENOENT || errno == EACCES)
|
||||
continue;
|
||||
throw SysError(format("opening %1%") % fdStr);
|
||||
throw SysError("opening %1%", fdStr);
|
||||
}
|
||||
struct dirent * fd_ent;
|
||||
while (errno = 0, fd_ent = readdir(fdDir.get())) {
|
||||
|
|
@ -413,7 +416,7 @@ void LocalStore::findRuntimeRoots(Roots & roots, bool censor)
|
|||
if (errno) {
|
||||
if (errno == ESRCH)
|
||||
continue;
|
||||
throw SysError(format("iterating /proc/%1%/fd") % ent->d_name);
|
||||
throw SysError("iterating /proc/%1%/fd", ent->d_name);
|
||||
}
|
||||
fdDir.reset();
|
||||
|
||||
|
|
@ -541,7 +544,7 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path)
|
|||
struct stat st;
|
||||
if (lstat(realPath.c_str(), &st)) {
|
||||
if (errno == ENOENT) return;
|
||||
throw SysError(format("getting status of %1%") % realPath);
|
||||
throw SysError("getting status of %1%", realPath);
|
||||
}
|
||||
|
||||
printInfo(format("deleting '%1%'") % path);
|
||||
|
|
@ -559,10 +562,10 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path)
|
|||
// size.
|
||||
try {
|
||||
if (chmod(realPath.c_str(), st.st_mode | S_IWUSR) == -1)
|
||||
throw SysError(format("making '%1%' writable") % realPath);
|
||||
throw SysError("making '%1%' writable", realPath);
|
||||
Path tmp = trashDir + "/" + std::string(baseNameOf(path));
|
||||
if (rename(realPath.c_str(), tmp.c_str()))
|
||||
throw SysError(format("unable to rename '%1%' to '%2%'") % realPath % tmp);
|
||||
throw SysError("unable to rename '%1%' to '%2%'", realPath, tmp);
|
||||
state.bytesInvalidated += size;
|
||||
} catch (SysError & e) {
|
||||
if (e.errNo == ENOSPC) {
|
||||
|
|
@ -681,7 +684,7 @@ void LocalStore::tryToDelete(GCState & state, const Path & path)
|
|||
void LocalStore::removeUnusedLinks(const GCState & state)
|
||||
{
|
||||
AutoCloseDir dir(opendir(linksDir.c_str()));
|
||||
if (!dir) throw SysError(format("opening directory '%1%'") % linksDir);
|
||||
if (!dir) throw SysError("opening directory '%1%'", linksDir);
|
||||
|
||||
long long actualSize = 0, unsharedSize = 0;
|
||||
|
||||
|
|
@ -694,7 +697,7 @@ void LocalStore::removeUnusedLinks(const GCState & state)
|
|||
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st) == -1)
|
||||
throw SysError(format("statting '%1%'") % path);
|
||||
throw SysError("statting '%1%'", path);
|
||||
|
||||
if (st.st_nlink != 1) {
|
||||
actualSize += st.st_size;
|
||||
|
|
@ -705,14 +708,14 @@ void LocalStore::removeUnusedLinks(const GCState & state)
|
|||
printMsg(lvlTalkative, format("deleting unused link '%1%'") % path);
|
||||
|
||||
if (unlink(path.c_str()) == -1)
|
||||
throw SysError(format("deleting '%1%'") % path);
|
||||
throw SysError("deleting '%1%'", path);
|
||||
|
||||
state.results.bytesFreed += st.st_size;
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
if (stat(linksDir.c_str(), &st) == -1)
|
||||
throw SysError(format("statting '%1%'") % linksDir);
|
||||
throw SysError("statting '%1%'", linksDir);
|
||||
long long overhead = st.st_blocks * 512ULL;
|
||||
|
||||
printInfo(format("note: currently hard linking saves %.2f MiB")
|
||||
|
|
@ -747,7 +750,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
|
|||
|
||||
/* Find the roots. Since we've grabbed the GC lock, the set of
|
||||
permanent roots cannot increase now. */
|
||||
printError("finding garbage collector roots...");
|
||||
printInfo("finding garbage collector roots...");
|
||||
Roots rootMap;
|
||||
if (!options.ignoreLiveness)
|
||||
findRootsNoTemp(rootMap, true);
|
||||
|
|
@ -799,14 +802,14 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
|
|||
} else if (options.maxFreed > 0) {
|
||||
|
||||
if (state.shouldDelete)
|
||||
printError("deleting garbage...");
|
||||
printInfo("deleting garbage...");
|
||||
else
|
||||
printError("determining live/dead paths...");
|
||||
printInfo("determining live/dead paths...");
|
||||
|
||||
try {
|
||||
|
||||
AutoCloseDir dir(opendir(realStoreDir.c_str()));
|
||||
if (!dir) throw SysError(format("opening directory '%1%'") % realStoreDir);
|
||||
if (!dir) throw SysError("opening directory '%1%'", realStoreDir);
|
||||
|
||||
/* Read the store and immediately delete all paths that
|
||||
aren't valid. When using --max-freed etc., deleting
|
||||
|
|
@ -868,7 +871,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
|
|||
|
||||
/* Clean up the links directory. */
|
||||
if (options.action == GCOptions::gcDeleteDead || options.action == GCOptions::gcDeleteSpecific) {
|
||||
printError("deleting unused links...");
|
||||
printInfo("deleting unused links...");
|
||||
removeUnusedLinks(state);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ static void atomicWrite(const Path & path, const std::string & s)
|
|||
AutoDelete del(tmp, false);
|
||||
writeFile(tmp, s);
|
||||
if (rename(tmp.c_str(), path.c_str()))
|
||||
throw SysError(format("renaming '%1%' to '%2%'") % tmp % path);
|
||||
throw SysError("renaming '%1%' to '%2%'", tmp, path);
|
||||
del.cancel();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ struct LocalStoreAccessor : public FSAccessor
|
|||
{
|
||||
Path storePath = store->toStorePath(path);
|
||||
if (!store->isValidPath(store->parseStorePath(storePath)))
|
||||
throw InvalidPath(format("path '%1%' is not a valid store path") % storePath);
|
||||
throw InvalidPath("path '%1%' is not a valid store path", storePath);
|
||||
return store->getRealStoreDir() + std::string(path, store->storeDir.size());
|
||||
}
|
||||
|
||||
|
|
@ -33,11 +33,11 @@ struct LocalStoreAccessor : public FSAccessor
|
|||
struct stat st;
|
||||
if (lstat(realPath.c_str(), &st)) {
|
||||
if (errno == ENOENT || errno == ENOTDIR) return {Type::tMissing, 0, false};
|
||||
throw SysError(format("getting status of '%1%'") % path);
|
||||
throw SysError("getting status of '%1%'", path);
|
||||
}
|
||||
|
||||
if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode))
|
||||
throw Error(format("file '%1%' has unsupported type") % path);
|
||||
throw Error("file '%1%' has unsupported type", path);
|
||||
|
||||
return {
|
||||
S_ISREG(st.st_mode) ? Type::tRegular :
|
||||
|
|
|
|||
|
|
@ -87,18 +87,22 @@ LocalStore::LocalStore(const Params & params)
|
|||
|
||||
struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str());
|
||||
if (!gr)
|
||||
printError(format("warning: the group '%1%' specified in 'build-users-group' does not exist")
|
||||
% settings.buildUsersGroup);
|
||||
logError({
|
||||
.name = "'build-users-group' not found",
|
||||
.hint = hintfmt(
|
||||
"warning: the group '%1%' specified in 'build-users-group' does not exist",
|
||||
settings.buildUsersGroup)
|
||||
});
|
||||
else {
|
||||
struct stat st;
|
||||
if (stat(realStoreDir.c_str(), &st))
|
||||
throw SysError(format("getting attributes of path '%1%'") % realStoreDir);
|
||||
throw SysError("getting attributes of path '%1%'", realStoreDir);
|
||||
|
||||
if (st.st_uid != 0 || st.st_gid != gr->gr_gid || (st.st_mode & ~S_IFMT) != perm) {
|
||||
if (chown(realStoreDir.c_str(), 0, gr->gr_gid) == -1)
|
||||
throw SysError(format("changing ownership of path '%1%'") % realStoreDir);
|
||||
throw SysError("changing ownership of path '%1%'", realStoreDir);
|
||||
if (chmod(realStoreDir.c_str(), perm) == -1)
|
||||
throw SysError(format("changing permissions on path '%1%'") % realStoreDir);
|
||||
throw SysError("changing permissions on path '%1%'", realStoreDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -109,12 +113,12 @@ LocalStore::LocalStore(const Params & params)
|
|||
struct stat st;
|
||||
while (path != "/") {
|
||||
if (lstat(path.c_str(), &st))
|
||||
throw SysError(format("getting status of '%1%'") % path);
|
||||
throw SysError("getting status of '%1%'", path);
|
||||
if (S_ISLNK(st.st_mode))
|
||||
throw Error(format(
|
||||
throw Error(
|
||||
"the path '%1%' is a symlink; "
|
||||
"this is not allowed for the Nix store and its parent directories")
|
||||
% path);
|
||||
"this is not allowed for the Nix store and its parent directories",
|
||||
path);
|
||||
path = dirOf(path);
|
||||
}
|
||||
}
|
||||
|
|
@ -147,7 +151,7 @@ LocalStore::LocalStore(const Params & params)
|
|||
globalLock = openLockFile(globalLockPath.c_str(), true);
|
||||
|
||||
if (!lockFile(globalLock.get(), ltRead, false)) {
|
||||
printError("waiting for the big Nix store lock...");
|
||||
printInfo("waiting for the big Nix store lock...");
|
||||
lockFile(globalLock.get(), ltRead, true);
|
||||
}
|
||||
|
||||
|
|
@ -155,8 +159,8 @@ LocalStore::LocalStore(const Params & params)
|
|||
upgrade. */
|
||||
int curSchema = getSchema();
|
||||
if (curSchema > nixSchemaVersion)
|
||||
throw Error(format("current Nix store schema is version %1%, but I only support %2%")
|
||||
% curSchema % nixSchemaVersion);
|
||||
throw Error("current Nix store schema is version %1%, but I only support %2%",
|
||||
curSchema, nixSchemaVersion);
|
||||
|
||||
else if (curSchema == 0) { /* new store */
|
||||
curSchema = nixSchemaVersion;
|
||||
|
|
@ -178,7 +182,7 @@ LocalStore::LocalStore(const Params & params)
|
|||
"please upgrade Nix to version 1.11 first.");
|
||||
|
||||
if (!lockFile(globalLock.get(), ltWrite, false)) {
|
||||
printError("waiting for exclusive access to the Nix store...");
|
||||
printInfo("waiting for exclusive access to the Nix store...");
|
||||
lockFile(globalLock.get(), ltWrite, true);
|
||||
}
|
||||
|
||||
|
|
@ -256,7 +260,7 @@ LocalStore::~LocalStore()
|
|||
}
|
||||
|
||||
if (future.valid()) {
|
||||
printError("waiting for auto-GC to finish on exit...");
|
||||
printInfo("waiting for auto-GC to finish on exit...");
|
||||
future.get();
|
||||
}
|
||||
|
||||
|
|
@ -284,7 +288,7 @@ int LocalStore::getSchema()
|
|||
if (pathExists(schemaPath)) {
|
||||
string s = readFile(schemaPath);
|
||||
if (!string2Int(s, curSchema))
|
||||
throw Error(format("'%1%' is corrupt") % schemaPath);
|
||||
throw Error("'%1%' is corrupt", schemaPath);
|
||||
}
|
||||
return curSchema;
|
||||
}
|
||||
|
|
@ -293,7 +297,7 @@ int LocalStore::getSchema()
|
|||
void LocalStore::openDB(State & state, bool create)
|
||||
{
|
||||
if (access(dbDir.c_str(), R_OK | W_OK))
|
||||
throw SysError(format("Nix database directory '%1%' is not writable") % dbDir);
|
||||
throw SysError("Nix database directory '%1%' is not writable", dbDir);
|
||||
|
||||
/* Open the Nix database. */
|
||||
string dbPath = dbDir + "/db.sqlite";
|
||||
|
|
@ -367,7 +371,7 @@ void LocalStore::makeStoreWritable()
|
|||
throw SysError("setting up a private mount namespace");
|
||||
|
||||
if (mount(0, realStoreDir.c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1)
|
||||
throw SysError(format("remounting %1% writable") % realStoreDir);
|
||||
throw SysError("remounting %1% writable", realStoreDir);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -388,7 +392,7 @@ static void canonicaliseTimestampAndPermissions(const Path & path, const struct
|
|||
| 0444
|
||||
| (st.st_mode & S_IXUSR ? 0111 : 0);
|
||||
if (chmod(path.c_str(), mode) == -1)
|
||||
throw SysError(format("changing mode of '%1%' to %2$o") % path % mode);
|
||||
throw SysError("changing mode of '%1%' to %2$o", path, mode);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -406,7 +410,7 @@ static void canonicaliseTimestampAndPermissions(const Path & path, const struct
|
|||
#else
|
||||
if (!S_ISLNK(st.st_mode) && utimes(path.c_str(), times) == -1)
|
||||
#endif
|
||||
throw SysError(format("changing modification time of '%1%'") % path);
|
||||
throw SysError("changing modification time of '%1%'", path);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -415,7 +419,7 @@ void canonicaliseTimestampAndPermissions(const Path & path)
|
|||
{
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
throw SysError(format("getting attributes of path '%1%'") % path);
|
||||
throw SysError("getting attributes of path '%1%'", path);
|
||||
canonicaliseTimestampAndPermissions(path, st);
|
||||
}
|
||||
|
||||
|
|
@ -430,17 +434,17 @@ static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSe
|
|||
setattrlist() to remove other attributes as well. */
|
||||
if (lchflags(path.c_str(), 0)) {
|
||||
if (errno != ENOTSUP)
|
||||
throw SysError(format("clearing flags of path '%1%'") % path);
|
||||
throw SysError("clearing flags of path '%1%'", path);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
throw SysError(format("getting attributes of path '%1%'") % path);
|
||||
throw SysError("getting attributes of path '%1%'", path);
|
||||
|
||||
/* Really make sure that the path is of a supported type. */
|
||||
if (!(S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode)))
|
||||
throw Error(format("file '%1%' has an unsupported type") % path);
|
||||
throw Error("file '%1%' has an unsupported type", path);
|
||||
|
||||
#if __linux__
|
||||
/* Remove extended attributes / ACLs. */
|
||||
|
|
@ -474,7 +478,7 @@ static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSe
|
|||
if (fromUid != (uid_t) -1 && st.st_uid != fromUid) {
|
||||
assert(!S_ISDIR(st.st_mode));
|
||||
if (inodesSeen.find(Inode(st.st_dev, st.st_ino)) == inodesSeen.end())
|
||||
throw BuildError(format("invalid ownership on file '%1%'") % path);
|
||||
throw BuildError("invalid ownership on file '%1%'", path);
|
||||
mode_t mode = st.st_mode & ~S_IFMT;
|
||||
assert(S_ISLNK(st.st_mode) || (st.st_uid == geteuid() && (mode == 0444 || mode == 0555) && st.st_mtime == mtimeStore));
|
||||
return;
|
||||
|
|
@ -498,8 +502,8 @@ static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSe
|
|||
if (!S_ISLNK(st.st_mode) &&
|
||||
chown(path.c_str(), geteuid(), getegid()) == -1)
|
||||
#endif
|
||||
throw SysError(format("changing owner of '%1%' to %2%")
|
||||
% path % geteuid());
|
||||
throw SysError("changing owner of '%1%' to %2%",
|
||||
path, geteuid());
|
||||
}
|
||||
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
|
|
@ -518,11 +522,11 @@ void canonicalisePathMetaData(const Path & path, uid_t fromUid, InodesSeen & ino
|
|||
be a symlink, since we can't change its ownership. */
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
throw SysError(format("getting attributes of path '%1%'") % path);
|
||||
throw SysError("getting attributes of path '%1%'", path);
|
||||
|
||||
if (st.st_uid != geteuid()) {
|
||||
assert(S_ISLNK(st.st_mode));
|
||||
throw Error(format("wrong ownership of top-level store path '%1%'") % path);
|
||||
throw Error("wrong ownership of top-level store path '%1%'", path);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -859,7 +863,7 @@ void LocalStore::querySubstitutablePathInfos(const StorePathSet & paths,
|
|||
} catch (SubstituterDisabled &) {
|
||||
} catch (Error & e) {
|
||||
if (settings.tryFallback)
|
||||
printError(e.what());
|
||||
logError(e.info());
|
||||
else
|
||||
throw;
|
||||
}
|
||||
|
|
@ -1187,7 +1191,7 @@ void LocalStore::invalidatePathChecked(const StorePath & path)
|
|||
|
||||
bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
|
||||
{
|
||||
printError(format("reading the Nix store..."));
|
||||
printInfo(format("reading the Nix store..."));
|
||||
|
||||
bool errors = false;
|
||||
|
||||
|
|
@ -1219,12 +1223,15 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
|
|||
Path linkPath = linksDir + "/" + link.name;
|
||||
string hash = hashPath(htSHA256, linkPath).first.to_string(Base32, false);
|
||||
if (hash != link.name) {
|
||||
printError(
|
||||
"link '%s' was modified! expected hash '%s', got '%s'",
|
||||
linkPath, link.name, hash);
|
||||
logError({
|
||||
.name = "Invalid hash",
|
||||
.hint = hintfmt(
|
||||
"link '%s' was modified! expected hash '%s', got '%s'",
|
||||
linkPath, link.name, hash)
|
||||
});
|
||||
if (repair) {
|
||||
if (unlink(linkPath.c_str()) == 0)
|
||||
printError("removed link '%s'", linkPath);
|
||||
printInfo("removed link '%s'", linkPath);
|
||||
else
|
||||
throw SysError("removing corrupt link '%s'", linkPath);
|
||||
} else {
|
||||
|
|
@ -1254,8 +1261,11 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
|
|||
auto current = hashSink->finish();
|
||||
|
||||
if (info->narHash != nullHash && info->narHash != current.first) {
|
||||
printError("path '%s' was modified! expected hash '%s', got '%s'",
|
||||
printStorePath(i), info->narHash.to_string(Base32, true), current.first.to_string(Base32, true));
|
||||
logError({
|
||||
.name = "Invalid hash - path modified",
|
||||
.hint = hintfmt("path '%s' was modified! expected hash '%s', got '%s'",
|
||||
printStorePath(i), info->narHash.to_string(Base32, true), current.first.to_string(Base32, true))
|
||||
});
|
||||
if (repair) repairPath(i); else errors = true;
|
||||
} else {
|
||||
|
||||
|
|
@ -1263,14 +1273,14 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
|
|||
|
||||
/* Fill in missing hashes. */
|
||||
if (info->narHash == nullHash) {
|
||||
printError("fixing missing hash on '%s'", printStorePath(i));
|
||||
printInfo("fixing missing hash on '%s'", printStorePath(i));
|
||||
info->narHash = current.first;
|
||||
update = true;
|
||||
}
|
||||
|
||||
/* Fill in missing narSize fields (from old stores). */
|
||||
if (info->narSize == 0) {
|
||||
printError("updating size field on '%s' to %s", printStorePath(i), current.second);
|
||||
printInfo("updating size field on '%s' to %s", printStorePath(i), current.second);
|
||||
info->narSize = current.second;
|
||||
update = true;
|
||||
}
|
||||
|
|
@ -1286,7 +1296,7 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
|
|||
/* It's possible that the path got GC'ed, so ignore
|
||||
errors on invalid paths. */
|
||||
if (isValidPath(i))
|
||||
printError("error: %s", e.msg());
|
||||
logError(e.info());
|
||||
else
|
||||
warn(e.msg());
|
||||
errors = true;
|
||||
|
|
@ -1306,7 +1316,10 @@ void LocalStore::verifyPath(const Path & pathS, const StringSet & store,
|
|||
if (!done.insert(pathS).second) return;
|
||||
|
||||
if (!isStorePath(pathS)) {
|
||||
printError("path '%s' is not in the Nix store", pathS);
|
||||
logError({
|
||||
.name = "Nix path not found",
|
||||
.hint = hintfmt("path '%s' is not in the Nix store", pathS)
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1325,16 +1338,19 @@ void LocalStore::verifyPath(const Path & pathS, const StringSet & store,
|
|||
}
|
||||
|
||||
if (canInvalidate) {
|
||||
printError("path '%s' disappeared, removing from database...", pathS);
|
||||
printInfo("path '%s' disappeared, removing from database...", pathS);
|
||||
auto state(_state.lock());
|
||||
invalidatePath(*state, path);
|
||||
} else {
|
||||
printError("path '%s' disappeared, but it still has valid referrers!", pathS);
|
||||
logError({
|
||||
.name = "Missing path with referrers",
|
||||
.hint = hintfmt("path '%s' disappeared, but it still has valid referrers!", pathS)
|
||||
});
|
||||
if (repair)
|
||||
try {
|
||||
repairPath(path);
|
||||
} catch (Error & e) {
|
||||
warn(e.msg());
|
||||
logWarning(e.info());
|
||||
errors = true;
|
||||
}
|
||||
else errors = true;
|
||||
|
|
@ -1374,7 +1390,7 @@ static void makeMutable(const Path & path)
|
|||
AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
if (errno == ELOOP) return; // it's a symlink
|
||||
throw SysError(format("opening file '%1%'") % path);
|
||||
throw SysError("opening file '%1%'", path);
|
||||
}
|
||||
|
||||
unsigned int flags = 0, old;
|
||||
|
|
@ -1392,7 +1408,7 @@ static void makeMutable(const Path & path)
|
|||
void LocalStore::upgradeStore7()
|
||||
{
|
||||
if (getuid() != 0) return;
|
||||
printError("removing immutable bits from the Nix store (this may take a while)...");
|
||||
printInfo("removing immutable bits from the Nix store (this may take a while)...");
|
||||
makeMutable(realStoreDir);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ struct NarAccessor : public FSAccessor
|
|||
auto i = get(path);
|
||||
|
||||
if (i.type != FSAccessor::Type::tDirectory)
|
||||
throw Error(format("path '%1%' inside NAR file is not a directory") % path);
|
||||
throw Error("path '%1%' inside NAR file is not a directory", path);
|
||||
|
||||
StringSet res;
|
||||
for (auto & child : i.children)
|
||||
|
|
@ -197,7 +197,7 @@ struct NarAccessor : public FSAccessor
|
|||
{
|
||||
auto i = get(path);
|
||||
if (i.type != FSAccessor::Type::tRegular)
|
||||
throw Error(format("path '%1%' inside NAR file is not a regular file") % path);
|
||||
throw Error("path '%1%' inside NAR file is not a regular file", path);
|
||||
|
||||
if (getNarBytes) return getNarBytes(i.start, i.size);
|
||||
|
||||
|
|
@ -209,7 +209,7 @@ struct NarAccessor : public FSAccessor
|
|||
{
|
||||
auto i = get(path);
|
||||
if (i.type != FSAccessor::Type::tSymlink)
|
||||
throw Error(format("path '%1%' inside NAR file is not a symlink") % path);
|
||||
throw Error("path '%1%' inside NAR file is not a symlink", path);
|
||||
return i.target;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string &
|
|||
: ValidPathInfo(StorePath::dummy.clone()) // FIXME: hack
|
||||
{
|
||||
auto corrupt = [&]() {
|
||||
throw Error(format("NAR info file '%1%' is corrupt") % whence);
|
||||
throw Error("NAR info file '%1%' is corrupt", whence);
|
||||
};
|
||||
|
||||
auto parseHashField = [&](const string & s) {
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ static void makeWritable(const Path & path)
|
|||
{
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
throw SysError(format("getting attributes of path '%1%'") % path);
|
||||
throw SysError("getting attributes of path '%1%'", path);
|
||||
if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1)
|
||||
throw SysError(format("changing writability of '%1%'") % path);
|
||||
throw SysError("changing writability of '%1%'", path);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ LocalStore::InodeHash LocalStore::loadInodeHash()
|
|||
InodeHash inodeHash;
|
||||
|
||||
AutoCloseDir dir(opendir(linksDir.c_str()));
|
||||
if (!dir) throw SysError(format("opening directory '%1%'") % linksDir);
|
||||
if (!dir) throw SysError("opening directory '%1%'", linksDir);
|
||||
|
||||
struct dirent * dirent;
|
||||
while (errno = 0, dirent = readdir(dir.get())) { /* sic */
|
||||
|
|
@ -55,7 +55,7 @@ LocalStore::InodeHash LocalStore::loadInodeHash()
|
|||
// We don't care if we hit non-hash files, anything goes
|
||||
inodeHash.insert(dirent->d_ino);
|
||||
}
|
||||
if (errno) throw SysError(format("reading directory '%1%'") % linksDir);
|
||||
if (errno) throw SysError("reading directory '%1%'", linksDir);
|
||||
|
||||
printMsg(lvlTalkative, format("loaded %1% hash inodes") % inodeHash.size());
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ Strings LocalStore::readDirectoryIgnoringInodes(const Path & path, const InodeHa
|
|||
Strings names;
|
||||
|
||||
AutoCloseDir dir(opendir(path.c_str()));
|
||||
if (!dir) throw SysError(format("opening directory '%1%'") % path);
|
||||
if (!dir) throw SysError("opening directory '%1%'", path);
|
||||
|
||||
struct dirent * dirent;
|
||||
while (errno = 0, dirent = readdir(dir.get())) { /* sic */
|
||||
|
|
@ -83,7 +83,7 @@ Strings LocalStore::readDirectoryIgnoringInodes(const Path & path, const InodeHa
|
|||
if (name == "." || name == "..") continue;
|
||||
names.push_back(name);
|
||||
}
|
||||
if (errno) throw SysError(format("reading directory '%1%'") % path);
|
||||
if (errno) throw SysError("reading directory '%1%'", path);
|
||||
|
||||
return names;
|
||||
}
|
||||
|
|
@ -96,7 +96,7 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
|
|||
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
throw SysError(format("getting attributes of path '%1%'") % path);
|
||||
throw SysError("getting attributes of path '%1%'", path);
|
||||
|
||||
#if __APPLE__
|
||||
/* HFS/macOS has some undocumented security feature disabling hardlinking for
|
||||
|
|
@ -130,7 +130,10 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
|
|||
NixOS (example: $fontconfig/var/cache being modified). Skip
|
||||
those files. FIXME: check the modification time. */
|
||||
if (S_ISREG(st.st_mode) && (st.st_mode & S_IWUSR)) {
|
||||
printError(format("skipping suspicious writable file '%1%'") % path);
|
||||
logWarning({
|
||||
.name = "Suspicious file",
|
||||
.hint = hintfmt("skipping suspicious writable file '%1%'", path)
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -186,7 +189,7 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
|
|||
current file with a hard link to that file. */
|
||||
struct stat stLink;
|
||||
if (lstat(linkPath.c_str(), &stLink))
|
||||
throw SysError(format("getting attributes of path '%1%'") % linkPath);
|
||||
throw SysError("getting attributes of path '%1%'", linkPath);
|
||||
|
||||
if (st.st_ino == stLink.st_ino) {
|
||||
debug(format("'%1%' is already linked to '%2%'") % path % linkPath);
|
||||
|
|
@ -194,7 +197,10 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
|
|||
}
|
||||
|
||||
if (st.st_size != stLink.st_size) {
|
||||
printError(format("removing corrupted link '%1%'") % linkPath);
|
||||
logWarning({
|
||||
.name = "Corrupted link",
|
||||
.hint = hintfmt("removing corrupted link '%1%'", linkPath)
|
||||
});
|
||||
unlink(linkPath.c_str());
|
||||
goto retry;
|
||||
}
|
||||
|
|
@ -229,7 +235,10 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
|
|||
/* Atomically replace the old file with the new hard link. */
|
||||
if (rename(tempLink.c_str(), path.c_str()) == -1) {
|
||||
if (unlink(tempLink.c_str()) == -1)
|
||||
printError(format("unable to unlink '%1%'") % tempLink);
|
||||
logError({
|
||||
.name = "Unlink error",
|
||||
.hint = hintfmt("unable to unlink '%1%'", tempLink)
|
||||
});
|
||||
if (errno == EMLINK) {
|
||||
/* Some filesystems generate too many links on the rename,
|
||||
rather than on the original link. (Probably it
|
||||
|
|
@ -238,7 +247,7 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
|
|||
debug("'%s' has reached maximum number of links", linkPath);
|
||||
return;
|
||||
}
|
||||
throw SysError(format("cannot rename '%1%' to '%2%'") % tempLink % path);
|
||||
throw SysError("cannot rename '%1%' to '%2%'", tempLink, path);
|
||||
}
|
||||
|
||||
stats.filesLinked++;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ AutoCloseFD openLockFile(const Path & path, bool create)
|
|||
|
||||
fd = open(path.c_str(), O_CLOEXEC | O_RDWR | (create ? O_CREAT : 0), 0600);
|
||||
if (!fd && (create || errno != ENOENT))
|
||||
throw SysError(format("opening lock file '%1%'") % path);
|
||||
throw SysError("opening lock file '%1%'", path);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
|
@ -51,7 +51,7 @@ bool lockFile(int fd, LockType lockType, bool wait)
|
|||
while (flock(fd, type) != 0) {
|
||||
checkInterrupt();
|
||||
if (errno != EINTR)
|
||||
throw SysError(format("acquiring/releasing lock"));
|
||||
throw SysError("acquiring/releasing lock");
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ bool lockFile(int fd, LockType lockType, bool wait)
|
|||
checkInterrupt();
|
||||
if (errno == EWOULDBLOCK) return false;
|
||||
if (errno != EINTR)
|
||||
throw SysError(format("acquiring/releasing lock"));
|
||||
throw SysError("acquiring/releasing lock");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -124,7 +124,7 @@ bool PathLocks::lockPaths(const PathSet & paths,
|
|||
hasn't been unlinked). */
|
||||
struct stat st;
|
||||
if (fstat(fd.get(), &st) == -1)
|
||||
throw SysError(format("statting lock file '%1%'") % lockPath);
|
||||
throw SysError("statting lock file '%1%'", lockPath);
|
||||
if (st.st_size != 0)
|
||||
/* This lock file has been unlinked, so we're holding
|
||||
a lock on a deleted file. This means that other
|
||||
|
|
@ -160,7 +160,8 @@ void PathLocks::unlock()
|
|||
|
||||
if (close(i.first) == -1)
|
||||
printError(
|
||||
format("error (ignored): cannot close lock file on '%1%'") % i.second);
|
||||
"error (ignored): cannot close lock file on '%1%'",
|
||||
i.second);
|
||||
|
||||
debug(format("lock released on '%1%'") % i.second);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ Generations findGenerations(Path profile, int & curGen)
|
|||
gen.number = n;
|
||||
struct stat st;
|
||||
if (lstat(gen.path.c_str(), &st) != 0)
|
||||
throw SysError(format("statting '%1%'") % gen.path);
|
||||
throw SysError("statting '%1%'", gen.path);
|
||||
gen.creationTime = st.st_mtime;
|
||||
gens.push_back(gen);
|
||||
}
|
||||
|
|
@ -117,7 +117,7 @@ Path createGeneration(ref<LocalFSStore> store, Path profile, Path outPath)
|
|||
static void removeFile(const Path & path)
|
||||
{
|
||||
if (remove(path.c_str()) == -1)
|
||||
throw SysError(format("cannot unlink '%1%'") % path);
|
||||
throw SysError("cannot unlink '%1%'", path);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -149,7 +149,7 @@ void deleteGenerations(const Path & profile, const std::set<unsigned int> & gens
|
|||
Generations gens = findGenerations(profile, curGen);
|
||||
|
||||
if (gensToDelete.find(curGen) != gensToDelete.end())
|
||||
throw Error(format("cannot delete current generation of profile %1%'") % profile);
|
||||
throw Error("cannot delete current generation of profile %1%'", profile);
|
||||
|
||||
for (auto & i : gens) {
|
||||
if (gensToDelete.find(i.number) == gensToDelete.end()) continue;
|
||||
|
|
@ -226,7 +226,7 @@ void deleteGenerationsOlderThan(const Path & profile, const string & timeSpec, b
|
|||
int days;
|
||||
|
||||
if (!string2Int(strDays, days) || days < 1)
|
||||
throw Error(format("invalid number of days specifier '%1%'") % timeSpec);
|
||||
throw Error("invalid number of days specifier '%1%'", timeSpec);
|
||||
|
||||
time_t oldTime = curTime - days * 24 * 3600;
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ PathSet scanForReferences(const string & path,
|
|||
auto baseName = std::string(baseNameOf(i));
|
||||
string::size_type pos = baseName.find('-');
|
||||
if (pos == string::npos)
|
||||
throw Error(format("bad reference '%1%'") % i);
|
||||
throw Error("bad reference '%1%'", i);
|
||||
string s = string(baseName, 0, pos);
|
||||
assert(s.size() == refLength);
|
||||
assert(backMap.find(s) == backMap.end());
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ std::pair<ref<FSAccessor>, Path> RemoteFSAccessor::fetch(const Path & path_)
|
|||
std::string restPath = std::string(path, storePath.size());
|
||||
|
||||
if (!store->isValidPath(store->parseStorePath(storePath)))
|
||||
throw InvalidPath(format("path '%1%' is not a valid store path") % storePath);
|
||||
throw InvalidPath("path '%1%' is not a valid store path", storePath);
|
||||
|
||||
auto i = nars.find(storePath);
|
||||
if (i != nars.end()) return {i->second, restPath};
|
||||
|
|
|
|||
|
|
@ -116,11 +116,11 @@ ref<RemoteStore::Connection> UDSRemoteStore::openConnection()
|
|||
struct sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
if (socketPath.size() + 1 >= sizeof(addr.sun_path))
|
||||
throw Error(format("socket path '%1%' is too long") % socketPath);
|
||||
throw Error("socket path '%1%' is too long", socketPath);
|
||||
strcpy(addr.sun_path, socketPath.c_str());
|
||||
|
||||
if (::connect(conn->fd.get(), (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
||||
throw SysError(format("cannot connect to daemon at '%1%'") % socketPath);
|
||||
throw SysError("cannot connect to daemon at '%1%'", socketPath);
|
||||
|
||||
conn->from.fd = conn->fd.get();
|
||||
conn->to.fd = conn->fd.get();
|
||||
|
|
@ -365,7 +365,7 @@ void RemoteStore::queryPathInfoUncached(const StorePath & path,
|
|||
} catch (Error & e) {
|
||||
// Ugly backwards compatibility hack.
|
||||
if (e.msg().find("is not valid") != std::string::npos)
|
||||
throw InvalidPath(e.what());
|
||||
throw InvalidPath(e.info());
|
||||
throw;
|
||||
}
|
||||
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 17) {
|
||||
|
|
|
|||
|
|
@ -32,8 +32,10 @@ namespace nix {
|
|||
struct S3Error : public Error
|
||||
{
|
||||
Aws::S3::S3Errors err;
|
||||
S3Error(Aws::S3::S3Errors err, const FormatOrString & fs)
|
||||
: Error(fs), err(err) { };
|
||||
|
||||
template<typename... Args>
|
||||
S3Error(Aws::S3::S3Errors err, const Args & ... args)
|
||||
: Error(args...), err(err) { };
|
||||
};
|
||||
|
||||
/* Helper: given an Outcome<R, E>, return R in case of success, or
|
||||
|
|
@ -109,7 +111,9 @@ class RetryStrategy : public Aws::Client::DefaultRetryStrategy
|
|||
auto retry = Aws::Client::DefaultRetryStrategy::ShouldRetry(error, attemptedRetries);
|
||||
if (retry)
|
||||
printError("AWS error '%s' (%s), will retry in %d ms",
|
||||
error.GetExceptionName(), error.GetMessage(), CalculateDelayBeforeNextRetry(error, attemptedRetries));
|
||||
error.GetExceptionName(),
|
||||
error.GetMessage(),
|
||||
CalculateDelayBeforeNextRetry(error, attemptedRetries));
|
||||
return retry;
|
||||
}
|
||||
};
|
||||
|
|
@ -249,7 +253,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
|
|||
// If bucket listing is disabled, 404s turn into 403s
|
||||
|| error.GetErrorType() == Aws::S3::S3Errors::ACCESS_DENIED)
|
||||
return false;
|
||||
throw Error(format("AWS error fetching '%s': %s") % path % error.GetMessage());
|
||||
throw Error("AWS error fetching '%s': %s", path, error.GetMessage());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ SQLite::SQLite(const Path & path, bool create)
|
|||
{
|
||||
if (sqlite3_open_v2(path.c_str(), &db,
|
||||
SQLITE_OPEN_READWRITE | (create ? SQLITE_OPEN_CREATE : 0), 0) != SQLITE_OK)
|
||||
throw Error(format("cannot open SQLite database '%s'") % path);
|
||||
throw Error("cannot open SQLite database '%s'", path);
|
||||
|
||||
if (sqlite3_busy_timeout(db, 60 * 60 * 1000) != SQLITE_OK)
|
||||
throwSQLiteError(db, "setting timeout");
|
||||
|
|
@ -204,7 +204,10 @@ void handleSQLiteBusy(const SQLiteBusy & e)
|
|||
|
||||
if (now > lastWarned + 10) {
|
||||
lastWarned = now;
|
||||
printError("warning: %s", e.what());
|
||||
logWarning(
|
||||
ErrorInfo { .name = "Sqlite busy",
|
||||
.hint = hintfmt(e.what())
|
||||
});
|
||||
}
|
||||
|
||||
/* Sleep for a while since retrying the transaction right away
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "types.hh"
|
||||
#include "error.hh"
|
||||
|
||||
struct sqlite3;
|
||||
struct sqlite3_stmt;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ bool Store::isInStore(const Path & path) const
|
|||
Path Store::toStorePath(const Path & path) const
|
||||
{
|
||||
if (!isInStore(path))
|
||||
throw Error(format("path '%1%' is not in the Nix store") % path);
|
||||
throw Error("path '%1%' is not in the Nix store", path);
|
||||
Path::size_type slash = path.find('/', storeDir.size() + 1);
|
||||
if (slash == Path::npos)
|
||||
return path;
|
||||
|
|
@ -775,7 +775,11 @@ void ValidPathInfo::sign(const Store & store, const SecretKey & secretKey)
|
|||
bool ValidPathInfo::isContentAddressed(const Store & store) const
|
||||
{
|
||||
auto warn = [&]() {
|
||||
printError("warning: path '%s' claims to be content-addressed but isn't", store.printStorePath(path));
|
||||
logWarning(
|
||||
ErrorInfo{
|
||||
.name = "Path not content-addressed",
|
||||
.hint = hintfmt("path '%s' claims to be content-addressed but isn't", store.printStorePath(path))
|
||||
});
|
||||
};
|
||||
|
||||
if (hasPrefix(ca, "text:")) {
|
||||
|
|
@ -934,7 +938,7 @@ std::list<ref<Store>> getDefaultSubstituters()
|
|||
try {
|
||||
stores.push_back(openStore(uri));
|
||||
} catch (Error & e) {
|
||||
printError("warning: %s", e.what());
|
||||
logWarning(e.info());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue