gitcc_git/
status.rs

1//! Status
2
3use std::collections::BTreeMap;
4
5use git2::StatusOptions;
6
7use crate::{error::Error, repo::GitRepository};
8
9/// Status of a file
10pub type Status = git2::Status;
11
12/// Status show option
13pub type StatusShow = git2::StatusShow;
14
15/// Checks if the repo is clean, ie has no uncommited and untracked files
16pub fn repo_status(
17    repo: &GitRepository,
18    show: StatusShow,
19) -> Result<BTreeMap<String, git2::Status>, Error> {
20    if repo.is_bare() {
21        return Err(Error::msg("cannot report status on bare repository"));
22    }
23
24    let mut opts = StatusOptions::new();
25    opts.show(show).include_untracked(true);
26    let entries: BTreeMap<String, git2::Status> = repo
27        .statuses(Some(&mut opts))?
28        .into_iter()
29        .map(|e| {
30            (
31                e.path().map(|p| p.to_string()).unwrap_or_default(),
32                e.status(),
33            )
34        })
35        .collect();
36
37    Ok(entries)
38}
39
40#[cfg(test)]
41mod tests {
42    use crate::repo::discover_repo;
43
44    // Note this useful idiom: importing names from outer (for mod tests) scope.
45    use super::*;
46
47    #[test]
48    fn test_repo_status() {
49        let cwd = std::env::current_dir().unwrap();
50        let repo = discover_repo(&cwd).unwrap();
51        let dirty_files = repo_status(&repo, StatusShow::IndexAndWorkdir).unwrap();
52        for (file, status) in dirty_files {
53            eprintln!("{:?}: {:?}", file, status);
54        }
55    }
56}