diff options
Diffstat (limited to 'tvix/glue/src/builtins/fetchers.rs')
-rw-r--r-- | tvix/glue/src/builtins/fetchers.rs | 60 |
1 files changed, 35 insertions, 25 deletions
diff --git a/tvix/glue/src/builtins/fetchers.rs b/tvix/glue/src/builtins/fetchers.rs index c7602c03e8..1ad43b3833 100644 --- a/tvix/glue/src/builtins/fetchers.rs +++ b/tvix/glue/src/builtins/fetchers.rs @@ -6,16 +6,17 @@ use crate::{ tvix_store_io::TvixStoreIO, }; use nix_compat::nixhash; -use nix_compat::nixhash::NixHash; use std::rc::Rc; -use tracing::info; use tvix_eval::builtin_macros::builtins; use tvix_eval::generators::Gen; use tvix_eval::generators::GenCo; use tvix_eval::{CatchableErrorKind, ErrorKind, Value}; +use url::Url; +// Used as a return type for extract_fetch_args, which is sharing some +// parsing code between the fetchurl and fetchTarball builtins. struct NixFetchArgs { - url_str: String, + url: Url, name: Option<String>, sha256: Option<[u8; 32]>, } @@ -30,8 +31,12 @@ async fn extract_fetch_args( // Get the raw bytes, not the ToString repr. let url_str = String::from_utf8(url_str.as_bytes().to_vec()).map_err(|_| ErrorKind::Utf8)?; + + // Parse the URL. + let url = Url::parse(&url_str).map_err(|e| ErrorKind::TvixError(Rc::new(e)))?; + return Ok(Ok(NixFetchArgs { - url_str, + url, name: None, sha256: None, })); @@ -55,7 +60,14 @@ async fn extract_fetch_args( Err(cek) => return Ok(Err(cek)), }; - // TODO: disallow other attrset keys, to match Nix' behaviour. + // Disallow other attrset keys, to match Nix' behaviour. + // We complain about the first unexpected key we find in the list. + const VALID_KEYS: [&[u8]; 3] = [b"url", b"name", b"sha256"]; + if let Some(first_invalid_key) = attrs.keys().find(|k| !&VALID_KEYS.contains(&k.as_bytes())) { + return Err(ErrorKind::UnexpectedArgumentBuiltin( + first_invalid_key.clone(), + )); + } // parse the sha256 string into a digest. let sha256 = match sha256_str { @@ -69,18 +81,16 @@ async fn extract_fetch_args( None => None, }; - Ok(Ok(NixFetchArgs { - url_str, - name, - sha256, - })) + // Parse the URL. + let url = Url::parse(&url_str).map_err(|e| ErrorKind::TvixError(Rc::new(e)))?; + + Ok(Ok(NixFetchArgs { url, name, sha256 })) } #[allow(unused_variables)] // for the `state` arg, for now #[builtins(state = "Rc<TvixStoreIO>")] pub(crate) mod fetcher_builtins { - use crate::builtins::FetcherError; - use url::Url; + use nix_compat::nixhash::NixHash; use super::*; @@ -112,8 +122,6 @@ pub(crate) mod fetcher_builtins { } None => { // If we don't have enough info, do the fetch now. - info!(?fetch, "triggering required fetch"); - let (store_path, _root_node) = state .tokio_handle .block_on(async { state.fetcher.ingest_and_persist(&name, fetch).await }) @@ -138,16 +146,15 @@ pub(crate) mod fetcher_builtins { // Derive the name from the URL basename if not set explicitly. let name = args .name - .unwrap_or_else(|| url_basename(&args.url_str).to_owned()); - - // Parse the URL. - let url = Url::parse(&args.url_str) - .map_err(|e| ErrorKind::TvixError(Rc::new(FetcherError::InvalidUrl(e))))?; + .unwrap_or_else(|| url_basename(&args.url).to_owned()); fetch_lazy( state, name, - Fetch::URL(url, args.sha256.map(NixHash::Sha256)), + Fetch::URL { + url: args.url, + exp_hash: args.sha256.map(NixHash::Sha256), + }, ) } @@ -168,11 +175,14 @@ pub(crate) mod fetcher_builtins { .name .unwrap_or_else(|| DEFAULT_NAME_FETCH_TARBALL.to_owned()); - // Parse the URL. - let url = Url::parse(&args.url_str) - .map_err(|e| ErrorKind::TvixError(Rc::new(FetcherError::InvalidUrl(e))))?; - - fetch_lazy(state, name, Fetch::Tarball(url, args.sha256)) + fetch_lazy( + state, + name, + Fetch::Tarball { + url: args.url, + exp_nar_sha256: args.sha256, + }, + ) } #[builtin("fetchGit")] |