diff options
author | sterni <sternenseemann@systemli.org> | 2022-09-13T18·11+0200 |
---|---|---|
committer | clbot <clbot@tvl.fyi> | 2022-09-15T20·58+0000 |
commit | 067f2b16f6f5d8fce73b8420a53b51a15c90f589 (patch) | |
tree | cdfa2d5a70b14d1b438769aa282273d8efc469ac /tvix/eval/src/builtins/mod.rs | |
parent | e834a2cbc47cf18d5f35bb258ccc754c54c4f4e1 (diff) |
feat(tvix/eval): implement Value::coerce_to_path() r/4865
This function is necessary for all builtins that expect some form of path as an argument. It is merely a wrapper around coerce_to_string that can shortcut if we already have a path. The absolute path check is done in the same way as in C++ Nix for compatibility, although it should probably be revised in the long term (think about Windows, for example). Since coercing to a path is not an operation possible in the language directly, this function can live in the builtins module as the only place it is required. Change-Id: I69ed5455c00d193fea88b8fa83e28907a761cab5 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6574 Autosubmit: sterni <sternenseemann@systemli.org> Reviewed-by: tazjin <tazjin@tvl.su> Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/eval/src/builtins/mod.rs')
-rw-r--r-- | tvix/eval/src/builtins/mod.rs | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/tvix/eval/src/builtins/mod.rs b/tvix/eval/src/builtins/mod.rs index 33abfe492d10..7a2f46e2d47d 100644 --- a/tvix/eval/src/builtins/mod.rs +++ b/tvix/eval/src/builtins/mod.rs @@ -5,12 +5,14 @@ use std::{ collections::{BTreeMap, HashMap}, + path::PathBuf, rc::Rc, }; use crate::{ errors::ErrorKind, value::{Builtin, CoercionKind, NixAttrs, NixList, NixString, Value}, + vm::VM, }; use crate::arithmetic_op; @@ -36,6 +38,30 @@ macro_rules! force { }; } +/// Coerce a Nix Value to a plain path, e.g. in order to access the file it +/// points to in an I/O builtin. This coercion can _never_ be performed in +/// a Nix program directly (i.e. the trick `path: /. + path` to convert from +/// a string to a path wouldn't hit this code), so the target file +/// doesn't need to be realised or imported into the Nix store. +pub fn coerce_value_to_path(v: &Value, vm: &mut VM) -> Result<PathBuf, ErrorKind> { + force!(vm, v, value, { + match value { + Value::Thunk(t) => coerce_value_to_path(&t.value(), vm), + Value::Path(p) => Ok(p.clone()), + _ => value + .coerce_to_string(CoercionKind::Weak, vm) + .map(|s| PathBuf::from(s.as_str())) + .and_then(|path| { + if path.is_absolute() { + Ok(path) + } else { + Err(ErrorKind::NotAnAbsolutePath(path)) + } + }), + } + }) +} + /// Return all pure builtins, that is all builtins that do not rely on /// I/O outside of the VM and which can be used in any contexts (e.g. /// WASM). |