mirror of
https://github.com/NixOS/nix.git
synced 2025-11-14 22:42:41 +01:00
Merge remote-tracking branch 'origin/master' into flakes
This commit is contained in:
commit
0f5032c5a4
12 changed files with 400 additions and 47 deletions
|
|
@ -461,6 +461,28 @@ static void commonChildInit(Pipe & logPipe)
|
|||
close(fdDevNull);
|
||||
}
|
||||
|
||||
void handleDiffHook(uid_t uid, uid_t gid, Path tryA, Path tryB, Path drvPath, Path tmpDir)
|
||||
{
|
||||
auto diffHook = settings.diffHook;
|
||||
if (diffHook != "" && settings.runDiffHook) {
|
||||
try {
|
||||
RunOptions diffHookOptions(diffHook,{tryA, tryB, drvPath, tmpDir});
|
||||
diffHookOptions.searchPath = true;
|
||||
diffHookOptions.uid = uid;
|
||||
diffHookOptions.gid = gid;
|
||||
diffHookOptions.chdir = "/";
|
||||
|
||||
auto diffRes = runProgram(diffHookOptions);
|
||||
if (!statusOk(diffRes.first))
|
||||
throw ExecError(diffRes.first, fmt("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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -803,9 +825,6 @@ private:
|
|||
/* Whether we're currently doing a chroot build. */
|
||||
bool useChroot = false;
|
||||
|
||||
/* Whether we need to perform hash rewriting if there are valid output paths. */
|
||||
bool needsHashRewrite;
|
||||
|
||||
Path chrootRootDir;
|
||||
|
||||
/* RAII object to delete the chroot directory. */
|
||||
|
|
@ -885,6 +904,9 @@ public:
|
|||
Worker & worker, BuildMode buildMode = bmNormal);
|
||||
~DerivationGoal();
|
||||
|
||||
/* Whether we need to perform hash rewriting if there are valid output paths. */
|
||||
bool needsHashRewrite();
|
||||
|
||||
void timedOut() override;
|
||||
|
||||
string key() override
|
||||
|
|
@ -997,13 +1019,6 @@ DerivationGoal::DerivationGoal(const Path & drvPath, const StringSet & wantedOut
|
|||
, wantedOutputs(wantedOutputs)
|
||||
, buildMode(buildMode)
|
||||
{
|
||||
#if __linux__
|
||||
needsHashRewrite = !useChroot;
|
||||
#else
|
||||
/* Darwin requires hash rewriting even when sandboxing is enabled. */
|
||||
needsHashRewrite = true;
|
||||
#endif
|
||||
|
||||
state = &DerivationGoal::getDerivation;
|
||||
name = (format("building of '%1%'") % drvPath).str();
|
||||
trace("created");
|
||||
|
|
@ -1044,6 +1059,17 @@ DerivationGoal::~DerivationGoal()
|
|||
}
|
||||
|
||||
|
||||
inline bool DerivationGoal::needsHashRewrite()
|
||||
{
|
||||
#if __linux__
|
||||
return !useChroot;
|
||||
#else
|
||||
/* Darwin requires hash rewriting even when sandboxing is enabled. */
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void DerivationGoal::killChild()
|
||||
{
|
||||
if (pid != -1) {
|
||||
|
|
@ -2083,7 +2109,7 @@ void DerivationGoal::startBuilder()
|
|||
#endif
|
||||
}
|
||||
|
||||
if (needsHashRewrite) {
|
||||
if (needsHashRewrite()) {
|
||||
|
||||
if (pathExists(homeDir))
|
||||
throw Error(format("directory '%1%' exists; please remove it") % homeDir);
|
||||
|
|
@ -3039,8 +3065,7 @@ void DerivationGoal::registerOutputs()
|
|||
InodesSeen inodesSeen;
|
||||
|
||||
Path checkSuffix = ".check";
|
||||
bool runDiffHook = settings.runDiffHook;
|
||||
bool keepPreviousRound = settings.keepFailed || runDiffHook;
|
||||
bool keepPreviousRound = settings.keepFailed || settings.runDiffHook;
|
||||
|
||||
std::exception_ptr delayedException;
|
||||
|
||||
|
|
@ -3067,7 +3092,7 @@ void DerivationGoal::registerOutputs()
|
|||
if (buildMode != bmCheck) actualPath = worker.store.toRealPath(path);
|
||||
}
|
||||
|
||||
if (needsHashRewrite) {
|
||||
if (needsHashRewrite()) {
|
||||
Path redirected = redirectedOutputs[path];
|
||||
if (buildMode == bmRepair
|
||||
&& redirectedBadOutputs.find(path) != redirectedBadOutputs.end()
|
||||
|
|
@ -3185,11 +3210,17 @@ void DerivationGoal::registerOutputs()
|
|||
if (!worker.store.isValidPath(path)) continue;
|
||||
auto info = *worker.store.queryPathInfo(path);
|
||||
if (hash.first != info.narHash) {
|
||||
if (settings.keepFailed) {
|
||||
if (settings.runDiffHook || settings.keepFailed) {
|
||||
Path dst = worker.store.toRealPath(path + checkSuffix);
|
||||
deletePath(dst);
|
||||
if (rename(actualPath.c_str(), dst.c_str()))
|
||||
throw SysError(format("renaming '%1%' to '%2%'") % actualPath % dst);
|
||||
|
||||
handleDiffHook(
|
||||
buildUser ? buildUser->getUID() : getuid(),
|
||||
buildUser ? buildUser->getGID() : getgid(),
|
||||
path, dst, drvPath, tmpDir);
|
||||
|
||||
throw Error(format("derivation '%1%' may not be deterministic: output '%2%' differs from '%3%'")
|
||||
% drvPath % path % dst);
|
||||
} else
|
||||
|
|
@ -3254,16 +3285,10 @@ void DerivationGoal::registerOutputs()
|
|||
? fmt("output '%1%' of '%2%' differs from '%3%' from previous round", i->second.path, drvPath, prev)
|
||||
: fmt("output '%1%' of '%2%' differs from previous round", i->second.path, drvPath);
|
||||
|
||||
auto diffHook = settings.diffHook;
|
||||
if (prevExists && diffHook != "" && runDiffHook) {
|
||||
try {
|
||||
auto diff = runProgram(diffHook, true, {prev, i->second.path});
|
||||
if (diff != "")
|
||||
printError(chomp(diff));
|
||||
} catch (Error & error) {
|
||||
printError("diff hook execution failed: %s", error.what());
|
||||
}
|
||||
}
|
||||
handleDiffHook(
|
||||
buildUser ? buildUser->getUID() : getuid(),
|
||||
buildUser ? buildUser->getGID() : getgid(),
|
||||
prev, i->second.path, drvPath, tmpDir);
|
||||
|
||||
if (settings.enforceDeterminism)
|
||||
throw NotDeterministic(msg);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <future>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#include <limits.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
|
@ -1038,6 +1039,16 @@ void runProgram2(const RunOptions & options)
|
|||
if (source && dup2(in.readSide.get(), STDIN_FILENO) == -1)
|
||||
throw SysError("dupping stdin");
|
||||
|
||||
if (options.chdir && chdir((*options.chdir).c_str()) == -1)
|
||||
throw SysError("chdir failed");
|
||||
if (options.gid && setgid(*options.gid) == -1)
|
||||
throw SysError("setgid failed");
|
||||
/* Drop all other groups if we're setgid. */
|
||||
if (options.gid && setgroups(0, 0) == -1)
|
||||
throw SysError("setgroups failed");
|
||||
if (options.uid && setuid(*options.uid) == -1)
|
||||
throw SysError("setuid failed");
|
||||
|
||||
Strings args_(options.args);
|
||||
args_.push_front(options.program);
|
||||
|
||||
|
|
|
|||
|
|
@ -271,6 +271,9 @@ string runProgram(Path program, bool searchPath = false,
|
|||
|
||||
struct RunOptions
|
||||
{
|
||||
std::optional<uid_t> uid;
|
||||
std::optional<uid_t> gid;
|
||||
std::optional<Path> chdir;
|
||||
Path program;
|
||||
bool searchPath = true;
|
||||
Strings args;
|
||||
|
|
@ -427,6 +430,7 @@ void ignoreException();
|
|||
/* Some ANSI escape sequences. */
|
||||
#define ANSI_NORMAL "\e[0m"
|
||||
#define ANSI_BOLD "\e[1m"
|
||||
#define ANSI_FAINT "\e[2m"
|
||||
#define ANSI_RED "\e[31;1m"
|
||||
#define ANSI_GREEN "\e[32;1m"
|
||||
#define ANSI_BLUE "\e[34;1m"
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ std::string programPath;
|
|||
|
||||
struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
|
||||
{
|
||||
bool printBuildLogs = false;
|
||||
|
||||
NixArgs() : MultiCommand(*RegisterCommand::commands), MixCommonArgs("nix")
|
||||
{
|
||||
mkFlag()
|
||||
|
|
@ -41,6 +43,11 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
|
|||
throw Exit();
|
||||
});
|
||||
|
||||
mkFlag()
|
||||
.longName("print-build-logs")
|
||||
.description("print full build logs on stderr")
|
||||
.set(&printBuildLogs, true);
|
||||
|
||||
mkFlag()
|
||||
.longName("version")
|
||||
.description("show version information")
|
||||
|
|
@ -109,8 +116,7 @@ void mainWrapped(int argc, char * * argv)
|
|||
|
||||
Finally f([]() { stopProgressBar(); });
|
||||
|
||||
if (isatty(STDERR_FILENO))
|
||||
startProgressBar();
|
||||
startProgressBar(args.printBuildLogs);
|
||||
|
||||
args.command->prepare();
|
||||
args.command->run();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "util.hh"
|
||||
#include "sync.hh"
|
||||
#include "store-api.hh"
|
||||
#include "names.hh"
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
|
|
@ -38,6 +39,7 @@ private:
|
|||
std::map<ActivityType, uint64_t> expectedByType;
|
||||
bool visible = true;
|
||||
ActivityId parent;
|
||||
std::optional<std::string> name;
|
||||
};
|
||||
|
||||
struct ActivitiesByType
|
||||
|
|
@ -68,10 +70,16 @@ private:
|
|||
|
||||
std::condition_variable quitCV, updateCV;
|
||||
|
||||
bool printBuildLogs;
|
||||
bool isTTY;
|
||||
|
||||
public:
|
||||
|
||||
ProgressBar()
|
||||
ProgressBar(bool printBuildLogs, bool isTTY)
|
||||
: printBuildLogs(printBuildLogs)
|
||||
, isTTY(isTTY)
|
||||
{
|
||||
state_.lock()->active = isTTY;
|
||||
updateThread = std::thread([&]() {
|
||||
auto state(state_.lock());
|
||||
while (state->active) {
|
||||
|
|
@ -109,8 +117,14 @@ public:
|
|||
|
||||
void log(State & state, Verbosity lvl, const std::string & s)
|
||||
{
|
||||
writeToStderr("\r\e[K" + s + ANSI_NORMAL "\n");
|
||||
draw(state);
|
||||
if (state.active) {
|
||||
writeToStderr("\r\e[K" + s + ANSI_NORMAL "\n");
|
||||
draw(state);
|
||||
} else {
|
||||
auto s2 = s + ANSI_NORMAL "\n";
|
||||
if (!isTTY) s2 = filterANSIEscapes(s2, true);
|
||||
writeToStderr(s2);
|
||||
}
|
||||
}
|
||||
|
||||
void startActivity(ActivityId act, Verbosity lvl, ActivityType type,
|
||||
|
|
@ -141,6 +155,7 @@ public:
|
|||
auto nrRounds = getI(fields, 3);
|
||||
if (nrRounds != 1)
|
||||
i->s += fmt(" (round %d/%d)", curRound, nrRounds);
|
||||
i->name = DrvName(name).name;
|
||||
}
|
||||
|
||||
if (type == actSubstitute) {
|
||||
|
|
@ -217,11 +232,15 @@ public:
|
|||
auto i = state->its.find(act);
|
||||
assert(i != state->its.end());
|
||||
ActInfo info = *i->second;
|
||||
state->activities.erase(i->second);
|
||||
info.lastLine = lastLine;
|
||||
state->activities.emplace_back(info);
|
||||
i->second = std::prev(state->activities.end());
|
||||
update();
|
||||
if (printBuildLogs) {
|
||||
log(*state, lvlInfo, ANSI_FAINT + info.name.value_or("unnamed") + "> " + ANSI_NORMAL + lastLine);
|
||||
} else {
|
||||
state->activities.erase(i->second);
|
||||
info.lastLine = lastLine;
|
||||
state->activities.emplace_back(info);
|
||||
i->second = std::prev(state->activities.end());
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -395,9 +414,9 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
void startProgressBar()
|
||||
void startProgressBar(bool printBuildLogs)
|
||||
{
|
||||
logger = new ProgressBar();
|
||||
logger = new ProgressBar(printBuildLogs, isatty(STDERR_FILENO));
|
||||
}
|
||||
|
||||
void stopProgressBar()
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
void startProgressBar();
|
||||
void startProgressBar(bool printBuildLogs = false);
|
||||
|
||||
void stopProgressBar();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue