changeset_git/repository/
staging.rs1use std::path::Path;
2
3use crate::Result;
4
5use super::Repository;
6
7impl Repository {
8 pub fn stage_files(&self, paths: &[&Path]) -> Result<()> {
12 let mut index = self.inner.index()?;
13
14 for path in paths {
15 let relative_path = self.to_relative_path(path);
16
17 if path.exists() || self.root().join(&relative_path).exists() {
18 index.add_path(&relative_path)?;
19 } else {
20 index.remove_path(&relative_path)?;
21 }
22 }
23
24 index.write()?;
25 Ok(())
26 }
27
28 pub fn stage_all(&self) -> Result<()> {
32 let mut index = self.inner.index()?;
33
34 index.add_all(["*"].iter(), git2::IndexAddOption::DEFAULT, None)?;
35 index.write()?;
36
37 Ok(())
38 }
39}
40
41#[cfg(test)]
42mod tests {
43 use super::super::tests::setup_test_repo;
44 use std::fs;
45 use std::path::Path;
46
47 #[test]
48 fn stage_single_file() -> anyhow::Result<()> {
49 let (dir, repo) = setup_test_repo()?;
50
51 fs::write(dir.path().join("file.txt"), "content")?;
52
53 repo.stage_files(&[Path::new("file.txt")])?;
54
55 let index = repo.inner.index()?;
56 assert!(index.get_path(Path::new("file.txt"), 0).is_some());
57
58 Ok(())
59 }
60
61 #[test]
62 fn stage_multiple_files() -> anyhow::Result<()> {
63 let (dir, repo) = setup_test_repo()?;
64
65 fs::write(dir.path().join("file1.txt"), "content1")?;
66 fs::write(dir.path().join("file2.txt"), "content2")?;
67
68 repo.stage_files(&[Path::new("file1.txt"), Path::new("file2.txt")])?;
69
70 let index = repo.inner.index()?;
71 assert!(index.get_path(Path::new("file1.txt"), 0).is_some());
72 assert!(index.get_path(Path::new("file2.txt"), 0).is_some());
73
74 Ok(())
75 }
76
77 #[test]
78 fn stage_all_files() -> anyhow::Result<()> {
79 let (dir, repo) = setup_test_repo()?;
80
81 fs::write(dir.path().join("file1.txt"), "content1")?;
82 fs::write(dir.path().join("file2.txt"), "content2")?;
83
84 repo.stage_all()?;
85
86 let index = repo.inner.index()?;
87 assert!(index.get_path(Path::new("file1.txt"), 0).is_some());
88 assert!(index.get_path(Path::new("file2.txt"), 0).is_some());
89
90 Ok(())
91 }
92
93 #[test]
94 fn stage_deleted_file() -> anyhow::Result<()> {
95 let (dir, repo) = setup_test_repo()?;
96
97 fs::write(dir.path().join("file.txt"), "content")?;
98 repo.stage_files(&[Path::new("file.txt")])?;
99
100 let sig = git2::Signature::now("Test", "test@example.com")?;
101 let mut index = repo.inner.index()?;
102 let tree_id = index.write_tree()?;
103 let tree = repo.inner.find_tree(tree_id)?;
104 let parent = repo.inner.head()?.peel_to_commit()?;
105 repo.inner
106 .commit(Some("HEAD"), &sig, &sig, "Add file", &tree, &[&parent])?;
107
108 fs::remove_file(dir.path().join("file.txt"))?;
109 repo.stage_files(&[Path::new("file.txt")])?;
110
111 let index = repo.inner.index()?;
112 assert!(index.get_path(Path::new("file.txt"), 0).is_none());
113
114 Ok(())
115 }
116}