diff options
Diffstat (limited to 'tvix/glue/src/builtins')
-rw-r--r-- | tvix/glue/src/builtins/errors.rs | 6 | ||||
-rw-r--r-- | tvix/glue/src/builtins/import.rs | 40 |
2 files changed, 45 insertions, 1 deletions
diff --git a/tvix/glue/src/builtins/errors.rs b/tvix/glue/src/builtins/errors.rs index f6d5745c56e2..af8a24e6abb8 100644 --- a/tvix/glue/src/builtins/errors.rs +++ b/tvix/glue/src/builtins/errors.rs @@ -4,7 +4,7 @@ use nix_compat::{ store_path::BuildStorePathError, }; use reqwest::Url; -use std::rc::Rc; +use std::{path::PathBuf, rc::Rc}; use thiserror::Error; use tvix_castore::import; @@ -65,8 +65,12 @@ pub enum FetcherError { pub enum ImportError { #[error("non-file '{0}' cannot be imported in 'flat' mode")] FlatImportOfNonFile(String), + #[error("hash mismatch at ingestion of '{0}', expected: '{1}', got: '{2}'")] HashMismatch(String, NixHash, NixHash), + + #[error("path '{}' is not in the Nix store", .0.display())] + PathNotInStore(PathBuf), } impl From<ImportError> for tvix_eval::ErrorKind { diff --git a/tvix/glue/src/builtins/import.rs b/tvix/glue/src/builtins/import.rs index 4a15afa8142d..4a8a29b417df 100644 --- a/tvix/glue/src/builtins/import.rs +++ b/tvix/glue/src/builtins/import.rs @@ -104,11 +104,13 @@ async fn filtered_ingest( #[builtins(state = "Rc<TvixStoreIO>")] mod import_builtins { + use std::os::unix::ffi::OsStrExt; use std::rc::Rc; use super::*; use nix_compat::nixhash::{CAHash, NixHash}; + use nix_compat::store_path::StorePath; use tvix_eval::generators::Gen; use tvix_eval::{generators::GenCo, ErrorKind, Value}; use tvix_eval::{NixContextElement, NixString}; @@ -280,6 +282,44 @@ mod import_builtins { .into(), ) } + + #[builtin("storePath")] + async fn builtin_store_path( + state: Rc<TvixStoreIO>, + co: GenCo, + path: Value, + ) -> Result<Value, ErrorKind> { + let p = std::str::from_utf8(match &path { + Value::String(s) => s.as_bytes(), + Value::Path(p) => p.as_os_str().as_bytes(), + _ => { + return Err(ErrorKind::TypeError { + expected: "string or path", + actual: path.type_of(), + }) + } + })?; + + let path_exists = if let Ok((store_path, sub_path)) = StorePath::from_absolute_path_full(p) + { + if !sub_path.as_os_str().is_empty() { + false + } else { + state.store_path_exists(store_path.as_ref()).await? + } + } else { + false + }; + + if !path_exists { + return Err(ImportError::PathNotInStore(p.into()).into()); + } + + Ok(Value::String(NixString::new_context_from( + [NixContextElement::Plain(p.into())].into(), + p, + ))) + } } pub use import_builtins::builtins as import_builtins; |