systemprompt-cli 0.2.2

Unified CLI for systemprompt.io AI governance: agent orchestration, MCP governance, analytics, profiles, cloud deploy, and self-hosted operations.
Documentation
use anyhow::{Context, Result, bail};
use std::path::PathBuf;
use std::process::Command;
use systemprompt_logging::CliService;

use super::{adjust_ssl_mode, ensure_pg_tool, find_pg_restore};
use crate::cli_settings::CliConfig;

pub fn execute(
    profile_name: &str,
    database_url: &str,
    file: &str,
    skip_confirm: bool,
    config: &CliConfig,
) -> Result<()> {
    let file_path = PathBuf::from(file);
    if !file_path.exists() {
        bail!("Backup file not found: {}", file);
    }

    let is_custom_or_dir = std::path::Path::new(file)
        .extension()
        .is_some_and(|ext| ext.eq_ignore_ascii_case("dump"))
        || file_path.is_dir();

    if is_custom_or_dir {
        find_pg_restore()?;
    } else {
        ensure_pg_tool("psql")?;
    }

    CliService::section("Cloud Database Restore");
    CliService::key_value("Profile", profile_name);
    CliService::key_value("File", file);
    CliService::warning("This will overwrite data in the cloud database!");

    if !skip_confirm {
        if !config.is_interactive() {
            bail!("Restore requires -y flag in non-interactive mode");
        }

        let confirm = dialoguer::Confirm::with_theme(&dialoguer::theme::ColorfulTheme::default())
            .with_prompt(format!(
                "Restore backup to cloud database for profile '{}'?",
                profile_name
            ))
            .default(false)
            .interact()?;

        if !confirm {
            CliService::info("Cancelled");
            return Ok(());
        }
    }

    let adjusted_url = adjust_ssl_mode(database_url);
    let spinner = CliService::spinner("Restoring database...");

    let result = if is_custom_or_dir {
        let pg_restore = find_pg_restore()?;
        Command::new(pg_restore)
            .arg("--no-owner")
            .arg("--no-privileges")
            .arg("--clean")
            .arg("--if-exists")
            .arg("-d")
            .arg(&adjusted_url)
            .arg(file)
            .output()
            .context("Failed to execute pg_restore")?
    } else {
        Command::new("psql")
            .arg(&adjusted_url)
            .arg("-f")
            .arg(file)
            .output()
            .context("Failed to execute psql")?
    };

    spinner.finish_and_clear();

    if result.status.success() {
        CliService::success("Database restored successfully");
    } else {
        let stderr = String::from_utf8_lossy(&result.stderr);
        if stderr.contains("ERROR") {
            bail!("Restore failed:\n{}", stderr);
        }
        CliService::warning("Restore completed with warnings:");
        CliService::info(&stderr.chars().take(500).collect::<String>());
    }

    Ok(())
}