use std::path::PathBuf;
use std::str::FromStr;
use clap::Parser;
use indexmap::IndexMap;
use miette::miette;
use rattler_conda_types::Platform;
use crate::environment::{get_up_to_date_prefix, LockFileUsage};
use crate::project::manifest::FeatureName;
use crate::{consts, project::SpecType, Project};
#[derive(Debug, Default, Parser)]
pub struct Args {
#[arg(required = true)]
pub deps: Vec<String>,
#[arg(long)]
pub manifest_path: Option<PathBuf>,
#[arg(long, conflicts_with = "build")]
pub host: bool,
#[arg(long, conflicts_with = "host")]
pub build: bool,
#[arg(long)]
pub pypi: bool,
#[arg(long, short)]
pub platform: Option<Platform>,
#[arg(long, short)]
pub feature: Option<String>,
}
fn convert_pkg_name<T>(deps: &[String]) -> miette::Result<Vec<T>>
where
T: FromStr,
{
deps.iter()
.map(|dep| {
T::from_str(dep)
.map_err(|_| miette!("Can't convert dependency name `{dep}` to package name"))
})
.collect()
}
pub async fn execute(args: Args) -> miette::Result<()> {
let mut project = Project::load_or_else_discover(args.manifest_path.as_deref())?;
let deps = args.deps;
let spec_type = if args.host {
SpecType::Host
} else if args.build {
SpecType::Build
} else {
SpecType::Run
};
let section_name: String = if args.pypi {
consts::PYPI_DEPENDENCIES.to_string()
} else {
spec_type.name().to_string()
};
let table_name = if let Some(p) = &args.platform {
format!("target.{}.{}", p.as_str(), section_name)
} else {
section_name
};
let feature_name = args
.feature
.map_or(FeatureName::Default, FeatureName::Named);
fn format_ok_message(pkg_name: &str, pkg_extras: &str, table_name: &str) -> String {
format!(
"Removed {} from [{}]",
console::style(format!("{pkg_name} {pkg_extras}")).bold(),
console::style(table_name).bold()
)
}
let mut sucessful_output: Vec<String> = Vec::with_capacity(deps.len());
if args.pypi {
let all_pkg_name = convert_pkg_name::<rip::types::PackageName>(&deps)?;
for dep in all_pkg_name.iter() {
let (name, req) =
project
.manifest
.remove_pypi_dependency(dep, args.platform, &feature_name)?;
sucessful_output.push(format_ok_message(
name.as_str(),
&req.to_string(),
&table_name,
));
}
} else {
let all_pkg_name = convert_pkg_name::<rattler_conda_types::PackageName>(&deps)?;
for dep in all_pkg_name.iter() {
let (name, req) =
project
.manifest
.remove_dependency(dep, spec_type, args.platform, &feature_name)?;
sucessful_output.push(format_ok_message(
name.as_source(),
&req.to_string(),
&table_name,
));
}
};
project.save()?;
eprintln!("{}", sucessful_output.join("\n"));
get_up_to_date_prefix(
&project.default_environment(),
LockFileUsage::Update,
false,
IndexMap::default(),
)
.await?;
Ok(())
}