turnout 0.2.0

A developer's switchyard: point local apps at any backend stand, keep servers and secrets at hand, build and deploy from any directory
use anyhow::Result;

use crate::{paths, store};

pub fn run() -> Result<()> {
    println!("turnout {}", env!("CARGO_PKG_VERSION"));
    println!("Data directory: {}", paths::data_dir()?.display());
    if !store::is_initialized()? {
        println!("Not set up yet - run `turnout setup` first.");
        return Ok(());
    }
    let apps = store::load_apps()?;
    let servers = store::load_servers()?;
    match apps.len() {
        0 => println!("Apps:    none yet"),
        n => println!("Apps:    {} ({})", n, apps.iter().map(|a| a.name.as_str()).collect::<Vec<_>>().join(", ")),
    }
    match servers.len() {
        0 => println!("Servers: none yet"),
        n => println!("Servers: {} ({})", n, servers.iter().map(|s| s.name.as_str()).collect::<Vec<_>>().join(", ")),
    }
    let groups = store::load_groups()?;
    if !groups.is_empty() {
        for group in &groups {
            println!("Group:   {} ({})", group.name, group.apps.join(", "));
        }
    }
    let credentials = store::load_credentials()?;
    if credentials.is_empty() {
        println!("Access:  none saved");
    } else {
        let mut names: Vec<&str> = credentials.iter().map(|c| c.server.as_str()).collect();
        names.dedup();
        println!("Access:  saved for {}", names.join(", "));
    }
    let state = store::load_state()?;
    if !state.bindings.is_empty() {
        println!("Bindings:");
        for (app, server) in &state.bindings {
            println!("  {app} -> {server}");
        }
    }
    match &state.gateway {
        Some(gateway) if crate::commands::gateway::probe(gateway) => {
            let ports: Vec<String> = gateway.ports.iter().map(|(port, app)| format!("{app}:{port}")).collect();
            println!("Gateway: running (pid {}; {})", gateway.pid, ports.join(", "));
        }
        Some(gateway) => println!("Gateway: recorded (pid {}) but not responding - try `turnout gateway stop`", gateway.pid),
        None => println!("Gateway: not running"),
    }
    Ok(())
}