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::SSH qw/sshOpts openSSHConnection/;
|
||||
use Nix::CopyClosure;
|
||||
use Nix::Store;
|
||||
no warnings('once');
|
||||
|
||||
|
||||
|
@ -286,7 +287,7 @@ if (system("exec ssh $hostName @sshOpts '(read; kill -INT -\$\$) <&0 & nix-store
|
|||
foreach my $output (@outputs) {
|
||||
my $maybeSignRemote = "";
|
||||
$maybeSignRemote = "--sign" if $UID != 0;
|
||||
|
||||
next if isValidPath($output);
|
||||
system("exec ssh $hostName @sshOpts 'nix-store --export $maybeSignRemote $output'" .
|
||||
"| NIX_HELD_LOCKS=$output @bindir@/nix-store --import > /dev/null") == 0
|
||||
or die "cannot copy $output from $hostName: $?";
|
||||
|
|
|
@ -756,6 +756,9 @@ private:
|
|||
/* Referenceable paths (i.e., input and output paths). */
|
||||
PathSet allPaths;
|
||||
|
||||
/* Outputs that are already valid. */
|
||||
PathSet validPaths;
|
||||
|
||||
/* User selected for running the builder. */
|
||||
UserLock buildUser;
|
||||
|
||||
|
@ -1141,7 +1144,7 @@ void DerivationGoal::tryToBuild()
|
|||
omitted, but that would be less efficient.) Note that since we
|
||||
now hold the locks on the output paths, no other process can
|
||||
build this derivation, so no further checks are necessary. */
|
||||
PathSet validPaths = checkPathValidity(true);
|
||||
validPaths = checkPathValidity(true);
|
||||
if (validPaths.size() == drv.outputs.size()) {
|
||||
debug(format("skipping build of derivation `%1%', someone beat us to it")
|
||||
% drvPath);
|
||||
|
@ -1150,23 +1153,17 @@ void DerivationGoal::tryToBuild()
|
|||
return;
|
||||
}
|
||||
|
||||
if (validPaths.size() > 0)
|
||||
/* !!! fix this; try to delete valid paths */
|
||||
throw Error(
|
||||
format("derivation `%1%' is blocked by its output paths")
|
||||
% drvPath);
|
||||
printMsg(lvlError, format("BLOCKERS: %1%") % showPaths(validPaths));
|
||||
|
||||
/* If any of the outputs already exist but are not valid, delete
|
||||
them. */
|
||||
foreach (DerivationOutputs::iterator, i, drv.outputs) {
|
||||
Path path = i->second.path;
|
||||
if (worker.store.isValidPath(path))
|
||||
throw Error(format("obstructed build: path `%1%' exists") % path);
|
||||
if (pathExists(path)) {
|
||||
if (worker.store.isValidPath(path)) continue;
|
||||
if (!pathExists(path)) continue;
|
||||
debug(format("removing unregistered path `%1%'") % path);
|
||||
deletePathWrapped(path);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check again whether any output previously failed to build,
|
||||
because some other process may have tried and failed before we
|
||||
|
@ -1283,6 +1280,10 @@ void DerivationGoal::buildDone()
|
|||
Path path = i->second.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)
|
||||
throw SysError(format("moving build output `%1%' from the chroot to the Nix store") % path);
|
||||
}
|
||||
|
@ -1747,6 +1748,9 @@ void DerivationGoal::startBuilder()
|
|||
#else
|
||||
throw Error("chroot builds are not supported on this platform");
|
||||
#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