@@ -44,16 +44,6 @@ void EvalState::realiseContext(const PathSet & context)
4444 throw InvalidPathError (store->printStorePath (ctx));
4545 if (!outputName.empty () && ctx.isDerivation ()) {
4646 drvs.push_back (StorePathWithOutputs{ctx, {outputName}});
47-
48- /* Add the output of this derivation to the allowed
49- paths. */
50- if (allowedPaths) {
51- auto drv = store->derivationFromPath (ctx);
52- DerivationOutputs::iterator i = drv.outputs .find (outputName);
53- if (i == drv.outputs .end ())
54- throw Error (" derivation '%s' does not have an output named '%s'" , ctxS, outputName);
55- allowedPaths->insert (store->printStorePath (i->second .path (*store, drv.name )));
56- }
5747 }
5848 }
5949
@@ -69,8 +59,50 @@ void EvalState::realiseContext(const PathSet & context)
6959 store->queryMissing (drvs, willBuild, willSubstitute, unknown, downloadSize, narSize);
7060
7161 store->buildPaths (drvs);
62+
63+ /* Add the output of this derivations to the allowed
64+ paths. */
65+ if (allowedPaths) {
66+ for (auto & [drvPath, outputs] : drvs) {
67+ auto outputPaths = store->queryDerivationOutputMap (drvPath);
68+ for (auto & outputName : outputs) {
69+ if (outputPaths.count (outputName) == 0 )
70+ throw Error (" derivation '%s' does not have an output named '%s'" ,
71+ store->printStorePath (drvPath), outputName);
72+ allowedPaths->insert (store->printStorePath (outputPaths.at (outputName)));
73+ }
74+ }
75+ }
7276}
7377
78+ /* Add and attribute to the given attribute map from the output name to
79+ the output path, or a placeholder.
80+
81+ Where possible the path is used, but for floating CA derivations we
82+ may not know it. For sake of determinism we always assume we don't
83+ and instead put in a place holder. In either case, however, the
84+ string context will contain the drv path and output name, so
85+ downstream derivations will have the proper dependency, and in
86+ addition, before building, the placeholder will be rewritten to be
87+ the actual path.
88+
89+ The 'drv' and 'drvPath' outputs must correspond. */
90+ static void mkOutputString (EvalState & state, Value & v,
91+ const StorePath & drvPath, const BasicDerivation & drv,
92+ std::pair<string, DerivationOutput> o)
93+ {
94+ auto optOutputPath = o.second .path (*state.store , drv.name , o.first );
95+ mkString (
96+ *state.allocAttr (v, state.symbols .create (o.first )),
97+ optOutputPath
98+ ? state.store ->printStorePath (*optOutputPath)
99+ /* Downstream we would substitute this for an actual path once
100+ we build the floating CA derivation */
101+ /* FIXME: we need to depend on the basic derivation, not
102+ derivation */
103+ : downstreamPlaceholder (*state.store , drvPath, o.first ),
104+ {" !" + o.first + " !" + state.store ->printStorePath (drvPath)});
105+ }
74106
75107/* Load and evaluate an expression from path specified by the
76108 argument. */
@@ -114,9 +146,8 @@ static void import(EvalState & state, const Pos & pos, Value & vPath, Value * vS
114146 state.mkList (*outputsVal, drv.outputs .size ());
115147 unsigned int outputs_index = 0 ;
116148
117- for (const auto & o : drv.outputsAndPaths (*state.store )) {
118- v2 = state.allocAttr (w, state.symbols .create (o.first ));
119- mkString (*v2, state.store ->printStorePath (o.second .second ), {" !" + o.first + " !" + path});
149+ for (const auto & o : drv.outputs ) {
150+ mkOutputString (state, w, storePath, drv, o);
120151 outputsVal->listElems ()[outputs_index] = state.allocValue ();
121152 mkString (*(outputsVal->listElems ()[outputs_index++]), o.first );
122153 }
@@ -1080,16 +1111,18 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
10801111
10811112 /* Optimisation, but required in read-only mode! because in that
10821113 case we don't actually write store derivations, so we can't
1083- read them later. */
1084- drvHashes.insert_or_assign (drvPath,
1085- hashDerivationModulo (*state.store , Derivation (drv), false ));
1114+ read them later.
1115+
1116+ However, we don't bother doing this for floating CA derivations because
1117+ their "hash modulo" is indeterminate until built. */
1118+ if (drv.type () != DerivationType::CAFloating)
1119+ drvHashes.insert_or_assign (drvPath,
1120+ hashDerivationModulo (*state.store , Derivation (drv), false ));
10861121
10871122 state.mkAttrs (v, 1 + drv.outputs .size ());
10881123 mkString (*state.allocAttr (v, state.sDrvPath ), drvPathS, {" =" + drvPathS});
1089- for (auto & i : drv.outputsAndPaths (*state.store )) {
1090- mkString (*state.allocAttr (v, state.symbols .create (i.first )),
1091- state.store ->printStorePath (i.second .second ), {" !" + i.first + " !" + drvPathS});
1092- }
1124+ for (auto & i : drv.outputs )
1125+ mkOutputString (state, v, drvPath, drv, i);
10931126 v.attrs ->sort ();
10941127}
10951128
0 commit comments