aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/parser.y
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2016-04-14 15:32:24 +0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2016-04-14 15:32:24 +0200
commit363f37d0843d87e03bd4dcb600ce04e7be60d7e1 (patch)
tree006704025fa074f412c530938dd804080fc3ba3b /src/libexpr/parser.y
parentfc6a03298989383aa6d4562b51820d45a0f728eb (diff)
Make the search path lazier with non-fatal errors
Thus, -I / $NIX_PATH entries are now downloaded only when they are needed for evaluation. An error to download an entry is a non-fatal warning (just like non-existant paths). This does change the semantics of builtins.nixPath, which now returns the original, rather than resulting path. E.g., before we had [ { path = "/nix/store/hgm3yxf1lrrwa3z14zpqaj5p9vs0qklk-nixexprs.tar.xz"; prefix = "nixpkgs"; } ... ] but now [ { path = "https://nixos.org/channels/nixos-16.03/nixexprs.tar.xz"; prefix = "nixpkgs"; } ... ] Fixes #792.
Diffstat (limited to 'src/libexpr/parser.y')
-rw-r--r--src/libexpr/parser.y60
1 files changed, 42 insertions, 18 deletions
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 11dc7bb5c..20ae1a696 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -600,7 +600,7 @@ Expr * EvalState::parseExprFromString(const string & s, const Path & basePath)
}
-void EvalState::addToSearchPath(const string & s, bool warn)
+void EvalState::addToSearchPath(const string & s)
{
size_t pos = s.find('=');
string prefix;
@@ -612,16 +612,7 @@ void EvalState::addToSearchPath(const string & s, bool warn)
path = string(s, pos + 1);
}
- if (isUri(path))
- path = makeDownloader()->downloadCached(store, path, true);
-
- path = absPath(path);
- if (pathExists(path)) {
- debug(format("adding path ‘%1%’ to the search path") % path);
- /* Resolve symlinks in the path to support restricted mode. */
- searchPath.push_back(std::pair<string, Path>(prefix, canonPath(path, true)));
- } else if (warn)
- printMsg(lvlError, format("warning: Nix search path entry ‘%1%’ does not exist, ignoring") % path);
+ searchPath.emplace_back(prefix, path);
}
@@ -634,17 +625,19 @@ Path EvalState::findFile(const string & path)
Path EvalState::findFile(SearchPath & searchPath, const string & path, const Pos & pos)
{
for (auto & i : searchPath) {
- assert(!isUri(i.second));
- Path res;
+ std::string suffix;
if (i.first.empty())
- res = i.second + "/" + path;
+ suffix = "/" + path;
else {
- if (path.compare(0, i.first.size(), i.first) != 0 ||
- (path.size() > i.first.size() && path[i.first.size()] != '/'))
+ auto s = i.first.size();
+ if (path.compare(0, s, i.first) != 0 ||
+ (path.size() > s && path[s] != '/'))
continue;
- res = i.second +
- (path.size() == i.first.size() ? "" : "/" + string(path, i.first.size()));
+ suffix = path.size() == s ? "" : "/" + string(path, s);
}
+ auto r = resolveSearchPathElem(i);
+ if (!r.first) continue;
+ Path res = r.second + suffix;
if (pathExists(res)) return canonPath(res);
}
format f = format(
@@ -655,4 +648,35 @@ Path EvalState::findFile(SearchPath & searchPath, const string & path, const Pos
}
+std::pair<bool, std::string> EvalState::resolveSearchPathElem(const SearchPathElem & elem)
+{
+ auto i = searchPathResolved.find(elem.second);
+ if (i != searchPathResolved.end()) return i->second;
+
+ std::pair<bool, std::string> res;
+
+ if (isUri(elem.second)) {
+ try {
+ res = { true, makeDownloader()->downloadCached(store, elem.second, true) };
+ } catch (DownloadError & e) {
+ printMsg(lvlError, format("warning: Nix search path entry ‘%1%’ cannot be downloaded, ignoring") % elem.second);
+ res = { false, "" };
+ }
+ } else {
+ auto path = absPath(elem.second);
+ if (pathExists(path))
+ res = { true, path };
+ else {
+ printMsg(lvlError, format("warning: Nix search path entry ‘%1%’ does not exist, ignoring") % elem.second);
+ res = { false, "" };
+ }
+ }
+
+ debug(format("resolved search path element ‘%s’ to ‘%s’") % elem.second % res.second);
+
+ searchPathResolved[elem.second] = res;
+ return res;
+}
+
+
}