rustic_git/commands/
add.rs1use std::path::Path;
2
3use crate::{Repository, Result};
4use crate::utils::git;
5
6impl Repository {
7 pub fn add<P: AsRef<Path>>(&self, paths: &[P]) -> Result<()> {
17 Self::ensure_git()?;
18
19 if paths.is_empty() {
20 return Ok(());
21 }
22
23 let mut args = vec!["add"];
24 let path_strings: Vec<String> = paths
25 .iter()
26 .map(|p| p.as_ref().to_string_lossy().to_string())
27 .collect();
28
29 for path_str in &path_strings {
30 args.push(path_str);
31 }
32
33 let _stdout = git(&args, Some(self.repo_path()))?;
34 Ok(())
35 }
36
37 pub fn add_all(&self) -> Result<()> {
43 Self::ensure_git()?;
44 let _stdout = git(&["add", "."], Some(self.repo_path()))?;
45 Ok(())
46 }
47
48 pub fn add_update(&self) -> Result<()> {
54 Self::ensure_git()?;
55 let _stdout = git(&["add", "-u"], Some(self.repo_path()))?;
56 Ok(())
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63 use std::fs;
64 use std::path::Path;
65
66 fn create_test_repo(path: &str) -> Repository {
67 if Path::new(path).exists() {
69 fs::remove_dir_all(path).unwrap();
70 }
71
72 Repository::init(path, false).unwrap()
73 }
74
75 fn create_test_file(repo_path: &str, filename: &str, content: &str) {
76 let file_path = format!("{}/{}", repo_path, filename);
77 fs::write(file_path, content).unwrap();
78 }
79
80 #[test]
81 fn test_add_specific_files() {
82 let test_path = "/tmp/test_add_repo";
83 let repo = create_test_repo(test_path);
84
85 create_test_file(test_path, "file1.txt", "content 1");
87 create_test_file(test_path, "file2.txt", "content 2");
88
89 let result = repo.add(&["file1.txt"]);
91 assert!(result.is_ok());
92
93 let status = repo.status().unwrap();
95 let added_files: Vec<_> = status.files.iter()
96 .filter(|(s, _)| matches!(s, crate::FileStatus::Added))
97 .map(|(_, f)| f.as_str())
98 .collect();
99
100 assert!(added_files.contains(&"file1.txt"));
101
102 fs::remove_dir_all(test_path).unwrap();
104 }
105
106 #[test]
107 fn test_add_multiple_files() {
108 let test_path = "/tmp/test_add_multiple_repo";
109 let repo = create_test_repo(test_path);
110
111 create_test_file(test_path, "file1.txt", "content 1");
113 create_test_file(test_path, "file2.txt", "content 2");
114 create_test_file(test_path, "file3.txt", "content 3");
115
116 let result = repo.add(&["file1.txt", "file2.txt"]);
118 assert!(result.is_ok());
119
120 let status = repo.status().unwrap();
122 let added_files: Vec<_> = status.files.iter()
123 .filter(|(s, _)| matches!(s, crate::FileStatus::Added))
124 .map(|(_, f)| f.as_str())
125 .collect();
126
127 assert!(added_files.contains(&"file1.txt"));
128 assert!(added_files.contains(&"file2.txt"));
129 assert_eq!(added_files.len(), 2);
130
131 fs::remove_dir_all(test_path).unwrap();
133 }
134
135 #[test]
136 fn test_add_all() {
137 let test_path = "/tmp/test_add_all_repo";
138 let repo = create_test_repo(test_path);
139
140 create_test_file(test_path, "file1.txt", "content 1");
142 create_test_file(test_path, "file2.txt", "content 2");
143 fs::create_dir(format!("{}/subdir", test_path)).unwrap();
144 create_test_file(test_path, "subdir/file3.txt", "content 3");
145
146 let result = repo.add_all();
148 assert!(result.is_ok());
149
150 let status = repo.status().unwrap();
152 let added_files: Vec<_> = status.files.iter()
153 .filter(|(s, _)| matches!(s, crate::FileStatus::Added))
154 .map(|(_, f)| f.as_str())
155 .collect();
156
157 assert!(added_files.contains(&"file1.txt"));
158 assert!(added_files.contains(&"file2.txt"));
159 assert!(added_files.contains(&"subdir/file3.txt"));
160
161 fs::remove_dir_all(test_path).unwrap();
163 }
164
165 #[test]
166 fn test_add_empty_paths() {
167 let test_path = "/tmp/test_add_empty_repo";
168 let repo = create_test_repo(test_path);
169
170 let result = repo.add::<&str>(&[]);
172 assert!(result.is_ok());
173
174 fs::remove_dir_all(test_path).unwrap();
176 }
177
178 #[test]
179 fn test_add_nonexistent_file() {
180 let test_path = "/tmp/test_add_nonexistent_repo";
181 let repo = create_test_repo(test_path);
182
183 let result = repo.add(&["nonexistent.txt"]);
185 assert!(result.is_err());
186
187 fs::remove_dir_all(test_path).unwrap();
189 }
190}