mod action;
mod detect;
mod error;
mod install;
#[cfg(test)]
mod tests;
use indexmap::IndexMap;
use smol_str::SmolStr;
use super::condition::{ConditionOrRef, Conditions, EvalContext};
use super::pkg_config_files::PkgConfigFiles;
pub(crate) use action::PkgShellConfig;
pub use action::{ActionKind, ShellInitAction};
pub use detect::DetectStrategy;
pub use error::Error;
pub use install::InstallHint;
pub use crate::platform::Shell;
#[derive(serde::Deserialize, schemars::JsonSchema, Debug, Clone, PartialEq, Default)]
#[serde(rename_all = "snake_case")]
pub(crate) enum PkgEnable {
#[default]
On,
Detect,
Disabled,
}
#[derive(serde::Deserialize, schemars::JsonSchema, Debug, Clone, PartialEq, Default)]
#[serde(deny_unknown_fields)]
pub struct PkgConfig {
#[serde(default)]
pub(super) enable: PkgEnable,
#[serde(default)]
pub(super) detect: Option<DetectStrategy>,
#[serde(default)]
pub(super) inputs: IndexMap<SmolStr, SmolStr>,
#[serde(default)]
pub(super) when: Option<ConditionOrRef>,
#[serde(default)]
pub name: Option<SmolStr>,
#[serde(default)]
pub description: Option<String>,
#[serde(default)]
pub install_hint: InstallHint,
#[serde(default)]
pub(crate) shell: PkgShellConfig,
#[serde(default)]
pub(super) configs: Vec<PkgConfigFiles>,
}
impl PkgConfig {
pub fn is_installed(
&self,
conditions: &Conditions,
ctx: &EvalContext<'_>,
) -> Result<bool, Error> {
if !self.evaluate_when(conditions, ctx)? {
return Ok(false);
}
match self.enable {
PkgEnable::On | PkgEnable::Detect => {
let Some(detect) = self.detect.as_ref() else {
return Ok(true);
};
let lookup = [&self.inputs, ctx.inputs];
detect.check(conditions, ctx, &lookup)
}
PkgEnable::Disabled => Ok(false),
}
}
pub fn enable_on_but_detect_missing(
&self,
conditions: &Conditions,
ctx: &EvalContext<'_>,
) -> Result<bool, Error> {
if !matches!(self.enable, PkgEnable::On) {
return Ok(false);
}
if !self.evaluate_when(conditions, ctx)? {
return Ok(false);
}
let Some(detect) = self.detect.as_ref() else {
return Ok(false);
};
let lookup = [&self.inputs, ctx.inputs];
detect.check(conditions, ctx, &lookup).map(|r| !r)
}
pub fn enable_on_and_detect_matches(
&self,
conditions: &Conditions,
ctx: &EvalContext<'_>,
) -> Result<bool, Error> {
if !matches!(self.enable, PkgEnable::On) {
return Ok(false);
}
if !self.evaluate_when(conditions, ctx)? {
return Ok(false);
}
let Some(detect) = self.detect.as_ref() else {
return Ok(false);
};
let lookup = [&self.inputs, ctx.inputs];
detect.check(conditions, ctx, &lookup)
}
pub fn is_disabled(&self) -> bool {
matches!(self.enable, PkgEnable::Disabled)
}
pub fn matched_detect(
&self,
conditions: &Conditions,
ctx: &EvalContext<'_>,
) -> Result<Option<&DetectStrategy>, Error> {
if !self.evaluate_when(conditions, ctx)? {
return Ok(None);
}
match self.enable {
PkgEnable::On | PkgEnable::Detect => {
if let Some(detect) = self.detect.as_ref() {
let lookup = [&self.inputs, ctx.inputs];
detect
.check(conditions, ctx, &lookup)
.map(|r| r.then_some(detect))
} else {
Ok(None)
}
}
PkgEnable::Disabled => Ok(None),
}
}
pub(crate) fn evaluate_when(
&self,
conditions: &Conditions,
ctx: &EvalContext<'_>,
) -> Result<bool, Error> {
match self.when.as_ref() {
None => Ok(true),
Some(cor) => Ok(conditions.evaluate(cor, ctx)?),
}
}
pub(crate) fn inputs(&self) -> &IndexMap<SmolStr, SmolStr> {
&self.inputs
}
pub(super) fn configs(&self) -> &[PkgConfigFiles] {
&self.configs
}
}