Skip to content

Commit 609a6d6

Browse files
committed
Merge branch 'single-ca-drv-build' of https://github.com/obsidiansystems/nix
2 parents 733d2e9 + 3a5cdd7 commit 609a6d6

30 files changed

Lines changed: 1098 additions & 513 deletions

perl/lib/Nix/Store.xs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,11 +303,14 @@ SV * derivationFromPath(char * drvPath)
303303
hash = newHV();
304304

305305
HV * outputs = newHV();
306-
for (auto & i : drv.outputsAndPaths(*store()))
306+
for (auto & i : drv.outputsAndOptPaths(*store())) {
307307
hv_store(
308308
outputs, i.first.c_str(), i.first.size(),
309-
newSVpv(store()->printStorePath(i.second.second).c_str(), 0),
309+
!i.second.second
310+
? newSV(0) /* null value */
311+
: newSVpv(store()->printStorePath(*i.second.second).c_str(), 0),
310312
0);
313+
}
311314
hv_stores(hash, "outputs", newRV((SV *) outputs));
312315

313316
AV * inputDrvs = newAV();

src/libexpr/get-drvs.cc

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,11 @@ DrvInfo::DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPat
3838
auto i = drv.outputs.find(outputName);
3939
if (i == drv.outputs.end())
4040
throw Error("derivation '%s' does not have output '%s'", store->printStorePath(drvPath), outputName);
41+
auto & [outputName, output] = *i;
4142

42-
outPath = store->printStorePath(i->second.path(*store, drv.name));
43+
auto optStorePath = output.path(*store, drv.name, outputName);
44+
if (optStorePath)
45+
outPath = store->printStorePath(*optStorePath);
4346
}
4447

4548

@@ -77,12 +80,15 @@ string DrvInfo::queryDrvPath() const
7780

7881
string DrvInfo::queryOutPath() const
7982
{
80-
if (outPath == "" && attrs) {
83+
if (!outPath && attrs) {
8184
Bindings::iterator i = attrs->find(state->sOutPath);
8285
PathSet context;
83-
outPath = i != attrs->end() ? state->coerceToPath(*i->pos, *i->value, context) : "";
86+
if (i != attrs->end())
87+
outPath = state->coerceToPath(*i->pos, *i->value, context);
8488
}
85-
return outPath;
89+
if (!outPath)
90+
throw UnimplementedError("CA derivations are not yet supported");
91+
return *outPath;
8692
}
8793

8894

src/libexpr/get-drvs.hh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ private:
2020
mutable string name;
2121
mutable string system;
2222
mutable string drvPath;
23-
mutable string outPath;
23+
mutable std::optional<string> outPath;
2424
mutable string outputName;
2525
Outputs outputs;
2626

src/libexpr/primops.cc

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)