Skip to content

Commit

Permalink
Add traceContext primop
Browse files Browse the repository at this point in the history
This primop lets you get information on paths realised (pathExists,
import, readFile) by Nix. It tracks paths realised in Nix & puts the
results under the "paths" attr. For instance:

$ nix eval --impure --expr '(builtins.traceContext (import ./.).outPath)'
{ paths = [ "/nix/store/2mpgi4bvn8py4liv9w3mjxd2c5r7bvv8-source" "/nix/store/3k7i1rdqcgyzjxvqm37hapdidy4ls4s3-source" "/nix/store/kqxic0j6wpsaw2bb51hr1yc1nb1z2xw8-source" ]; value = "/nix/store/3k7i1rdqcgyzjxvqm37hapdidy4ls4s3-source"; }

This is an alternative to the --include-eval-refs from
NixOS#3523 & --include-ifd from
NixOS#3506.
  • Loading branch information
matthewbauer committed Apr 21, 2021
1 parent 8d651a1 commit 08d4ae1
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/libexpr/eval.hh
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,10 @@ private:
friend struct ExprSelect;
friend void prim_getAttr(EvalState & state, const Pos & pos, Value * * args, Value & v);
friend void prim_match(EvalState & state, const Pos & pos, Value * * args, Value & v);

bool trackRealisedPaths;
std::vector<StorePath> realisedPaths;
friend void prim_traceContext(EvalState & state, const Pos & pos, Value * * args, Value & v);
};


Expand Down
37 changes: 37 additions & 0 deletions src/libexpr/primops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ void EvalState::realiseContext(const PathSet & context)
auto ctx = store->parseStorePath(ctxS);
if (!store->isValidPath(ctx))
throw InvalidPathError(store->printStorePath(ctx));
if (trackRealisedPaths)
realisedPaths.push_back(ctx);
if (!outputName.empty() && ctx.isDerivation()) {
drvs.push_back({ctx, {outputName}});
}
Expand Down Expand Up @@ -3498,6 +3500,41 @@ static RegisterPrimOp primop_splitVersion({
.fun = prim_splitVersion,
});

void prim_traceContext(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
bool oldTrackRealisedPaths = state.trackRealisedPaths;
state.trackRealisedPaths = true;

std::vector<StorePath> oldRealisedPaths = std::move(state.realisedPaths);
state.realisedPaths = {};

state.mkAttrs(v, 2);

state.forceValueDeep(*args[0]);
v.attrs->push_back(Attr(state.sValue, args[0]));

Value * paths = state.allocAttr(v, state.symbols.create("paths"));
state.mkList(*paths, state.realisedPaths.size());
int n = 0;
for (auto p : state.realisedPaths)
mkString(*(paths->listElems()[n++] = state.allocValue()), state.store->printStorePath(p));

state.trackRealisedPaths = oldTrackRealisedPaths;
state.realisedPaths.insert(state.realisedPaths.begin(), oldRealisedPaths.begin(), oldRealisedPaths.end());
}

static RegisterPrimOp primop_traceContext({
.name = "__traceContext",
.args = {"e"},
.doc = R"(
Evaluate expression *e*, recording what paths are realised.
Then return an attrset with the expression results under "value"
and the paths realised "paths". This function is useful for
finding what paths are needed for an expression to evaluation.
)",
.fun = prim_traceContext,
});


/*************************************************************
* Primop registration
Expand Down

0 comments on commit 08d4ae1

Please sign in to comment.