proto_cli 0.57.3

A multi-language version manager, a unified toolchain.
use crate::session::ProtoSession;
use clap::Args;
use iocraft::prelude::element;
use proto_core::{PinLocation, ProtoConfig, ToolContext};
use proto_pdk_api::{PluginFunction, UnpinVersionInput, UnpinVersionOutput};
use starbase::AppResult;
use starbase_console::ui::*;
use starbase_styles::encode_style_tags;

#[derive(Args, Clone, Debug)]
pub struct UnpinArgs {
    #[arg(required = true, help = "ID of tool")]
    pub context: ToolContext,

    #[arg(long, default_value_t, help = "Directory location to unpin from")]
    pub from: PinLocation,

    #[arg(
        long,
        help = "Unpin from the tool's native file instead of .prototools"
    )]
    pub tool_native: bool,
}

#[tracing::instrument(skip_all)]
pub async fn unpin(session: ProtoSession, args: UnpinArgs) -> AppResult {
    let tool = session.load_tool(&args.context).await?;
    let mut value = None;
    let config_dir = tool.proto.get_config_dir(args.from);
    let config_path;

    if args.tool_native {
        if tool.plugin.has_func(PluginFunction::UnpinVersion).await {
            let output: UnpinVersionOutput = tool
                .plugin
                .call_func_with(
                    PluginFunction::UnpinVersion,
                    UnpinVersionInput {
                        context: tool.create_plugin_unresolved_context(),
                        dir: tool.to_virtual_path(config_dir),
                    },
                )
                .await?;

            if let Some(file) = output.file
                && output.unpinned
            {
                config_path = tool.from_virtual_path(file);
                value = output.version.map(|version| version.to_string());
            } else {
                session.console.render_err(element! {
                    Notice(variant: Variant::Failure) {
                        StyledText(
                            content: format!(
                                "Failed to unpin a version for <id>{}</id>.",
                                args.context,
                            )
                        )
                        #(output.error.map(|error| {
                            element! {
                                StyledText(content: error)
                            }
                        }))
                    }
                })?;

                return Ok(Some(1));
            }
        } else {
            session.console.render_err(element! {
                Notice(variant: Variant::Caution) {
                    StyledText(
                        content: format!(
                            "{} does not support unpinning from a native file. Remove <shell>--tool-native</shell> and try again.",
                            tool.get_name()
                        )
                    )
                }
            })?;

            return Ok(Some(1));
        }
    } else {
        config_path = ProtoConfig::update_document(config_dir, |doc| {
            value = doc
                .as_table_mut()
                .remove(tool.context.as_str())
                .map(|item| item.to_string());
        })?;
    }

    let Some(value) = value else {
        session.console.render_err(element! {
            Notice(variant: Variant::Caution) {
                StyledText(
                    content: format!(
                        "No version pinned for <id>{}</id> in config <path>{}</path>",
                        args.context,
                        config_path.display()
                    ),
                )
            }
        })?;

        return Ok(Some(1));
    };

    session.console.render(element! {
        Notice(variant: Variant::Success) {
            StyledText(
                content: format!(
                    "Removed <id>{}</id> version <version>{}</version> from config <path>{}</path>",
                    args.context,
                    encode_style_tags(value),
                    config_path.display()
                ),
            )
        }
    })?;

    Ok(None)
}