use inquire::Confirm;
use regex::Regex;
use std::fs;
use tracing::instrument;
use crate::{
path,
utils::{
dryrun::get_dry_run,
paths::{self, check_path_dir},
regex_package,
state::Result,
},
utpm_bail, utpm_log,
};
use super::UnlinkArgs;
fn package_path(namespace: &str) -> Result<String> {
if namespace == "preview" {
Ok(paths::package_cache_path()?.to_string_lossy().to_string())
} else {
Ok(paths::package_path()?.to_string_lossy().to_string())
}
}
#[instrument(skip(cmd))]
pub async fn run(cmd: &UnlinkArgs) -> Result<bool> {
utpm_log!(trace, "executing unlink command");
let packages = &cmd.package;
let re_all = regex_package();
let re_name = Regex::new(r"^@([a-zA-Z]+)\/([a-zA-Z]+(?:\-[a-zA-Z]+)?)$").unwrap();
let re_namespace = Regex::new(r"^@([a-zA-Z]+)$").unwrap();
let path = if let Some(cap) = re_all.captures(packages.as_str()) {
let (_, [namespace, package, major, minor, patch]) = cap.extract();
path!(
package_path(namespace)?,
namespace,
package,
format!("{major}.{minor}.{patch}")
)
} else if let Some(cap) = re_name.captures(packages.as_str()) {
let (_, [namespace, package]) = cap.extract();
path!(package_path(namespace)?, namespace, package)
} else if let Some(cap) = re_namespace.captures(packages.as_str()) {
let (_, [namespace]) = cap.extract();
path!(package_path(namespace)?, namespace)
} else {
utpm_bail!(PackageNotValid);
};
if !check_path_dir(&path) {
utpm_bail!(PackageNotExist)
}
if !cmd.yes {
match Confirm::new("This is irreversible. Are you sure to delete this?")
.with_help_message(format!("You want to delete {packages}").as_str())
.prompt()
{
Ok(_) => {
utpm_log!(info, "Deleting {}", path.display());
if !get_dry_run() {
fs::remove_dir_all(path)?;
}
Ok(true)
},
Err(_) => Ok(false),
}
} else {
utpm_log!(info, "Deleting {}", path.display());
if !get_dry_run() {
fs::remove_dir_all(path)?;
}
Ok(true)
}
}