diff --git a/CHANGELOG.md b/CHANGELOG.md index 37363306cea..5c4cbef4204 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ platform for the generated documentation. ([Jiangda Wang](https://github.com/frank-iii)) +- `gleam deps` now supports `why` operation that takes a package name input, finds it in the deps tree, and then print all the requirements for it from the other packages + ([Ramkarthik Krishnamurthy](https://github.com/ramkarthik)) + ### Compiler - The warning for the deprecated `[..]` pattern has been improved. diff --git a/compiler-cli/src/dependencies.rs b/compiler-cli/src/dependencies.rs index fc28a8e903e..f363efca01d 100644 --- a/compiler-cli/src/dependencies.rs +++ b/compiler-cli/src/dependencies.rs @@ -32,22 +32,16 @@ use crate::{ }; pub fn list() -> Result<()> { - let runtime = tokio::runtime::Runtime::new().expect("Unable to start Tokio async runtime"); - let project = fs::get_project_root(fs::get_current_directory()?)?; - let paths = ProjectPaths::new(project); - let config = crate::config::root_config()?; - let (_, manifest) = get_manifest( - &paths, - runtime.handle().clone(), - Mode::Dev, - &config, - &cli::Reporter::new(), - UseManifest::Yes, - )?; + let (_, manifest) = load_manifest()?; list_manifest_packages(std::io::stdout(), manifest) } -fn list_manifest_packages(mut buffer: W, manifest: Manifest) -> Result<()> { +pub fn why(package: String) -> Result<()> { + let (_, manifest) = load_manifest()?; + list_manifest_package_dependencies(std::io::stdout(), manifest, package) +} + +pub fn list_manifest_packages(mut buffer: W, manifest: Manifest) -> Result<()> { manifest .packages .into_iter() @@ -58,6 +52,23 @@ fn list_manifest_packages(mut buffer: W, manifest: Manifest) }) } +fn list_manifest_package_dependencies(mut buffer: W, manifest: Manifest, source_package: String) -> Result<()> { + manifest + .packages + .into_iter() + .try_for_each(|package| package.requirements.into_iter().try_for_each(|req| { + if source_package == req { + writeln!(buffer, "{} {}", package.name, package.version) + } else { + write!(buffer, "") + } + })) + .map_err(|e| Error::StandardIo { + action:StandardIoAction::Write, + err: Some(e.kind()), + }) +} + #[test] fn list_manifest_format() { let mut buffer = vec![]; @@ -106,6 +117,75 @@ zzz 0.4.0 ) } +#[test] +fn list_manifest_dependencies_format() { + let mut buffer = vec![]; + let source_package = String::from("gleam_stdlib"); + let manifest = Manifest { + requirements: HashMap::new(), + packages: vec![ + ManifestPackage { + name: "root".into(), + version: Version::parse("1.0.0").unwrap(), + build_tools: ["gleam".into()].into(), + otp_app: None, + requirements: vec![], + source: ManifestPackageSource::Hex { + outer_checksum: Base16Checksum(vec![1, 2, 3, 4]), + }, + }, + ManifestPackage { + name: "aaa".into(), + version: Version::new(0, 4, 2), + build_tools: ["rebar3".into(), "make".into()].into(), + otp_app: Some("aaa_app".into()), + requirements: vec!["zzz".into(), "gleam_stdlib".into()], + source: ManifestPackageSource::Hex { + outer_checksum: Base16Checksum(vec![3, 22]), + }, + }, + ManifestPackage { + name: "zzz".into(), + version: Version::new(0, 4, 0), + build_tools: ["mix".into()].into(), + otp_app: None, + requirements: vec![], + source: ManifestPackageSource::Hex { + outer_checksum: Base16Checksum(vec![3, 22]), + }, + }, + ManifestPackage { + name: "gleam_erlang".into(), + version: Version::new(0, 24, 0), + build_tools: ["mix".into()].into(), + otp_app: None, + requirements: vec!["gleam_stdlib".into()], + source: ManifestPackageSource::Hex { + outer_checksum: Base16Checksum(vec![3, 22]), + }, + }, + ManifestPackage { + name: "gleeunit".into(), + version: Version::new(1, 0, 2), + build_tools: ["mix".into()].into(), + otp_app: None, + requirements: vec!["gleam_stdlib".into(), "cowlib".into(), "cowboy".into()], + source: ManifestPackageSource::Hex { + outer_checksum: Base16Checksum(vec![3, 22]), + }, + }, + ], + }; + list_manifest_package_dependencies(&mut buffer, manifest, source_package).unwrap(); + assert_eq!( + std::str::from_utf8(&buffer).unwrap(), + r#"aaa 0.4.2 +gleam_erlang 0.24.0 +gleeunit 1.0.2 +"# + ) +} + #[derive(Debug, Clone, Copy)] pub enum UseManifest { Yes, @@ -642,6 +722,21 @@ fn get_manifest( } } +fn load_manifest() -> Result<(bool, Manifest)> { + let runtime = tokio::runtime::Runtime::new().expect("Unable to start Tokio async runtime"); + let project = fs::get_project_root(fs::get_current_directory()?)?; + let paths = ProjectPaths::new(project); + let config = crate::config::root_config()?; + get_manifest( + &paths, + runtime.handle().clone(), + Mode::Dev, + &config, + &cli::Reporter::new(), + UseManifest::Yes, + ) +} + fn is_same_requirements( requirements1: &HashMap, requirements2: &HashMap, diff --git a/compiler-cli/src/main.rs b/compiler-cli/src/main.rs index 528f1ba0f8d..f7a3d9b480a 100644 --- a/compiler-cli/src/main.rs +++ b/compiler-cli/src/main.rs @@ -336,6 +336,13 @@ enum Dependencies { /// Update dependency packages to their latest versions Update, + + /// Find out version requirements + Why { + /// The name of the package + #[arg(required = true)] + package: String, + }, } #[derive(Subcommand, Debug)] @@ -461,6 +468,8 @@ fn main() { Command::Deps(Dependencies::Update) => dependencies::update(), + Command::Deps(Dependencies::Why { package }) => dependencies::why(package), + Command::New(options) => new::create(options, COMPILER_VERSION), Command::Shell => shell::command(),