use crate::project::manifest::Feature;
use crate::{
consts,
prefix::Prefix,
project::{
manifest::{PyPiRequirement, SystemRequirements},
virtual_packages::get_minimal_virtual_packages,
Dependencies, Environment, SolveGroup,
},
EnvironmentName, Project, SpecType,
};
use indexmap::{IndexMap, IndexSet};
use itertools::Either;
use rattler_conda_types::{Channel, GenericVirtualPackage, Platform};
use std::collections::HashSet;
use std::path::PathBuf;
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
pub enum GroupedEnvironment<'p> {
Group(SolveGroup<'p>),
Environment(Environment<'p>),
}
impl<'p> From<SolveGroup<'p>> for GroupedEnvironment<'p> {
fn from(source: SolveGroup<'p>) -> Self {
let mut envs = source.environments().peekable();
let first = envs.next();
let second = envs.peek();
if second.is_some() {
GroupedEnvironment::Group(source)
} else if let Some(first) = first {
GroupedEnvironment::Environment(first)
} else {
unreachable!("empty solve group")
}
}
}
impl<'p> From<Environment<'p>> for GroupedEnvironment<'p> {
fn from(source: Environment<'p>) -> Self {
match source.solve_group() {
Some(group) if group.environments().len() > 1 => GroupedEnvironment::Group(group),
_ => GroupedEnvironment::Environment(source),
}
}
}
impl<'p> GroupedEnvironment<'p> {
pub fn from_name(project: &'p Project, name: &GroupedEnvironmentName) -> Option<Self> {
match name {
GroupedEnvironmentName::Group(g) => {
Some(GroupedEnvironment::Group(project.solve_group(g)?))
}
GroupedEnvironmentName::Environment(env) => {
Some(GroupedEnvironment::Environment(project.environment(env)?))
}
}
}
pub fn project(&self) -> &'p Project {
match self {
GroupedEnvironment::Group(group) => group.project(),
GroupedEnvironment::Environment(env) => env.project(),
}
}
pub fn prefix(&self) -> Prefix {
Prefix::new(self.dir())
}
pub fn dir(&self) -> PathBuf {
match self {
GroupedEnvironment::Group(solve_group) => solve_group.dir(),
GroupedEnvironment::Environment(env) => env.dir(),
}
}
pub fn name(&self) -> GroupedEnvironmentName {
match self {
GroupedEnvironment::Group(group) => {
GroupedEnvironmentName::Group(group.name().to_string())
}
GroupedEnvironment::Environment(env) => {
GroupedEnvironmentName::Environment(env.name().clone())
}
}
}
pub fn dependencies(&self, kind: Option<SpecType>, platform: Option<Platform>) -> Dependencies {
match self {
GroupedEnvironment::Group(group) => group.dependencies(kind, platform),
GroupedEnvironment::Environment(env) => env.dependencies(kind, platform),
}
}
pub fn pypi_dependencies(
&self,
platform: Option<Platform>,
) -> IndexMap<rip::types::PackageName, Vec<PyPiRequirement>> {
match self {
GroupedEnvironment::Group(group) => group.pypi_dependencies(platform),
GroupedEnvironment::Environment(env) => env.pypi_dependencies(platform),
}
}
pub fn system_requirements(&self) -> SystemRequirements {
match self {
GroupedEnvironment::Group(group) => group.system_requirements(),
GroupedEnvironment::Environment(env) => env.system_requirements(),
}
}
pub fn virtual_packages(&self, platform: Platform) -> Vec<GenericVirtualPackage> {
get_minimal_virtual_packages(platform, &self.system_requirements())
.into_iter()
.map(GenericVirtualPackage::from)
.collect()
}
pub fn channels(&self) -> IndexSet<&'p Channel> {
match self {
GroupedEnvironment::Group(group) => group.channels(),
GroupedEnvironment::Environment(env) => env.channels(),
}
}
pub fn platforms(&self) -> HashSet<Platform> {
match self {
GroupedEnvironment::Group(group) => group
.environments()
.flat_map(|env| env.platforms())
.collect(),
GroupedEnvironment::Environment(env) => env.platforms(),
}
}
pub fn has_pypi_dependencies(&self) -> bool {
match self {
GroupedEnvironment::Group(group) => group.has_pypi_dependencies(),
GroupedEnvironment::Environment(env) => env.has_pypi_dependencies(),
}
}
pub fn features(&self) -> impl Iterator<Item = &'p Feature> + DoubleEndedIterator + 'p {
match self {
GroupedEnvironment::Group(group) => Either::Left(group.features(true)),
GroupedEnvironment::Environment(env) => Either::Right(env.features(true)),
}
}
}
#[derive(Clone)]
pub enum GroupedEnvironmentName {
Group(String),
Environment(EnvironmentName),
}
impl GroupedEnvironmentName {
pub fn fancy_display(&self) -> console::StyledObject<&str> {
match self {
GroupedEnvironmentName::Group(name) => {
consts::SOLVE_GROUP_STYLE.apply_to(name.as_str())
}
GroupedEnvironmentName::Environment(name) => name.fancy_display(),
}
}
pub fn as_str(&self) -> &str {
match self {
GroupedEnvironmentName::Group(group) => group.as_str(),
GroupedEnvironmentName::Environment(env) => env.as_str(),
}
}
}