diff options
Diffstat (limited to 'src/libexpr')
-rw-r--r-- | src/libexpr/primops.cc | 59 |
1 files changed, 47 insertions, 12 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 66173cdaf05f..dc361c043f67 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -347,6 +347,8 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) derivation. */ foreach (PathSet::iterator, i, context) { Path path = *i; + bool explicitlyPassed = false; + string output = "out"; /* Paths marked with `=' denote that the path of a derivation is explicitly passed to the builder. Since that allows the @@ -361,8 +363,15 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) foreach (PathSet::iterator, j, refs) { drv.inputSrcs.insert(*j); if (isDerivation(*j)) - drv.inputDrvs[*j] = singleton<StringSet>("out"); + drv.inputDrvs[*j] = store->queryDerivationOutputNames(*j); } + explicitlyPassed = true; + } else if (path.at(0) == '!') { + size_t index; + path = string(path, 1); + index = path.find("!"); + output = path.substr(0, index); + path = string(path, index + 1); } /* See prim_unsafeDiscardOutputDependency. */ @@ -376,7 +385,12 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) debug(format("derivation uses `%1%'") % path); if (!useDrvAsSrc && isDerivation(path)) - drv.inputDrvs[path] = singleton<StringSet>("out"); + if (explicitlyPassed) + drv.inputDrvs[path] = store->queryDerivationOutputNames(path); + else if (drv.inputDrvs.find(path) == drv.inputDrvs.end()) + drv.inputDrvs[path] = singleton<StringSet>(output); + else + drv.inputDrvs[path].insert(output); else drv.inputSrcs.insert(path); } @@ -450,7 +464,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) /* The output path of an output X is ‘<X>Path’, e.g. ‘outPath’. */ mkString(*state.allocAttr(v, state.symbols.create(i->first + "Path")), - i->second.path, singleton<PathSet>(drvPath)); + i->second.path, singleton<PathSet>("!" + i->first + "!" + drvPath)); } v.attrs->sort(); } @@ -1042,15 +1056,6 @@ void EvalState::createBaseEnv() addPrimOp("__getEnv", 1, prim_getEnv); addPrimOp("__trace", 2, prim_trace); - // Derivations - addPrimOp("derivationStrict", 1, prim_derivationStrict); - - /* Add a wrapper around the derivation primop that computes the - `drvPath' and `outPath' attributes lazily. */ - string s = "attrs: let res = derivationStrict attrs; in attrs // { drvPath = res.drvPath; outPath = res.outPath; type = \"derivation\"; }"; - mkThunk_(v, parseExprFromString(s, "/")); - addConstant("derivation", v); - // Paths addPrimOp("__toPath", 1, prim_toPath); addPrimOp("__storePath", 1, prim_storePath); @@ -1099,6 +1104,36 @@ void EvalState::createBaseEnv() addPrimOp("__parseDrvName", 1, prim_parseDrvName); addPrimOp("__compareVersions", 2, prim_compareVersions); + // Derivations + addPrimOp("derivationStrict", 1, prim_derivationStrict); + + /* Add a wrapper around the derivation primop that computes the + `drvPath' and `outPath' attributes lazily. */ + string s = "attrs: \ + let \ + strict = derivationStrict attrs; \ + attrValues = attrs: \ + map (name: builtins.getAttr name attrs) (builtins.attrNames attrs); \ + outputToAttrListElement = output: \ + { \ + name = output; \ + value = attrs // { \ + outPath = builtins.getAttr (output + \"Path\") strict; \ + drvPath = strict.drvPath; \ + type = \"derivation\"; \ + currentOutput = output; \ + } // outputsAttrs // { all = allList; }; \ + }; \ + outputsList = if attrs ? outputs then \ + map outputToAttrListElement attrs.outputs else \ + [ (outputToAttrListElement \"out\") ]; \ + outputsAttrs = builtins.listToAttrs outputsList; \ + allList = attrValues outputsAttrs; \ + head = if attrs ? outputs then builtins.head attrs.outputs else \"out\"; \ + in builtins.getAttr head outputsAttrs"; + mkThunk_(v, parseExprFromString(s, "/")); + addConstant("derivation", v); + /* Now that we've added all primops, sort the `builtins' attribute set, because attribute lookups expect it to be sorted. */ baseEnv.values[0]->attrs->sort(); |