use crate::patterns::{merge_iter, merge_plugin_partials};
use crate::toolchain::*;
use crate::{config_enum, config_struct};
use miette::IntoDiagnostic;
use moon_common::{Id, IdExt};
use rustc_hash::FxHashMap;
use schematic::{Config, Schematic, validate};
use serde_json::Value;
use std::collections::BTreeMap;
use std::env;
use version_spec::UnresolvedVersionSpec;
use warpgate_api::PluginLocator;
config_enum!(
#[derive(Schematic)]
#[serde(untagged)]
pub enum ToolchainPluginVersionFrom {
Enabled(bool),
Id(String),
}
);
impl Default for ToolchainPluginVersionFrom {
fn default() -> Self {
Self::Enabled(true)
}
}
config_struct!(
#[derive(Config)]
#[config(allow_unknown_fields)]
pub struct ToolchainPluginConfig {
#[setting(default = true)]
pub inherit_aliases: bool,
#[setting(default = true)]
pub install_dependencies: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub plugin: Option<PluginLocator>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub version: Option<UnresolvedVersionSpec>,
pub version_from_prototools: ToolchainPluginVersionFrom,
#[setting(flatten, merge = merge_iter)]
pub config: BTreeMap<String, Value>,
}
);
impl ToolchainPluginConfig {
pub fn to_json(&self) -> Value {
let mut data = Value::Object(self.config.clone().into_iter().collect());
if let Some(version) = &self.version {
data["version"] = Value::String(version.to_string());
}
data
}
}
config_struct!(
#[derive(Config)]
#[config(allow_unknown_fields)]
pub struct ToolchainsConfig {
#[setting(default = "./cache/schemas/toolchains.json", rename = "$schema")]
pub schema: String,
#[setting(extend, validate = validate::extends_from)]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extends: Option<schematic::ExtendsFrom>,
#[setting(nested)]
pub moon: MoonConfig,
#[setting(nested)]
pub proto: ProtoConfig,
#[setting(flatten, nested, merge = merge_plugin_partials)]
pub plugins: FxHashMap<Id, ToolchainPluginConfig>,
}
);
impl ToolchainsConfig {
pub fn get_enabled(&self) -> Vec<Id> {
let mut tools = self.plugins.keys().cloned().collect::<Vec<_>>();
tools.push(Id::raw("system"));
tools
}
pub fn get_plugin_config(&self, id: impl AsRef<str>) -> Option<&ToolchainPluginConfig> {
let (stable_id, unstable_id) = Id::stable_and_unstable(id);
self.plugins
.get(&stable_id)
.or_else(|| self.plugins.get(&unstable_id))
}
pub fn inherit_versions_from_env_vars(&mut self) -> miette::Result<()> {
for (id, config) in &mut self.plugins {
if let Ok(version) = env::var(format!("MOON_{}_VERSION", id.to_env_var())) {
config.version = Some(UnresolvedVersionSpec::parse(version).into_diagnostic()?);
}
}
Ok(())
}
pub fn requires_proto(&self) -> bool {
for config in self.plugins.values() {
if config.version.is_some() {
return true;
}
}
false
}
pub fn should_invalidate(&self, other: &Self) -> bool {
self.plugins != other.plugins
}
}