24
24
25
25
namespace nix {
26
26
27
- DerivationGoal::DerivationGoal (const StorePath & drvPath ,
27
+ DerivationGoal::DerivationGoal (ref< const SingleDerivedPath> drvReq ,
28
28
const OutputsSpec & wantedOutputs, Worker & worker, BuildMode buildMode)
29
29
: Goal(worker, loadDerivation())
30
- , drvPath(drvPath )
30
+ , drvReq(drvReq )
31
31
, wantedOutputs(wantedOutputs)
32
32
, buildMode(buildMode)
33
33
{
34
34
name = fmt (
35
35
" building of '%s' from .drv file" ,
36
- DerivedPath::Built { makeConstantStorePathRef (drvPath) , wantedOutputs }.to_string (worker.store ));
36
+ DerivedPath::Built { drvReq , wantedOutputs }.to_string (worker.store ));
37
37
trace (" created" );
38
38
39
39
mcExpectedBuilds = std::make_unique<MaintainCount<uint64_t >>(worker.expectedBuilds );
@@ -43,16 +43,16 @@ DerivationGoal::DerivationGoal(const StorePath & drvPath,
43
43
44
44
DerivationGoal::DerivationGoal (const StorePath & drvPath, const BasicDerivation & drv,
45
45
const OutputsSpec & wantedOutputs, Worker & worker, BuildMode buildMode)
46
- : Goal(worker, haveDerivation())
47
- , drvPath( drvPath)
46
+ : Goal(worker, haveDerivation(drvPath ))
47
+ , drvReq(makeConstantStorePathRef( drvPath) )
48
48
, wantedOutputs(wantedOutputs)
49
49
, buildMode(buildMode)
50
50
{
51
51
this ->drv = std::make_unique<Derivation>(drv);
52
52
53
53
name = fmt (
54
54
" building of '%s' from in-memory derivation" ,
55
- DerivedPath::Built { makeConstantStorePathRef (drvPath) , drv.outputNames () }.to_string (worker.store ));
55
+ DerivedPath::Built { drvReq , drv.outputNames () }.to_string (worker.store ));
56
56
trace (" created" );
57
57
58
58
mcExpectedBuilds = std::make_unique<MaintainCount<uint64_t >>(worker.expectedBuilds );
@@ -61,13 +61,24 @@ DerivationGoal::DerivationGoal(const StorePath & drvPath, const BasicDerivation
61
61
}
62
62
63
63
64
+ static StorePath pathPartOfReq (const SingleDerivedPath & req)
65
+ {
66
+ return std::visit (
67
+ overloaded{
68
+ [&](const SingleDerivedPath::Opaque & bo) { return bo.path ; },
69
+ [&](const SingleDerivedPath::Built & bfd) { return pathPartOfReq (*bfd.drvPath ); },
70
+ },
71
+ req.raw ());
72
+ }
73
+
74
+
64
75
std::string DerivationGoal::key ()
65
76
{
66
77
/* Ensure that derivations get built in order of their name,
67
78
i.e. a derivation named "aardvark" always comes before
68
79
"baboon". And substitution goals always happen before
69
80
derivation goals (due to "b$"). */
70
- return " b$" + std::string (drvPath .name ()) + " $" + worker.store . printStorePath (drvPath );
81
+ return " b$" + std::string (pathPartOfReq (*drvReq) .name ()) + " $" + drvReq-> to_string ( worker.store );
71
82
}
72
83
73
84
@@ -99,18 +110,37 @@ Goal::Co DerivationGoal::loadDerivation() {
99
110
/* The first thing to do is to make sure that the derivation
100
111
exists. If it doesn't, it may be created through a
101
112
substitute. */
102
-
103
- if (buildMode != bmNormal || !worker.evalStore .isValidPath (drvPath)) {
104
- Goals waitees{upcast_goal (worker.makePathSubstitutionGoal (drvPath))};
113
+ if (auto optDrvPath = [this ]() -> std::optional<StorePath> {
114
+ if (buildMode != bmNormal)
115
+ return std::nullopt;
116
+
117
+ auto drvPath = StorePath::dummy;
118
+ try {
119
+ drvPath = resolveDerivedPath (worker.store , *drvReq);
120
+ } catch (MissingRealisation &) {
121
+ return std::nullopt;
122
+ }
123
+ auto cond = worker.evalStore .isValidPath (drvPath) || worker.store .isValidPath (drvPath);
124
+ return cond ? std::optional{drvPath} : std::nullopt;
125
+ }()) {
126
+ trace (
127
+ fmt (" already have drv '%s' for '%s', can go straight to building" ,
128
+ worker.store .printStorePath (*optDrvPath),
129
+ drvReq->to_string (worker.store )));
130
+ } else {
131
+ trace (" need to obtain drv we want to build" );
132
+ Goals waitees{worker.makeGoal (DerivedPath::fromSingle (*drvReq))};
105
133
co_await await (std::move (waitees));
106
134
}
107
135
108
- trace (" loading derivation" );
136
+ trace (" outer load and build derivation" );
109
137
110
138
if (nrFailed != 0 ) {
111
- co_return done (BuildResult::MiscFailure, {}, Error (" cannot build missing derivation '%s'" , worker.store . printStorePath (drvPath )));
139
+ co_return amDone (ecFailed, Error (" cannot build missing derivation '%s'" , drvReq-> to_string ( worker.store )));
112
140
}
113
141
142
+ StorePath drvPath = resolveDerivedPath (worker.store , *drvReq);
143
+
114
144
/* `drvPath' should already be a root, but let's be on the safe
115
145
side: if the user forgot to make it a root, we wouldn't want
116
146
things being garbage collected while we're busy. */
@@ -129,13 +159,13 @@ Goal::Co DerivationGoal::loadDerivation() {
129
159
}
130
160
}
131
161
assert (drv);
132
- }
133
162
134
- co_return haveDerivation ();
163
+ co_return haveDerivation (drvPath);
164
+ }
135
165
}
136
166
137
167
138
- Goal::Co DerivationGoal::haveDerivation ()
168
+ Goal::Co DerivationGoal::haveDerivation (StorePath drvPath )
139
169
{
140
170
trace (" have derivation" );
141
171
@@ -221,11 +251,11 @@ Goal::Co DerivationGoal::haveDerivation()
221
251
222
252
{
223
253
/* Check what outputs paths are not already valid. */
224
- auto [allValid, validOutputs] = checkPathValidity ();
254
+ auto [allValid, validOutputs] = checkPathValidity (drvPath );
225
255
226
256
/* If they are all valid, then we're done. */
227
257
if (allValid && buildMode == bmNormal) {
228
- co_return done (BuildResult::AlreadyValid, std::move (validOutputs));
258
+ co_return done (drvPath, BuildResult::AlreadyValid, std::move (validOutputs));
229
259
}
230
260
}
231
261
@@ -262,7 +292,7 @@ Goal::Co DerivationGoal::haveDerivation()
262
292
assert (!drv->type ().isImpure ());
263
293
264
294
if (nrFailed > 0 && nrFailed > nrNoSubstituters && !settings.tryFallback ) {
265
- co_return done (BuildResult::TransientFailure, {},
295
+ co_return done (drvPath, BuildResult::TransientFailure, {},
266
296
Error (" some substitutes for the outputs of derivation '%s' failed (usually happens due to networking issues); try '--fallback' to build derivation from source " ,
267
297
worker.store .printStorePath (drvPath)));
268
298
}
@@ -271,16 +301,16 @@ Goal::Co DerivationGoal::haveDerivation()
271
301
272
302
if (needRestart == NeedRestartForMoreOutputs::OutputsAddedDoNeed) {
273
303
needRestart = NeedRestartForMoreOutputs::OutputsUnmodifedDontNeed;
274
- co_return haveDerivation ();
304
+ co_return haveDerivation (std::move (drvPath) );
275
305
}
276
306
277
- auto [allValid, validOutputs] = checkPathValidity ();
307
+ auto [allValid, validOutputs] = checkPathValidity (drvPath );
278
308
279
309
if (buildMode == bmNormal && allValid) {
280
- co_return done (BuildResult::Substituted, std::move (validOutputs));
310
+ co_return done (drvPath, BuildResult::Substituted, std::move (validOutputs));
281
311
}
282
312
if (buildMode == bmRepair && allValid) {
283
- co_return repairClosure ();
313
+ co_return repairClosure (std::move (drvPath) );
284
314
}
285
315
if (buildMode == bmCheck && !allValid)
286
316
throw Error (" some outputs of '%s' are not valid, so checking is not possible" ,
@@ -303,7 +333,7 @@ struct value_comparison
303
333
};
304
334
305
335
306
- Goal::Co DerivationGoal::repairClosure ()
336
+ Goal::Co DerivationGoal::repairClosure (StorePath drvPath )
307
337
{
308
338
assert (!drv->type ().isImpure ());
309
339
@@ -313,7 +343,7 @@ Goal::Co DerivationGoal::repairClosure()
313
343
that produced those outputs. */
314
344
315
345
/* Get the output closure. */
316
- auto outputs = queryDerivationOutputMap ();
346
+ auto outputs = queryDerivationOutputMap (drvPath );
317
347
StorePathSet outputClosure;
318
348
for (auto & i : outputs) {
319
349
if (!wantedOutputs.contains (i.first )) continue ;
@@ -371,11 +401,11 @@ Goal::Co DerivationGoal::repairClosure()
371
401
throw Error (" some paths in the output closure of derivation '%s' could not be repaired" ,
372
402
worker.store .printStorePath (drvPath));
373
403
}
374
- co_return done (BuildResult::AlreadyValid, assertPathValidity ());
404
+ co_return done (drvPath, BuildResult::AlreadyValid, assertPathValidity (drvPath ));
375
405
}
376
406
377
407
378
- std::map<std::string, std::optional<StorePath>> DerivationGoal::queryPartialDerivationOutputMap ()
408
+ std::map<std::string, std::optional<StorePath>> DerivationGoal::queryPartialDerivationOutputMap (const StorePath & drvPath )
379
409
{
380
410
assert (!drv->type ().isImpure ());
381
411
@@ -391,7 +421,7 @@ std::map<std::string, std::optional<StorePath>> DerivationGoal::queryPartialDeri
391
421
return res;
392
422
}
393
423
394
- OutputPathMap DerivationGoal::queryDerivationOutputMap ()
424
+ OutputPathMap DerivationGoal::queryDerivationOutputMap (const StorePath & drvPath )
395
425
{
396
426
assert (!drv->type ().isImpure ());
397
427
@@ -407,7 +437,7 @@ OutputPathMap DerivationGoal::queryDerivationOutputMap()
407
437
}
408
438
409
439
410
- std::pair<bool , SingleDrvOutputs> DerivationGoal::checkPathValidity ()
440
+ std::pair<bool , SingleDrvOutputs> DerivationGoal::checkPathValidity (const StorePath & drvPath )
411
441
{
412
442
if (drv->type ().isImpure ()) return { false , {} };
413
443
@@ -422,7 +452,7 @@ std::pair<bool, SingleDrvOutputs> DerivationGoal::checkPathValidity()
422
452
}, wantedOutputs.raw );
423
453
SingleDrvOutputs validOutputs;
424
454
425
- for (auto & i : queryPartialDerivationOutputMap ()) {
455
+ for (auto & i : queryPartialDerivationOutputMap (drvPath )) {
426
456
auto initialOutput = get (initialOutputs, i.first );
427
457
if (!initialOutput)
428
458
// this is an invalid output, gets catched with (!wantedOutputsLeft.empty())
@@ -487,16 +517,17 @@ std::pair<bool, SingleDrvOutputs> DerivationGoal::checkPathValidity()
487
517
}
488
518
489
519
490
- SingleDrvOutputs DerivationGoal::assertPathValidity ()
520
+ SingleDrvOutputs DerivationGoal::assertPathValidity (const StorePath & drvPath )
491
521
{
492
- auto [allValid, validOutputs] = checkPathValidity ();
522
+ auto [allValid, validOutputs] = checkPathValidity (drvPath );
493
523
if (!allValid)
494
524
throw Error (" some outputs are unexpectedly invalid" );
495
525
return validOutputs;
496
526
}
497
527
498
528
499
529
Goal::Done DerivationGoal::done (
530
+ const StorePath & drvPath,
500
531
BuildResult::Status status,
501
532
SingleDrvOutputs builtOutputs,
502
533
std::optional<Error> ex)
0 commit comments