* Build hooks: use nix-store --import. This prevents a redundant
scan for runtime dependencies (i.e. the local machine shouldn't do a scan that the remote machine has already done). Also pipe directly into `nix-store --import': don't use a temporary file.
This commit is contained in:
parent
6f8c96d123
commit
b682fae9d9
3 changed files with 29 additions and 22 deletions
|
@ -192,7 +192,7 @@ my $buildFlags = "--max-silent-time $maxSilentTime";
|
||||||
# connection dies. Without it, the remote process might continue to
|
# connection dies. Without it, the remote process might continue to
|
||||||
# run indefinitely (that is, until it next tries to write to
|
# run indefinitely (that is, until it next tries to write to
|
||||||
# stdout/stderr).
|
# stdout/stderr).
|
||||||
if (system("ssh -tt $sshOpts $hostName 'nix-store -rvvK $buildFlags $drvPath'") != 0) {
|
if (system("ssh -tt $sshOpts $hostName 'nix-store --realise -K $buildFlags $drvPath > /dev/null'") != 0) {
|
||||||
# If we couldn't run ssh or there was an ssh problem (indicated by
|
# If we couldn't run ssh or there was an ssh problem (indicated by
|
||||||
# exit code 255), then we return exit code 1; otherwise we assume
|
# exit code 255), then we return exit code 1; otherwise we assume
|
||||||
# that the builder failed, which we indicated to Nix using exit
|
# that the builder failed, which we indicated to Nix using exit
|
||||||
|
@ -209,17 +209,6 @@ foreach my $output (split '\n', $outputs) {
|
||||||
my $maybeSignRemote = "";
|
my $maybeSignRemote = "";
|
||||||
$maybeSignRemote = "--sign" if $UID != 0;
|
$maybeSignRemote = "--sign" if $UID != 0;
|
||||||
|
|
||||||
system("ssh $sshOpts $hostName 'nix-store --export $maybeSignRemote $output' > dump") == 0
|
system("ssh $sshOpts $hostName 'nix-store --export $maybeSignRemote $output' | @bindir@/nix-store --import > /dev/null") == 0
|
||||||
or die "cannot copy $output from $hostName: $?";
|
or die "cannot copy $output from $hostName: $?";
|
||||||
|
|
||||||
# This doesn't work yet, since the caller has a lock on the output
|
|
||||||
# path. We should move towards lock-free invocation of build
|
|
||||||
# hooks and substitutes.
|
|
||||||
#system("nix-store --import < dump") == 0
|
|
||||||
# or die "cannot import $output: $?";
|
|
||||||
|
|
||||||
# Hack: skip the first 8 bytes (the nix-store --export next
|
|
||||||
# archive marker). The archive follows.
|
|
||||||
system("(dd bs=1 count=8 of=/dev/null && cat) < dump | nix-store --restore $output") == 0
|
|
||||||
or die "cannot restore $output: $?";
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1240,6 +1240,12 @@ DerivationGoal::HookReply DerivationGoal::tryBuildHook()
|
||||||
|
|
||||||
initChild();
|
initChild();
|
||||||
|
|
||||||
|
string s;
|
||||||
|
foreach (DerivationOutputs::const_iterator, i, drv.outputs)
|
||||||
|
s += i->second.path + " ";
|
||||||
|
if (setenv("NIX_HELD_LOCKS", s.c_str(), 1))
|
||||||
|
throw SysError("setting an environment variable");
|
||||||
|
|
||||||
execl(buildHook.c_str(), buildHook.c_str(),
|
execl(buildHook.c_str(), buildHook.c_str(),
|
||||||
(worker.canBuildMore() ? (string) "1" : "0").c_str(),
|
(worker.canBuildMore() ? (string) "1" : "0").c_str(),
|
||||||
thisSystem.c_str(),
|
thisSystem.c_str(),
|
||||||
|
@ -1946,12 +1952,20 @@ void DerivationGoal::computeClosure()
|
||||||
map<Path, PathSet> allReferences;
|
map<Path, PathSet> allReferences;
|
||||||
map<Path, Hash> contentHashes;
|
map<Path, Hash> contentHashes;
|
||||||
|
|
||||||
|
/* When using a build hook, the build hook can register the output
|
||||||
|
as valid (by doing `nix-store --import'). If so we don't have
|
||||||
|
to do anything here. */
|
||||||
|
if (usingBuildHook) {
|
||||||
|
bool allValid = true;
|
||||||
|
foreach (DerivationOutputs::iterator, i, drv.outputs)
|
||||||
|
if (!worker.store.isValidPath(i->second.path)) allValid = false;
|
||||||
|
if (allValid) return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check whether the output paths were created, and grep each
|
/* Check whether the output paths were created, and grep each
|
||||||
output path to determine what other paths it references. Also make all
|
output path to determine what other paths it references. Also make all
|
||||||
output paths read-only. */
|
output paths read-only. */
|
||||||
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
foreach (DerivationOutputs::iterator, i, drv.outputs) {
|
||||||
i != drv.outputs.end(); ++i)
|
|
||||||
{
|
|
||||||
Path path = i->second.path;
|
Path path = i->second.path;
|
||||||
if (!pathExists(path)) {
|
if (!pathExists(path)) {
|
||||||
throw BuildError(
|
throw BuildError(
|
||||||
|
@ -2043,14 +2057,11 @@ void DerivationGoal::computeClosure()
|
||||||
paths referenced by each of them. !!! this should be
|
paths referenced by each of them. !!! this should be
|
||||||
atomic so that either all paths are registered as valid, or
|
atomic so that either all paths are registered as valid, or
|
||||||
none are. */
|
none are. */
|
||||||
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
foreach (DerivationOutputs::iterator, i, drv.outputs)
|
||||||
i != drv.outputs.end(); ++i)
|
|
||||||
{
|
|
||||||
worker.store.registerValidPath(i->second.path,
|
worker.store.registerValidPath(i->second.path,
|
||||||
contentHashes[i->second.path],
|
contentHashes[i->second.path],
|
||||||
allReferences[i->second.path],
|
allReferences[i->second.path],
|
||||||
drvPath);
|
drvPath);
|
||||||
}
|
|
||||||
|
|
||||||
/* It is now safe to delete the lock files, since all future
|
/* It is now safe to delete the lock files, since all future
|
||||||
lockers will see that the output paths are valid; they will not
|
lockers will see that the output paths are valid; they will not
|
||||||
|
|
|
@ -924,7 +924,14 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
|
||||||
|
|
||||||
if (!isValidPath(dstPath)) {
|
if (!isValidPath(dstPath)) {
|
||||||
|
|
||||||
PathLocks outputLock(singleton<PathSet, Path>(dstPath));
|
PathLocks outputLock;
|
||||||
|
|
||||||
|
/* Lock the output path. But don't lock if we're being called
|
||||||
|
from a build hook (whose parent process already acquired a
|
||||||
|
lock on this path). */
|
||||||
|
Strings locksHeld = tokenizeString(getEnv("NIX_HELD_LOCKS"));
|
||||||
|
if (find(locksHeld.begin(), locksHeld.end(), dstPath) == locksHeld.end())
|
||||||
|
outputLock.lockPaths(singleton<PathSet, Path>(dstPath));
|
||||||
|
|
||||||
if (!isValidPath(dstPath)) {
|
if (!isValidPath(dstPath)) {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue