From 6ae16a7dacf3853ebf68ea2e0ca69729d54dfae6 Mon Sep 17 00:00:00 2001 From: daimond113 Date: Sun, 2 Feb 2025 15:23:10 +0100 Subject: [PATCH] feat: add list and remove commands Fixes #22. --- src/cli/commands/add.rs | 16 ++++++----- src/cli/commands/list.rs | 51 ++++++++++++++++++++++++++++++++ src/cli/commands/mod.rs | 10 +++++++ src/cli/commands/remove.rs | 59 ++++++++++++++++++++++++++++++++++++++ src/cli/install.rs | 13 ++++----- src/cli/mod.rs | 10 ++++++- src/manifest/mod.rs | 9 ++++++ 7 files changed, 152 insertions(+), 16 deletions(-) create mode 100644 src/cli/commands/list.rs create mode 100644 src/cli/commands/remove.rs diff --git a/src/cli/commands/add.rs b/src/cli/commands/add.rs index 6bef863..0d93eff 100644 --- a/src/cli/commands/add.rs +++ b/src/cli/commands/add.rs @@ -4,9 +4,11 @@ use anyhow::Context; use clap::Args; use semver::VersionReq; -use crate::cli::{config::read_config, AnyPackageIdentifier, VersionedPackageName}; +use crate::cli::{ + config::read_config, dep_type_to_key, AnyPackageIdentifier, VersionedPackageName, +}; use pesde::{ - manifest::{target::TargetKind, Alias}, + manifest::{target::TargetKind, Alias, DependencyType}, names::PackageNames, source::{ git::{specifier::GitDependencySpecifier, GitPackageSource}, @@ -167,13 +169,13 @@ impl AddCommand { .context("failed to read manifest")?, ) .context("failed to parse manifest")?; - let dependency_key = if self.peer { - "peer_dependencies" + let dependency_key = dep_type_to_key(if self.peer { + DependencyType::Peer } else if self.dev { - "dev_dependencies" + DependencyType::Dev } else { - "dependencies" - }; + DependencyType::Standard + }); let alias = match self.alias { Some(alias) => alias, diff --git a/src/cli/commands/list.rs b/src/cli/commands/list.rs new file mode 100644 index 0000000..8c376a2 --- /dev/null +++ b/src/cli/commands/list.rs @@ -0,0 +1,51 @@ +use std::collections::BTreeMap; + +use anyhow::Context; +use clap::Args; + +use crate::cli::{ + dep_type_to_key, + style::{INFO_STYLE, SUCCESS_STYLE}, +}; +use pesde::{ + manifest::{Alias, DependencyType}, + source::specifiers::DependencySpecifiers, + Project, +}; + +#[derive(Debug, Args)] +pub struct ListCommand {} + +impl ListCommand { + pub async fn run(self, project: Project) -> anyhow::Result<()> { + let manifest = project + .deser_manifest() + .await + .context("failed to read manifest")?; + + let all_deps = manifest + .all_dependencies() + .context("failed to get all dependencies")? + .into_iter() + .fold( + BTreeMap::>::new(), + |mut acc, (alias, (spec, ty))| { + acc.entry(ty).or_default().insert(alias, spec); + acc + }, + ); + + for (dep_ty, deps) in all_deps { + let dep_key = dep_type_to_key(dep_ty); + println!("{}", INFO_STYLE.apply_to(dep_key)); + + for (alias, spec) in deps { + println!("{}: {spec}", SUCCESS_STYLE.apply_to(alias)); + } + + println!(); + } + + Ok(()) + } +} diff --git a/src/cli/commands/mod.rs b/src/cli/commands/mod.rs index ebadd00..a104e75 100644 --- a/src/cli/commands/mod.rs +++ b/src/cli/commands/mod.rs @@ -8,12 +8,14 @@ mod deprecate; mod execute; mod init; mod install; +mod list; mod outdated; #[cfg(feature = "patches")] mod patch; #[cfg(feature = "patches")] mod patch_commit; mod publish; +mod remove; mod run; #[cfg(feature = "version-management")] mod self_install; @@ -41,6 +43,9 @@ pub enum Subcommand { /// Adds a dependency to the project Add(add::AddCommand), + /// Removes a dependency from the project + Remove(remove::RemoveCommand), + /// Installs all dependencies for the project Install(install::InstallCommand), @@ -50,6 +55,9 @@ pub enum Subcommand { /// Checks for outdated dependencies Outdated(outdated::OutdatedCommand), + /// Lists all dependencies in the project + List(list::ListCommand), + /// Runs a script, an executable package, or a file with Lune Run(run::RunCommand), @@ -91,9 +99,11 @@ impl Subcommand { Subcommand::Cas(cas) => cas.run(project).await, Subcommand::Init(init) => init.run(project).await, Subcommand::Add(add) => add.run(project).await, + Subcommand::Remove(remove) => remove.run(project).await, Subcommand::Install(install) => install.run(project, reqwest).await, Subcommand::Update(update) => update.run(project, reqwest).await, Subcommand::Outdated(outdated) => outdated.run(project).await, + Subcommand::List(list) => list.run(project).await, Subcommand::Run(run) => run.run(project).await, Subcommand::Publish(publish) => publish.run(project, reqwest).await, Subcommand::Yank(yank) => yank.run(project, reqwest).await, diff --git a/src/cli/commands/remove.rs b/src/cli/commands/remove.rs new file mode 100644 index 0000000..3d9ab5f --- /dev/null +++ b/src/cli/commands/remove.rs @@ -0,0 +1,59 @@ +use std::str::FromStr; + +use anyhow::Context; +use clap::Args; + +use crate::cli::{ + dep_type_to_key, + style::{INFO_STYLE, SUCCESS_STYLE}, +}; +use pesde::{ + manifest::{Alias, DependencyType}, + Project, +}; + +#[derive(Debug, Args)] +pub struct RemoveCommand { + /// The alias of the package to remove + #[arg(index = 1)] + alias: Alias, +} + +impl RemoveCommand { + pub async fn run(self, project: Project) -> anyhow::Result<()> { + let mut manifest = toml_edit::DocumentMut::from_str( + &project + .read_manifest() + .await + .context("failed to read manifest")?, + ) + .context("failed to parse manifest")?; + + let Some(dep_key) = DependencyType::VARIANTS + .iter() + .copied() + .map(dep_type_to_key) + .find(|dependency_key| { + manifest[dependency_key] + .as_table_mut() + .is_some_and(|table| table.remove(self.alias.as_str()).is_some()) + }) + else { + anyhow::bail!("package under alias `{}` not found in manifest", self.alias) + }; + + project + .write_manifest(manifest.to_string()) + .await + .context("failed to write manifest")?; + + println!( + "{} removed {} from {}!", + SUCCESS_STYLE.apply_to("success!"), + INFO_STYLE.apply_to(self.alias), + INFO_STYLE.apply_to(dep_key) + ); + + Ok(()) + } +} diff --git a/src/cli/install.rs b/src/cli/install.rs index a1bdb49..cf0931f 100644 --- a/src/cli/install.rs +++ b/src/cli/install.rs @@ -1,6 +1,6 @@ use super::files::make_executable; use crate::cli::{ - bin_dir, + bin_dir, dep_type_to_key, reporters::{self, CliReporter}, resolve_overrides, run_on_workspace_members, style::{ADDED_STYLE, REMOVED_STYLE, WARN_PREFIX}, @@ -550,13 +550,10 @@ pub fn print_package_diff(prefix: &str, old_graph: DependencyGraph, new_graph: D for (ty, set) in dependency_groups { println!(); - - let ty_name = match ty { - DependencyType::Standard => "dependencies", - DependencyType::Peer => "peer_dependencies", - DependencyType::Dev => "dev_dependencies", - }; - println!("{}", style(format!("{ty_name}:")).yellow().bold()); + println!( + "{}", + style(format!("{}:", dep_type_to_key(ty))).yellow().bold() + ); for (id, added) in set { println!( diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 0503518..e930e2a 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -11,7 +11,7 @@ use pesde::{ manifest::{ overrides::{OverrideKey, OverrideSpecifier}, target::TargetKind, - Manifest, + DependencyType, Manifest, }, names::{PackageName, PackageNames}, source::{ @@ -352,3 +352,11 @@ pub async fn get_index(project: &Project, index: Option<&str>) -> anyhow::Result } } } + +pub fn dep_type_to_key(dep_type: DependencyType) -> &'static str { + match dep_type { + DependencyType::Standard => "dependencies", + DependencyType::Dev => "dev_dependencies", + DependencyType::Peer => "peer_dependencies", + } +} diff --git a/src/manifest/mod.rs b/src/manifest/mod.rs index 0ca3b1c..93dd497 100644 --- a/src/manifest/mod.rs +++ b/src/manifest/mod.rs @@ -184,6 +184,15 @@ pub enum DependencyType { Dev, } +impl DependencyType { + /// All possible dependency types + pub const VARIANTS: &'static [DependencyType] = &[ + DependencyType::Standard, + DependencyType::Peer, + DependencyType::Dev, + ]; +} + impl Manifest { /// Get all dependencies from the manifest #[instrument(skip(self), ret(level = "trace"), level = "debug")]