flyboat 2.0.0

Container environment manager for development
Documentation
use crate::cli::ConnectArgs;
use crate::config::GlobalConfig;
use crate::default_container_name;
use crate::docker::Engine;
use crate::docker::run::container_name;
use crate::environment::EnvironmentManager;
use crate::{Error, Result};
use colored::Colorize;

pub fn execute_connect(args: &ConnectArgs, verbose: bool) -> Result<()> {
    let manager = EnvironmentManager::new()?;
    let paths = manager.paths();

    // Load global config for defaults
    let global_config = GlobalConfig::load(&paths.global_config())?;

    // Find environment (for validation)
    let env = manager.search_result(&args.env)?;

    if verbose {
        eprintln!("Connecting to environment: {}", env.name.green());
    }

    // Determine engine
    let engine = match &args.engine {
        Some(e) => e.parse::<Engine>()?,
        None => global_config.get_container_engine()?,
    };

    // Resolve container name postfix
    let name_postfix = args.name.clone().unwrap_or_else(default_container_name);

    // Generate container name (no arch for connect - find running container)
    let cont_name = container_name(&env.name, None, &name_postfix);

    // Check if container is running
    let check_output = crate::docker::execute_command_output(
        &engine,
        ["ps", "-q", "-f", &format!("name={}", cont_name)],
        &env.path,
    )?;

    let status = if check_output.stdout.is_empty() {
        // Try with architecture suffixes
        let arch_variants = ["arm64", "x86", "i386"];
        let mut found = false;
        let mut found_name = String::new();

        for arch in arch_variants {
            let arch_cont_name = container_name(&env.name, Some(arch), &name_postfix);

            let check = crate::docker::execute_command_output(
                &engine,
                ["ps", "-q", "-f", &format!("name={}", arch_cont_name)],
                &env.path,
            )
            .ok();

            if let Some(output) = check
                && !output.stdout.is_empty()
            {
                found = true;
                found_name = arch_cont_name;
                break;
            }
        }

        if !found {
            return Err(Error::ContainerNotFound(format!(
                "No running container found for '{}'. Start one with: flyboat run {}",
                env.name, env.name
            )));
        }

        println!(
            "{} to container {}",
            "Connecting".blue(),
            found_name.green()
        );

        crate::docker::execute_command_status(
            &engine,
            ["exec", "-it", &found_name, "bash"],
            &env.path,
        )?
    } else {
        println!("{} to container {}", "Connecting".blue(), cont_name.green());

        if verbose {
            eprintln!("  {} exec -it {} bash", engine.command(), cont_name);
        }

        crate::docker::execute_command_status(
            &engine,
            ["exec", "-it", &cont_name, "bash"],
            &env.path,
        )?
    };

    if !status.success() {
        crate::docker::handle_docker_exit_codes(status.code())?
    }

    Ok(())
}