use std::path::Path;
use crate::utils::git;
use crate::{Repository, Result};
impl Repository {
pub fn add<P: AsRef<Path>>(&self, paths: &[P]) -> Result<()> {
Self::ensure_git()?;
if paths.is_empty() {
return Ok(());
}
let mut args = vec!["add"];
let path_strings: Vec<String> = paths
.iter()
.map(|p| p.as_ref().to_string_lossy().to_string())
.collect();
for path_str in &path_strings {
args.push(path_str);
}
let _stdout = git(&args, Some(self.repo_path()))?;
Ok(())
}
pub fn add_all(&self) -> Result<()> {
Self::ensure_git()?;
let _stdout = git(&["add", "."], Some(self.repo_path()))?;
Ok(())
}
pub fn add_update(&self) -> Result<()> {
Self::ensure_git()?;
let _stdout = git(&["add", "-u"], Some(self.repo_path()))?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
fn create_test_repo(path: &PathBuf) -> Repository {
if path.exists() {
fs::remove_dir_all(path).unwrap();
}
Repository::init(path, false).unwrap()
}
fn create_test_file(repo_path: &Path, filename: &str, content: &str) {
let file_path = repo_path.join(filename);
fs::write(file_path, content).unwrap();
}
#[test]
fn test_add_specific_files() {
let test_path = env::temp_dir().join("test_add_repo");
let repo = create_test_repo(&test_path);
create_test_file(&test_path, "file1.txt", "content 1");
create_test_file(&test_path, "file2.txt", "content 2");
let result = repo.add(&["file1.txt"]);
assert!(result.is_ok());
let status = repo.status().unwrap();
let added_files: Vec<_> = status
.staged_files()
.map(|entry| entry.path.to_str().unwrap())
.collect();
assert!(added_files.contains(&"file1.txt"));
fs::remove_dir_all(&test_path).unwrap();
}
#[test]
fn test_add_multiple_files() {
let test_path = env::temp_dir().join("test_add_multiple_repo");
let repo = create_test_repo(&test_path);
create_test_file(&test_path, "file1.txt", "content 1");
create_test_file(&test_path, "file2.txt", "content 2");
create_test_file(&test_path, "file3.txt", "content 3");
let result = repo.add(&["file1.txt", "file2.txt"]);
assert!(result.is_ok());
let status = repo.status().unwrap();
let added_files: Vec<_> = status
.staged_files()
.map(|entry| entry.path.to_str().unwrap())
.collect();
assert!(added_files.contains(&"file1.txt"));
assert!(added_files.contains(&"file2.txt"));
assert_eq!(added_files.len(), 2);
fs::remove_dir_all(&test_path).unwrap();
}
#[test]
fn test_add_all() {
let test_path = env::temp_dir().join("test_add_all_repo");
let repo = create_test_repo(&test_path);
create_test_file(&test_path, "file1.txt", "content 1");
create_test_file(&test_path, "file2.txt", "content 2");
fs::create_dir(test_path.join("subdir")).unwrap();
create_test_file(&test_path, "subdir/file3.txt", "content 3");
let result = repo.add_all();
assert!(result.is_ok());
let status = repo.status().unwrap();
let added_files: Vec<_> = status
.staged_files()
.map(|entry| entry.path.to_str().unwrap())
.collect();
assert!(added_files.contains(&"file1.txt"));
assert!(added_files.contains(&"file2.txt"));
assert!(added_files.contains(&"subdir/file3.txt"));
fs::remove_dir_all(&test_path).unwrap();
}
#[test]
fn test_add_empty_paths() {
let test_path = env::temp_dir().join("test_add_empty_repo");
let repo = create_test_repo(&test_path);
let result = repo.add::<&str>(&[]);
assert!(result.is_ok());
fs::remove_dir_all(&test_path).unwrap();
}
#[test]
fn test_add_nonexistent_file() {
let test_path = env::temp_dir().join("test_add_nonexistent_repo");
let repo = create_test_repo(&test_path);
let result = repo.add(&["nonexistent.txt"]);
assert!(result.is_err());
fs::remove_dir_all(&test_path).unwrap();
}
}