1use std::path::PathBuf;
2
3use serde::Serialize;
4
5use crate::check::WorktreeSnapshot;
6use crate::context;
7use crate::{
8 Config, EnvironmentInput, IgnoredInitScript, InitScriptDiscovery, Result, Worktree,
9 WorktreeOptions,
10};
11
12#[derive(Debug, Clone, Default, PartialEq, Eq)]
14pub struct StatusOptions {
15 pub cwd: Option<PathBuf>,
17 pub root: Option<PathBuf>,
19 pub environment: EnvironmentInput,
21 pub config: Option<PathBuf>,
23 pub no_init_script: bool,
25}
26
27#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
29#[serde(tag = "status", rename_all = "snake_case")]
30pub enum InitScriptStatus {
31 Skipped,
33 NotFound {
35 ignored: Vec<IgnoredInitScript>,
37 },
38 Found {
40 path: PathBuf,
42 },
43}
44
45#[derive(Debug, Clone, PartialEq, Eq)]
47pub struct StatusReport {
48 pub context: Worktree,
50 pub init_script: InitScriptStatus,
52 pub config: Option<PathBuf>,
54}
55
56#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
58pub struct StatusSnapshotReport {
59 pub context: WorktreeSnapshot,
61 pub init_script: InitScriptStatus,
63 pub config: Option<PathBuf>,
65}
66
67impl From<&StatusReport> for StatusSnapshotReport {
68 fn from(report: &StatusReport) -> Self {
69 Self {
70 context: WorktreeSnapshot::from(&report.context),
71 init_script: report.init_script.clone(),
72 config: report.config.clone(),
73 }
74 }
75}
76
77pub fn inspect_status(options: StatusOptions) -> Result<StatusReport> {
87 let context = context::resolve(&WorktreeOptions {
88 cwd: options.cwd,
89 root: options.root,
90 environment: options.environment,
91 })?;
92 let init_script = if options.no_init_script || options.config.is_some() {
93 InitScriptStatus::Skipped
94 } else {
95 inspect_init_script(&context)
96 };
97 let config = Config::discover_path(&context, options.config.as_deref())?;
98
99 Ok(StatusReport {
100 context,
101 init_script,
102 config,
103 })
104}
105
106pub fn inspect_status_snapshot(options: StatusOptions) -> Result<StatusSnapshotReport> {
117 inspect_status(options).map(|report| StatusSnapshotReport::from(&report))
118}
119
120fn inspect_init_script(context: &Worktree) -> InitScriptStatus {
121 let scripts = InitScriptDiscovery::discover(context);
122
123 if let Some(path) = scripts.executable {
124 InitScriptStatus::Found { path }
125 } else {
126 InitScriptStatus::NotFound {
127 ignored: scripts.ignored,
128 }
129 }
130}