1use std::path::Path;
11
12use crate::error::Result;
13use crate::git::cli::GitCli;
14use crate::git::porcelain::parse_submodule_status;
15
16pub fn uninitialized(git: &dyn GitCli, worktree_dir: &Path) -> Result<Vec<String>> {
22 let output = git.run_raw(worktree_dir, &["submodule", "status"])?;
23 if !output.success {
24 return Ok(Vec::new());
25 }
26 Ok(parse_submodule_status(&output.stdout)
27 .into_iter()
28 .filter(|s| s.is_uninitialized())
29 .map(|s| s.path)
30 .collect())
31}
32
33pub fn update_init(git: &dyn GitCli, worktree_dir: &Path) -> Result<()> {
37 git.run(
38 worktree_dir,
39 &["submodule", "update", "--init", "--recursive"],
40 )?;
41 Ok(())
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47 use crate::git::cli::RealGit;
48 use crate::testutil::TestRepo;
49
50 #[test]
51 fn no_submodules_yields_empty() {
52 let repo = TestRepo::init();
53 assert!(uninitialized(&RealGit, repo.root()).unwrap().is_empty());
54 }
55
56 #[test]
57 fn reports_uninitialized_submodule() {
58 let repo = TestRepo::init();
59 repo.add_submodule("libs/sub");
60 repo.deinit_submodule("libs/sub");
62 let pending = uninitialized(&RealGit, repo.root()).unwrap();
63 assert_eq!(pending, vec!["libs/sub".to_string()]);
64 }
65
66 #[test]
67 fn update_init_populates_submodule() {
68 let repo = TestRepo::init();
69 repo.add_submodule("libs/sub");
70 repo.deinit_submodule("libs/sub");
71 assert!(!repo.root().join("libs/sub/sub.txt").exists());
73 update_init(&RealGit, repo.root()).unwrap();
74 assert!(repo.root().join("libs/sub/sub.txt").exists());
75 assert!(uninitialized(&RealGit, repo.root()).unwrap().is_empty());
76 }
77
78 #[test]
79 fn uninitialized_is_empty_outside_a_repo() {
80 let dir = tempfile::tempdir().unwrap();
83 assert!(uninitialized(&RealGit, dir.path()).unwrap().is_empty());
84 }
85}