diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ede2e4b49e..8526adb35bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,7 +74,7 @@ - The compiler will now raise warning for inefficient use of `list.length()` when trying to check is list empty via `0 < list.length(list)` or -`list.length(list) > 0` as well as in other cases. For example, the following + `list.length(list) > 0` as well as in other cases. For example, the following code: ```gleam @@ -343,3 +343,7 @@ - Fixed a bug where adding `echo` to the subject of a `case` expression would prevent variant inference from working correctly. ([Surya Rose](https://github.com/GearsDatapacks)) + +- Added an error message when attempting to update packages that are not dependencies + of the project, instead of failing silently. + ([Etienne Boutet](https://github.com/EtienneBoutet)) diff --git a/compiler-cli/src/dependencies.rs b/compiler-cli/src/dependencies.rs index 4c44a6b1071..60ee48d70e0 100644 --- a/compiler-cli/src/dependencies.rs +++ b/compiler-cli/src/dependencies.rs @@ -225,6 +225,9 @@ pub fn update(paths: &ProjectPaths, packages: Vec) -> Result<()> { UseManifest::Yes }; + let manifest = read_manifest_from_disc(paths)?; + assert_packages_exist_locally(&manifest, packages.clone())?; + // Update specific packages _ = download( paths, @@ -240,6 +243,24 @@ pub fn update(paths: &ProjectPaths, packages: Vec) -> Result<()> { Ok(()) } +pub fn assert_packages_exist_locally(manifest: &Manifest, packages: Vec) -> Result<()> { + let missing_packages: Vec = packages + .iter() + .filter(|package_name| { + let package_name_eco = EcoString::from(package_name.as_str()); + !manifest.packages.iter().any(|p| p.name == package_name_eco) + }) + .cloned() + .collect(); + + if !missing_packages.is_empty() { + return Err(Error::PackagesToUpdateNotExist { + packages: missing_packages, + }); + } + Ok(()) +} + /// Edit the manifest.toml file in this proejct, removing all extra requirements and packages /// that are no longer present in the gleam.toml config. pub fn cleanup(paths: &ProjectPaths, telemetry: Telem) -> Result { diff --git a/compiler-cli/src/dependencies/tests.rs b/compiler-cli/src/dependencies/tests.rs index 8ec847c6393..312c840305a 100644 --- a/compiler-cli/src/dependencies/tests.rs +++ b/compiler-cli/src/dependencies/tests.rs @@ -1347,3 +1347,32 @@ fn test_pretty_print_major_versions_available() { insta::assert_snapshot!(output); } + +#[test] +fn test_assert_packages_exist_locally() { + let manifest = Manifest { + requirements: HashMap::from([ + ( + "existing_package".into(), + Requirement::hex("~>1.0").unwrap(), + ), + ("dev_package".into(), Requirement::hex("~>2.0").unwrap()), + ]), + packages: vec![ + manifest_package("existing_package", "1.0.0", vec![]), + manifest_package("dev_package", "2.0.0", vec![]), + ], + }; + + assert!(assert_packages_exist_locally(&manifest, vec!["existing_package".to_string()]).is_ok()); + assert!(assert_packages_exist_locally(&manifest, vec!["dev_package".to_string()]).is_ok()); + + let result = assert_packages_exist_locally(&manifest, vec!["nonexisting_package".to_string()]); + assert!(result.is_err()); + match result { + Err(Error::PackagesToUpdateNotExist { packages }) => { + assert_eq!(packages, vec!["nonexisting_package".to_string()]); + } + _ => panic!("Expected PackagesToUpdateNotExist error"), + } +} diff --git a/compiler-core/src/error.rs b/compiler-core/src/error.rs index d2e3e7f308b..751a5fae979 100644 --- a/compiler-core/src/error.rs +++ b/compiler-core/src/error.rs @@ -205,6 +205,9 @@ file_names.iter().map(|x| x.as_str()).join(", "))] #[error("Packages not exist: {}", packages.iter().join(", "))] RemovedPackagesNotExist { packages: Vec }, + #[error("Packages to update not exist: {}", packages.iter().join(", "))] + PackagesToUpdateNotExist { packages: Vec }, + #[error("unable to find project root")] UnableToFindProjectRoot { path: String }, @@ -958,6 +961,24 @@ If you want to overwrite these files, delete them and run the command again. "These packages are not dependencies of your package so they could not be removed. +{} +", + packages + .iter() + .map(|p| format!(" - {}", p.as_str())) + .join("\n") + ), + level: Level::Error, + hint: None, + location: None, + }], + + Error::PackagesToUpdateNotExist { packages } => vec![Diagnostic { + title: "Packages not found".into(), + text: format!( + "These packages are not dependencies of your package so they could not +be updated. + {} ", packages