diff --git a/Cargo.lock b/Cargo.lock index 2a5b81bb..7c999fde 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3479,6 +3479,7 @@ dependencies = [ "indicatif", "insta", "itertools 0.13.0", + "lazy_static", "marked-yaml", "memchr", "memmap2 0.9.5", diff --git a/Cargo.toml b/Cargo.toml index 94cbbc3b..c6d4797c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -141,6 +141,7 @@ rattler_shell = { version = "0.22.4", default-features = false, features = ["sys rattler_solve = { version = "1.1.0", default-features = false, features = ["resolvo", "serde"] } rattler_virtual_packages = { version = "1.1.7", default-features = false } rattler_package_streaming = { version = "0.22.10", default-features = false } +lazy_static = "1.5.0" [dev-dependencies] insta = { version = "1.40.0", features = ["yaml"] } diff --git a/src/recipe/jinja.rs b/src/recipe/jinja.rs index b4ba4481..df84a633 100644 --- a/src/recipe/jinja.rs +++ b/src/recipe/jinja.rs @@ -366,6 +366,16 @@ fn parse_platform(platform: &str) -> Result { }) } +lazy_static::lazy_static! { + /// The syntax config for MiniJinja / rattler-build + pub static ref SYNTAX_CONFIG: SyntaxConfig = SyntaxConfig::builder() + .block_delimiters("{%", "%}") + .variable_delimiters("${{", "}}") + .comment_delimiters("#{{", "}}") + .build() + .unwrap(); +} + fn set_jinja(config: &SelectorConfig) -> minijinja::Environment<'static> { let SelectorConfig { target_platform, @@ -382,14 +392,7 @@ fn set_jinja(config: &SelectorConfig) -> minijinja::Environment<'static> { default_filters(&mut env); // Ok to unwrap here because we know that the syntax is valid - env.set_syntax( - SyntaxConfig::builder() - .block_delimiters("{%", "%}") - .variable_delimiters("${{", "}}") - .comment_delimiters("#{{", "}}") - .build() - .unwrap(), - ); + env.set_syntax(SYNTAX_CONFIG.clone()); let variant = Arc::new(variant.clone()); diff --git a/src/used_variables.rs b/src/used_variables.rs index 4672bbfe..2c8ad113 100644 --- a/src/used_variables.rs +++ b/src/used_variables.rs @@ -12,16 +12,14 @@ use std::collections::{HashSet, VecDeque}; use marked_yaml::Span; -use minijinja::{ - machinery::{ - ast::{self, Expr, Stmt}, - WhitespaceConfig, - }, - syntax::SyntaxConfig, +use minijinja::machinery::{ + ast::{self, Expr, Stmt}, + parse_expr, WhitespaceConfig, }; use crate::recipe::{ custom_yaml::{self, HasSpan, Node, ScalarNode, SequenceNodeInternal}, + jinja::SYNTAX_CONFIG, parser::CollectErrors, ParsingError, }; @@ -45,16 +43,12 @@ fn parse<'source>( expr: &'source str, filename: &str, ) -> Result, minijinja::Error> { - let syntax_config = SyntaxConfig::builder() - .block_delimiters("{%", "%}") - .variable_delimiters("${{", "}}") - .comment_delimiters("#{{", "}}") - .build() - .unwrap(); - - let whitespace_config = WhitespaceConfig::default(); - - minijinja::machinery::parse(expr, filename, syntax_config, whitespace_config) + minijinja::machinery::parse( + expr, + filename, + SYNTAX_CONFIG.clone(), + WhitespaceConfig::default(), + ) } /// Extract all variables from a jinja expression (called from [`extract_variables`]) @@ -149,6 +143,7 @@ fn find_jinja( ) -> Result<(), Vec> { let mut errs = Vec::::new(); let mut queue = VecDeque::from([(node, src)]); + while let Some((node, src)) = queue.pop_front() { match node { Node::Mapping(map) => { @@ -162,11 +157,10 @@ fn find_jinja( match item { SequenceNodeInternal::Simple(node) => queue.push_back((node, src)), SequenceNodeInternal::Conditional(if_sel) => { - // we need to convert the if condition to a Jinja expression to parse it - let as_jinja_expr = format!("${{{{ {} }}}}", if_sel.cond().as_str()); - match parse(&as_jinja_expr, "jinja.yaml") { - Ok(ast) => { - extract_variables(&ast, variables); + match parse_expr(if_sel.cond().as_str()) { + Ok(expr) => { + extract_variable_from_expression(&expr, variables); + // extract_variables(&ast, variables); queue.push_back((if_sel.then(), src)); // find_jinja(if_sel.then(), src, variables)?; if let Some(otherwise) = if_sel.otherwise() {