refactor(snix/eval,snix/glue): add snix_eval::try_cek! macros
Fixes #146 Change-Id: I971fac0d9d18e4ea73a527e499ac7ac213658477 Reviewed-on: https://cl.snix.dev/c/snix/+/30638 Reviewed-by: Florian Klink <flokli@flokli.de> Autosubmit: Axel Karjalainen <axel@axka.fi> Tested-by: besadii
This commit is contained in:
parent
8d0ae4f7ae
commit
4aa1137d8e
7 changed files with 227 additions and 210 deletions
|
|
@ -16,7 +16,10 @@ mod impure_builtins {
|
||||||
use std::os::unix::ffi::OsStrExt;
|
use std::os::unix::ffi::OsStrExt;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::builtins::{coerce_value_to_path, hash::hash_nix_string};
|
use crate::{
|
||||||
|
builtins::{coerce_value_to_path, hash::hash_nix_string},
|
||||||
|
try_cek_to_value,
|
||||||
|
};
|
||||||
|
|
||||||
#[builtin("getEnv")]
|
#[builtin("getEnv")]
|
||||||
async fn builtin_get_env(co: GenCo, var: Value) -> Result<Value, ErrorKind> {
|
async fn builtin_get_env(co: GenCo, var: Value) -> Result<Value, ErrorKind> {
|
||||||
|
|
@ -28,67 +31,52 @@ mod impure_builtins {
|
||||||
|
|
||||||
#[builtin("hashFile")]
|
#[builtin("hashFile")]
|
||||||
async fn builtin_hash_file(co: GenCo, algo: Value, path: Value) -> Result<Value, ErrorKind> {
|
async fn builtin_hash_file(co: GenCo, algo: Value, path: Value) -> Result<Value, ErrorKind> {
|
||||||
let path = match coerce_value_to_path(&co, path).await? {
|
let path = try_cek_to_value!(coerce_value_to_path(&co, path).await?);
|
||||||
Err(cek) => return Ok(Value::from(cek)),
|
|
||||||
Ok(p) => p,
|
|
||||||
};
|
|
||||||
let r = generators::request_open_file(&co, path).await;
|
let r = generators::request_open_file(&co, path).await;
|
||||||
hash_nix_string(algo.to_str()?, r).map(Value::from)
|
hash_nix_string(algo.to_str()?, r).map(Value::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[builtin("pathExists")]
|
#[builtin("pathExists")]
|
||||||
async fn builtin_path_exists(co: GenCo, path: Value) -> Result<Value, ErrorKind> {
|
async fn builtin_path_exists(co: GenCo, path: Value) -> Result<Value, ErrorKind> {
|
||||||
match coerce_value_to_path(&co, path).await? {
|
let path = try_cek_to_value!(coerce_value_to_path(&co, path).await?);
|
||||||
Err(cek) => Ok(Value::from(cek)),
|
Ok(generators::request_path_exists(&co, path).await)
|
||||||
Ok(path) => Ok(generators::request_path_exists(&co, path).await),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[builtin("readDir")]
|
#[builtin("readDir")]
|
||||||
async fn builtin_read_dir(co: GenCo, path: Value) -> Result<Value, ErrorKind> {
|
async fn builtin_read_dir(co: GenCo, path: Value) -> Result<Value, ErrorKind> {
|
||||||
match coerce_value_to_path(&co, path).await? {
|
let path = try_cek_to_value!(coerce_value_to_path(&co, path).await?);
|
||||||
Err(cek) => Ok(Value::from(cek)),
|
let dir = generators::request_read_dir(&co, path).await;
|
||||||
Ok(path) => {
|
let res = dir.into_iter().map(|(name, ftype)| {
|
||||||
let dir = generators::request_read_dir(&co, path).await;
|
(
|
||||||
let res = dir.into_iter().map(|(name, ftype)| {
|
// TODO: propagate Vec<u8> or bytes::Bytes into NixString.
|
||||||
(
|
NixString::from(
|
||||||
// TODO: propagate Vec<u8> or bytes::Bytes into NixString.
|
String::from_utf8(name.to_vec()).expect("parsing file name as string"),
|
||||||
NixString::from(
|
),
|
||||||
String::from_utf8(name.to_vec()).expect("parsing file name as string"),
|
Value::from(ftype.to_string()),
|
||||||
),
|
)
|
||||||
Value::from(ftype.to_string()),
|
});
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(Value::attrs(NixAttrs::from_iter(res)))
|
Ok(Value::attrs(NixAttrs::from_iter(res)))
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[builtin("readFile")]
|
#[builtin("readFile")]
|
||||||
async fn builtin_read_file(co: GenCo, path: Value) -> Result<Value, ErrorKind> {
|
async fn builtin_read_file(co: GenCo, path: Value) -> Result<Value, ErrorKind> {
|
||||||
match coerce_value_to_path(&co, path).await? {
|
let path = try_cek_to_value!(coerce_value_to_path(&co, path).await?);
|
||||||
Err(cek) => Ok(Value::from(cek)),
|
let mut buf = Vec::new();
|
||||||
Ok(path) => {
|
generators::request_open_file(&co, path)
|
||||||
let mut buf = Vec::new();
|
.await
|
||||||
generators::request_open_file(&co, path)
|
.read_to_end(&mut buf)?;
|
||||||
.await
|
Ok(Value::from(buf))
|
||||||
.read_to_end(&mut buf)?;
|
|
||||||
Ok(Value::from(buf))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[builtin("readFileType")]
|
#[builtin("readFileType")]
|
||||||
async fn builtin_read_file_type(co: GenCo, path: Value) -> Result<Value, ErrorKind> {
|
async fn builtin_read_file_type(co: GenCo, path: Value) -> Result<Value, ErrorKind> {
|
||||||
match coerce_value_to_path(&co, path).await? {
|
let path = try_cek_to_value!(coerce_value_to_path(&co, path).await?);
|
||||||
Err(cek) => Ok(Value::from(cek)),
|
Ok(Value::from(
|
||||||
Ok(path) => Ok(Value::from(
|
generators::request_read_file_type(&co, path)
|
||||||
generators::request_read_file_type(&co, path)
|
.await
|
||||||
.await
|
.to_string(),
|
||||||
.to_string(),
|
))
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ use std::collections::VecDeque;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::{Mutex, OnceLock};
|
use std::sync::{Mutex, OnceLock};
|
||||||
|
|
||||||
use crate::arithmetic_op;
|
|
||||||
use crate::value::PointerEquality;
|
use crate::value::PointerEquality;
|
||||||
use crate::vm::generators::{self, GenCo};
|
use crate::vm::generators::{self, GenCo};
|
||||||
use crate::warnings::WarningKind;
|
use crate::warnings::WarningKind;
|
||||||
|
|
@ -24,6 +23,7 @@ use crate::{
|
||||||
errors::{CatchableErrorKind, ErrorKind},
|
errors::{CatchableErrorKind, ErrorKind},
|
||||||
value::{CoercionKind, NixAttrs, NixList, NixString, Thunk, Value},
|
value::{CoercionKind, NixAttrs, NixList, NixString, Thunk, Value},
|
||||||
};
|
};
|
||||||
|
use crate::{arithmetic_op, try_cek};
|
||||||
|
|
||||||
use self::versions::{VersionPart, VersionPartsIter};
|
use self::versions::{VersionPart, VersionPartsIter};
|
||||||
|
|
||||||
|
|
@ -59,25 +59,23 @@ pub async fn coerce_value_to_path(
|
||||||
return Ok(Ok(*p));
|
return Ok(Ok(*p));
|
||||||
}
|
}
|
||||||
|
|
||||||
match generators::request_string_coerce(
|
let vs = try_cek!(
|
||||||
co,
|
generators::request_string_coerce(
|
||||||
value,
|
co,
|
||||||
CoercionKind {
|
value,
|
||||||
strong: false,
|
CoercionKind {
|
||||||
import_paths: false,
|
strong: false,
|
||||||
},
|
import_paths: false,
|
||||||
)
|
},
|
||||||
.await
|
)
|
||||||
{
|
.await
|
||||||
Ok(vs) => {
|
);
|
||||||
let path = vs.to_path()?.to_owned();
|
|
||||||
if path.is_absolute() {
|
let path = vs.to_path()?.to_owned();
|
||||||
Ok(Ok(path))
|
if path.is_absolute() {
|
||||||
} else {
|
Ok(Ok(path))
|
||||||
Err(ErrorKind::NotAnAbsolutePath(path))
|
} else {
|
||||||
}
|
Err(ErrorKind::NotAnAbsolutePath(path))
|
||||||
}
|
|
||||||
Err(cek) => Ok(Err(cek)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,7 +104,9 @@ mod pure_builtins {
|
||||||
use os_str_bytes::OsStringBytes;
|
use os_str_bytes::OsStringBytes;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
use crate::{AddContext, NixContext, NixContextElement, value::PointerEquality};
|
use crate::{
|
||||||
|
AddContext, NixContext, NixContextElement, try_cek_to_value, value::PointerEquality,
|
||||||
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|
@ -302,23 +302,20 @@ mod pure_builtins {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
res.push_str(&separator);
|
res.push_str(&separator);
|
||||||
}
|
}
|
||||||
match generators::request_string_coerce(
|
let mut s = try_cek_to_value!(
|
||||||
&co,
|
generators::request_string_coerce(
|
||||||
val,
|
&co,
|
||||||
CoercionKind {
|
val,
|
||||||
strong: false,
|
CoercionKind {
|
||||||
import_paths: true,
|
strong: false,
|
||||||
},
|
import_paths: true,
|
||||||
)
|
},
|
||||||
.await
|
)
|
||||||
{
|
.await
|
||||||
Ok(mut s) => {
|
);
|
||||||
res.push_str(&s);
|
res.push_str(&s);
|
||||||
if let Some(other_context) = s.take_context() {
|
if let Some(other_context) = s.take_context() {
|
||||||
context.extend(other_context.into_iter());
|
context.extend(other_context.into_iter());
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(c) => return Ok(Value::Catchable(Box::new(c))),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// FIXME: pass immediately the string res.
|
// FIXME: pass immediately the string res.
|
||||||
|
|
@ -372,11 +369,11 @@ mod pure_builtins {
|
||||||
#[builtin("elem")]
|
#[builtin("elem")]
|
||||||
async fn builtin_elem(co: GenCo, x: Value, xs: Value) -> Result<Value, ErrorKind> {
|
async fn builtin_elem(co: GenCo, x: Value, xs: Value) -> Result<Value, ErrorKind> {
|
||||||
for val in xs.to_list()? {
|
for val in xs.to_list()? {
|
||||||
match generators::check_equality(&co, x.clone(), val, PointerEquality::AllowAll).await?
|
match try_cek_to_value!(
|
||||||
{
|
generators::check_equality(&co, x.clone(), val, PointerEquality::AllowAll).await?
|
||||||
Ok(true) => return Ok(true.into()),
|
) {
|
||||||
Ok(false) => continue,
|
true => return Ok(true.into()),
|
||||||
Err(cek) => return Ok(Value::from(cek)),
|
false => continue,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(false.into())
|
Ok(false.into())
|
||||||
|
|
@ -504,13 +501,10 @@ mod pure_builtins {
|
||||||
let attrs = val.to_attrs()?;
|
let attrs = val.to_attrs()?;
|
||||||
let key = attrs.select_required("key")?;
|
let key = attrs.select_required("key")?;
|
||||||
|
|
||||||
let value_missing = bgc_insert_key(&co, key.clone(), &mut done_keys).await?;
|
let value_missing =
|
||||||
|
try_cek_to_value!(bgc_insert_key(&co, key.clone(), &mut done_keys).await?);
|
||||||
|
|
||||||
if let Err(cek) = value_missing {
|
if !value_missing {
|
||||||
return Ok(Value::Catchable(Box::new(cek)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Ok(false) = value_missing {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -909,10 +903,9 @@ mod pure_builtins {
|
||||||
#[builtin("lessThan")]
|
#[builtin("lessThan")]
|
||||||
async fn builtin_less_than(co: GenCo, x: Value, y: Value) -> Result<Value, ErrorKind> {
|
async fn builtin_less_than(co: GenCo, x: Value, y: Value) -> Result<Value, ErrorKind> {
|
||||||
let span = generators::request_span(&co).await;
|
let span = generators::request_span(&co).await;
|
||||||
match x.nix_cmp_ordering(y, co, span).await? {
|
match try_cek_to_value!(x.nix_cmp_ordering(y, co, span).await?) {
|
||||||
Err(cek) => Ok(Value::from(cek)),
|
Ordering::Less => Ok(Value::Bool(true)),
|
||||||
Ok(Ordering::Less) => Ok(Value::Bool(true)),
|
_ => Ok(Value::Bool(false)),
|
||||||
Ok(_) => Ok(Value::Bool(false)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1474,23 +1467,18 @@ mod pure_builtins {
|
||||||
return Ok(s);
|
return Ok(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
match coerce_value_to_path(&co, s).await? {
|
let path = try_cek_to_value!(coerce_value_to_path(&co, s).await?);
|
||||||
Err(cek) => Ok(Value::from(cek)),
|
let path: Value = crate::value::canon_path(path).into();
|
||||||
Ok(path) => {
|
let span = generators::request_span(&co).await;
|
||||||
let path: Value = crate::value::canon_path(path).into();
|
path.coerce_to_string(
|
||||||
let span = generators::request_span(&co).await;
|
co,
|
||||||
Ok(path
|
CoercionKind {
|
||||||
.coerce_to_string(
|
strong: false,
|
||||||
co,
|
import_paths: false,
|
||||||
CoercionKind {
|
},
|
||||||
strong: false,
|
span,
|
||||||
import_paths: false,
|
)
|
||||||
},
|
.await
|
||||||
span,
|
|
||||||
)
|
|
||||||
.await?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[builtin("tryEval")]
|
#[builtin("tryEval")]
|
||||||
|
|
@ -1521,18 +1509,17 @@ async fn bgc_insert_key(
|
||||||
done: &mut Vec<Value>,
|
done: &mut Vec<Value>,
|
||||||
) -> Result<Result<bool, CatchableErrorKind>, ErrorKind> {
|
) -> Result<Result<bool, CatchableErrorKind>, ErrorKind> {
|
||||||
for existing in done.iter() {
|
for existing in done.iter() {
|
||||||
match generators::check_equality(
|
if try_cek!(
|
||||||
co,
|
generators::check_equality(
|
||||||
existing.clone(),
|
co,
|
||||||
key.clone(),
|
existing.clone(),
|
||||||
// TODO(tazjin): not actually sure which semantics apply here
|
key.clone(),
|
||||||
PointerEquality::ForbidAll,
|
// TODO(tazjin): not actually sure which semantics apply here
|
||||||
)
|
PointerEquality::ForbidAll,
|
||||||
.await?
|
)
|
||||||
{
|
.await?
|
||||||
Ok(true) => return Ok(Ok(false)),
|
) {
|
||||||
Ok(false) => (),
|
return Ok(Ok(false));
|
||||||
Err(cek) => return Ok(Err(cek)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ use crate::{
|
||||||
builtins::coerce_value_to_path,
|
builtins::coerce_value_to_path,
|
||||||
generators::pin_generator,
|
generators::pin_generator,
|
||||||
observer::NoOpObserver,
|
observer::NoOpObserver,
|
||||||
|
try_cek_to_value,
|
||||||
value::{Builtin, Thunk},
|
value::{Builtin, Thunk},
|
||||||
vm::generators::{self, GenCo},
|
vm::generators::{self, GenCo},
|
||||||
};
|
};
|
||||||
|
|
@ -25,10 +26,7 @@ async fn import_impl(
|
||||||
mut args: Vec<Value>,
|
mut args: Vec<Value>,
|
||||||
) -> Result<Value, ErrorKind> {
|
) -> Result<Value, ErrorKind> {
|
||||||
// TODO(sterni): canon_path()?
|
// TODO(sterni): canon_path()?
|
||||||
let mut path = match coerce_value_to_path(&co, args.pop().unwrap()).await? {
|
let mut path = try_cek_to_value!(coerce_value_to_path(&co, args.pop().unwrap()).await?);
|
||||||
Err(cek) => return Ok(Value::Catchable(Box::new(cek))),
|
|
||||||
Ok(path) => path,
|
|
||||||
};
|
|
||||||
|
|
||||||
if path.is_dir() {
|
if path.is_dir() {
|
||||||
path.push("default.nix");
|
path.push("default.nix");
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,81 @@ use crate::spans::ToSpan;
|
||||||
use crate::value::{CoercionKind, NixString};
|
use crate::value::{CoercionKind, NixString};
|
||||||
use crate::{SourceCode, Value};
|
use crate::{SourceCode, Value};
|
||||||
|
|
||||||
|
/// Propagates a [catchable error](CatchableErrorKind) as `Ok(Err(_))` or returns the unwrapped value in `Ok`.
|
||||||
|
///
|
||||||
|
/// You should use the try operator (`?`) to propagate uncatchable errors before passing catchable
|
||||||
|
/// errors to `try_cek`.
|
||||||
|
///
|
||||||
|
/// **Input type:** `Result<T, CatchableErrorKind>`
|
||||||
|
///
|
||||||
|
/// **Output type:** `T`
|
||||||
|
///
|
||||||
|
/// **Return type of containing function:** `Result<Result<_, CatchableErrorKind>, _>`
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use snix_eval::{try_cek, CatchableErrorKind};
|
||||||
|
///
|
||||||
|
/// # #[derive(Debug)] struct MyUncatchableError;
|
||||||
|
/// # fn example() -> Result<Result<(), CatchableErrorKind>, MyUncatchableError> {
|
||||||
|
/// fn my_fn() -> Result<Result<i32, CatchableErrorKind>, MyUncatchableError> {
|
||||||
|
/// Ok(Ok(42))
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let value: i32 = try_cek!(my_fn()?);
|
||||||
|
/// assert_eq!(value, 42);
|
||||||
|
///
|
||||||
|
/// fn my_other_fn() -> Result<Result<i32, CatchableErrorKind>, MyUncatchableError> {
|
||||||
|
/// Ok(Err(CatchableErrorKind::AssertionFailed))
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// try_cek!(my_other_fn()?); // results in `return Ok(Err(cek))`
|
||||||
|
/// unreachable!();
|
||||||
|
///
|
||||||
|
/// # Ok(Ok(()))
|
||||||
|
/// # }
|
||||||
|
/// # fn main() {
|
||||||
|
/// # pretty_assertions::assert_matches!(example().unwrap(), Err(CatchableErrorKind::AssertionFailed));
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! try_cek {
|
||||||
|
($result:expr) => {
|
||||||
|
match $result {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(cek) => {
|
||||||
|
// Type-check to avoid accidental misuse
|
||||||
|
let cek: $crate::CatchableErrorKind = cek;
|
||||||
|
return Ok(Err(cek));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Propagates a [catchable error](CatchableErrorKind) as `Ok(Value::Catchable(_))` or returns the unwrapped value in `Ok`.
|
||||||
|
///
|
||||||
|
/// **Input type:** `Result<T, CatchableErrorKind>`
|
||||||
|
///
|
||||||
|
/// **Output type:** `T`
|
||||||
|
///
|
||||||
|
/// **Return type of containing function:** `Result<Value, _>`
|
||||||
|
///
|
||||||
|
/// See [`try_cek!`]'s documentation for more.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! try_cek_to_value {
|
||||||
|
($result:expr) => {
|
||||||
|
match $result {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(cek) => {
|
||||||
|
// Type-check to avoid accidental misuse
|
||||||
|
let cek: $crate::CatchableErrorKind = cek;
|
||||||
|
return Ok(Value::Catchable(Box::new(cek)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// "CatchableErrorKind" errors -- those which can be detected by
|
/// "CatchableErrorKind" errors -- those which can be detected by
|
||||||
/// `builtins.tryEval`.
|
/// `builtins.tryEval`.
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,7 @@ pub(crate) mod derivation_builtins {
|
||||||
|
|
||||||
use nix_compat::store_path::hash_placeholder;
|
use nix_compat::store_path::hash_placeholder;
|
||||||
use snix_eval::generators::Gen;
|
use snix_eval::generators::Gen;
|
||||||
use snix_eval::{NixContext, NixContextElement, NixString};
|
use snix_eval::{NixContext, NixContextElement, NixString, try_cek_to_value};
|
||||||
|
|
||||||
use crate::builtins::utils::{select_string, strong_importing_coerce_to_string};
|
use crate::builtins::utils::{select_string, strong_importing_coerce_to_string};
|
||||||
use crate::fetchurl::fetchurl_derivation_to_fetch;
|
use crate::fetchurl::fetchurl_derivation_to_fetch;
|
||||||
|
|
@ -279,13 +279,10 @@ pub(crate) mod derivation_builtins {
|
||||||
// These are only set in drv.arguments.
|
// These are only set in drv.arguments.
|
||||||
"args" => {
|
"args" => {
|
||||||
for arg in value.to_list()? {
|
for arg in value.to_list()? {
|
||||||
match strong_importing_coerce_to_string(&co, arg).await {
|
let s =
|
||||||
Err(cek) => return Ok(Value::from(cek)),
|
try_cek_to_value!(strong_importing_coerce_to_string(&co, arg).await);
|
||||||
Ok(s) => {
|
input_context.mimic(&s);
|
||||||
input_context.mimic(&s);
|
drv.arguments.push(s.to_str()?.to_owned())
|
||||||
drv.arguments.push(s.to_str()?.to_owned())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -338,28 +335,23 @@ pub(crate) mod derivation_builtins {
|
||||||
|
|
||||||
// handle builder and system.
|
// handle builder and system.
|
||||||
"builder" | "system" => {
|
"builder" | "system" => {
|
||||||
match strong_importing_coerce_to_string(&co, value).await {
|
let val_str =
|
||||||
Err(cek) => return Ok(Value::from(cek)),
|
try_cek_to_value!(strong_importing_coerce_to_string(&co, value).await);
|
||||||
Ok(val_str) => {
|
input_context.mimic(&val_str);
|
||||||
input_context.mimic(&val_str);
|
|
||||||
|
|
||||||
if arg_name == "builder" {
|
if arg_name == "builder" {
|
||||||
val_str.to_str()?.clone_into(&mut drv.builder);
|
val_str.to_str()?.clone_into(&mut drv.builder);
|
||||||
} else {
|
} else {
|
||||||
val_str.to_str()?.clone_into(&mut drv.system);
|
val_str.to_str()?.clone_into(&mut drv.system);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Either populate drv.environment or structured_attrs.
|
// Either populate drv.environment or structured_attrs.
|
||||||
if let Some(ref mut structured_attrs) = structured_attrs {
|
if let Some(ref mut structured_attrs) = structured_attrs {
|
||||||
// No need to check for dups, we only iterate over every attribute name once
|
// No need to check for dups, we only iterate over every attribute name once
|
||||||
structured_attrs.insert(
|
structured_attrs
|
||||||
arg_name.to_owned(),
|
.insert(arg_name.to_owned(), val_str.to_str()?.to_owned().into());
|
||||||
val_str.to_str()?.to_owned().into(),
|
} else {
|
||||||
);
|
insert_env(&mut drv, arg_name, val_str.as_bytes().into())?;
|
||||||
} else {
|
|
||||||
insert_env(&mut drv, arg_name, val_str.as_bytes().into())?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -384,14 +376,11 @@ pub(crate) mod derivation_builtins {
|
||||||
// No need to check for dups, we only iterate over every attribute name once
|
// No need to check for dups, we only iterate over every attribute name once
|
||||||
structured_attrs.insert(arg_name.to_owned(), val_json);
|
structured_attrs.insert(arg_name.to_owned(), val_json);
|
||||||
} else {
|
} else {
|
||||||
match strong_importing_coerce_to_string(&co, value).await {
|
let val_str =
|
||||||
Err(cek) => return Ok(Value::from(cek)),
|
try_cek_to_value!(strong_importing_coerce_to_string(&co, value).await);
|
||||||
Ok(val_str) => {
|
input_context.mimic(&val_str);
|
||||||
input_context.mimic(&val_str);
|
|
||||||
|
|
||||||
insert_env(&mut drv, arg_name, val_str.as_bytes().into())?;
|
insert_env(&mut drv, arg_name, val_str.as_bytes().into())?;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -400,27 +389,21 @@ pub(crate) mod derivation_builtins {
|
||||||
|
|
||||||
// Configure fixed-output derivations if required.
|
// Configure fixed-output derivations if required.
|
||||||
{
|
{
|
||||||
let output_hash = match select_string(&co, &input, "outputHash")
|
let output_hash = try_cek_to_value!(
|
||||||
.await
|
select_string(&co, &input, "outputHash")
|
||||||
.context("evaluating the `outputHash` parameter")?
|
.await
|
||||||
{
|
.context("evaluating the `outputHash` parameter")?
|
||||||
Err(cek) => return Ok(Value::from(cek)),
|
);
|
||||||
Ok(s) => s,
|
let output_hash_algo = try_cek_to_value!(
|
||||||
};
|
select_string(&co, &input, "outputHashAlgo")
|
||||||
let output_hash_algo = match select_string(&co, &input, "outputHashAlgo")
|
.await
|
||||||
.await
|
.context("evaluating the `outputHashAlgo` parameter")?
|
||||||
.context("evaluating the `outputHashAlgo` parameter")?
|
);
|
||||||
{
|
let output_hash_mode = try_cek_to_value!(
|
||||||
Err(cek) => return Ok(Value::from(cek)),
|
select_string(&co, &input, "outputHashMode")
|
||||||
Ok(s) => s,
|
.await
|
||||||
};
|
.context("evaluating the `outputHashMode` parameter")?
|
||||||
let output_hash_mode = match select_string(&co, &input, "outputHashMode")
|
);
|
||||||
.await
|
|
||||||
.context("evaluating the `outputHashMode` parameter")?
|
|
||||||
{
|
|
||||||
Err(cek) => return Ok(Value::from(cek)),
|
|
||||||
Ok(s) => s,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(warning) =
|
if let Some(warning) =
|
||||||
handle_fixed_output(&mut drv, output_hash, output_hash_algo, output_hash_mode)?
|
handle_fixed_output(&mut drv, output_hash, output_hash_algo, output_hash_mode)?
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use nix_compat::nixhash::{HashAlgo, NixHash};
|
||||||
use snix_eval::builtin_macros::builtins;
|
use snix_eval::builtin_macros::builtins;
|
||||||
use snix_eval::generators::Gen;
|
use snix_eval::generators::Gen;
|
||||||
use snix_eval::generators::GenCo;
|
use snix_eval::generators::GenCo;
|
||||||
use snix_eval::{CatchableErrorKind, ErrorKind, Value};
|
use snix_eval::{CatchableErrorKind, ErrorKind, Value, try_cek};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
|
@ -56,18 +56,10 @@ async fn extract_fetch_args(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let url_str = match select_string(co, &attrs, "url").await? {
|
let url_str = try_cek!(select_string(co, &attrs, "url").await?)
|
||||||
Ok(s) => s.ok_or_else(|| ErrorKind::AttributeNotFound { name: "url".into() })?,
|
.ok_or_else(|| ErrorKind::AttributeNotFound { name: "url".into() })?;
|
||||||
Err(cek) => return Ok(Err(cek)),
|
let name = try_cek!(select_string(co, &attrs, "name").await?);
|
||||||
};
|
let sha256_str = try_cek!(select_string(co, &attrs, "sha256").await?);
|
||||||
let name = match select_string(co, &attrs, "name").await? {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(cek) => return Ok(Err(cek)),
|
|
||||||
};
|
|
||||||
let sha256_str = match select_string(co, &attrs, "sha256").await? {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(cek) => return Ok(Err(cek)),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Ok(NixFetchArgs {
|
Ok(Ok(NixFetchArgs {
|
||||||
url: Url::parse(&url_str).map_err(|e| ErrorKind::SnixError(Rc::new(e)))?,
|
url: Url::parse(&url_str).map_err(|e| ErrorKind::SnixError(Rc::new(e)))?,
|
||||||
|
|
@ -89,6 +81,7 @@ async fn extract_fetch_args(
|
||||||
pub(crate) mod fetcher_builtins {
|
pub(crate) mod fetcher_builtins {
|
||||||
use bstr::ByteSlice;
|
use bstr::ByteSlice;
|
||||||
use nix_compat::{flakeref, nixhash::NixHash};
|
use nix_compat::{flakeref, nixhash::NixHash};
|
||||||
|
use snix_eval::try_cek_to_value;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
@ -137,10 +130,7 @@ pub(crate) mod fetcher_builtins {
|
||||||
co: GenCo,
|
co: GenCo,
|
||||||
args: Value,
|
args: Value,
|
||||||
) -> Result<Value, ErrorKind> {
|
) -> Result<Value, ErrorKind> {
|
||||||
let args = match extract_fetch_args(&co, args).await? {
|
let args = try_cek_to_value!(extract_fetch_args(&co, args).await?);
|
||||||
Ok(args) => args,
|
|
||||||
Err(cek) => return Ok(Value::from(cek)),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Derive the name from the URL basename if not set explicitly.
|
// Derive the name from the URL basename if not set explicitly.
|
||||||
let name = args
|
let name = args
|
||||||
|
|
@ -163,10 +153,7 @@ pub(crate) mod fetcher_builtins {
|
||||||
co: GenCo,
|
co: GenCo,
|
||||||
args: Value,
|
args: Value,
|
||||||
) -> Result<Value, ErrorKind> {
|
) -> Result<Value, ErrorKind> {
|
||||||
let args = match extract_fetch_args(&co, args).await? {
|
let args = try_cek_to_value!(extract_fetch_args(&co, args).await?);
|
||||||
Ok(args) => args,
|
|
||||||
Err(cek) => return Ok(Value::from(cek)),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Name defaults to "source" if not set explicitly.
|
// Name defaults to "source" if not set explicitly.
|
||||||
const DEFAULT_NAME_FETCH_TARBALL: &str = "source";
|
const DEFAULT_NAME_FETCH_TARBALL: &str = "source";
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ use bstr::ByteSlice;
|
||||||
use snix_eval::{
|
use snix_eval::{
|
||||||
CatchableErrorKind, CoercionKind, ErrorKind, NixAttrs, NixString, Value,
|
CatchableErrorKind, CoercionKind, ErrorKind, NixAttrs, NixString, Value,
|
||||||
generators::{self, GenCo},
|
generators::{self, GenCo},
|
||||||
|
try_cek,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(super) async fn strong_importing_coerce_to_string(
|
pub(super) async fn strong_importing_coerce_to_string(
|
||||||
|
|
@ -26,10 +27,8 @@ pub(super) async fn select_string(
|
||||||
key: &str,
|
key: &str,
|
||||||
) -> Result<Result<Option<String>, CatchableErrorKind>, ErrorKind> {
|
) -> Result<Result<Option<String>, CatchableErrorKind>, ErrorKind> {
|
||||||
if let Some(attr) = attrs.select(key) {
|
if let Some(attr) = attrs.select(key) {
|
||||||
match strong_importing_coerce_to_string(co, attr.clone()).await {
|
let str = try_cek!(strong_importing_coerce_to_string(co, attr.clone()).await);
|
||||||
Err(cek) => return Ok(Err(cek)),
|
return Ok(Ok(Some(str.to_str()?.to_owned())));
|
||||||
Ok(str) => return Ok(Ok(Some(str.to_str()?.to_owned()))),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Ok(None))
|
Ok(Ok(None))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue