From d74236d1f2c3bca4fcc8cb1574fb962e813f69d3 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 23 Aug 2016 17:11:19 +0200 Subject: [PATCH] nix build: Use Nix search path That is, unless --file is specified, the Nix search path is synthesized into an attribute set. Thus you can say $ nix build nixpkgs.hello assuming $NIX_PATH contains an entry of the form "nixpkgs=...". This is more verbose than $ nix build hello but is less ambiguous. --- src/libexpr/eval.cc | 7 ++++--- src/libexpr/eval.hh | 6 ++++-- src/nix-env/nix-env.cc | 3 +-- src/nix/installables.cc | 42 ++++++++++++++++++++++++++++++++++++----- src/nix/installables.hh | 12 +++++++++++- 5 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 0833603b2..625888b19 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -379,9 +379,9 @@ void EvalState::addPrimOp(const string & name, } -void EvalState::getBuiltin(const string & name, Value & v) +Value & EvalState::getBuiltin(const string & name) { - v = *baseEnv.values[0]->attrs->find(symbols.create(name))->value; + return *baseEnv.values[0]->attrs->find(symbols.create(name))->value; } @@ -462,7 +462,7 @@ void mkString(Value & v, const char * s) } -void mkString(Value & v, const string & s, const PathSet & context) +Value & mkString(Value & v, const string & s, const PathSet & context) { mkString(v, s.c_str()); if (!context.empty()) { @@ -473,6 +473,7 @@ void mkString(Value & v, const string & s, const PathSet & context) v.string.context[n++] = dupString(i.c_str()); v.string.context[n] = 0; } + return v; } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 80e369f2d..47e4d99bf 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -43,7 +43,7 @@ struct Env }; -void mkString(Value & v, const string & s, const PathSet & context = PathSet()); +Value & mkString(Value & v, const string & s, const PathSet & context = PathSet()); void copyContext(const Value & v, PathSet & context); @@ -108,6 +108,8 @@ public: void addToSearchPath(const string & s); + SearchPath getSearchPath() { return searchPath; } + Path checkSourcePath(const Path & path); /* Parse a Nix expression from the specified file. */ @@ -204,7 +206,7 @@ private: public: - void getBuiltin(const string & name, Value & v); + Value & getBuiltin(const string & name); private: diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 3f0486bb6..955a24661 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -128,9 +128,8 @@ static void getAllExprs(EvalState & state, } attrs.insert(attrName); /* Load the expression on demand. */ - Value & vFun(*state.allocValue()); + Value & vFun = state.getBuiltin("import"); Value & vArg(*state.allocValue()); - state.getBuiltin("import", vFun); mkString(vArg, path2); if (v.attrs->size() == v.attrs->capacity()) throw Error(format("too many Nix expressions in directory ‘%1%’") % path); diff --git a/src/nix/installables.cc b/src/nix/installables.cc index 6257c7679..8341bbc5a 100644 --- a/src/nix/installables.cc +++ b/src/nix/installables.cc @@ -9,6 +9,41 @@ namespace nix { +Value * MixInstallables::buildSourceExpr(EvalState & state) +{ + Value * vRoot = state.allocValue(); + + if (file != "") { + Expr * e = state.parseExprFromFile(resolveExprPath(lookupFileArg(state, file))); + state.eval(e, *vRoot); + } + + else { + + /* Construct the installation source from $NIX_PATH. */ + + auto searchPath = state.getSearchPath(); + + state.mkAttrs(*vRoot, searchPath.size()); + + std::unordered_set seen; + + for (auto & i : searchPath) { + if (i.first == "") continue; + if (seen.count(i.first)) continue; + seen.insert(i.first); + if (!pathExists(i.second)) continue; + mkApp(*state.allocAttr(*vRoot, state.symbols.create(i.first)), + state.getBuiltin("import"), + mkString(*state.allocValue(), i.second)); + } + + vRoot->attrs->sort(); + } + + return vRoot; +} + UserEnvElems MixInstallables::evalInstallables(ref store) { UserEnvElems res; @@ -46,15 +81,12 @@ UserEnvElems MixInstallables::evalInstallables(ref store) EvalState state({}, store); - Expr * e = state.parseExprFromFile(resolveExprPath(lookupFileArg(state, file))); - - Value vRoot; - state.eval(e, vRoot); + auto vRoot = buildSourceExpr(state); std::map autoArgs_; Bindings & autoArgs(*evalAutoArgs(state, autoArgs_)); - Value & v(*findAlongAttrPath(state, installable, autoArgs, vRoot)); + Value & v(*findAlongAttrPath(state, installable, autoArgs, *vRoot)); state.forceValue(v); DrvInfos drvs; diff --git a/src/nix/installables.hh b/src/nix/installables.hh index 5eb897d46..a58f7dc59 100644 --- a/src/nix/installables.hh +++ b/src/nix/installables.hh @@ -21,10 +21,13 @@ struct UserEnvElem typedef std::vector UserEnvElems; +struct Value; +class EvalState; + struct MixInstallables : virtual Args { Strings installables; - Path file = ""; + Path file; MixInstallables() { @@ -33,6 +36,13 @@ struct MixInstallables : virtual Args } UserEnvElems evalInstallables(ref store); + + /* Return a value representing the Nix expression from which we + are installing. This is either the file specified by ‘--file’, + or an attribute set constructed from $NIX_PATH, e.g. ‘{ nixpkgs + = import ...; bla = import ...; }’. */ + Value * buildSourceExpr(EvalState & state); + }; }