feat(tvix/glue): Implement builtins.storePath
This one's relatively simple - we just check if the store path exists, and if it does we make a new contextful string containing the store path as its only context element. Automatic testing seems tricky for this (I think?) so I tested it manually: tvix-repl> builtins.storePath /nix/store/yn46i4xx5alh7gs6fpkxk430i34rp2q9-hello-2.12.1 => "/nix/store/yn46i4xx5alh7gs6fpkxk430i34rp2q9-hello-2.12.1" :: string Change-Id: I8a0d9726e4102ab872c53c2419679c2c855a5a18 Reviewed-on: https://cl.tvl.fyi/c/depot/+/11696 Tested-by: BuildkiteCI Autosubmit: aspen <root@gws.fyi> Reviewed-by: flokli <flokli@flokli.de>
This commit is contained in:
parent
c3572048d5
commit
72b9a126b8
7 changed files with 62 additions and 2 deletions
|
@ -54,6 +54,12 @@ impl From<HashSet<NixContextElement>> for NixContext {
|
|||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> From<[NixContextElement; N]> for NixContext {
|
||||
fn from(value: [NixContextElement; N]) -> Self {
|
||||
Self(HashSet::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl NixContext {
|
||||
/// Creates an empty context that can be populated
|
||||
/// and passed to form a contextful [NixString], albeit
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
0
tvix/glue/src/tests/empty-file
Normal file
0
tvix/glue/src/tests/empty-file
Normal file
1
tvix/glue/src/tests/tvix_tests/eval-okay-storePath.exp
Normal file
1
tvix/glue/src/tests/tvix_tests/eval-okay-storePath.exp
Normal file
|
@ -0,0 +1 @@
|
|||
{ contextMatches = true; hasContext = true; }
|
9
tvix/glue/src/tests/tvix_tests/eval-okay-storePath.nix
Normal file
9
tvix/glue/src/tests/tvix_tests/eval-okay-storePath.nix
Normal file
|
@ -0,0 +1,9 @@
|
|||
let
|
||||
path = builtins.unsafeDiscardStringContext "${../empty-file}";
|
||||
storePath = builtins.storePath path;
|
||||
context = builtins.getContext storePath;
|
||||
in
|
||||
{
|
||||
hasContext = builtins.hasContext storePath;
|
||||
contextMatches = context == { "${path}" = { path = true; }; };
|
||||
}
|
|
@ -421,7 +421,7 @@ impl EvalIO for TvixStoreIO {
|
|||
{
|
||||
if self
|
||||
.tokio_handle
|
||||
.block_on(async { self.store_path_to_node(&store_path, &sub_path).await })?
|
||||
.block_on(self.store_path_to_node(&store_path, &sub_path))?
|
||||
.is_some()
|
||||
{
|
||||
Ok(true)
|
||||
|
|
Loading…
Reference in a new issue