about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2023-03-04T00·43+0300
committertazjin <tazjin@tvl.su>2023-03-13T20·30+0000
commita59e264457f030fedf63c6d2925c896d6790d390 (patch)
treec5036a4f33ff1afde2b0c1fdf412823a66c93b80
parentc7007767336b5c7cc29b1fd10cd62132c99941e6 (diff)
feat(tvix/cli): bundle corepkgs/fetchurl.nix with tvix-cli r/5981
This file which ships with C++ Nix is required for evaluating nixpkgs.
Like C++ Nix, we now inject a pseudo path in EvalIO from which this
will resolve as <nix/fetchurl.nix>

Change-Id: Ic948c476a2cfc6381d5655d308bc2d5fa25b7123
Reviewed-on: https://cl.tvl.fyi/c/depot/+/8213
Reviewed-by: raitobezarius <tvl@lahfa.xyz>
Tested-by: BuildkiteCI
-rw-r--r--tvix/cli/src/fetchurl.nix53
-rw-r--r--tvix/cli/src/main.rs10
-rw-r--r--tvix/cli/src/nix_compat.rs14
3 files changed, 76 insertions, 1 deletions
diff --git a/tvix/cli/src/fetchurl.nix b/tvix/cli/src/fetchurl.nix
new file mode 100644
index 0000000000..3f182a5a31
--- /dev/null
+++ b/tvix/cli/src/fetchurl.nix
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: LGPL-2.1
+#
+# This file is vendored from C++ Nix, as it needs to be bundled with
+# an evaluator to be able to evaluate nixpkgs.
+#
+# Source: https://github.com/NixOS/nix/blob/2.3.16/corepkgs/fetchurl.nix
+
+{ system ? "" # obsolete
+, url
+, hash ? "" # an SRI hash
+
+  # Legacy hash specification
+, md5 ? ""
+, sha1 ? ""
+, sha256 ? ""
+, sha512 ? ""
+, outputHash ? if hash != "" then hash else if sha512 != "" then sha512 else if sha1 != "" then sha1 else if md5 != "" then md5 else sha256
+, outputHashAlgo ? if hash != "" then "" else if sha512 != "" then "sha512" else if sha1 != "" then "sha1" else if md5 != "" then "md5" else "sha256"
+
+, executable ? false
+, unpack ? false
+, name ? baseNameOf (toString url)
+}:
+
+derivation {
+  builder = "builtin:fetchurl";
+
+  # New-style output content requirements.
+  inherit outputHashAlgo outputHash;
+  outputHashMode = if unpack || executable then "recursive" else "flat";
+
+  inherit name url executable unpack;
+
+  system = "builtin";
+
+  # No need to double the amount of network traffic
+  preferLocalBuild = true;
+
+  impureEnvVars = [
+    # We borrow these environment variables from the caller to allow
+    # easy proxy configuration.  This is impure, but a fixed-output
+    # derivation like fetchurl is allowed to do so since its result is
+    # by definition pure.
+    "http_proxy"
+    "https_proxy"
+    "ftp_proxy"
+    "all_proxy"
+    "no_proxy"
+  ];
+
+  # To make "nix-prefetch-url" work.
+  urls = [ url ];
+}
diff --git a/tvix/cli/src/main.rs b/tvix/cli/src/main.rs
index 0942c128ec..beac126324 100644
--- a/tvix/cli/src/main.rs
+++ b/tvix/cli/src/main.rs
@@ -56,7 +56,15 @@ fn interpret(code: &str, path: Option<PathBuf>, args: &Args, explain: bool) -> b
     let known_paths: Rc<RefCell<KnownPaths>> = Default::default();
 
     eval.io_handle = Box::new(nix_compat::NixCompatIO::new(known_paths.clone()));
-    eval.nix_path = args.nix_search_path.clone();
+
+    // bundle fetchurl.nix (used in nixpkgs) by resolving <nix> to
+    // `/__corepkgs__`, which has special handling in [`nix_compat`].
+    eval.nix_path = args
+        .nix_search_path
+        .as_ref()
+        .map(|p| format!("nix=/__corepkgs__:{}", p))
+        .or_else(|| Some("nix=/__corepkgs__".to_string()));
+
     eval.builtins
         .extend(derivation::derivation_builtins(known_paths));
 
diff --git a/tvix/cli/src/nix_compat.rs b/tvix/cli/src/nix_compat.rs
index 2bee43882f..cc9e0db5fd 100644
--- a/tvix/cli/src/nix_compat.rs
+++ b/tvix/cli/src/nix_compat.rs
@@ -59,10 +59,24 @@ impl EvalIO for NixCompatIO {
 
     // Pass the rest of the functions through to `Self::underlying`
     fn path_exists(&self, path: PathBuf) -> Result<bool, ErrorKind> {
+        if path.starts_with("/__corepkgs__") {
+            return Ok(true);
+        }
+
         self.underlying.path_exists(path)
     }
 
     fn read_to_string(&self, path: PathBuf) -> Result<String, ErrorKind> {
+        // Bundled version of corepkgs/fetchurl.nix. This workaround
+        // is similar to what cppnix does for passing the path
+        // through.
+        //
+        // TODO: this comparison is bad and allocates, we should use
+        // the sane path library.
+        if path.starts_with("/__corepkgs__/fetchurl.nix") {
+            return Ok(include_str!("fetchurl.nix").to_string());
+        }
+
         self.underlying.read_to_string(path)
     }