Skip to content

Commit ad893ac

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. (cherry picked from commit c97b050)
1 parent 06bb1c2 commit ad893ac

File tree

7 files changed

+53
-25
lines changed

7 files changed

+53
-25
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
, drv{std::make_unique<Derivation>(drv)}
3333
, buildMode(buildMode)
@@ -107,7 +107,7 @@ static void runPostBuildHook(
107107

108108
/* At least one of the output paths could not be
109109
produced using a substitute. So we have to build instead. */
110-
Goal::Co DerivationBuildingGoal::gaveUpOnSubstitution()
110+
Goal::Co DerivationBuildingGoal::gaveUpOnSubstitution(bool storeDerivation)
111111
{
112112
Goals waitees;
113113

@@ -155,6 +155,13 @@ Goal::Co DerivationBuildingGoal::gaveUpOnSubstitution()
155155

156156
/* Determine the full set of input paths. */
157157

158+
if (storeDerivation) {
159+
assert(drv->inputDrvs.map.empty());
160+
/* Store the resolved derivation, as part of the record of
161+
what we're actually building */
162+
writeDerivation(worker.store, *drv);
163+
}
164+
158165
{
159166
/* If we get this far, we know no dynamic drvs inputs */
160167

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
, drv{std::make_unique<Derivation>(drv)}
@@ -59,7 +60,7 @@ std::string DerivationGoal::key()
5960
}.to_string(worker.store);
6061
}
6162

62-
Goal::Co DerivationGoal::haveDerivation()
63+
Goal::Co DerivationGoal::haveDerivation(bool storeDerivation)
6364
{
6465
trace("have derivation");
6566

@@ -153,11 +154,8 @@ Goal::Co DerivationGoal::haveDerivation()
153154
if (resolutionGoal->resolvedDrv) {
154155
auto & [pathResolved, drvResolved] = *resolutionGoal->resolvedDrv;
155156

156-
/* Store the resolved derivation, as part of the record of
157-
what we're actually building */
158-
writeDerivation(worker.store, drvResolved);
159-
160-
auto resolvedDrvGoal = worker.makeDerivationGoal(pathResolved, drvResolved, wantedOutput, buildMode);
157+
auto resolvedDrvGoal =
158+
worker.makeDerivationGoal(pathResolved, drvResolved, wantedOutput, buildMode, /*storeDerivation=*/true);
161159
{
162160
Goals waitees{resolvedDrvGoal};
163161
co_await await(std::move(waitees));
@@ -233,7 +231,7 @@ Goal::Co DerivationGoal::haveDerivation()
233231

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

236-
auto g = worker.makeDerivationBuildingGoal(drvPath, *drv, buildMode);
234+
auto g = worker.makeDerivationBuildingGoal(drvPath, *drv, buildMode, storeDerivation);
237235

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

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ Goal::Co DerivationTrampolineGoal::haveDerivation(StorePath drvPath, Derivation
145145
/* Build this step! */
146146

147147
for (auto & output : resolvedWantedOutputs) {
148-
auto g = upcast_goal(worker.makeDerivationGoal(drvPath, drv, output, buildMode));
148+
auto g = upcast_goal(worker.makeDerivationGoal(drvPath, drv, output, buildMode, false));
149149
g->preserveException = true;
150150
/* We will finish with it ourselves, as if we were the derivational goal. */
151151
concreteDrvGoals.insert(std::move(g));

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: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,17 @@ typedef enum { rpAccept, rpDecline, rpPostpone } HookReply;
2929
*/
3030
struct DerivationBuildingGoal : public Goal
3131
{
32-
DerivationBuildingGoal(const StorePath & drvPath, const Derivation & drv, Worker & worker, BuildMode buildMode);
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+
*/
41+
DerivationBuildingGoal(
42+
const StorePath & drvPath, const Derivation & drv, Worker & worker, BuildMode buildMode, bool storeDerivation);
3343
~DerivationBuildingGoal();
3444

3545
private:
@@ -99,7 +109,7 @@ private:
99109
/**
100110
* The states.
101111
*/
102-
Co gaveUpOnSubstitution();
112+
Co gaveUpOnSubstitution(bool storeDerivation);
103113
Co tryToBuild();
104114

105115
/**

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);
51+
BuildMode buildMode,
52+
bool storeDerivation);
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
@@ -217,7 +217,11 @@ public:
217217
const StorePath & drvPath, const OutputsSpec & wantedOutputs, const Derivation & drv, BuildMode buildMode);
218218

219219
std::shared_ptr<DerivationGoal> makeDerivationGoal(
220-
const StorePath & drvPath, const Derivation & drv, const OutputName & wantedOutput, BuildMode buildMode);
220+
const StorePath & drvPath,
221+
const Derivation & drv,
222+
const OutputName & wantedOutput,
223+
BuildMode buildMode,
224+
bool storeDerivation);
221225

222226
/**
223227
* @ref DerivationResolutionGoal "derivation resolution goal"
@@ -228,8 +232,8 @@ public:
228232
/**
229233
* @ref DerivationBuildingGoal "derivation building goal"
230234
*/
231-
std::shared_ptr<DerivationBuildingGoal>
232-
makeDerivationBuildingGoal(const StorePath & drvPath, const Derivation & drv, BuildMode buildMode);
235+
std::shared_ptr<DerivationBuildingGoal> makeDerivationBuildingGoal(
236+
const StorePath & drvPath, const Derivation & drv, BuildMode buildMode, bool storeDerivation);
233237

234238
/**
235239
* @ref PathSubstitutionGoal "substitution goal"

0 commit comments

Comments
 (0)