feat(tvix/glue/fetchers): support file:// URLs
Nix supports file:// - URLs for `fetchurl` and `fetchTarball`. Convert the enums and function arguments to hold a URL type. reqwest::Url is a re-export of the url crate, but they don't re-export the parsing errors, and as we want to hold these in our Error types, add it to Cargo.toml explicitly. The Fetcher::download function now checks on the scheme, and either opens the file locally, or does do a HTTP request as before. Fetch gets its custom debug impl, removing potentially sensitive username and password out of URLs. Change-Id: I777db1fe487370e822cbfec4624034aca5e08045 Reviewed-on: https://cl.tvl.fyi/c/depot/+/11504 Autosubmit: flokli <flokli@flokli.de> Reviewed-by: raitobezarius <tvl@lahfa.xyz> Tested-by: BuildkiteCI
This commit is contained in:
parent
dfef3d18d1
commit
8181817e53
9 changed files with 124 additions and 37 deletions
|
|
@ -3,6 +3,7 @@ use nix_compat::{
|
|||
nixhash::{self, NixHash},
|
||||
store_path::BuildStorePathError,
|
||||
};
|
||||
use reqwest::Url;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
|
||||
|
|
@ -33,7 +34,7 @@ impl From<DerivationError> for tvix_eval::ErrorKind {
|
|||
pub enum FetcherError {
|
||||
#[error("hash mismatch in file downloaded from {url}:\n wanted: {wanted}\n got: {got}")]
|
||||
HashMismatch {
|
||||
url: String,
|
||||
url: Url,
|
||||
wanted: NixHash,
|
||||
got: NixHash,
|
||||
},
|
||||
|
|
@ -41,6 +42,9 @@ pub enum FetcherError {
|
|||
#[error("Invalid hash type '{0}' for fetcher")]
|
||||
InvalidHashType(&'static str),
|
||||
|
||||
#[error("Unable to parse URL: {0}")]
|
||||
InvalidUrl(#[from] url::ParseError),
|
||||
|
||||
#[error(transparent)]
|
||||
Http(#[from] reqwest::Error),
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//! Contains builtins that fetch paths from the Internet
|
||||
//! Contains builtins that fetch paths from the Internet, or local filesystem.
|
||||
|
||||
use super::utils::select_string;
|
||||
use crate::{
|
||||
|
|
@ -15,7 +15,7 @@ use tvix_eval::generators::GenCo;
|
|||
use tvix_eval::{CatchableErrorKind, ErrorKind, Value};
|
||||
|
||||
struct NixFetchArgs {
|
||||
url: String,
|
||||
url_str: String,
|
||||
name: Option<String>,
|
||||
sha256: Option<[u8; 32]>,
|
||||
}
|
||||
|
|
@ -26,11 +26,12 @@ async fn extract_fetch_args(
|
|||
co: &GenCo,
|
||||
args: Value,
|
||||
) -> Result<Result<NixFetchArgs, CatchableErrorKind>, ErrorKind> {
|
||||
if let Ok(url) = args.to_str() {
|
||||
if let Ok(url_str) = args.to_str() {
|
||||
// Get the raw bytes, not the ToString repr.
|
||||
let url = String::from_utf8(url.as_bytes().to_vec()).map_err(|_| ErrorKind::Utf8)?;
|
||||
let url_str =
|
||||
String::from_utf8(url_str.as_bytes().to_vec()).map_err(|_| ErrorKind::Utf8)?;
|
||||
return Ok(Ok(NixFetchArgs {
|
||||
url,
|
||||
url_str,
|
||||
name: None,
|
||||
sha256: None,
|
||||
}));
|
||||
|
|
@ -41,7 +42,7 @@ async fn extract_fetch_args(
|
|||
actual: args.type_of(),
|
||||
})?;
|
||||
|
||||
let url = match select_string(co, &attrs, "url").await? {
|
||||
let url_str = match select_string(co, &attrs, "url").await? {
|
||||
Ok(s) => s.ok_or_else(|| ErrorKind::AttributeNotFound { name: "url".into() })?,
|
||||
Err(cek) => return Ok(Err(cek)),
|
||||
};
|
||||
|
|
@ -68,12 +69,19 @@ async fn extract_fetch_args(
|
|||
None => None,
|
||||
};
|
||||
|
||||
Ok(Ok(NixFetchArgs { url, name, sha256 }))
|
||||
Ok(Ok(NixFetchArgs {
|
||||
url_str,
|
||||
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 super::*;
|
||||
|
||||
/// Consumes a fetch.
|
||||
|
|
@ -130,12 +138,16 @@ 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).to_owned());
|
||||
.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))))?;
|
||||
|
||||
fetch_lazy(
|
||||
state,
|
||||
name,
|
||||
Fetch::URL(args.url, args.sha256.map(NixHash::Sha256)),
|
||||
Fetch::URL(url, args.sha256.map(NixHash::Sha256)),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +168,11 @@ pub(crate) mod fetcher_builtins {
|
|||
.name
|
||||
.unwrap_or_else(|| DEFAULT_NAME_FETCH_TARBALL.to_owned());
|
||||
|
||||
fetch_lazy(state, name, Fetch::Tarball(args.url, args.sha256))
|
||||
// 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))
|
||||
}
|
||||
|
||||
#[builtin("fetchGit")]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue