diff --git a/CHANGELOG.md b/CHANGELOG.md index 810852efa..9d677eb74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,8 +12,14 @@ ## Unreleased +#### 💥 Breaking + +- Removed `proto global`, use `proto pin --global` instead. +- Removed `proto local`, use `proto pin` instead. + #### 🚀 Updates +- Added a `proto pin` command, which is a merge of the old `proto global` and `proto local` commands. - Updated `proto install` to auto-clean stale plugins after a successful installation. ## 0.18.5 diff --git a/crates/cli/src/app.rs b/crates/cli/src/app.rs index b138c83c9..940f41849 100644 --- a/crates/cli/src/app.rs +++ b/crates/cli/src/app.rs @@ -1,8 +1,7 @@ use crate::commands::{ - AddPluginArgs, AliasArgs, BinArgs, CleanArgs, CompletionsArgs, GlobalArgs, InstallArgs, - InstallGlobalArgs, ListArgs, ListGlobalArgs, ListRemoteArgs, LocalArgs, PluginsArgs, - RemovePluginArgs, RunArgs, SetupArgs, ToolsArgs, UnaliasArgs, UninstallArgs, - UninstallGlobalArgs, + AddPluginArgs, AliasArgs, BinArgs, CleanArgs, CompletionsArgs, InstallArgs, InstallGlobalArgs, + ListArgs, ListGlobalArgs, ListRemoteArgs, PinArgs, PluginsArgs, RemovePluginArgs, RunArgs, + SetupArgs, ToolsArgs, UnaliasArgs, UninstallArgs, UninstallGlobalArgs, }; use clap::builder::styling::{Color, Style, Styles}; use clap::{Parser, Subcommand, ValueEnum}; @@ -132,13 +131,6 @@ pub enum Commands { )] InstallGlobal(InstallGlobalArgs), - #[command( - name = "global", - about = "Set the global default version of a tool.", - long_about = "Set the global default version of a tool. This will pin the version in the ~/.proto/tools installation directory." - )] - Global(GlobalArgs), - #[command( alias = "ls", name = "list", @@ -164,11 +156,12 @@ pub enum Commands { ListRemote(ListRemoteArgs), #[command( - name = "local", - about = "Set the local version of a tool.", - long_about = "Set the local version of a tool. This will create a .prototools file (if it does not exist)\nin the current working directory with the appropriate tool and version." + alias = "p", + name = "pin", + about = "Pin a default global or local version of a tool.", + long_about = "Pin a default version of a tool globally to ~/.proto/tools, or locally to .prototools (in the current working directory)." )] - Local(LocalArgs), + Pin(PinArgs), #[command(name = "plugins", about = "List all active and configured plugins.")] Plugins(PluginsArgs), diff --git a/crates/cli/src/commands/global.rs b/crates/cli/src/commands/global.rs deleted file mode 100644 index 758a65db9..000000000 --- a/crates/cli/src/commands/global.rs +++ /dev/null @@ -1,34 +0,0 @@ -use clap::Args; -use proto_core::{load_tool, Id, UnresolvedVersionSpec}; -use starbase::system; -use starbase_styles::color; -use tracing::{debug, info}; - -#[derive(Args, Clone, Debug)] -pub struct GlobalArgs { - #[arg(required = true, help = "ID of tool")] - id: Id, - - #[arg(required = true, help = "Version or alias of tool")] - spec: UnresolvedVersionSpec, -} - -#[system] -pub async fn global(args: ArgsRef) -> SystemResult { - let mut tool = load_tool(&args.id).await?; - - tool.manifest.default_version = Some(args.spec.clone()); - tool.manifest.save()?; - - debug!( - version = args.spec.to_string(), - manifest = ?tool.manifest.path, - "Wrote the global version", - ); - - info!( - "Set the global {} version to {}", - tool.get_name(), - color::hash(args.spec.to_string()) - ); -} diff --git a/crates/cli/src/commands/local.rs b/crates/cli/src/commands/local.rs deleted file mode 100644 index 74051c2ae..000000000 --- a/crates/cli/src/commands/local.rs +++ /dev/null @@ -1,37 +0,0 @@ -use clap::Args; -use proto_core::{load_tool, Id, ToolsConfig, UnresolvedVersionSpec}; -use starbase::system; -use starbase_styles::color; -use std::{env, path::PathBuf}; -use tracing::{debug, info}; - -#[derive(Args, Clone, Debug)] -pub struct LocalArgs { - #[arg(required = true, help = "ID of tool")] - id: Id, - - #[arg(required = true, help = "Version or alias of tool")] - spec: UnresolvedVersionSpec, -} - -#[system] -pub async fn local(args: ArgsRef) { - let tool = load_tool(&args.id).await?; - let local_path = env::current_dir().unwrap_or_else(|_| PathBuf::from(".")); - - let mut config = ToolsConfig::load_from(local_path)?; - config.tools.insert(args.id.clone(), args.spec.clone()); - config.save()?; - - debug!( - version = args.spec.to_string(), - config = ?config.path, - "Wrote the local version", - ); - - info!( - "Set the local {} version to {}", - tool.get_name(), - color::hash(args.spec.to_string()) - ); -} diff --git a/crates/cli/src/commands/mod.rs b/crates/cli/src/commands/mod.rs index 857bf6061..541642ff4 100644 --- a/crates/cli/src/commands/mod.rs +++ b/crates/cli/src/commands/mod.rs @@ -3,14 +3,13 @@ mod alias; mod bin; mod clean; mod completions; -mod global; mod install; mod install_all; mod install_global; mod list; mod list_global; mod list_remote; -mod local; +mod pin; mod plugins; mod remove_plugin; mod run; @@ -26,14 +25,13 @@ pub use alias::*; pub use bin::*; pub use clean::*; pub use completions::*; -pub use global::*; pub use install::*; pub use install_all::*; pub use install_global::*; pub use list::*; pub use list_global::*; pub use list_remote::*; -pub use local::*; +pub use pin::*; pub use plugins::*; pub use remove_plugin::*; pub use run::*; diff --git a/crates/cli/src/commands/pin.rs b/crates/cli/src/commands/pin.rs new file mode 100644 index 000000000..5fb192fed --- /dev/null +++ b/crates/cli/src/commands/pin.rs @@ -0,0 +1,63 @@ +use std::env; +use std::path::PathBuf; + +use clap::Args; +use proto_core::{load_tool, Id, ToolsConfig, UnresolvedVersionSpec}; +use starbase::system; +use starbase_styles::color; +use tracing::{debug, info}; + +#[derive(Args, Clone, Debug)] +pub struct PinArgs { + #[arg(required = true, help = "ID of tool")] + id: Id, + + #[arg(required = true, help = "Version or alias of tool")] + spec: UnresolvedVersionSpec, + + #[arg( + long, + help = "Add to the global user config instead of local .prototools" + )] + global: bool, +} + +#[system] +pub async fn pin(args: ArgsRef) -> SystemResult { + let mut tool = load_tool(&args.id).await?; + + if args.global { + tool.manifest.default_version = Some(args.spec.clone()); + tool.manifest.save()?; + + debug!( + version = args.spec.to_string(), + manifest = ?tool.manifest.path, + "Wrote the global version", + ); + + info!( + "Set the global {} version to {}", + tool.get_name(), + color::hash(args.spec.to_string()) + ); + } else { + let local_path = env::current_dir().unwrap_or_else(|_| PathBuf::from(".")); + + let mut config = ToolsConfig::load_from(local_path)?; + config.tools.insert(args.id.clone(), args.spec.clone()); + config.save()?; + + debug!( + version = args.spec.to_string(), + config = ?config.path, + "Wrote the local version", + ); + + info!( + "Set the local {} version to {}", + tool.get_name(), + color::hash(args.spec.to_string()) + ); + } +} diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 5ec97ab4f..14f8ad0a8 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -48,11 +48,10 @@ async fn main() -> MainResult { Commands::Completions(args) => app.execute_with_args(commands::completions, args), Commands::Install(args) => app.execute_with_args(commands::install, args), Commands::InstallGlobal(args) => app.execute_with_args(commands::install_global, args), - Commands::Global(args) => app.execute_with_args(commands::global, args), Commands::List(args) => app.execute_with_args(commands::list, args), Commands::ListGlobal(args) => app.execute_with_args(commands::list_global, args), Commands::ListRemote(args) => app.execute_with_args(commands::list_remote, args), - Commands::Local(args) => app.execute_with_args(commands::local, args), + Commands::Pin(args) => app.execute_with_args(commands::pin, args), Commands::Plugins(args) => app.execute_with_args(commands::plugins, args), Commands::RemovePlugin(args) => app.execute_with_args(commands::remove_plugin, args), Commands::Run(args) => app.execute_with_args(commands::run, args), diff --git a/crates/cli/tests/global_test.rs b/crates/cli/tests/global_test.rs deleted file mode 100644 index 3a76c100d..000000000 --- a/crates/cli/tests/global_test.rs +++ /dev/null @@ -1,76 +0,0 @@ -mod utils; - -use proto_core::{ToolManifest, UnresolvedVersionSpec}; -use utils::*; - -mod global { - use super::*; - - #[test] - fn updates_manifest_file() { - let temp = create_empty_sandbox(); - let manifest_file = temp.path().join("tools/node/manifest.json"); - - assert!(!manifest_file.exists()); - - let mut cmd = create_proto_command(temp.path()); - cmd.arg("global") - .arg("node") - .arg("19.0.0") - .assert() - .success(); - - assert!(manifest_file.exists()); - - let manifest = ToolManifest::load(manifest_file).unwrap(); - - assert_eq!( - manifest.default_version, - Some(UnresolvedVersionSpec::parse("19.0.0").unwrap()) - ); - } - - #[test] - fn can_set_alias_as_default() { - let temp = create_empty_sandbox(); - let manifest_file = temp.path().join("tools/npm/manifest.json"); - - assert!(!manifest_file.exists()); - - let mut cmd = create_proto_command(temp.path()); - cmd.arg("global") - .arg("npm") - .arg("bundled") - .assert() - .success(); - - assert!(manifest_file.exists()); - - let manifest = ToolManifest::load(manifest_file).unwrap(); - - assert_eq!( - manifest.default_version, - Some(UnresolvedVersionSpec::Alias("bundled".into())) - ); - } - - #[test] - fn can_set_partial_version_as_default() { - let temp = create_empty_sandbox(); - let manifest_file = temp.path().join("tools/npm/manifest.json"); - - assert!(!manifest_file.exists()); - - let mut cmd = create_proto_command(temp.path()); - cmd.arg("global").arg("npm").arg("1.2").assert().success(); - - assert!(manifest_file.exists()); - - let manifest = ToolManifest::load(manifest_file).unwrap(); - - assert_eq!( - manifest.default_version, - Some(UnresolvedVersionSpec::parse("1.2").unwrap()) - ); - } -} diff --git a/crates/cli/tests/local_test.rs b/crates/cli/tests/pin_test.rs similarity index 51% rename from crates/cli/tests/local_test.rs rename to crates/cli/tests/pin_test.rs index 3f2408e0a..3a8c2fc14 100644 --- a/crates/cli/tests/local_test.rs +++ b/crates/cli/tests/pin_test.rs @@ -1,9 +1,10 @@ mod utils; +use proto_core::{ToolManifest, UnresolvedVersionSpec}; use std::fs; use utils::*; -mod local { +mod pin_local { use super::*; #[test] @@ -14,11 +15,7 @@ mod local { assert!(!version_file.exists()); let mut cmd = create_proto_command(temp.path()); - cmd.arg("local") - .arg("node") - .arg("19.0.0") - .assert() - .success(); + cmd.arg("pin").arg("node").arg("19.0.0").assert().success(); assert!(version_file.exists()); assert_eq!( @@ -33,14 +30,10 @@ mod local { let version_file = temp.path().join(".prototools"); let mut cmd = create_proto_command(temp.path()); - cmd.arg("local") - .arg("node") - .arg("19.0.0") - .assert() - .success(); + cmd.arg("pin").arg("node").arg("19.0.0").assert().success(); let mut cmd = create_proto_command(temp.path()); - cmd.arg("local").arg("npm").arg("9.0.0").assert().success(); + cmd.arg("pin").arg("npm").arg("9.0.0").assert().success(); assert_eq!( fs::read_to_string(version_file).unwrap(), @@ -63,7 +56,7 @@ npm = "9.0.0" ); let mut cmd = create_proto_command(temp.path()); - cmd.arg("local").arg("node").arg("19").assert().success(); + cmd.arg("pin").arg("node").arg("19").assert().success(); assert_eq!( fs::read_to_string(version_file).unwrap(), @@ -81,11 +74,7 @@ npm = "9.0.0" assert!(!version_file.exists()); let mut cmd = create_proto_command(temp.path()); - cmd.arg("local") - .arg("npm") - .arg("bundled") - .assert() - .success(); + cmd.arg("pin").arg("npm").arg("bundled").assert().success(); assert!(version_file.exists()); assert_eq!( @@ -102,7 +91,7 @@ npm = "9.0.0" assert!(!version_file.exists()); let mut cmd = create_proto_command(temp.path()); - cmd.arg("local").arg("npm").arg("1.2").assert().success(); + cmd.arg("pin").arg("npm").arg("1.2").assert().success(); assert!(version_file.exists()); assert_eq!( @@ -111,3 +100,82 @@ npm = "9.0.0" ) } } + +mod pin_global { + use super::*; + + #[test] + fn updates_manifest_file() { + let temp = create_empty_sandbox(); + let manifest_file = temp.path().join("tools/node/manifest.json"); + + assert!(!manifest_file.exists()); + + let mut cmd = create_proto_command(temp.path()); + cmd.arg("pin") + .arg("--global") + .arg("node") + .arg("19.0.0") + .assert() + .success(); + + assert!(manifest_file.exists()); + + let manifest = ToolManifest::load(manifest_file).unwrap(); + + assert_eq!( + manifest.default_version, + Some(UnresolvedVersionSpec::parse("19.0.0").unwrap()) + ); + } + + #[test] + fn can_set_alias_as_default() { + let temp = create_empty_sandbox(); + let manifest_file = temp.path().join("tools/npm/manifest.json"); + + assert!(!manifest_file.exists()); + + let mut cmd = create_proto_command(temp.path()); + cmd.arg("pin") + .arg("--global") + .arg("npm") + .arg("bundled") + .assert() + .success(); + + assert!(manifest_file.exists()); + + let manifest = ToolManifest::load(manifest_file).unwrap(); + + assert_eq!( + manifest.default_version, + Some(UnresolvedVersionSpec::Alias("bundled".into())) + ); + } + + #[test] + fn can_set_partial_version_as_default() { + let temp = create_empty_sandbox(); + let manifest_file = temp.path().join("tools/npm/manifest.json"); + + assert!(!manifest_file.exists()); + + let mut cmd = create_proto_command(temp.path()); + cmd.arg("pin") + .arg("--global") + .arg("npm") + .arg("1.2") + .assert() + .success(); + + assert!(manifest_file.exists()); + + let manifest = ToolManifest::load(manifest_file).unwrap(); + + assert_eq!( + manifest.default_version, + Some(UnresolvedVersionSpec::parse("1.2").unwrap()) + ); + } +}