use crate::error::{KopiError, Result};
use log::{debug, warn};
use std::fs;
use std::path::Path;
pub fn perform_safety_checks(distribution: &str, version: &str) -> Result<()> {
debug!("Performing safety checks for {distribution}@{version}");
if is_active_global_jdk(distribution, version)? {
return Err(KopiError::ValidationError(format!(
"Cannot uninstall {distribution}@{version} - it is currently active globally. Use \
--force to override this check"
)));
}
if is_active_local_jdk(distribution, version)? {
return Err(KopiError::ValidationError(format!(
"Cannot uninstall {distribution}@{version} - it is currently active in this project. \
Use --force to override this check"
)));
}
check_running_processes(distribution, version)?;
Ok(())
}
pub fn is_active_global_jdk(distribution: &str, version: &str) -> Result<bool> {
debug!("Checking if {distribution}@{version} is active global JDK");
Ok(false)
}
pub fn is_active_local_jdk(distribution: &str, version: &str) -> Result<bool> {
debug!("Checking if {distribution}@{version} is active local JDK");
Ok(false)
}
fn check_running_processes(_distribution: &str, _version: &str) -> Result<()> {
Ok(())
}
pub fn verify_removal_permission(path: &Path) -> Result<()> {
debug!("Verifying removal permission for {}", path.display());
if !path.exists() {
return Err(KopiError::DirectoryNotFound(path.display().to_string()));
}
if let Some(parent) = path.parent() {
match fs::metadata(parent) {
Ok(metadata) => {
if metadata.permissions().readonly() {
return Err(KopiError::PermissionDenied(format!(
"Parent directory is read-only: {}",
parent.display()
)));
}
}
Err(e) => {
return Err(KopiError::PermissionDenied(format!(
"Cannot access parent directory: {e}"
)));
}
}
}
Ok(())
}
pub fn check_tool_dependencies(path: &Path) -> Result<()> {
debug!("Checking tool dependencies for {}", path.display());
if path.join("bin/java").exists() {
warn!("Note: Other tools may have references to this JDK installation");
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::TempDir;
#[test]
fn test_active_jdk_stubs() {
assert!(!is_active_global_jdk("temurin", "21.0.5+11").unwrap());
assert!(!is_active_local_jdk("temurin", "21.0.5+11").unwrap());
assert!(!is_active_global_jdk("corretto", "17.0.9").unwrap());
assert!(!is_active_local_jdk("corretto", "17.0.9").unwrap());
}
#[test]
fn test_safety_checks_pass_with_stubs() {
assert!(perform_safety_checks("temurin", "21.0.5+11").is_ok());
assert!(perform_safety_checks("corretto", "17.0.9").is_ok());
}
#[test]
fn test_verify_removal_permission() {
let temp_dir = TempDir::new().unwrap();
let test_path = temp_dir.path().join("test_jdk");
fs::create_dir(&test_path).unwrap();
assert!(verify_removal_permission(&test_path).is_ok());
let non_existent = temp_dir.path().join("non_existent");
assert!(verify_removal_permission(&non_existent).is_err());
}
#[test]
fn test_check_tool_dependencies() {
let temp_dir = TempDir::new().unwrap();
let jdk_path = temp_dir.path().join("jdk");
fs::create_dir(&jdk_path).unwrap();
assert!(check_tool_dependencies(&jdk_path).is_ok());
fs::create_dir(jdk_path.join("bin")).unwrap();
fs::write(jdk_path.join("bin/java"), "mock").unwrap();
assert!(check_tool_dependencies(&jdk_path).is_ok());
}
#[test]
#[cfg(unix)]
fn test_permission_check_readonly_parent() {
use std::os::unix::fs::PermissionsExt;
let temp_dir = TempDir::new().unwrap();
let parent = temp_dir.path().join("readonly_parent");
fs::create_dir(&parent).unwrap();
let test_path = parent.join("jdk");
fs::create_dir(&test_path).unwrap();
let mut perms = fs::metadata(&parent).unwrap().permissions();
perms.set_mode(0o444);
fs::set_permissions(&parent, perms).unwrap();
let result = verify_removal_permission(&test_path);
let mut perms = fs::metadata(&parent).unwrap().permissions();
perms.set_mode(0o755);
fs::set_permissions(&parent, perms).unwrap();
assert!(result.is_err());
}
}