diff --git a/tvix/eval/src/io.rs b/tvix/eval/src/io.rs index 4e7404ef9..d20912f21 100644 --- a/tvix/eval/src/io.rs +++ b/tvix/eval/src/io.rs @@ -16,7 +16,7 @@ //! how store paths are opened and so on. use smol_str::SmolStr; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::rc::Rc; use crate::errors::ErrorKind; @@ -42,6 +42,15 @@ pub trait EvalIO { /// of its entries associated with their [`FileType`]. fn read_dir(&self, path: PathBuf) -> Result, ErrorKind>; + /// Import the given path. What this means depends on the + /// implementation, for example for a `std::io`-based + /// implementation this might be a no-op, while for a Tvix store + /// this might be a copy of the given files to the store. + /// + /// This is primarily used in the context of things like coercing + /// a local path to a string, or builtins like `path`. + fn import_path(&self, path: &Path) -> Result; + /// Returns the root of the store directory, if such a thing /// exists in the evaluation context. fn store_dir(&self) -> Option { @@ -103,6 +112,12 @@ impl EvalIO for StdIO { Ok(result) } + + // this is a no-op for `std::io`, as the user can already refer to + // the path directly + fn import_path(&self, path: &Path) -> Result { + Ok(path.to_path_buf()) + } } /// Dummy implementation of [`EvalIO`], can be used in contexts where @@ -127,4 +142,10 @@ impl EvalIO for DummyIO { "I/O methods are not implemented in DummyIO", )) } + + fn import_path(&self, _: &Path) -> Result { + Err(ErrorKind::NotImplemented( + "I/O methods are not implemented in DummyIO", + )) + } } diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs index 583d0c38e..3e59c19c3 100644 --- a/tvix/eval/src/value/mod.rs +++ b/tvix/eval/src/value/mod.rs @@ -185,7 +185,8 @@ impl Value { // sequences without NUL bytes, whereas Tvix only allows valid // Unicode. See also b/189. (Value::Path(p), kind) if kind != CoercionKind::ThunksOnly => { - Ok(p.to_string_lossy().into_owned().into()) + let imported = vm.io().import_path(p)?; + Ok(imported.to_string_lossy().into_owned().into()) } // Attribute sets can be converted to strings if they either have an diff --git a/tvix/eval/tests/nix_oracle.rs b/tvix/eval/tests/nix_oracle.rs index 4910a18be..e241a26f8 100644 --- a/tvix/eval/tests/nix_oracle.rs +++ b/tvix/eval/tests/nix_oracle.rs @@ -40,7 +40,10 @@ fn nix_eval(expr: &str) -> String { #[track_caller] fn compare_eval(expr: &str) { let nix_result = nix_eval(expr); - let tvix_result = tvix_eval::Evaluation::new(expr, None) + let mut eval = tvix_eval::Evaluation::new(expr, None); + eval.io_handle = Box::new(tvix_eval::StdIO); + + let tvix_result = eval .evaluate() .value .expect("tvix evaluation should succeed")