1use std::path::PathBuf;
2
3use crate::{AheadBehind, BranchName, OutpostError, OutpostResult, SourceRepo};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct OutpostSummary {
7 pub path: PathBuf,
8 pub current_branch: Option<BranchName>,
9 pub state: OutpostState,
10 pub ahead_behind: Option<AheadBehind>,
11 pub locked: bool,
12 pub lock_reason: Option<String>,
13}
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum OutpostState {
17 Clean,
18 Dirty,
19 Missing,
20 NotManaged,
21}
22
23pub fn run(source: &SourceRepo) -> OutpostResult<Vec<OutpostSummary>> {
24 source
25 .registry()?
26 .entries()
27 .iter()
28 .map(|entry| summarize_entry(source, entry))
29 .collect()
30}
31
32fn summarize_entry(
33 source: &SourceRepo,
34 entry: &crate::RegistryEntry,
35) -> OutpostResult<OutpostSummary> {
36 let mut summary = OutpostSummary {
37 path: entry.path.clone(),
38 current_branch: None,
39 state: OutpostState::Missing,
40 ahead_behind: None,
41 locked: entry.locked,
42 lock_reason: entry.lock_reason.clone(),
43 };
44
45 if !entry.path.exists() {
46 return Ok(summary);
47 }
48
49 let outpost = match crate::safety::check_path_is_managed_outpost_of(source, &entry.path) {
50 Ok(outpost) => outpost,
51 Err(OutpostError::RegistryEntryNotManaged(_)) => {
52 summary.state = OutpostState::NotManaged;
53 return Ok(summary);
54 }
55 Err(err) => return Err(err),
56 };
57
58 summary.current_branch = outpost.current_branch().ok();
59 summary.ahead_behind = outpost.ahead_behind_source().ok();
60 summary.state = if outpost.is_dirty()? {
61 OutpostState::Dirty
62 } else {
63 OutpostState::Clean
64 };
65
66 Ok(summary)
67}