diff --git a/src/libexpr/eval-settings.cc b/src/libexpr/eval-settings.cc index 85d8485b14e..e70f942ea3d 100644 --- a/src/libexpr/eval-settings.cc +++ b/src/libexpr/eval-settings.cc @@ -7,44 +7,6 @@ namespace nix { -/* Very hacky way to parse $NIX_PATH, which is colon-separated, but - can contain URLs (e.g. "nixpkgs=https://bla...:foo=https://"). */ -static Strings parseNixPath(const std::string & s) -{ - Strings res; - - auto p = s.begin(); - - while (p != s.end()) { - auto start = p; - auto start2 = p; - - while (p != s.end() && *p != ':') { - if (*p == '=') start2 = p + 1; - ++p; - } - - if (p == s.end()) { - if (p != start) res.push_back(std::string(start, p)); - break; - } - - if (*p == ':') { - auto prefix = std::string(start2, s.end()); - if (EvalSettings::isPseudoUrl(prefix) || hasPrefix(prefix, "flake:")) { - ++p; - while (p != s.end() && *p != ':') ++p; - } - res.push_back(std::string(start, p)); - if (p == s.end()) break; - } - - ++p; - } - - return res; -} - EvalSettings::EvalSettings(bool & readOnlyMode, EvalSettings::LookupPathHooks lookupPathHooks) : readOnlyMode{readOnlyMode} , lookupPathHooks{lookupPathHooks} diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 2a08621231f..407fc5bc172 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -212,10 +212,48 @@ static Symbol getName(const AttrName & name, EvalState & state, Env & env) } } +/* Very hacky way to parse $NIX_PATH, which is colon-separated, but + can contain URLs (e.g. "nixpkgs=https://bla...:foo=https://"). */ +static Strings parseNixPath(const std::string & s) +{ + Strings res; + + auto p = s.begin(); + + while (p != s.end()) { + auto start = p; + auto start2 = p; + + while (p != s.end() && *p != ':') { + if (*p == '=') start2 = p + 1; + ++p; + } + + if (p == s.end()) { + if (p != start) res.push_back(std::string(start, p)); + break; + } + + if (*p == ':') { + auto prefix = std::string(start2, s.end()); + if (EvalSettings::isPseudoUrl(prefix) || hasPrefix(prefix, "flake:")) { + ++p; + while (p != s.end() && *p != ':') ++p; + } + res.push_back(std::string(start, p)); + if (p == s.end()) break; + } + + ++p; + } + + return res; +} + static constexpr size_t BASE_ENV_SIZE = 128; EvalState::EvalState( - const LookupPath & _lookupPath, + const LookupPath & lookupPathFromArguments, ref store, const EvalSettings & settings, std::shared_ptr buildStore) @@ -329,12 +367,37 @@ EvalState::EvalState( vStringSymlink.mkString("symlink"); vStringUnknown.mkString("unknown"); - /* Initialise the Nix expression search path. */ + /* + * Initialise the Nix expression search path. + * + * We're implementing the logic of command-line arguments overriding + * environment variables here, because the settings mechanism doesn't + * have a way to deal with that. + * It needs to be cleaned up, but that would be a bigger endeavor. + * As a first step, the following should be a separate function. + */ + //assert(lookupPath.empty()); if (!settings.pureEval) { - for (auto & i : _lookupPath.elements) + /* Add elements from `-I` arguments first */ + for (auto & i : lookupPathFromArguments.elements) { lookupPath.elements.emplace_back(LookupPath::Elem {i}); - for (auto & i : settings.nixPath.get()) - lookupPath.elements.emplace_back(LookupPath::Elem::parse(i)); + } + /* The environment variable takes lower priority by appending */ + if (auto var = getEnv("NIX_PATH")) { + for (auto & i : parseNixPath(*var)) + lookupPath.elements.emplace_back(LookupPath::Elem {i}); + } + + /* Configuration values take lowest precedence. + * FIXME: Currently one can't override `NIX_PATH` with `--nix-path` + * because that's indistiguishable from `nix-path` in the + * configurationf file. We could add hack in the argument parsing logic + * that checks if `NIX_PATH` is set. + */ + if (!settings.restrictEval) { + for (auto & i : settings.nixPath.get()) + lookupPath.elements.emplace_back(LookupPath::Elem {i}); + } } /* Allow access to all paths in the search path. */ diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index e45358055ed..da3582207f7 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -40,6 +40,8 @@ namespace eval_cache { class EvalCache; } +static Strings parseNixPath(const std::string &); + /** * Function that implements a primop. */ diff --git a/tests/functional/nix_path.sh b/tests/functional/nix_path.sh index 2c1889a4734..b407ef4c188 100755 --- a/tests/functional/nix_path.sh +++ b/tests/functional/nix_path.sh @@ -77,6 +77,7 @@ echo "nix-path = foo=$TEST_ROOT/from-nix-path-file" >> $NIX_CONF_DIR/nix.conf [[ $(NIX_PATH=$TEST_ROOT/from-NIX_PATH nix-instantiate --extra-nix-path foo=$TEST_ROOT --find-file foo/bar.nix) = $TEST_ROOT/from-NIX_PATH/bar.nix ]] # --nix-path overrides NIX_PATH +# TODO: this will likely fail [[ $(NIX_PATH=foo=$TEST_ROOT/from-NIX_PATH nix-instantiate --nix-path foo=$TEST_ROOT/from-nix-path --find-file foo/bar.nix) = $TEST_ROOT/from-nix-path/bar.nix ]] # if --nix-path does not have the desired entry, it fails (! NIX_PATH=$TEST_ROOT/from-NIX_PATH nix-instantiate --nix-path foo=$TEST_ROOT --find-file foo/bar.nix)