turbopack_core/
condition.rs1use anyhow::Result;
2use futures::{StreamExt, stream};
3use serde::{Deserialize, Serialize};
4use turbo_tasks::{NonLocalValue, ResolvedVc, trace::TraceRawVcs};
5use turbo_tasks_fs::FileSystemPath;
6
7#[derive(Debug, Clone, Serialize, Deserialize, TraceRawVcs, PartialEq, Eq, NonLocalValue)]
8pub enum ContextCondition {
9 All(Vec<ContextCondition>),
10 Any(Vec<ContextCondition>),
11 Not(Box<ContextCondition>),
12 InDirectory(String),
13 InPath(ResolvedVc<FileSystemPath>),
14}
15
16impl ContextCondition {
17 pub fn all(conditions: Vec<ContextCondition>) -> ContextCondition {
19 ContextCondition::All(conditions)
20 }
21
22 pub fn any(conditions: Vec<ContextCondition>) -> ContextCondition {
24 ContextCondition::Any(conditions)
25 }
26
27 #[allow(clippy::should_implement_trait)]
29 pub fn not(condition: ContextCondition) -> ContextCondition {
30 ContextCondition::Not(Box::new(condition))
31 }
32
33 pub async fn matches(&self, path: &FileSystemPath) -> Result<bool> {
35 match self {
36 ContextCondition::All(conditions) => {
37 #[allow(clippy::manual_try_fold)]
39 stream::iter(conditions)
40 .fold(Ok(true), |acc, c| async move {
41 Ok(acc? && Box::pin(c.matches(path)).await?)
42 })
43 .await
44 }
45 ContextCondition::Any(conditions) => {
46 #[allow(clippy::manual_try_fold)]
48 stream::iter(conditions)
49 .fold(Ok(false), |acc, c| async move {
50 Ok(acc? || Box::pin(c.matches(path)).await?)
51 })
52 .await
53 }
54 ContextCondition::Not(condition) => Box::pin(condition.matches(path)).await.map(|b| !b),
55 ContextCondition::InPath(other_path) => {
56 Ok(path.is_inside_or_equal_ref(&*other_path.await?))
57 }
58 ContextCondition::InDirectory(dir) => Ok(path.path.starts_with(&format!("{dir}/"))
59 || path.path.contains(&format!("/{dir}/"))
60 || path.path.ends_with(&format!("/{dir}"))
61 || path.path == *dir),
62 }
63 }
64}