From de2264db461d85beab921179f1761abf49fe20cf Mon Sep 17 00:00:00 2001 From: Rabindra Dhakal Date: Thu, 10 Oct 2024 15:37:41 +0545 Subject: [PATCH] feat(use): add ability to switch package variants --- README.md | 1 + src/cli.rs | 9 +++++++++ src/lib.rs | 3 +++ src/registry/installed.rs | 27 ++++++++++++++++++++++++++- src/registry/mod.rs | 31 +++++++++++++++++++++++++++++++ src/registry/package/install.rs | 1 - 6 files changed, 70 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cba970d..cd98aec 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ Commands: list List all available packages inspect Inspect package build log run Run packages without installing to PATH [aliases: exec] + use Use different variant of a package help Print this message or the help of the given subcommand(s) Options: diff --git a/src/cli.rs b/src/cli.rs index 3843a51..8ff5984 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -100,4 +100,13 @@ pub enum Commands { #[arg(required = true)] command: Vec, }, + + /// Use different variant of a package + #[command(arg_required_else_help = true)] + #[clap(name = "use")] + Use { + /// The package to use + #[arg(required = true)] + package: String, + }, } diff --git a/src/lib.rs b/src/lib.rs index 3cb2f5c..ea1909c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,6 +51,9 @@ pub async fn init() -> Result<()> { Commands::Run { command } => { registry.run(command.as_ref()).await?; } + Commands::Use { package } => { + registry.use_package(&package).await?; + } }; Ok(()) diff --git a/src/registry/installed.rs b/src/registry/installed.rs index b4f6e7a..0e812fc 100644 --- a/src/registry/installed.rs +++ b/src/registry/installed.rs @@ -7,7 +7,7 @@ use tokio::fs; use crate::{ core::{ - constant::INSTALL_TRACK_PATH, + constant::{BIN_PATH, INSTALL_TRACK_PATH}, util::{format_bytes, parse_size}, }, registry::package::parse_package_query, @@ -229,4 +229,29 @@ impl InstalledPackages { None } } + + pub async fn use_package(&self, resolved_package: &ResolvedPackage) -> Result<()> { + if let Some(installed) = self.find_package(resolved_package) { + let install_path = resolved_package + .package + .get_install_path(&installed.checksum); + let symlink_path = &BIN_PATH.join(&installed.bin_name); + + if symlink_path.exists() { + fs::remove_file(symlink_path).await?; + } + + fs::symlink(&install_path, symlink_path) + .await + .context(format!( + "Failed to link {} to {}", + install_path.to_string_lossy(), + symlink_path.to_string_lossy() + ))?; + } else { + return Err(anyhow::anyhow!("NOT_INSTALLED")); + } + + Ok(()) + } } diff --git a/src/registry/mod.rs b/src/registry/mod.rs index ef25161..bd8672b 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -226,6 +226,37 @@ impl PackageRegistry { pub async fn run(&self, command: &[String]) -> Result<()> { self.storage.run(command).await } + + pub async fn use_package(&self, package_name: &str) -> Result<()> { + let installed_guard = self.installed_packages.lock().await; + let resolved_package = self.storage.resolve_package(package_name)?; + let result = installed_guard.use_package(&resolved_package).await; + drop(installed_guard); + match result { + Ok(_) => { + println!("{} linked to binary path", package_name); + Ok(()) + } + Err(e) => { + if e.to_string() == "NOT_INSTALLED" { + println!("Package is not yet installed."); + let package_name = resolved_package.package.full_name('/'); + self.storage + .install_packages( + &[package_name.to_owned()], + true, + false, + self.installed_packages.clone(), + ) + .await?; + + Ok(()) + } else { + Err(e) + } + } + } + } } pub fn select_package_variant(packages: &[ResolvedPackage]) -> Result<&ResolvedPackage> { diff --git a/src/registry/package/install.rs b/src/registry/package/install.rs index 88f4a5b..8071f0d 100644 --- a/src/registry/package/install.rs +++ b/src/registry/package/install.rs @@ -26,7 +26,6 @@ impl Installer { .join("tmp") .join(package.package.full_name('-')) .with_extension("part"); - println!("TMP PATH: {:#?}", temp_path); Self { resolved_package: package.to_owned(), install_path,