about summary refs log tree commit diff
path: root/tvix/eval/src/builtins/impure.rs
diff options
context:
space:
mode:
authorWilliam Carroll <wpcarro@gmail.com>2022-09-06T20·56-0700
committerwpcarro <wpcarro@gmail.com>2022-10-10T19·36+0000
commit41ddc37725a59b4af0f7043a7fd66b3fe48f935d (patch)
tree09cc3a4b6456546697d0d28f91f80be74b75ce00 /tvix/eval/src/builtins/impure.rs
parent899fbdbddb93050f26236ff7c72e7ae4704d497b (diff)
feat(tvix/eval): Support builtins.readDir r/5083
Co-authored-by: Griffin Smith <root@gws.fyi>
Change-Id: I5ff19efbe87d8f571f22ab0480500505afa624c5
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6552
Autosubmit: wpcarro <wpcarro@gmail.com>
Reviewed-by: tazjin <tazjin@tvl.su>
Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/eval/src/builtins/impure.rs')
-rw-r--r--tvix/eval/src/builtins/impure.rs41
1 files changed, 39 insertions, 2 deletions
diff --git a/tvix/eval/src/builtins/impure.rs b/tvix/eval/src/builtins/impure.rs
index 8e23003edb47..32653b665c36 100644
--- a/tvix/eval/src/builtins/impure.rs
+++ b/tvix/eval/src/builtins/impure.rs
@@ -1,6 +1,7 @@
 use std::{
     cell::RefCell,
     collections::{BTreeMap, HashMap},
+    io,
     rc::Rc,
     time::{SystemTime, UNIX_EPOCH},
 };
@@ -8,13 +9,49 @@ use std::{
 use crate::{
     errors::ErrorKind,
     observer::NoOpObserver,
-    value::{Builtin, NixString, Thunk},
+    value::{Builtin, NixAttrs, NixString, Thunk},
     vm::VM,
     SourceCode, Value,
 };
 
 fn impure_builtins() -> Vec<Builtin> {
-    vec![]
+    vec![Builtin::new(
+        "readDir",
+        &[true],
+        |args: Vec<Value>, vm: &mut VM| {
+            let path = super::coerce_value_to_path(&args[0], vm)?;
+            let mk_err = |err: io::Error| ErrorKind::IO {
+                path: Some(path.clone()),
+                error: Rc::new(err),
+            };
+
+            let mut res = BTreeMap::new();
+            for entry in path.read_dir().map_err(mk_err)? {
+                let entry = entry.map_err(mk_err)?;
+                let file_type = entry
+                    .metadata()
+                    .map_err(|err| ErrorKind::IO {
+                        path: Some(entry.path()),
+                        error: Rc::new(err),
+                    })?
+                    .file_type();
+                let val = if file_type.is_dir() {
+                    "directory"
+                } else if file_type.is_file() {
+                    "regular"
+                } else if file_type.is_symlink() {
+                    "symlink"
+                } else {
+                    "unknown"
+                };
+                res.insert(
+                    entry.file_name().to_string_lossy().as_ref().into(),
+                    val.into(),
+                );
+            }
+            Ok(Value::attrs(NixAttrs::from_map(res)))
+        },
+    )]
 }
 
 /// Return all impure builtins, that is all builtins which may perform I/O