use crate::env::*;
use crate::error::Error;
use crate::pm::*;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[cfg_attr(feature = "schematic", derive(schematic::Schematic))]
#[serde(untagged)]
pub enum DependencyName {
Single(String),
SingleMap(HashMap<SystemPackageManager, String>),
Multiple(Vec<String>),
MultipleMap(HashMap<SystemPackageManager, Vec<String>>),
}
impl Default for DependencyName {
fn default() -> DependencyName {
DependencyName::Single(String::new())
}
}
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
#[cfg_attr(feature = "schematic", derive(schematic::Schematic))]
#[serde(default)]
pub struct DependencyConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub arch: Option<SystemArch>,
pub dep: DependencyName,
#[serde(skip_serializing_if = "Option::is_none")]
pub manager: Option<SystemPackageManager>,
#[serde(skip_serializing_if = "Option::is_none")]
pub os: Option<SystemOS>,
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<String>,
}
impl DependencyConfig {
pub fn get_package_names(&self, pm: &SystemPackageManager) -> Result<Vec<String>, Error> {
let mut names = self
.get_package_names_and_versions(pm)?
.into_keys()
.collect::<Vec<_>>();
names.sort();
Ok(names)
}
pub fn get_package_names_and_versions(
&self,
pm: &SystemPackageManager,
) -> Result<HashMap<String, Option<String>>, Error> {
let names = match &self.dep {
DependencyName::Single(name) => vec![name.to_owned()],
DependencyName::SingleMap(map) => map
.get(pm)
.or_else(|| map.get(&SystemPackageManager::All))
.map(|name| vec![name.to_owned()])
.ok_or(Error::MissingName)?,
DependencyName::Multiple(list) => list.clone(),
DependencyName::MultipleMap(map) => map
.get(pm)
.or_else(|| map.get(&SystemPackageManager::All))
.cloned()
.ok_or(Error::MissingName)?,
};
Ok(names
.into_iter()
.map(|name| {
if name.contains('@') {
name.split_once('@')
.map(|(a, b)| (a.to_owned(), Some(b.to_owned())))
.unwrap()
} else {
(name, self.version.clone())
}
})
.collect())
}
pub fn has_name(&self, pm: &SystemPackageManager, name: &str) -> bool {
self.get_package_names(pm)
.map(|names| names.iter().any(|n| n == name))
.unwrap_or(false)
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[cfg_attr(feature = "schematic", derive(schematic::Schematic))]
#[serde(untagged)]
pub enum SystemDependency {
Name(String),
NameMap(HashMap<SystemPackageManager, String>),
Names(Vec<String>),
NamesMap(HashMap<SystemPackageManager, Vec<String>>),
Config(Box<DependencyConfig>),
}
impl SystemDependency {
pub fn name(name: impl AsRef<str>) -> SystemDependency {
SystemDependency::Name(name.as_ref().to_owned())
}
pub fn names<I, V>(names: I) -> SystemDependency
where
I: IntoIterator<Item = V>,
V: AsRef<str>,
{
SystemDependency::Names(names.into_iter().map(|n| n.as_ref().to_owned()).collect())
}
pub fn for_arch(arch: SystemArch, name: impl AsRef<str>) -> SystemDependency {
SystemDependency::Config(Box::new(DependencyConfig {
arch: Some(arch),
dep: DependencyName::Single(name.as_ref().into()),
..DependencyConfig::default()
}))
}
pub fn for_os(os: SystemOS, name: impl AsRef<str>) -> SystemDependency {
SystemDependency::Config(Box::new(DependencyConfig {
dep: DependencyName::Single(name.as_ref().into()),
os: Some(os),
..DependencyConfig::default()
}))
}
pub fn for_os_arch(os: SystemOS, arch: SystemArch, name: impl AsRef<str>) -> SystemDependency {
SystemDependency::Config(Box::new(DependencyConfig {
arch: Some(arch),
dep: DependencyName::Single(name.as_ref().into()),
os: Some(os),
..DependencyConfig::default()
}))
}
pub fn for_pm<I, V>(pm: SystemPackageManager, names: I) -> SystemDependency
where
I: IntoIterator<Item = V>,
V: AsRef<str>,
{
SystemDependency::Config(Box::new(DependencyConfig {
dep: DependencyName::Multiple(
names.into_iter().map(|n| n.as_ref().to_owned()).collect(),
),
manager: Some(pm),
..DependencyConfig::default()
}))
}
pub fn to_config(&self) -> DependencyConfig {
match self {
Self::Name(name) => DependencyConfig {
dep: DependencyName::Single(name.to_owned()),
..DependencyConfig::default()
},
Self::NameMap(map) => DependencyConfig {
dep: DependencyName::SingleMap(map.to_owned()),
..DependencyConfig::default()
},
Self::Names(names) => DependencyConfig {
dep: DependencyName::Multiple(names.to_owned()),
..DependencyConfig::default()
},
Self::NamesMap(map) => DependencyConfig {
dep: DependencyName::MultipleMap(map.to_owned()),
..DependencyConfig::default()
},
Self::Config(config) => (**config).to_owned(),
}
}
}