gitoxide_core/repository/
submodule.rs1use anyhow::bail;
2use gix::{commit::describe::SelectRef, prelude::ObjectIdExt, Repository, Submodule};
3
4use crate::OutputFormat;
5
6pub fn list(
7 repo: Repository,
8 mut out: impl std::io::Write,
9 format: OutputFormat,
10 dirty_suffix: Option<String>,
11) -> anyhow::Result<()> {
12 if format != OutputFormat::Human {
13 bail!("Only human output is supported for now")
14 }
15
16 let Some(submodules) = repo.submodules()? else {
17 return Ok(());
18 };
19 for sm in submodules {
20 print_sm(sm, dirty_suffix.as_deref(), &mut out)?;
21 }
22 Ok(())
23}
24
25fn print_sm(sm: Submodule<'_>, dirty_suffix: Option<&str>, out: &mut impl std::io::Write) -> anyhow::Result<()> {
26 let _span = gix::trace::coarse!("print_sm", path = ?sm.path());
27 let state = sm.state()?;
28 let mut sm_repo = sm.open()?;
29 if let Some(repo) = sm_repo.as_mut() {
30 repo.object_cache_size_if_unset(4 * 1024 * 1024);
31 }
32 writeln!(
33 out,
34 " {is_active} {path} {config} head:{head_id} index:{index_id} ({worktree}) [{url}]",
35 is_active = if !sm.is_active()? || !state.repository_exists {
36 "ⅹ"
37 } else {
38 "✓"
39 },
40 path = sm.path()?,
41 config = if state.superproject_configuration {
42 "config:yes"
43 } else {
44 "config:no"
45 },
46 head_id = submodule_short_hash(sm.head_id()?, sm_repo.as_ref()),
47 index_id = submodule_short_hash(sm.index_id()?, sm_repo.as_ref()),
48 worktree = match sm_repo {
49 Some(repo) => {
50 repo.head_commit()?
54 .describe()
55 .names(SelectRef::AllRefs)
56 .id_as_fallback(true)
57 .try_resolve()?
58 .expect("resolution present if ID can be used as fallback")
59 .format_with_dirty_suffix(dirty_suffix.map(ToOwned::to_owned))?
60 .to_string()
61 }
62 None => {
63 "no worktree".to_string()
64 }
65 },
66 url = sm.url()?.to_bstring()
67 )?;
68 Ok(())
69}
70
71fn submodule_short_hash(id: Option<gix::ObjectId>, repo: Option<&Repository>) -> String {
72 id.map_or_else(
73 || "none".to_string(),
74 |id| repo.map_or_else(|| id.to_string(), |repo| id.attach(repo).shorten_or_id().to_string()),
75 )
76}