diff options
-rw-r--r-- | tvix/eval/src/io.rs | 23 | ||||
-rw-r--r-- | tvix/eval/src/value/mod.rs | 3 | ||||
-rw-r--r-- | tvix/eval/tests/nix_oracle.rs | 5 |
3 files changed, 28 insertions, 3 deletions
diff --git a/tvix/eval/src/io.rs b/tvix/eval/src/io.rs index 4e7404ef9c53..d20912f21f61 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<Vec<(SmolStr, FileType)>, 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<PathBuf, ErrorKind>; + /// Returns the root of the store directory, if such a thing /// exists in the evaluation context. fn store_dir(&self) -> Option<String> { @@ -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<PathBuf, ErrorKind> { + 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<PathBuf, ErrorKind> { + 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 583d0c38e46e..3e59c19c3196 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 4910a18bec08..e241a26f8ffd 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") |