Skip to main content

callisto_cli/commands/
init.rs

1use std::process::ExitCode;
2
3use callisto_graph::commands::InitOptions;
4use callisto_model::ApplyPermit;
5use dialoguer::Confirm;
6
7use crate::cli::{GlobalArgs, InitArgs, OutputFormat};
8use crate::error::CliError;
9use crate::output::write_json;
10use crate::render;
11use crate::runner::CliCommandRunner;
12use crate::tty;
13use crate::workspace::load_workspace;
14
15pub fn handle(args: InitArgs, global: &GlobalArgs) -> Result<ExitCode, CliError> {
16    let runner = CliCommandRunner;
17    let ws = load_workspace(global, &runner)?;
18
19    if !args.yes && tty::is_interactive() {
20        let confirm = Confirm::new()
21            .with_prompt(format!(
22                "Initialize Callisto configuration in `{}`?",
23                ws.root.display()
24            ))
25            .default(true)
26            .interact()
27            .map_err(|e| CliError::Other(format!("Interactive prompt failed: {e}")))?;
28
29        if !confirm {
30            println!("Initialization cancelled.");
31            return Ok(ExitCode::SUCCESS);
32        }
33    }
34
35    let opts = InitOptions { yes: args.yes };
36
37    // `--yes` (answered above) and `--dry-run` gate different things: the
38    // former is consent to apply, the latter is permission to write at all.
39    // `--yes --dry-run` must therefore report the apply outcome and write
40    // nothing.
41    let permit = ApplyPermit::granted_unless_dry_run(global.dry_run);
42    let report = callisto_graph::commands::init(&ws, &opts, permit.as_ref())?;
43
44    if permit.is_none() && global.format == OutputFormat::Text {
45        println!("[DRY-RUN] Init plan calculated (no files written):");
46    }
47
48    match global.format {
49        OutputFormat::Json => write_json(&mut std::io::stdout(), &report)?,
50        OutputFormat::Text => render::render_init(&report, &mut std::io::stdout())?,
51    }
52
53    Ok(ExitCode::SUCCESS)
54}