use crate::fleet::error::Result;
use crate::fleet::git::{GitOps, SubmoduleOps, SubmoduleStatus, SubmoduleTree};
use crate::fleet::output::Formatter;
use crate::prelude::*;
use rayon::prelude::*;
pub fn execute<P: AsRef<Path> + Sync>(repo_root: P, _verbose: bool) -> Result<()> {
let tree = SubmoduleTree::discover_allow_empty(&repo_root)?;
let max_depth = tree
.top_down()
.iter()
.map(|node| node.depth + 1)
.max()
.unwrap_or(0);
let ignored = tree.ignored().len();
Formatter::print_info(&format!(
"Superproject + {} submodule(s) across {} level(s){}",
tree.len(),
max_depth,
if ignored == 0 {
String::new()
} else {
format!(" ({ignored} ignored)")
}
));
let rendered = crate::state::discard::rendered_as_written(
repo_root.as_ref(),
&crate::state::RunCache::new(),
)
.map_err(|e| crate::fleet::error::SuperGitError::Other(e.to_string()))?;
let repo = GitOps::open_repo(&repo_root)?;
let is_detached = GitOps::is_detached_head(&repo)?;
let current_branch = if is_detached {
None
} else {
Some(GitOps::current_branch(&repo)?)
};
let (changed, moved_pointers) = GitOps::uncommitted_files_and_pointers(&repo)?;
let (uncommitted_files, rendered_files) =
crate::fleet::git::split_rendered(repo_root.as_ref(), changed, &rendered);
let is_clean = uncommitted_files.is_empty();
let (ahead, behind) = if !is_detached {
GitOps::get_ahead_behind(&repo).unwrap_or((0, 0))
} else {
(0, 0)
};
let super_status = SubmoduleStatus {
name: "[SUPERPROJECT]".to_string(),
path: ".".to_string(),
current_branch,
is_clean,
is_detached,
ahead,
behind,
uncommitted_files,
rendered_files,
moved_pointers,
exists: true,
depth: 0,
};
let mut statuses: Vec<_> = tree
.top_down()
.par_iter()
.map(|node| SubmoduleOps::get_status(node, &rendered))
.collect::<Result<Vec<_>>>()?;
statuses.insert(0, super_status);
Formatter::print_status(&statuses);
Ok(())
}