use crate::session::{ProtoSession, SessionResult};
use clap::Args;
use proto_core::{PinLocation, ProtoConfig, ToolContext, reporter::NoticeOutput};
use proto_pdk_api::{PluginFunction, UnpinVersionInput, UnpinVersionOutput};
use starbase_console::ui::*;
use starbase_styles::encode_style_tags;
use tracing::instrument;
#[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,
}
#[instrument(skip(session))]
pub async fn unpin(session: ProtoSession, args: UnpinArgs) -> SessionResult {
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 {
let mut messages = vec![format!(
"Failed to unpin a version for <id>{}</id>.",
args.context,
)];
if let Some(error) = output.error {
messages.push(error);
}
session.console.notice_with(NoticeOutput {
variant: Variant::Failure,
messages,
..Default::default()
})?;
return Ok(Some(1));
}
} else {
session.console.notice(
Variant::Caution,
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.notice(
Variant::Caution,
format!(
"No version pinned for <id>{}</id> in config <path>{}</path>",
args.context,
config_path.display()
),
)?;
return Ok(Some(1));
};
session.console.notice(
Variant::Success,
format!(
"Removed <id>{}</id> version <version>{}</version> from config <path>{}</path>",
args.context,
encode_style_tags(value),
config_path.display()
),
)?;
Ok(None)
}