Skip to main content

outpost_core/ops/
list.rs

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}