From 96e86951a0ef6ff86d47a6306dc6b4ea6246901f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Corn=C3=A9=20Steenhuis?= Date: Wed, 28 Aug 2024 22:39:43 +0200 Subject: [PATCH] Sort artifacts by known format (#76) --- CHANGELOG.md | 8 +++++ lib/sources/artifact/format.rs | 37 ++++++++++++++++++++-- lib/sources/artifact/mod.rs | 2 ++ lib/sources/artifact/sorting.rs | 54 +++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a484d85..2d5dc94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Changed + +- Sort artifacts by known format ([#76]) + +[#76]: https://github.com/rojo-rbx/rokit/pull/76 + ## `0.2.5` - August 28th, 2024 ### Added diff --git a/lib/sources/artifact/format.rs b/lib/sources/artifact/format.rs index 67c2686..f300b40 100644 --- a/lib/sources/artifact/format.rs +++ b/lib/sources/artifact/format.rs @@ -5,11 +5,11 @@ use super::util::split_filename_and_extensions; /** An artifact format supported by Rokit. */ -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum ArtifactFormat { - Zip, - Tar, TarGz, + Tar, + Zip, Gz, } @@ -146,4 +146,35 @@ mod tests { assert_eq!(format_from_str("file.GZ"), Some(ArtifactFormat::Gz)); assert_eq!(format_from_str("file.Gz"), Some(ArtifactFormat::Gz)); } + + #[test] + fn test_ordering() { + let artifact_names = [ + "tool-v1.0.0-x86_64-linux.zip", + "tool-v1.0.0-x86_64-linux.tar", + "tool-v1.0.0-x86_64-linux.tar.gz", + "tool-v1.0.0-x86_64-linux.gz", + "tool-v1.0.0-x86_64-linux", + "tool-v1.0.0-x86_64-linux.elf", + ]; + + let mut artifact_formats: Vec> = artifact_names + .iter() + .map(|name| format_from_str(name)) + .collect(); + + artifact_formats.sort(); + + assert_eq!( + artifact_formats, + vec![ + None, + None, + Some(ArtifactFormat::TarGz), + Some(ArtifactFormat::Tar), + Some(ArtifactFormat::Zip), + Some(ArtifactFormat::Gz), + ] + ); + } } diff --git a/lib/sources/artifact/mod.rs b/lib/sources/artifact/mod.rs index 65bdeca..dc1f5b3 100644 --- a/lib/sources/artifact/mod.rs +++ b/lib/sources/artifact/mod.rs @@ -20,6 +20,7 @@ mod sorting; mod util; use self::sorting::sort_preferred_artifact; +use self::sorting::sort_preferred_formats; use self::util::split_filename_and_extensions; pub use self::format::ArtifactFormat; @@ -180,6 +181,7 @@ impl Artifact { current_desc .sort_by_preferred_compat(desc_a, desc_b) .then_with(|| sort_preferred_artifact(artifact_a, artifact_b)) + .then_with(|| sort_preferred_formats(artifact_a, artifact_b)) }); compatible_artifacts diff --git a/lib/sources/artifact/sorting.rs b/lib/sources/artifact/sorting.rs index e9208c0..c093ad8 100644 --- a/lib/sources/artifact/sorting.rs +++ b/lib/sources/artifact/sorting.rs @@ -75,8 +75,19 @@ fn word_is_not_arch_or_os_or_version_or_numeric(word: impl AsRef) -> bool { && !word.chars().all(char::is_numeric) } +pub(super) fn sort_preferred_formats(artifact_a: &Artifact, artifact_b: &Artifact) -> Ordering { + match (artifact_a.format, artifact_b.format) { + (None, None) => std::cmp::Ordering::Equal, + (None, _) => std::cmp::Ordering::Greater, + (_, None) => std::cmp::Ordering::Less, + (Some(format_a), Some(format_b)) => format_a.cmp(&format_b), + } +} + #[cfg(test)] mod tests { + use crate::sources::{ArtifactFormat, ArtifactProvider}; + use super::*; fn new_id(author: &str, name: &str) -> ToolId { @@ -163,4 +174,47 @@ mod tests { test_no_mentions("sentry-cli-linux-i686-2.32.1", "sentry-cli"); test_no_mentions("selene-light-0.27.1-linux.zip", "selene-light"); } + + #[test] + fn test_prefers_known_format() { + let artifact_names = vec![ + "tool-v1.0.0-x86_64-linux", + "tool-v1.0.0-x86_64-linux.elf", + "tool-v1.0.0-x86_64-linux.zip", + "tool-v1.0.0-x86_64-linux.tar", + "tool-v1.0.0-x86_64-linux.tar.gz", + "tool-v1.0.0-x86_64-linux.gz", + ]; + + let mut artifacts = artifact_names + .into_iter() + .map(|name| Artifact { + provider: ArtifactProvider::GitHub, + format: ArtifactFormat::from_path_or_url(name), + id: Some("id".to_string()), + url: Some("https://github.com".parse().unwrap()), + name: Some(name.to_string()), + tool_spec: new_id("author", name).into_spec(Version::parse("1.0.0").unwrap()), + }) + .collect::>(); + + artifacts.sort_by(sort_preferred_formats); + + let artifact_names_sorted = artifacts + .iter() + .map(|artifact| artifact.name.as_deref().unwrap()) + .collect::>(); + + assert_eq!( + artifact_names_sorted, + vec![ + "tool-v1.0.0-x86_64-linux.tar.gz", + "tool-v1.0.0-x86_64-linux.tar", + "tool-v1.0.0-x86_64-linux.zip", + "tool-v1.0.0-x86_64-linux.gz", + "tool-v1.0.0-x86_64-linux", + "tool-v1.0.0-x86_64-linux.elf", + ] + ); + } }