Support fixed-output derivations depending on impure derivations
This commit is contained in:
parent
5cd72598fe
commit
18935e8b9f
|
@ -342,9 +342,9 @@ void DerivationGoal::gaveUpOnSubstitution()
|
||||||
inputDrvOutputs.clear();
|
inputDrvOutputs.clear();
|
||||||
if (useDerivation)
|
if (useDerivation)
|
||||||
for (auto & i : dynamic_cast<Derivation *>(drv.get())->inputDrvs) {
|
for (auto & i : dynamic_cast<Derivation *>(drv.get())->inputDrvs) {
|
||||||
/* Ensure that pure derivations don't depend on impure
|
/* Ensure that pure, non-fixed-output derivations don't
|
||||||
derivations. */
|
depend on impure derivations. */
|
||||||
if (drv->type().isPure()) {
|
if (drv->type().isPure() && !drv->type().isFixed()) {
|
||||||
auto inputDrv = worker.evalStore.readDerivation(i.first);
|
auto inputDrv = worker.evalStore.readDerivation(i.first);
|
||||||
if (!inputDrv.type().isPure())
|
if (!inputDrv.type().isPure())
|
||||||
throw Error("pure derivation '%s' depends on impure derivation '%s'",
|
throw Error("pure derivation '%s' depends on impure derivation '%s'",
|
||||||
|
@ -993,6 +993,7 @@ void DerivationGoal::resolvedFinished()
|
||||||
auto newRealisation = realisation;
|
auto newRealisation = realisation;
|
||||||
newRealisation.id = DrvOutput { initialOutputs.at(wantedOutput).outputHash, wantedOutput };
|
newRealisation.id = DrvOutput { initialOutputs.at(wantedOutput).outputHash, wantedOutput };
|
||||||
newRealisation.signatures.clear();
|
newRealisation.signatures.clear();
|
||||||
|
if (!drv->type().isFixed())
|
||||||
newRealisation.dependentRealisations = drvOutputReferences(worker.store, *drv, realisation.outPath);
|
newRealisation.dependentRealisations = drvOutputReferences(worker.store, *drv, realisation.outPath);
|
||||||
signRealisation(newRealisation);
|
signRealisation(newRealisation);
|
||||||
worker.store.registerDrvOutput(newRealisation);
|
worker.store.registerDrvOutput(newRealisation);
|
||||||
|
|
|
@ -277,15 +277,15 @@ std::map<DrvOutput, StorePath> drvOutputReferences(
|
||||||
{
|
{
|
||||||
std::set<Realisation> inputRealisations;
|
std::set<Realisation> inputRealisations;
|
||||||
|
|
||||||
for (const auto& [inputDrv, outputNames] : drv.inputDrvs) {
|
for (const auto & [inputDrv, outputNames] : drv.inputDrvs) {
|
||||||
auto outputHashes =
|
auto outputHashes =
|
||||||
staticOutputHashes(store, store.readDerivation(inputDrv));
|
staticOutputHashes(store, store.readDerivation(inputDrv));
|
||||||
for (const auto& outputName : outputNames) {
|
for (const auto & outputName : outputNames) {
|
||||||
auto thisRealisation = store.queryRealisation(
|
auto thisRealisation = store.queryRealisation(
|
||||||
DrvOutput{outputHashes.at(outputName), outputName});
|
DrvOutput{outputHashes.at(outputName), outputName});
|
||||||
if (!thisRealisation)
|
if (!thisRealisation)
|
||||||
throw Error(
|
throw Error(
|
||||||
"output '%s' of derivation '%s' isn’t built", outputName,
|
"output '%s' of derivation '%s' isn't built", outputName,
|
||||||
store.printStorePath(inputDrv));
|
store.printStorePath(inputDrv));
|
||||||
inputRealisations.insert(*thisRealisation);
|
inputRealisations.insert(*thisRealisation);
|
||||||
}
|
}
|
||||||
|
@ -295,4 +295,5 @@ std::map<DrvOutput, StorePath> drvOutputReferences(
|
||||||
|
|
||||||
return drvOutputReferences(Realisation::closure(store, inputRealisations), info->references);
|
return drvOutputReferences(Realisation::closure(store, inputRealisations), info->references);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ rec {
|
||||||
outputs = [ "out" "stuff" ];
|
outputs = [ "out" "stuff" ];
|
||||||
buildCommand =
|
buildCommand =
|
||||||
''
|
''
|
||||||
|
echo impure
|
||||||
x=$(< $TEST_ROOT/counter)
|
x=$(< $TEST_ROOT/counter)
|
||||||
mkdir $out $stuff
|
mkdir $out $stuff
|
||||||
echo $x > $out/n
|
echo $x > $out/n
|
||||||
|
@ -23,6 +24,7 @@ rec {
|
||||||
name = "impure-on-impure";
|
name = "impure-on-impure";
|
||||||
buildCommand =
|
buildCommand =
|
||||||
''
|
''
|
||||||
|
echo impure-on-impure
|
||||||
x=$(< ${impure}/n)
|
x=$(< ${impure}/n)
|
||||||
mkdir $out
|
mkdir $out
|
||||||
printf X$x > $out/n
|
printf X$x > $out/n
|
||||||
|
@ -43,4 +45,24 @@ rec {
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
contentAddressed = mkDerivation {
|
||||||
|
name = "content-addressed";
|
||||||
|
buildCommand =
|
||||||
|
''
|
||||||
|
echo content-addressed
|
||||||
|
x=$(< ${impureOnImpure}/n)
|
||||||
|
printf ''${x:0:1} > $out
|
||||||
|
'';
|
||||||
|
outputHashAlgo = "sha256";
|
||||||
|
outputHashMode = "recursive";
|
||||||
|
outputHash = "sha256-eBYxcgkuWuiqs4cKNgKwkb3vY/HR0vVsJnqe8itJGcQ=";
|
||||||
|
};
|
||||||
|
|
||||||
|
inputAddressedAfterCA = mkDerivation {
|
||||||
|
name = "input-addressed-after-ca";
|
||||||
|
buildCommand =
|
||||||
|
''
|
||||||
|
cat ${contentAddressed} > $out
|
||||||
|
'';
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,10 @@ path2=$(nix build -L --no-link --json --file ./impure-derivations.nix impure | j
|
||||||
[[ $(< $path2/n) = 1 ]]
|
[[ $(< $path2/n) = 1 ]]
|
||||||
|
|
||||||
# Test impure derivations that depend on impure derivations.
|
# Test impure derivations that depend on impure derivations.
|
||||||
path3=$(nix build -L --no-link --json --file ./impure-derivations.nix impureOnImpure -vvvvv | jq -r .[].outputs.out)
|
path3=$(nix build -L --no-link --json --file ./impure-derivations.nix impureOnImpure | jq -r .[].outputs.out)
|
||||||
[[ $(< $path3/n) = X2 ]]
|
[[ $(< $path3/n) = X2 ]]
|
||||||
|
|
||||||
path4=$(nix build -L --no-link --json --file ./impure-derivations.nix impureOnImpure -vvvvv | jq -r .[].outputs.out)
|
path4=$(nix build -L --no-link --json --file ./impure-derivations.nix impureOnImpure | jq -r .[].outputs.out)
|
||||||
[[ $(< $path4/n) = X3 ]]
|
[[ $(< $path4/n) = X3 ]]
|
||||||
|
|
||||||
# Test that (self-)references work.
|
# Test that (self-)references work.
|
||||||
|
@ -37,3 +37,18 @@ nix build -L --no-link --json --file ./impure-derivations.nix inputAddressed 2>&
|
||||||
drvPath=$(nix eval --json --file ./impure-derivations.nix impure.drvPath | jq -r .)
|
drvPath=$(nix eval --json --file ./impure-derivations.nix impure.drvPath | jq -r .)
|
||||||
[[ $(nix show-derivation $drvPath | jq ".[\"$drvPath\"].outputs.out.impure") = true ]]
|
[[ $(nix show-derivation $drvPath | jq ".[\"$drvPath\"].outputs.out.impure") = true ]]
|
||||||
[[ $(nix show-derivation $drvPath | jq ".[\"$drvPath\"].outputs.stuff.impure") = true ]]
|
[[ $(nix show-derivation $drvPath | jq ".[\"$drvPath\"].outputs.stuff.impure") = true ]]
|
||||||
|
|
||||||
|
# Fixed-output derivations *can* depend on impure derivations.
|
||||||
|
path5=$(nix build -L --no-link --json --file ./impure-derivations.nix contentAddressed | jq -r .[].outputs.out)
|
||||||
|
[[ $(< $path5) = X ]]
|
||||||
|
[[ $(< $TEST_ROOT/counter) = 5 ]]
|
||||||
|
|
||||||
|
# And they should not be rebuilt.
|
||||||
|
path5=$(nix build -L --no-link --json --file ./impure-derivations.nix contentAddressed | jq -r .[].outputs.out)
|
||||||
|
[[ $(< $path5) = X ]]
|
||||||
|
[[ $(< $TEST_ROOT/counter) = 5 ]]
|
||||||
|
|
||||||
|
# Input-addressed derivations can depend on fixed-output derivations that depend on impure derivations.
|
||||||
|
path6=$(nix build -L --no-link --json --file ./impure-derivations.nix inputAddressedAfterCA | jq -r .[].outputs.out)
|
||||||
|
[[ $(< $path6) = X ]]
|
||||||
|
[[ $(< $TEST_ROOT/counter) = 5 ]]
|
||||||
|
|
Loading…
Reference in a new issue