use crate::config::OnConflict;
use crate::error::Result;
use std::path::Path;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum ConflictAction {
Proceed,
Skip,
Abort,
}
pub(crate) fn check_conflict(target: &Path) -> bool {
target.exists()
}
pub(crate) fn resolve_conflict(target: &Path, mode: OnConflict) -> Result<ConflictAction> {
match mode {
OnConflict::Abort => Ok(ConflictAction::Abort),
OnConflict::Skip => Ok(ConflictAction::Skip),
OnConflict::Overwrite => {
if target.is_symlink() || target.is_file() {
std::fs::remove_file(target)?;
} else if target.is_dir() {
std::fs::remove_dir_all(target)?;
}
Ok(ConflictAction::Proceed)
}
OnConflict::Backup => {
let backup_path = match target.extension() {
Some(ext) => target.with_extension(format!("{}.bak", ext.to_string_lossy())),
None => target.with_extension("bak"),
};
std::fs::rename(target, &backup_path)?;
Ok(ConflictAction::Proceed)
}
}
}
#[cfg(all(test, feature = "impure-test"))]
mod tests {
use super::*;
use tempfile::TempDir;
#[test]
fn test_check_conflict_exists() {
let temp = TempDir::new().unwrap();
let file = temp.path().join("existing.txt");
std::fs::write(&file, "content").unwrap();
assert!(check_conflict(&file));
}
#[test]
fn test_check_conflict_not_exists() {
let temp = TempDir::new().unwrap();
let file = temp.path().join("nonexistent.txt");
assert!(!check_conflict(&file));
}
#[test]
fn test_resolve_conflict_abort() {
let temp = TempDir::new().unwrap();
let file = temp.path().join("file.txt");
std::fs::write(&file, "content").unwrap();
let action = resolve_conflict(&file, OnConflict::Abort).unwrap();
assert_eq!(action, ConflictAction::Abort);
assert!(file.exists()); }
#[test]
fn test_resolve_conflict_skip() {
let temp = TempDir::new().unwrap();
let file = temp.path().join("file.txt");
std::fs::write(&file, "content").unwrap();
let action = resolve_conflict(&file, OnConflict::Skip).unwrap();
assert_eq!(action, ConflictAction::Skip);
assert!(file.exists()); }
#[test]
fn test_resolve_conflict_overwrite() {
let temp = TempDir::new().unwrap();
let file = temp.path().join("file.txt");
std::fs::write(&file, "content").unwrap();
let action = resolve_conflict(&file, OnConflict::Overwrite).unwrap();
assert_eq!(action, ConflictAction::Proceed);
assert!(!file.exists()); }
#[test]
fn test_resolve_conflict_backup() {
let temp = TempDir::new().unwrap();
let file = temp.path().join("file.txt");
std::fs::write(&file, "content").unwrap();
let action = resolve_conflict(&file, OnConflict::Backup).unwrap();
assert_eq!(action, ConflictAction::Proceed);
assert!(!file.exists()); assert!(temp.path().join("file.txt.bak").exists()); }
#[test]
fn test_resolve_conflict_backup_no_extension() {
let temp = TempDir::new().unwrap();
let file = temp.path().join("Makefile");
std::fs::write(&file, "content").unwrap();
let action = resolve_conflict(&file, OnConflict::Backup).unwrap();
assert_eq!(action, ConflictAction::Proceed);
assert!(!file.exists());
assert!(temp.path().join("Makefile.bak").exists());
}
}