From 1ec6e6e11e2dbca8803305757d472dabe5878129 Mon Sep 17 00:00:00 2001
From: Eelco Dolstra <edolstra@gmail.com>
Date: Tue, 26 Nov 2019 19:48:34 +0100
Subject: [PATCH] Add feature to disable URL literals

E.g.

  $ nix-build '<nixpkgs>' -A hello --experimental-features no-url-literals
  error: URL literals are disabled, at /nix/store/vsjamkzh15r3c779q2711az826hqgvzr-nixpkgs-20.03pre194957.bef773ed53f/nixpkgs/pkgs/top-level/all-packages.nix:1236:11

Helps with implementing https://github.com/NixOS/rfcs/pull/45.
---
 src/libexpr/parser.y    | 8 +++++++-
 src/libstore/globals.cc | 9 +++++++--
 src/libstore/globals.hh | 2 ++
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 93834bec6..10a057062 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -20,6 +20,7 @@
 
 #include "nixexpr.hh"
 #include "eval.hh"
+#include "globals.hh"
 
 namespace nix {
 
@@ -401,7 +402,12 @@ expr_simple
               new ExprVar(data->symbols.create("__nixPath"))),
           new ExprString(data->symbols.create(path)));
   }
-  | URI { $$ = new ExprString(data->symbols.create($1)); }
+  | URI {
+      static bool noURLLiterals = settings.isExperimentalFeatureEnabled("no-url-literals");
+      if (noURLLiterals)
+          throw ParseError("URL literals are disabled, at %s", CUR_POS);
+      $$ = new ExprString(data->symbols.create($1));
+  }
   | '(' expr ')' { $$ = $2; }
   /* Let expressions `let {..., body = ...}' are just desugared
      into `(rec {..., body = ...}).body'. */
diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc
index aa0823f41..6d3b95740 100644
--- a/src/libstore/globals.cc
+++ b/src/libstore/globals.cc
@@ -105,10 +105,15 @@ StringSet Settings::getDefaultSystemFeatures()
     return features;
 }
 
-void Settings::requireExperimentalFeature(const std::string & name)
+bool Settings::isExperimentalFeatureEnabled(const std::string & name)
 {
     auto & f = experimentalFeatures.get();
-    if (std::find(f.begin(), f.end(), name) == f.end())
+    return std::find(f.begin(), f.end(), name) != f.end();
+}
+
+void Settings::requireExperimentalFeature(const std::string & name)
+{
+    if (!isExperimentalFeatureEnabled(name))
         throw Error("experimental Nix feature '%s' is disabled", name);
 }
 
diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh
index 3eb2f698c..9f395425a 100644
--- a/src/libstore/globals.hh
+++ b/src/libstore/globals.hh
@@ -357,6 +357,8 @@ public:
     Setting<Strings> experimentalFeatures{this, {}, "experimental-features",
         "Experimental Nix features to enable."};
 
+    bool isExperimentalFeatureEnabled(const std::string & name);
+
     void requireExperimentalFeature(const std::string & name);
 };