diff --git a/src/libexpr/eval-settings.cc b/src/libexpr/eval-settings.cc index 93b4a5289dc..e09b40d9440 100644 --- a/src/libexpr/eval-settings.cc +++ b/src/libexpr/eval-settings.cc @@ -5,50 +5,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() -{ - auto var = getEnv("NIX_PATH"); - if (var) nixPath = parseNixPath(*var); -} - Strings EvalSettings::getDefaultNixPath() { Strings res; diff --git a/src/libexpr/eval-settings.hh b/src/libexpr/eval-settings.hh index e6666061ae0..a8cb2058b71 100644 --- a/src/libexpr/eval-settings.hh +++ b/src/libexpr/eval-settings.hh @@ -5,8 +5,6 @@ namespace nix { struct EvalSettings : Config { - EvalSettings(); - static Strings getDefaultNixPath(); static bool isPseudoUrl(std::string_view s); diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 6d445fd968b..a087e40ed5d 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -420,6 +420,43 @@ void initGC() gcInitialised = true; } +/* 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; +} ErrorBuilder & ErrorBuilder::atPos(PosIdx pos) { @@ -526,8 +563,15 @@ EvalState::EvalState( /* Initialise the Nix expression search path. */ if (!evalSettings.pureEval) { + // Command line specification for (auto & i : _searchPath.elements) searchPath.elements.emplace_back(SearchPath::Elem {i}); + // Environment variable + auto environment = getEnv("NIX_PATH"); + if (environment) + for (auto & i : parseNixPath(*environment)) + searchPath.elements.emplace_back(SearchPath::Elem::parse(i)); + // Config files and defaults for (auto & i : evalSettings.nixPath.get()) searchPath.elements.emplace_back(SearchPath::Elem::parse(i)); } diff --git a/tests/nix_path.sh b/tests/nix_path.sh index 2b222b4a1e4..a7a1e868ca2 100644 --- a/tests/nix_path.sh +++ b/tests/nix_path.sh @@ -7,6 +7,15 @@ export NIX_PATH=non-existent=/non-existent/but-unused-anyways:by-absolute-path=$ nix-instantiate --eval -E '' --restrict-eval nix-instantiate --eval -E '' --restrict-eval +tmpfile=$(mktemp) +echo "nix-path = " > "$tmpfile" +export NIX_USER_CONF_FILES="$tmpfile" + +# This should still work because the NIX_PATH environment variable will take +# precedence over the empty nix path set by the configuration file +nix-instantiate --eval -E '' --restrict-eval + + # Should ideally also test this, but there’s no pure way to do it, so just trust me that it works # nix-instantiate --eval -E '' -I nixpkgs=channel:nixos-unstable --restrict-eval