forked from lix-project/lix
Support building a derivation if some outputs are already valid
This handles the chroot and build hook cases, which are easy. Supporting the non-chroot-build case will require more work (hash rewriting!). Issue #21.
This commit is contained in:
parent
295027f533
commit
a2785b7391
|
@ -6,6 +6,7 @@ use IO::Handle;
|
||||||
use Nix::Config;
|
use Nix::Config;
|
||||||
use Nix::SSH qw/sshOpts openSSHConnection/;
|
use Nix::SSH qw/sshOpts openSSHConnection/;
|
||||||
use Nix::CopyClosure;
|
use Nix::CopyClosure;
|
||||||
|
use Nix::Store;
|
||||||
no warnings('once');
|
no warnings('once');
|
||||||
|
|
||||||
|
|
||||||
|
@ -286,7 +287,7 @@ if (system("exec ssh $hostName @sshOpts '(read; kill -INT -\$\$) <&0 & nix-store
|
||||||
foreach my $output (@outputs) {
|
foreach my $output (@outputs) {
|
||||||
my $maybeSignRemote = "";
|
my $maybeSignRemote = "";
|
||||||
$maybeSignRemote = "--sign" if $UID != 0;
|
$maybeSignRemote = "--sign" if $UID != 0;
|
||||||
|
next if isValidPath($output);
|
||||||
system("exec ssh $hostName @sshOpts 'nix-store --export $maybeSignRemote $output'" .
|
system("exec ssh $hostName @sshOpts 'nix-store --export $maybeSignRemote $output'" .
|
||||||
"| NIX_HELD_LOCKS=$output @bindir@/nix-store --import > /dev/null") == 0
|
"| NIX_HELD_LOCKS=$output @bindir@/nix-store --import > /dev/null") == 0
|
||||||
or die "cannot copy $output from $hostName: $?";
|
or die "cannot copy $output from $hostName: $?";
|
||||||
|
|
|
@ -756,6 +756,9 @@ private:
|
||||||
/* Referenceable paths (i.e., input and output paths). */
|
/* Referenceable paths (i.e., input and output paths). */
|
||||||
PathSet allPaths;
|
PathSet allPaths;
|
||||||
|
|
||||||
|
/* Outputs that are already valid. */
|
||||||
|
PathSet validPaths;
|
||||||
|
|
||||||
/* User selected for running the builder. */
|
/* User selected for running the builder. */
|
||||||
UserLock buildUser;
|
UserLock buildUser;
|
||||||
|
|
||||||
|
@ -1141,7 +1144,7 @@ void DerivationGoal::tryToBuild()
|
||||||
omitted, but that would be less efficient.) Note that since we
|
omitted, but that would be less efficient.) Note that since we
|
||||||
now hold the locks on the output paths, no other process can
|
now hold the locks on the output paths, no other process can
|
||||||
build this derivation, so no further checks are necessary. */
|
build this derivation, so no further checks are necessary. */
|
||||||
PathSet validPaths = checkPathValidity(true);
|
validPaths = checkPathValidity(true);
|
||||||
if (validPaths.size() == drv.outputs.size()) {
|
if (validPaths.size() == drv.outputs.size()) {
|
||||||
debug(format("skipping build of derivation `%1%', someone beat us to it")
|
debug(format("skipping build of derivation `%1%', someone beat us to it")
|
||||||
% drvPath);
|
% drvPath);
|
||||||
|
@ -1150,23 +1153,17 @@ void DerivationGoal::tryToBuild()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (validPaths.size() > 0)
|
printMsg(lvlError, format("BLOCKERS: %1%") % showPaths(validPaths));
|
||||||
/* !!! fix this; try to delete valid paths */
|
|
||||||
throw Error(
|
|
||||||
format("derivation `%1%' is blocked by its output paths")
|
|
||||||
% drvPath);
|
|
||||||
|
|
||||||
/* If any of the outputs already exist but are not valid, delete
|
/* If any of the outputs already exist but are not valid, delete
|
||||||
them. */
|
them. */
|
||||||
foreach (DerivationOutputs::iterator, i, drv.outputs) {
|
foreach (DerivationOutputs::iterator, i, drv.outputs) {
|
||||||
Path path = i->second.path;
|
Path path = i->second.path;
|
||||||
if (worker.store.isValidPath(path))
|
if (worker.store.isValidPath(path)) continue;
|
||||||
throw Error(format("obstructed build: path `%1%' exists") % path);
|
if (!pathExists(path)) continue;
|
||||||
if (pathExists(path)) {
|
|
||||||
debug(format("removing unregistered path `%1%'") % path);
|
debug(format("removing unregistered path `%1%'") % path);
|
||||||
deletePathWrapped(path);
|
deletePathWrapped(path);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Check again whether any output previously failed to build,
|
/* Check again whether any output previously failed to build,
|
||||||
because some other process may have tried and failed before we
|
because some other process may have tried and failed before we
|
||||||
|
@ -1283,6 +1280,10 @@ void DerivationGoal::buildDone()
|
||||||
Path path = i->second.path;
|
Path path = i->second.path;
|
||||||
|
|
||||||
if (useChroot && pathExists(chrootRootDir + path)) {
|
if (useChroot && pathExists(chrootRootDir + path)) {
|
||||||
|
/* Move output paths from the chroot to the Nix store.
|
||||||
|
If the output was already valid, just skip
|
||||||
|
(discard) it. */
|
||||||
|
if (validPaths.find(path) != validPaths.end()) continue;
|
||||||
if (rename((chrootRootDir + path).c_str(), path.c_str()) == -1)
|
if (rename((chrootRootDir + path).c_str(), path.c_str()) == -1)
|
||||||
throw SysError(format("moving build output `%1%' from the chroot to the Nix store") % path);
|
throw SysError(format("moving build output `%1%' from the chroot to the Nix store") % path);
|
||||||
}
|
}
|
||||||
|
@ -1747,6 +1748,9 @@ void DerivationGoal::startBuilder()
|
||||||
#else
|
#else
|
||||||
throw Error("chroot builds are not supported on this platform");
|
throw Error("chroot builds are not supported on this platform");
|
||||||
#endif
|
#endif
|
||||||
|
} else { // !useChroot
|
||||||
|
if (validPaths.size() > 0)
|
||||||
|
throw Error(format("derivation `%1%' is blocked by its output paths %2%") % drvPath % showPaths(validPaths));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue