about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRyan Lahfa <tvl@lahfa.xyz>2023-12-26T01·18+0100
committerclbot <clbot@tvl.fyi>2024-01-03T18·20+0000
commit09ec8b6fcf6ea5c04193c4539e4265a5c11a3386 (patch)
treeca58bccfa032b7a4cf5e8ac54fedb83727ee108e
parent96d06031affefeb0ee312e5fa5a6fcea29a7dff9 (diff)
feat(tvix/eval): implement `getContext` primop r/7331
Change-Id: I2c5068a28f9883a01b0ff80a5e5ab32ba18bfc1a
Reviewed-on: https://cl.tvl.fyi/c/depot/+/10437
Reviewed-by: tazjin <tazjin@tvl.su>
Autosubmit: raitobezarius <tvl@lahfa.xyz>
Tested-by: BuildkiteCI
-rw-r--r--tvix/eval/docs/builtins.md2
-rw-r--r--tvix/eval/src/builtins/mod.rs43
-rw-r--r--tvix/eval/src/value/string.rs4
3 files changed, 48 insertions, 1 deletions
diff --git a/tvix/eval/docs/builtins.md b/tvix/eval/docs/builtins.md
index a232331896..f3a4a29c26 100644
--- a/tvix/eval/docs/builtins.md
+++ b/tvix/eval/docs/builtins.md
@@ -61,7 +61,7 @@ The `impl` column indicates implementation status in tvix:
 | genList                       | false  |       |       |         |
 | genericClosure                | false  |       |       | todo    |
 | getAttr                       | false  |       |       |         |
-| getContext                    | false  |       |       | context |
+| getContext                    | false  |       |       |         |
 | getEnv                        | false  |       | false |         |
 | hasAttr                       | false  |       |       |         |
 | hasContext                    | false  |       |       |         |
diff --git a/tvix/eval/src/builtins/mod.rs b/tvix/eval/src/builtins/mod.rs
index 246efff12b..deb0f84ccc 100644
--- a/tvix/eval/src/builtins/mod.rs
+++ b/tvix/eval/src/builtins/mod.rs
@@ -23,6 +23,8 @@ use crate::{
     value::{CoercionKind, NixAttrs, NixList, NixString, Thunk, Value},
 };
 
+use crate::NixContextElement;
+
 use self::versions::{VersionPart, VersionPartsIter};
 
 mod to_xml;
@@ -581,6 +583,47 @@ mod pure_builtins {
         Ok(Value::Bool(v.has_context()))
     }
 
+    #[builtin("getContext")]
+    #[allow(non_snake_case)]
+    async fn builtin_getContext(co: GenCo, e: Value) -> Result<Value, ErrorKind> {
+        // also forces the value
+        let span = generators::request_span(&co).await;
+        let v = e
+            .coerce_to_string(
+                co,
+                CoercionKind {
+                    strong: true,
+                    import_paths: true,
+                },
+                span,
+            )
+            .await?;
+        let s = v.to_contextful_str()?;
+
+        let elements = s
+            .iter_context()
+            .flat_map(|context| context.iter())
+            .map(|ctx_element| match ctx_element {
+                NixContextElement::Plain(spath) => (
+                    spath.clone(),
+                    Value::attrs(NixAttrs::from_iter([("path", true)])),
+                ),
+                NixContextElement::Single { name, derivation } => (
+                    derivation.clone(),
+                    Value::attrs(NixAttrs::from_iter([(
+                        "outputs",
+                        Value::List(NixList::construct(1, vec![name.clone().into()])),
+                    )])),
+                ),
+                NixContextElement::Derivation(drv_path) => (
+                    drv_path.clone(),
+                    Value::attrs(NixAttrs::from_iter([("allOutputs", true)])),
+                ),
+            });
+
+        Ok(Value::attrs(NixAttrs::from_iter(elements)))
+    }
+
     #[builtin("hashString")]
     #[allow(non_snake_case)]
     async fn builtin_hashString(
diff --git a/tvix/eval/src/value/string.rs b/tvix/eval/src/value/string.rs
index aa82ed36eb..c528fd19f2 100644
--- a/tvix/eval/src/value/string.rs
+++ b/tvix/eval/src/value/string.rs
@@ -326,6 +326,10 @@ impl NixString {
         return self.1.as_mut();
     }
 
+    pub fn iter_context(&self) -> impl Iterator<Item = &NixContext> {
+        return self.1.iter();
+    }
+
     pub fn iter_plain(&self) -> impl Iterator<Item = &str> {
         return self.1.iter().flat_map(|context| context.iter_plain());
     }