1use anyhow::*;
2use std::io::Write;
3
4use crate::{config, repo};
5
6pub fn status<W: Write>(
7 wok_config: &mut config::Config,
8 umbrella: &repo::Repo,
9 stdout: &mut W,
10) -> Result<()> {
11 let umbrella_clean = is_repo_clean(&umbrella.git_repo, Some(&wok_config.repos))?;
13 let clean_status = if umbrella_clean { ", all clean" } else { "" };
14
15 writeln!(stdout, "On branch '{}'{}", &umbrella.head, clean_status)?;
16
17 for config_repo in &wok_config.repos {
19 if let Some(subrepo) = umbrella.get_subrepo_by_path(&config_repo.path) {
20 let subrepo_clean = is_repo_clean(&subrepo.git_repo, None)?;
21 let subrepo_clean_status = if subrepo_clean { ", all clean" } else { "" };
22
23 writeln!(
24 stdout,
25 "- '{}' is on branch '{}'{}",
26 config_repo.path.display(),
27 &subrepo.head,
28 subrepo_clean_status
29 )?;
30 }
31 }
32
33 Ok(())
34}
35
36fn is_repo_clean(
37 git_repo: &git2::Repository,
38 config_repos: Option<&[crate::config::Repo]>,
39) -> Result<bool> {
40 let mut status_options = git2::StatusOptions::new();
42 status_options.include_ignored(false);
43 status_options.include_untracked(true);
44
45 let statuses = git_repo.statuses(Some(&mut status_options))?;
46
47 for entry in statuses.iter() {
49 let status = entry.status();
50 let path = entry.path();
51
52 if status == git2::Status::WT_NEW && path == Some("wok.toml") {
54 continue;
55 }
56
57 if status == git2::Status::INDEX_NEW && path == Some(".gitmodules") {
59 continue;
60 }
61
62 if status == git2::Status::INDEX_NEW
64 && let Some(path_str) = path
65 && let Some(config_repos) = config_repos
66 && config_repos
67 .iter()
68 .any(|r| r.path.to_string_lossy() == path_str)
69 {
70 continue;
71 }
72
73 return Ok(false);
75 }
76
77 Ok(true)
78}