diff --git a/crates/cli/src/commands/clean.rs b/crates/cli/src/commands/clean.rs index eb69d26fa..092388150 100644 --- a/crates/cli/src/commands/clean.rs +++ b/crates/cli/src/commands/clean.rs @@ -1,7 +1,9 @@ use crate::helpers::ToolsLoader; use clap::Args; use dialoguer::Confirm; -use proto_core::{get_plugins_dir, get_temp_dir, load_tool, Id, ProtoError, Tool, VersionSpec}; +use proto_core::{ + get_plugins_dir, get_temp_dir, load_tool, remove_bin_file, Id, ProtoError, Tool, VersionSpec, +}; use starbase::diagnostics::IntoDiagnostic; use starbase::{system, SystemResult}; use starbase_styles::color; @@ -206,7 +208,7 @@ pub async fn purge_tool(id: &Id, yes: bool) -> SystemResult { // Delete binaries for bin in tool.get_bin_locations()? { - fs::remove_link(bin.path)?; + remove_bin_file(bin.path)?; } // Delete shims diff --git a/crates/core/src/helpers.rs b/crates/core/src/helpers.rs index a0cc60855..b7c1f7af5 100644 --- a/crates/core/src/helpers.rs +++ b/crates/core/src/helpers.rs @@ -5,6 +5,7 @@ use once_cell::sync::Lazy; use regex::Regex; use serde::de::DeserializeOwned; use serde::Serialize; +use sha2::digest::typenum::Len; use sha2::{Digest, Sha256}; use starbase_archive::is_supported_archive_extension; use starbase_utils::dirs::home_dir; @@ -235,3 +236,17 @@ pub fn write_json_file_with_lock( Ok(()) } + +pub fn remove_bin_file(path: impl AsRef) -> miette::Result<()> { + let path = path.as_ref(); + let metadata = std::fs::symlink_metadata(path).into_diagnostic()?; + + // Unix uses symlinks for bins, while Windows copies the file + if metadata.is_symlink() { + fs::remove_link(path)?; + } else { + fs::remove_file(path)?; + } + + Ok(()) +} diff --git a/crates/core/src/tool.rs b/crates/core/src/tool.rs index 9edd328f3..1c841a19a 100644 --- a/crates/core/src/tool.rs +++ b/crates/core/src/tool.rs @@ -1,5 +1,4 @@ use crate::error::ProtoError; -use crate::events::*; use crate::helpers::{ extract_filename_from_url, hash_file_contents, is_archive_file, is_cache_enabled, is_offline, ENV_VAR, @@ -9,6 +8,7 @@ use crate::proto::ProtoEnvironment; use crate::shimmer::{get_shim_file_names, ShimContext, SHIM_VERSION}; use crate::tool_manifest::ToolManifest; use crate::version_resolver::VersionResolver; +use crate::{events::*, remove_bin_file}; use extism::{manifest::Wasm, Manifest as PluginManifest}; use miette::IntoDiagnostic; use proto_pdk_api::*; @@ -1459,11 +1459,14 @@ impl Tool { "Creating binary symlink" ); - fs::remove_link(&output_path)?; + remove_bin_file(&output_path)?; + // Windows requires admin privileges to create soft/hard links, + // so just copy the binary... Annoying... #[cfg(windows)] { - std::os::windows::fs::symlink_file(input_path, &output_path).into_diagnostic()?; + // std::os::windows::fs::symlink_file(input_path, &output_path).into_diagnostic()?; + fs::copy_file(input_path, &output_path)?; } #[cfg(not(windows))] @@ -1561,7 +1564,7 @@ impl Tool { // otherwise the OS will throw errors for missing sources if self.manifest.default_version.is_none() || self.manifest.installed_versions.is_empty() { for bin in self.get_bin_locations()? { - fs::remove_link(bin.path)?; + remove_bin_file(bin.path)?; } }