about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2015-06-17T14·20+0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2015-06-17T14·20+0200
commit65f17cd3309e192dcf0d61d3d946a3610420a9d4 (patch)
tree097a00551e14e44cf6715bcd75996992785d311f
parent0d4d92fcf92030dbaad0f5251232657be218cc5d (diff)
Support URLs in $NIX_PATH
This didn't work (despite claims in the manual), because the colon in
"http://" was parsed as a element separator. So handle "://"
specially.
-rw-r--r--src/libexpr/eval.cc14
-rw-r--r--src/libutil/util.cc14
-rw-r--r--src/libutil/util.hh5
3 files changed, 32 insertions, 1 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 88cf9f4534..d61ee7e807 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -234,6 +234,18 @@ void initGC()
 }
 
 
+/* 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 string & in)
+{
+    string marker = "\001//";
+    auto res = tokenizeString<Strings>(replaceStrings(in, "://", marker), ":");
+    for (auto & s : res)
+        s = replaceStrings(s, marker, "://");
+    return res;
+}
+
+
 EvalState::EvalState(const Strings & _searchPath)
     : sWith(symbols.create("<with>"))
     , sOutPath(symbols.create("outPath"))
@@ -266,7 +278,7 @@ EvalState::EvalState(const Strings & _searchPath)
     assert(gcInitialised);
 
     /* Initialise the Nix expression search path. */
-    Strings paths = tokenizeString<Strings>(getEnv("NIX_PATH", ""), ":");
+    Strings paths = parseNixPath(getEnv("NIX_PATH", ""));
     for (auto & i : _searchPath) addToSearchPath(i, true);
     for (auto & i : paths) addToSearchPath(i);
     addToSearchPath("nix=" + settings.nixDataDir + "/nix/corepkgs");
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 903b97100b..596b79e10e 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -1095,6 +1095,20 @@ string trim(const string & s, const string & whitespace)
 }
 
 
+string replaceStrings(const std::string & s,
+    const std::string & from, const std::string & to)
+{
+    if (from.empty()) return s;
+    string res = s;
+    size_t pos = 0;
+    while ((pos = res.find(from, pos)) != std::string::npos) {
+        res.replace(pos, from.size(), to);
+        pos += to.size();
+    }
+    return res;
+}
+
+
 string statusToString(int status)
 {
     if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 6e20a22d9d..187e05ece0 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -341,6 +341,11 @@ string chomp(const string & s);
 string trim(const string & s, const string & whitespace = " \n\r\t");
 
 
+/* Replace all occurrences of a string inside another string. */
+string replaceStrings(const std::string & s,
+    const std::string & from, const std::string & to);
+
+
 /* Convert the exit status of a child as returned by wait() into an
    error string. */
 string statusToString(int status);