diff --git a/crates/konvoy-engine/src/update.rs b/crates/konvoy-engine/src/update.rs index 2113ec8..7beeff6 100644 --- a/crates/konvoy-engine/src/update.rs +++ b/crates/konvoy-engine/src/update.rs @@ -104,7 +104,7 @@ pub fn update(project_root: &Path) -> Result { message: format!("dependency `{dep_name}` is missing `version` field"), })?; - let (group_id, artifact_id) = split_maven_coordinate(maven)?; + let (group_id, artifact_id) = crate::common::split_maven_coordinate(maven)?; direct_deps.push(ResolvedMavenDep { name: (*dep_name).clone(), @@ -511,7 +511,7 @@ fn resolve_transitive( continue; } - let dep_name = derive_dep_name(&base_artifact_id); + let dep_name = base_artifact_id.clone(); let parent_name = requirer .clone() .or_else(|| { @@ -619,13 +619,6 @@ fn fetch_metadata_cached( // Helpers // --------------------------------------------------------------------------- -/// Split a `groupId:artifactId` string into its two parts. -/// -/// Re-export of [`crate::common::split_maven_coordinate`] for backward compatibility. -pub(crate) fn split_maven_coordinate(maven: &str) -> Result<(&str, &str), EngineError> { - crate::common::split_maven_coordinate(maven) -} - /// Return `true` if this dependency should be filtered from transitive resolution. /// /// Filters `kotlin-stdlib` and `kotlin-stdlib-common` which are JVM artifacts. @@ -646,15 +639,6 @@ fn is_filtered_dependency(group_id: &str, artifact_id: &str) -> bool { false } -/// Derive a user-friendly dependency name from a Maven artifact ID. -/// -/// Examples: -/// - `"kotlinx-coroutines-core"` → `"kotlinx-coroutines-core"` -/// - `"atomicfu"` → `"atomicfu"` -fn derive_dep_name(artifact_id: &str) -> String { - artifact_id.to_owned() -} - /// Extract the Maven classifier from a cinterop file URL. /// /// Given a URL like `"atomicfu-linuxx64-0.23.1-cinterop-interop.klib"`, @@ -866,22 +850,6 @@ kotlinx-coroutines = { maven = "org.jetbrains.kotlinx:kotlinx-coroutines-core", } } - #[test] - fn split_maven_coordinate_valid() { - let (g, a) = - split_maven_coordinate("org.jetbrains.kotlinx:kotlinx-coroutines-core").unwrap(); - assert_eq!(g, "org.jetbrains.kotlinx"); - assert_eq!(a, "kotlinx-coroutines-core"); - } - - #[test] - fn split_maven_coordinate_invalid() { - let result = split_maven_coordinate("no-colon-here"); - assert!(result.is_err()); - let err = result.unwrap_err().to_string(); - assert!(err.contains("invalid maven coordinate"), "error was: {err}"); - } - #[test] fn is_filtered_kotlin_stdlib() { assert!(is_filtered_dependency( @@ -911,15 +879,6 @@ kotlinx-coroutines = { maven = "org.jetbrains.kotlinx:kotlinx-coroutines-core", assert!(!is_filtered_dependency("org.jetbrains.kotlinx", "atomicfu")); } - #[test] - fn derive_dep_name_from_artifact_id() { - assert_eq!( - derive_dep_name("kotlinx-coroutines-core"), - "kotlinx-coroutines-core" - ); - assert_eq!(derive_dep_name("atomicfu"), "atomicfu"); - } - #[test] fn version_conflict_error_format() { let err = EngineError::MavenVersionConflict { diff --git a/crates/konvoy-util/src/lib.rs b/crates/konvoy-util/src/lib.rs index 0663ce1..e13a19c 100644 --- a/crates/konvoy-util/src/lib.rs +++ b/crates/konvoy-util/src/lib.rs @@ -1,5 +1,5 @@ #![forbid(unsafe_code)] -//! Hashing, filesystem utilities, and process helpers for Konvoy. +//! Hashing, filesystem utilities, and download helpers for Konvoy. pub mod artifact; pub mod download; @@ -10,4 +10,3 @@ pub mod maven; pub mod metadata; pub mod module_metadata; pub mod pom; -pub mod process; diff --git a/crates/konvoy-util/src/maven.rs b/crates/konvoy-util/src/maven.rs index 9dfd689..5c71e55 100644 --- a/crates/konvoy-util/src/maven.rs +++ b/crates/konvoy-util/src/maven.rs @@ -7,6 +7,14 @@ use crate::error::UtilError; /// Maven Central repository URL. pub const MAVEN_CENTRAL: &str = "https://repo1.maven.org/maven2"; +/// Build a Maven Central URL for an artifact file with the given extension. +/// +/// Pattern: `{MAVEN_CENTRAL}/{group_path}/{artifact_id}/{version}/{artifact_id}-{version}.{ext}` +pub fn maven_artifact_url(group_id: &str, artifact_id: &str, version: &str, ext: &str) -> String { + let group_path = group_id.replace('.', "/"); + format!("{MAVEN_CENTRAL}/{group_path}/{artifact_id}/{version}/{artifact_id}-{version}.{ext}") +} + /// A parsed Maven coordinate identifying a single artifact. #[derive(Debug, Clone, PartialEq, Eq)] pub struct MavenCoordinate { @@ -157,14 +165,9 @@ impl MavenCoordinate { /// Return the local cache path for this artifact, rooted at `cache_root`. /// - /// Uses the same directory layout as `repository_path` but as a `PathBuf`. + /// Uses the same directory layout as [`Self::repository_path`]. pub fn cache_path(&self, cache_root: &Path) -> PathBuf { - let group_path = self.group_id.replace('.', "/"); - cache_root - .join(group_path) - .join(&self.artifact_id) - .join(&self.version) - .join(self.filename()) + cache_root.join(self.repository_path()) } } diff --git a/crates/konvoy-util/src/module_metadata.rs b/crates/konvoy-util/src/module_metadata.rs index 374c4cc..aa6b9da 100644 --- a/crates/konvoy-util/src/module_metadata.rs +++ b/crates/konvoy-util/src/module_metadata.rs @@ -9,7 +9,6 @@ use serde::Deserialize; use crate::error::UtilError; -use crate::maven::MAVEN_CENTRAL; use crate::metadata::{ArtifactMetadata, MetadataDep, MetadataFile}; // --------------------------------------------------------------------------- @@ -124,8 +123,7 @@ pub fn parse_module_metadata(json: &str) -> Result /// The URL pattern is: /// `{MAVEN_CENTRAL}/{group_path}/{artifact_id}/{version}/{artifact_id}-{version}.module` pub fn module_metadata_url(group_id: &str, artifact_id: &str, version: &str) -> String { - let group_path = group_id.replace('.', "/"); - format!("{MAVEN_CENTRAL}/{group_path}/{artifact_id}/{version}/{artifact_id}-{version}.module") + crate::maven::maven_artifact_url(group_id, artifact_id, version, "module") } /// Fetch a Gradle Module Metadata file from Maven Central. diff --git a/crates/konvoy-util/src/pom.rs b/crates/konvoy-util/src/pom.rs index 782135d..ec4559b 100644 --- a/crates/konvoy-util/src/pom.rs +++ b/crates/konvoy-util/src/pom.rs @@ -11,7 +11,6 @@ //! - Property placeholders beyond `${project.version}` / `${project.groupId}` use crate::error::UtilError; -use crate::maven::MAVEN_CENTRAL; use crate::metadata::{ArtifactMetadata, MetadataDep}; /// A parsed Maven POM, containing identity and compile-scope dependencies. @@ -302,8 +301,7 @@ pub fn parse_pom( /// /// where `group_path` replaces dots in `group_id` with `/`. pub fn pom_url(group_id: &str, artifact_id: &str, version: &str) -> String { - let group_path = group_id.replace('.', "/"); - format!("{MAVEN_CENTRAL}/{group_path}/{artifact_id}/{version}/{artifact_id}-{version}.pom") + crate::maven::maven_artifact_url(group_id, artifact_id, version, "pom") } /// Fetch a POM file from Maven Central and return its contents as a string. diff --git a/crates/konvoy-util/src/process.rs b/crates/konvoy-util/src/process.rs deleted file mode 100644 index f838305..0000000 --- a/crates/konvoy-util/src/process.rs +++ /dev/null @@ -1,76 +0,0 @@ -//! Process execution helpers for Konvoy. - -use std::process::Command; - -use crate::error::UtilError; - -/// Structured output from a command execution. -#[derive(Debug)] -pub struct CommandOutput { - /// Standard output as a string. - pub stdout: String, - /// Standard error as a string. - pub stderr: String, - /// Whether the command exited successfully. - pub success: bool, - /// The exit code, if the process was not killed by a signal. - pub exit_code: Option, -} - -/// Execute a command and capture its output. -/// -/// # Errors -/// Returns an error if the command cannot be spawned (e.g. binary not found). -/// A non-zero exit code is **not** an error; check `CommandOutput::success` instead. -pub fn run_command(cmd: &mut Command) -> Result { - let output = cmd - .output() - .map_err(|source| UtilError::CommandExec { source })?; - - Ok(CommandOutput { - stdout: String::from_utf8_lossy(&output.stdout).into_owned(), - stderr: String::from_utf8_lossy(&output.stderr).into_owned(), - success: output.status.success(), - exit_code: output.status.code(), - }) -} - -#[cfg(test)] -#[allow(clippy::unwrap_used)] -mod tests { - use super::*; - - #[test] - fn run_command_success() { - let mut cmd = Command::new("echo"); - cmd.arg("hello"); - let result = run_command(&mut cmd); - let output = result.unwrap(); - assert!(output.success); - assert_eq!(output.stdout.trim(), "hello"); - assert_eq!(output.exit_code, Some(0)); - } - - #[test] - fn run_command_failure() { - let result = run_command(&mut Command::new("false")); - let output = result.unwrap(); - assert!(!output.success); - assert_ne!(output.exit_code, Some(0)); - } - - #[test] - fn run_command_missing_binary() { - let result = run_command(&mut Command::new("nonexistent_binary_xyz_123")); - assert!(result.is_err()); - } - - #[test] - fn run_command_captures_stderr() { - let mut cmd = Command::new("sh"); - cmd.args(["-c", "echo err >&2"]); - let result = run_command(&mut cmd); - let output = result.unwrap(); - assert!(output.stderr.contains("err")); - } -}