Skip to content

Commit c97b050

Browse files
committed
Fix ca/eval-store.sh test
The refactor in the last commit fixed the bug it was supposed to fix, but introduced a new bug in that sometimes we tried to write a resolved derivation to a store before all its `inputSrcs` were in that store. The solution is to defer writing the derivation until inside `DerivationBuildingGoal`, just before we do an actual build. At this point, we are sure that all inputs in are the store. This does have the side effect of meaning we don't write down the resolved derivation in the substituting case, only the building case, but I think that is actually fine. The store that actually does the building should make a record of what it built by storing the resolved derivation. Other stores that just substitute from that store don't necessary want that derivation however. They can trust the substituter to keep the record around, or baring that, they can attempt to re resolve everything, if they need to be audited.
1 parent 39f6fd9 commit c97b050

File tree

6 files changed

+55
-24
lines changed

6 files changed

+55
-24
lines changed

src/libstore/build/derivation-building-goal.cc

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
namespace nix {
2727

2828
DerivationBuildingGoal::DerivationBuildingGoal(
29-
const StorePath & drvPath, const Derivation & drv_, Worker & worker, BuildMode buildMode)
30-
: Goal(worker, gaveUpOnSubstitution())
29+
const StorePath & drvPath, const Derivation & drv_, Worker & worker, BuildMode buildMode, bool storeDerivation)
30+
: Goal(worker, gaveUpOnSubstitution(storeDerivation))
3131
, drvPath(drvPath)
3232
, buildMode(buildMode)
3333
{
@@ -124,7 +124,7 @@ static void runPostBuildHook(
124124

125125
/* At least one of the output paths could not be
126126
produced using a substitute. So we have to build instead. */
127-
Goal::Co DerivationBuildingGoal::gaveUpOnSubstitution()
127+
Goal::Co DerivationBuildingGoal::gaveUpOnSubstitution(bool storeDerivation)
128128
{
129129
Goals waitees;
130130

@@ -172,6 +172,13 @@ Goal::Co DerivationBuildingGoal::gaveUpOnSubstitution()
172172

173173
/* Determine the full set of input paths. */
174174

175+
if (storeDerivation) {
176+
assert(drv->inputDrvs.map.empty());
177+
/* Store the resolved derivation, as part of the record of
178+
what we're actually building */
179+
writeDerivation(worker.store, *drv);
180+
}
181+
175182
{
176183
/* If we get this far, we know no dynamic drvs inputs */
177184

src/libstore/build/derivation-goal.cc

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ DerivationGoal::DerivationGoal(
3030
const Derivation & drv,
3131
const OutputName & wantedOutput,
3232
Worker & worker,
33-
BuildMode buildMode)
34-
: Goal(worker, haveDerivation())
33+
BuildMode buildMode,
34+
bool storeDerivation)
35+
: Goal(worker, haveDerivation(storeDerivation))
3536
, drvPath(drvPath)
3637
, wantedOutput(wantedOutput)
3738
, outputHash{[&] {
@@ -65,7 +66,7 @@ std::string DerivationGoal::key()
6566
}.to_string(worker.store);
6667
}
6768

68-
Goal::Co DerivationGoal::haveDerivation()
69+
Goal::Co DerivationGoal::haveDerivation(bool storeDerivation)
6970
{
7071
trace("have derivation");
7172

@@ -159,11 +160,8 @@ Goal::Co DerivationGoal::haveDerivation()
159160
if (resolutionGoal->resolvedDrv) {
160161
auto & [pathResolved, drvResolved] = *resolutionGoal->resolvedDrv;
161162

162-
/* Store the resolved derivation, as part of the record of
163-
what we're actually building */
164-
writeDerivation(worker.store, drvResolved);
165-
166-
auto resolvedDrvGoal = worker.makeDerivationGoal(pathResolved, drvResolved, wantedOutput, buildMode);
163+
auto resolvedDrvGoal =
164+
worker.makeDerivationGoal(pathResolved, drvResolved, wantedOutput, buildMode, /*storeDerivation=*/true);
167165
{
168166
Goals waitees{resolvedDrvGoal};
169167
co_await await(std::move(waitees));
@@ -239,7 +237,7 @@ Goal::Co DerivationGoal::haveDerivation()
239237

240238
/* Give up on substitution for the output we want, actually build this derivation */
241239

242-
auto g = worker.makeDerivationBuildingGoal(drvPath, *drv, buildMode);
240+
auto g = worker.makeDerivationBuildingGoal(drvPath, *drv, buildMode, storeDerivation);
243241

244242
/* We will finish with it ourselves, as if we were the derivational goal. */
245243
g->preserveException = true;

src/libstore/build/worker.cc

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,14 @@ std::shared_ptr<DerivationTrampolineGoal> Worker::makeDerivationTrampolineGoal(
7676
}
7777

7878
std::shared_ptr<DerivationGoal> Worker::makeDerivationGoal(
79-
const StorePath & drvPath, const Derivation & drv, const OutputName & wantedOutput, BuildMode buildMode)
79+
const StorePath & drvPath,
80+
const Derivation & drv,
81+
const OutputName & wantedOutput,
82+
BuildMode buildMode,
83+
bool storeDerivation)
8084
{
81-
return initGoalIfNeeded(derivationGoals[drvPath][wantedOutput], drvPath, drv, wantedOutput, *this, buildMode);
85+
return initGoalIfNeeded(
86+
derivationGoals[drvPath][wantedOutput], drvPath, drv, wantedOutput, *this, buildMode, storeDerivation);
8287
}
8388

8489
std::shared_ptr<DerivationResolutionGoal>
@@ -87,10 +92,10 @@ Worker::makeDerivationResolutionGoal(const StorePath & drvPath, const Derivation
8792
return initGoalIfNeeded(derivationResolutionGoals[drvPath], drvPath, drv, *this, buildMode);
8893
}
8994

90-
std::shared_ptr<DerivationBuildingGoal>
91-
Worker::makeDerivationBuildingGoal(const StorePath & drvPath, const Derivation & drv, BuildMode buildMode)
95+
std::shared_ptr<DerivationBuildingGoal> Worker::makeDerivationBuildingGoal(
96+
const StorePath & drvPath, const Derivation & drv, BuildMode buildMode, bool storeDerivation)
9297
{
93-
return initGoalIfNeeded(derivationBuildingGoals[drvPath], drvPath, drv, *this, buildMode);
98+
return initGoalIfNeeded(derivationBuildingGoals[drvPath], drvPath, drv, *this, buildMode, storeDerivation);
9499
}
95100

96101
std::shared_ptr<PathSubstitutionGoal>

src/libstore/include/nix/store/build/derivation-building-goal.hh

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,21 @@ typedef enum { rpAccept, rpDecline, rpPostpone } HookReply;
2929
*/
3030
struct DerivationBuildingGoal : public Goal
3131
{
32+
/**
33+
* @param storeDerivation Whether to store the derivation in
34+
* `worker.store`. This is useful for newly-resolved derivations. In this
35+
* case, the derivation was not created a priori, e.g. purely (or close
36+
* enough) from evaluation of the Nix language, but also depends on the
37+
* exact content produced by upstream builds. It is strongly advised to
38+
* have a permanent record of such a resolved derivation in order to
39+
* faithfully reconstruct the build history.
40+
*/
3241
DerivationBuildingGoal(
33-
const StorePath & drvPath, const Derivation & drv, Worker & worker, BuildMode buildMode = bmNormal);
42+
const StorePath & drvPath,
43+
const Derivation & drv,
44+
Worker & worker,
45+
BuildMode buildMode = bmNormal,
46+
bool storeDerivation = false);
3447
~DerivationBuildingGoal();
3548

3649
private:
@@ -100,7 +113,7 @@ private:
100113
/**
101114
* The states.
102115
*/
103-
Co gaveUpOnSubstitution();
116+
Co gaveUpOnSubstitution(bool storeDerivation);
104117
Co tryToBuild();
105118

106119
/**

src/libstore/include/nix/store/build/derivation-goal.hh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,16 @@ struct DerivationGoal : public Goal
4040
*/
4141
OutputName wantedOutput;
4242

43+
/**
44+
* @param storeDerivation See `DerivationBuildingGoal`. This is just passed along.
45+
*/
4346
DerivationGoal(
4447
const StorePath & drvPath,
4548
const Derivation & drv,
4649
const OutputName & wantedOutput,
4750
Worker & worker,
48-
BuildMode buildMode = bmNormal);
51+
BuildMode buildMode = bmNormal,
52+
bool storeDerivation = false);
4953
~DerivationGoal() = default;
5054

5155
void timedOut(Error && ex) override
@@ -80,7 +84,7 @@ private:
8084
/**
8185
* The states.
8286
*/
83-
Co haveDerivation();
87+
Co haveDerivation(bool storeDerivation);
8488

8589
/**
8690
* Return `std::nullopt` if the output is unknown, e.g. un unbuilt

src/libstore/include/nix/store/build/worker.hh

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@ public:
223223
const StorePath & drvPath,
224224
const Derivation & drv,
225225
const OutputName & wantedOutput,
226-
BuildMode buildMode = bmNormal);
226+
BuildMode buildMode = bmNormal,
227+
bool storeDerivation = false);
227228

228229
/**
229230
* @ref DerivationResolutionGoal "derivation resolution goal"
@@ -234,8 +235,11 @@ public:
234235
/**
235236
* @ref DerivationBuildingGoal "derivation building goal"
236237
*/
237-
std::shared_ptr<DerivationBuildingGoal>
238-
makeDerivationBuildingGoal(const StorePath & drvPath, const Derivation & drv, BuildMode buildMode = bmNormal);
238+
std::shared_ptr<DerivationBuildingGoal> makeDerivationBuildingGoal(
239+
const StorePath & drvPath,
240+
const Derivation & drv,
241+
BuildMode buildMode = bmNormal,
242+
bool storeDerivation = false);
239243

240244
/**
241245
* @ref PathSubstitutionGoal "substitution goal"

0 commit comments

Comments
 (0)