#![allow(
clippy::field_reassign_with_default,
clippy::assertions_on_constants,
clippy::overly_complex_bool_expr,
clippy::useless_vec
)]
use rusty_commit::git;
use std::fs;
use std::process::Command;
use std::sync::Mutex;
use tempfile::tempdir;
static TEST_MUTEX: Mutex<()> = Mutex::new(());
fn with_test_lock<F, R>(f: F) -> R
where
F: FnOnce() -> R,
{
let _guard = TEST_MUTEX
.lock()
.unwrap_or_else(|poisoned| poisoned.into_inner());
f()
}
fn init_test_repo() -> tempfile::TempDir {
let temp_dir = tempdir().unwrap();
Command::new("git")
.args(["init"])
.current_dir(temp_dir.path())
.output()
.expect("Failed to init git repo");
Command::new("git")
.args(["config", "user.email", "test@example.com"])
.current_dir(temp_dir.path())
.output()
.expect("Failed to set git email");
Command::new("git")
.args(["config", "user.name", "Test User"])
.current_dir(temp_dir.path())
.output()
.expect("Failed to set git name");
temp_dir
}
fn init_test_repo_with_commit() -> tempfile::TempDir {
let temp_dir = init_test_repo();
fs::write(temp_dir.path().join(".gitignore"), "").expect("Failed to create .gitignore");
Command::new("git")
.args(["add", ".gitignore"])
.current_dir(temp_dir.path())
.output()
.expect("Failed to add .gitignore");
Command::new("git")
.args(["commit", "-m", "Initial commit"])
.current_dir(temp_dir.path())
.output()
.expect("Failed to create initial commit");
temp_dir
}
#[test]
fn test_assert_git_repo() {
with_test_lock(|| {
let temp_dir = init_test_repo();
let original_cwd = std::env::current_dir().unwrap();
std::env::set_current_dir(temp_dir.path()).unwrap();
assert!(git::assert_git_repo().is_ok());
let non_git_dir = tempdir().unwrap();
std::env::set_current_dir(non_git_dir.path()).unwrap();
assert!(git::assert_git_repo().is_err());
std::env::set_current_dir(&original_cwd).unwrap();
drop(temp_dir);
drop(non_git_dir);
});
}
#[test]
fn test_get_changed_files() {
with_test_lock(|| {
let temp_dir = init_test_repo_with_commit();
let original_cwd = std::env::current_dir().unwrap();
std::env::set_current_dir(temp_dir.path()).unwrap();
let files = git::get_changed_files().unwrap();
assert_eq!(files.len(), 0);
fs::write(temp_dir.path().join("test.txt"), "hello").unwrap();
let files = git::get_changed_files().unwrap();
assert_eq!(files.len(), 1);
assert_eq!(files[0], "test.txt");
std::env::set_current_dir(&original_cwd).unwrap();
drop(temp_dir);
});
}
#[test]
fn test_get_staged_files() {
with_test_lock(|| {
let temp_dir = init_test_repo_with_commit();
let original_cwd = std::env::current_dir().unwrap();
std::env::set_current_dir(temp_dir.path()).unwrap();
fs::write(temp_dir.path().join("staged.txt"), "content").unwrap();
Command::new("git")
.args(["add", "staged.txt"])
.current_dir(temp_dir.path())
.output()
.unwrap();
let staged = git::get_staged_files().unwrap();
assert_eq!(staged.len(), 1);
assert_eq!(staged[0], "staged.txt");
fs::write(temp_dir.path().join("unstaged.txt"), "content").unwrap();
let staged = git::get_staged_files().unwrap();
assert_eq!(staged.len(), 1);
std::env::set_current_dir(&original_cwd).unwrap();
drop(temp_dir);
});
}
#[test]
fn test_stage_files() {
with_test_lock(|| {
let temp_dir = init_test_repo_with_commit();
let original_cwd = std::env::current_dir().unwrap();
std::env::set_current_dir(temp_dir.path()).unwrap();
fs::write(temp_dir.path().join("file1.txt"), "content1").unwrap();
fs::write(temp_dir.path().join("file2.txt"), "content2").unwrap();
fs::write(temp_dir.path().join("file3.txt"), "content3").unwrap();
git::stage_files(&["file1.txt".to_string(), "file3.txt".to_string()]).unwrap();
let staged = git::get_staged_files().unwrap();
assert_eq!(staged.len(), 2);
assert!(staged.contains(&"file1.txt".to_string()));
assert!(staged.contains(&"file3.txt".to_string()));
assert!(!staged.contains(&"file2.txt".to_string()));
std::env::set_current_dir(&original_cwd).unwrap();
drop(temp_dir);
});
}
#[test]
fn test_get_staged_diff() {
with_test_lock(|| {
let temp_dir = init_test_repo_with_commit();
let original_cwd = std::env::current_dir().unwrap();
std::env::set_current_dir(temp_dir.path()).unwrap();
fs::write(temp_dir.path().join("new_file.txt"), "new content").unwrap();
fs::write(temp_dir.path().join("initial.txt"), "initial content").unwrap();
Command::new("git")
.args(["add", "."])
.current_dir(temp_dir.path())
.output()
.unwrap();
let diff = git::get_staged_diff().unwrap();
assert!(diff.contains("new_file.txt"));
assert!(diff.contains("new content"));
assert!(diff.contains("initial.txt"));
assert!(diff.contains("initial content"));
std::env::set_current_dir(&original_cwd).unwrap();
drop(temp_dir);
});
}
#[test]
fn test_get_repo_root() {
with_test_lock(|| {
let temp_dir = init_test_repo();
let original_cwd = std::env::current_dir().unwrap();
let sub_dir = temp_dir.path().join("subdir");
fs::create_dir(&sub_dir).unwrap();
std::env::set_current_dir(temp_dir.path()).unwrap();
let root = git::get_repo_root().unwrap();
let expected = temp_dir.path().canonicalize().unwrap();
let actual = std::path::PathBuf::from(&root).canonicalize().unwrap();
assert_eq!(actual, expected);
std::env::set_current_dir(&sub_dir).unwrap();
let root = git::get_repo_root().unwrap();
let actual = std::path::PathBuf::from(&root).canonicalize().unwrap();
assert_eq!(actual, expected);
std::env::set_current_dir(&original_cwd).unwrap();
drop(temp_dir);
});
}