From a04a0873dbfc66ad3b34a02ba79e760d908a6f3d Mon Sep 17 00:00:00 2001 From: brianheineman Date: Sat, 3 Aug 2024 14:34:48 -0600 Subject: [PATCH 1/2] refactor!: refactor extension matchers --- postgresql_extensions/src/lib.rs | 2 + postgresql_extensions/src/matcher.rs | 184 ++++++++++++++++++ .../src/repository/portal_corp/matcher.rs | 89 --------- .../src/repository/portal_corp/mod.rs | 3 - .../src/repository/portal_corp/repository.rs | 10 +- .../src/repository/steampipe/matcher.rs | 115 ----------- .../src/repository/steampipe/mod.rs | 3 - .../src/repository/steampipe/repository.rs | 8 +- .../src/repository/tensor_chord/matcher.rs | 88 --------- .../src/repository/tensor_chord/mod.rs | 3 - .../src/repository/tensor_chord/repository.rs | 10 +- 11 files changed, 206 insertions(+), 309 deletions(-) create mode 100644 postgresql_extensions/src/matcher.rs delete mode 100644 postgresql_extensions/src/repository/portal_corp/matcher.rs delete mode 100644 postgresql_extensions/src/repository/steampipe/matcher.rs delete mode 100644 postgresql_extensions/src/repository/tensor_chord/matcher.rs diff --git a/postgresql_extensions/src/lib.rs b/postgresql_extensions/src/lib.rs index c065e0e..4561a5f 100644 --- a/postgresql_extensions/src/lib.rs +++ b/postgresql_extensions/src/lib.rs @@ -91,11 +91,13 @@ pub mod blocking; mod error; pub mod extensions; +mod matcher; mod model; pub mod repository; pub use error::{Error, Result}; pub use extensions::{get_available_extensions, get_installed_extensions, install, uninstall}; +pub use matcher::{matcher, tar_gz_matcher, zip_matcher}; #[cfg(test)] pub use model::TestSettings; pub use model::{AvailableExtension, InstalledConfiguration, InstalledExtension}; diff --git a/postgresql_extensions/src/matcher.rs b/postgresql_extensions/src/matcher.rs new file mode 100644 index 0000000..e55da7b --- /dev/null +++ b/postgresql_extensions/src/matcher.rs @@ -0,0 +1,184 @@ +use postgresql_archive::Result; +use regex::Regex; +use semver::Version; +use std::collections::HashMap; +use std::env::consts; +use url::Url; + +/// .zip asset matcher that matches the asset name to the postgresql major version, target triple or +/// OS/CPU architecture. +/// +/// # Errors +/// * If the asset matcher fails. +#[allow(clippy::case_sensitive_file_extension_comparisons)] +pub fn zip_matcher(url: &str, name: &str, version: &Version) -> Result { + if !matcher(url, name, version)? { + return Ok(false); + } + + Ok(name.ends_with(".zip")) +} + +/// .tar.gz asset matcher that matches the asset name to the postgresql major version, target triple +/// or OS/CPU architecture. +/// +/// # Errors +/// * If the asset matcher fails. +#[allow(clippy::case_sensitive_file_extension_comparisons)] +pub fn tar_gz_matcher(url: &str, name: &str, version: &Version) -> Result { + if !matcher(url, name, version)? { + return Ok(false); + } + + Ok(name.ends_with(".tar.gz")) +} + +/// Default asset matcher that matches the asset name to the postgresql major version, target triple +/// or OS/CPU architecture. +/// +/// # Errors +/// * If the asset matcher fails. +pub fn matcher(url: &str, name: &str, _version: &Version) -> Result { + let Ok(url) = Url::parse(url) else { + return Ok(false); + }; + let query_parameters: HashMap = url.query_pairs().into_owned().collect(); + let Some(postgresql_version) = query_parameters.get("postgresql_version") else { + return Ok(false); + }; + let postgresql_major_version = match postgresql_version.split_once('.') { + None => return Ok(false), + Some((major, _)) => major, + }; + + let postgresql_version = format!("pg{postgresql_major_version}"); + let postgresql_version_re = regex(postgresql_version.as_str())?; + if !postgresql_version_re.is_match(name) { + return Ok(false); + } + + let target_re = regex(target_triple::TARGET)?; + if target_re.is_match(name) { + return Ok(true); + } + + let os = consts::OS; + let os_re = regex(os)?; + let matches_os = match os { + "macos" => { + let darwin_re = regex("darwin")?; + os_re.is_match(name) || darwin_re.is_match(name) + } + _ => os_re.is_match(name), + }; + + let arch = consts::ARCH; + let arch_re = regex(arch)?; + let matches_arch = match arch { + "x86_64" => { + let amd64_re = regex("amd64")?; + arch_re.is_match(name) || amd64_re.is_match(name) + } + "aarch64" => { + let arm64_re = regex("arm64")?; + arch_re.is_match(name) || arm64_re.is_match(name) + } + _ => arch_re.is_match(name), + }; + if matches_os && matches_arch { + return Ok(true); + } + + Ok(false) +} + +/// Creates a new regex for the specified key. +/// +/// # Arguments +/// * `key` - The key to create the regex for. +/// +/// # Returns +/// * The regex. +/// +/// # Errors +/// * If the regex cannot be created. +fn regex(key: &str) -> Result { + let regex = Regex::new(format!(r"[\W_]{key}[\W_]").as_str())?; + Ok(regex) +} + +#[cfg(test)] +mod tests { + use super::*; + use anyhow::Result; + + #[test] + fn test_invalid_url() -> Result<()> { + let url = "^"; + assert!(!matcher(url, "", &Version::new(0, 0, 0))?); + Ok(()) + } + + #[test] + fn test_no_version() -> Result<()> { + assert!(!matcher("https://foo", "", &Version::new(0, 0, 0))?); + Ok(()) + } + + #[test] + fn test_invalid_version() -> Result<()> { + assert!(!matcher( + "https://foo?postgresql_version=16", + "", + &Version::new(0, 0, 0) + )?); + Ok(()) + } + + #[test] + fn test_asset_match_success() -> Result<()> { + let postgresql_major_version = 16; + let url = format!("https://foo?postgresql_version={postgresql_major_version}.3"); + let version = Version::parse("1.2.3")?; + let target = target_triple::TARGET; + let os = consts::OS; + let arch = consts::ARCH; + let names = vec![ + format!("postgresql-pg16-{target}.zip"), + format!("postgresql-pg16-{os}-{arch}.zip"), + format!("postgresql-pg16-{target}.tar.gz"), + format!("postgresql-pg16-{os}-{arch}.tar.gz"), + format!("foo.{target}.pg16.tar.gz"), + format!("foo.{os}.{arch}.pg16.tar.gz"), + format!("foo-{arch}-{os}-pg16.tar.gz"), + format!("foo_{arch}_{os}_pg16.tar.gz"), + ]; + + for name in names { + assert!(matcher(url.as_str(), name.as_str(), &version)?, "{}", name); + } + Ok(()) + } + + #[test] + fn test_asset_match_errors() -> Result<()> { + let postgresql_major_version = 16; + let url = format!("https://foo?postgresql_version={postgresql_major_version}.3"); + let version = Version::parse("1.2.3")?; + let target = target_triple::TARGET; + let os = consts::OS; + let arch = consts::ARCH; + let names = vec![ + format!("foo{target}.tar.gz"), + format!("foo{os}-{arch}.tar.gz"), + format!("foo-{target}.tar"), + format!("foo-{os}-{arch}.tar"), + format!("foo-{os}{arch}.tar.gz"), + ]; + + for name in names { + assert!(!matcher(url.as_str(), name.as_str(), &version)?, "{}", name); + } + Ok(()) + } +} diff --git a/postgresql_extensions/src/repository/portal_corp/matcher.rs b/postgresql_extensions/src/repository/portal_corp/matcher.rs deleted file mode 100644 index eb714d7..0000000 --- a/postgresql_extensions/src/repository/portal_corp/matcher.rs +++ /dev/null @@ -1,89 +0,0 @@ -use postgresql_archive::Result; -use semver::Version; -use std::collections::HashMap; -use url::Url; - -/// Matcher for Portal Corp binaries from -/// -/// # Errors -/// * If the asset matcher fails. -#[allow(clippy::case_sensitive_file_extension_comparisons)] -pub fn matcher(url: &str, name: &str, _version: &Version) -> Result { - let Ok(url) = Url::parse(url) else { - return Ok(false); - }; - let query_parameters: HashMap = url.query_pairs().into_owned().collect(); - let Some(postgresql_version) = query_parameters.get("postgresql_version") else { - return Ok(false); - }; - let postgresql_major_version = match postgresql_version.split_once('.') { - None => return Ok(false), - Some((major, _)) => major, - }; - let target = target_triple::TARGET; - let expected_name = format!("pgvector-{target}-pg{postgresql_major_version}.zip"); - Ok(name == expected_name) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::repository::portal_corp; - - #[test] - fn test_match_success() -> Result<()> { - let postgresql_major_version = 16; - let url = format!( - "{}?postgresql_version={postgresql_major_version}.6", - portal_corp::URL - ); - let version = Version::parse("0.16.12")?; - let target = target_triple::TARGET; - let name = format!("pgvector-{target}-pg{postgresql_major_version}.zip"); - - assert!(matcher(url.as_str(), name.as_str(), &version)?, "{}", name); - Ok(()) - } - - #[test] - fn test_invalid_url() -> Result<()> { - let url = "^"; - assert!(!matcher(url, "", &Version::new(0, 0, 0))?); - Ok(()) - } - - #[test] - fn test_no_version() -> Result<()> { - assert!(!matcher(portal_corp::URL, "", &Version::new(0, 0, 0))?); - Ok(()) - } - - #[test] - fn test_invalid_version() -> Result<()> { - let url = format!("{}?postgresql_version=16", portal_corp::URL); - assert!(!matcher(url.as_str(), "", &Version::new(0, 0, 0))?); - Ok(()) - } - - #[test] - fn test_match_errors() -> Result<()> { - let postgresql_major_version = 16; - let url = format!( - "{}?postgresql_version={postgresql_major_version}.3", - portal_corp::URL - ); - let version = Version::parse("0.16.12")?; - let target = target_triple::TARGET; - let names = vec![ - format!("foo-{target}-pg{postgresql_major_version}.zip"), - format!("pgvector-pg{postgresql_major_version}.zip"), - format!("pgvector-{target}.zip"), - format!("pgvector-{target}-pg{postgresql_major_version}.tar.gz"), - ]; - - for name in names { - assert!(!matcher(url.as_str(), name.as_str(), &version)?, "{}", name); - } - Ok(()) - } -} diff --git a/postgresql_extensions/src/repository/portal_corp/mod.rs b/postgresql_extensions/src/repository/portal_corp/mod.rs index 17dd153..62d004b 100644 --- a/postgresql_extensions/src/repository/portal_corp/mod.rs +++ b/postgresql_extensions/src/repository/portal_corp/mod.rs @@ -1,6 +1,3 @@ -mod matcher; pub mod repository; pub const URL: &str = "https://github.com/portalcorp"; - -pub use matcher::matcher; diff --git a/postgresql_extensions/src/repository/portal_corp/repository.rs b/postgresql_extensions/src/repository/portal_corp/repository.rs index 4a82313..1d06a3d 100644 --- a/postgresql_extensions/src/repository/portal_corp/repository.rs +++ b/postgresql_extensions/src/repository/portal_corp/repository.rs @@ -1,10 +1,11 @@ +use crate::matcher::zip_matcher; use crate::model::AvailableExtension; use crate::repository::portal_corp::URL; -use crate::repository::{portal_corp, Repository}; +use crate::repository::Repository; use crate::Result; use async_trait::async_trait; +use postgresql_archive::get_archive; use postgresql_archive::repository::github::repository::GitHub; -use postgresql_archive::{get_archive, matcher}; use semver::{Version, VersionReq}; use std::fmt::Debug; use std::io::Cursor; @@ -31,7 +32,10 @@ impl PortalCorp { /// # Errors /// * If the repository cannot be initialized. pub fn initialize() -> Result<()> { - matcher::registry::register(|url| Ok(url.starts_with(URL)), portal_corp::matcher)?; + postgresql_archive::matcher::registry::register( + |url| Ok(url.starts_with(URL)), + zip_matcher, + )?; postgresql_archive::repository::registry::register( |url| Ok(url.starts_with(URL)), Box::new(GitHub::new), diff --git a/postgresql_extensions/src/repository/steampipe/matcher.rs b/postgresql_extensions/src/repository/steampipe/matcher.rs deleted file mode 100644 index b8e45c2..0000000 --- a/postgresql_extensions/src/repository/steampipe/matcher.rs +++ /dev/null @@ -1,115 +0,0 @@ -use postgresql_archive::Result; -use semver::Version; -use std::collections::HashMap; -use std::env::consts; -use url::Url; - -/// Matcher for Steampipe binaries from -/// -/// # Errors -/// * If the asset matcher fails. -#[allow(clippy::unnecessary_wraps)] -pub fn matcher(url: &str, name: &str, _version: &Version) -> Result { - let Ok(url) = Url::parse(url) else { - return Ok(false); - }; - let query_parameters: HashMap = url.query_pairs().into_owned().collect(); - let Some(postgresql_version) = query_parameters.get("postgresql_version") else { - return Ok(false); - }; - let postgresql_version = match postgresql_version.split_once('.') { - None => return Ok(false), - Some((major, _)) => major, - }; - if !name.starts_with("steampipe_postgres_") { - return Ok(false); - } - let os = get_os(); - let arch = get_arch(); - let suffix = format!(".pg{postgresql_version}.{os}_{arch}.tar.gz"); - Ok(name.ends_with(suffix.as_str())) -} - -/// Get the OS name for the Steampipe binary. -fn get_os() -> &'static str { - match consts::OS { - "macos" => "darwin", - _ => consts::OS, - } -} - -/// Get the architecture name for the Steampipe binary. -fn get_arch() -> &'static str { - match consts::ARCH { - "x86_64" => "amd64", - "aarch64" => "arm64", - _ => consts::ARCH, - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::repository::steampipe; - - #[test] - fn test_match_success() -> Result<()> { - let postgresql_major_version = 15; - let url = format!( - "{}?postgresql_version={postgresql_major_version}.7", - steampipe::URL - ); - let version = Version::parse("0.12.0")?; - let os = get_os(); - let arch = get_arch(); - let name = - format!("steampipe_postgres_csv.pg{postgresql_major_version}.{os}_{arch}.tar.gz"); - - assert!(matcher(url.as_str(), name.as_str(), &version)?, "{}", name); - Ok(()) - } - - #[test] - fn test_invalid_url() -> Result<()> { - let url = "^"; - assert!(!matcher(url, "", &Version::new(0, 0, 0))?); - Ok(()) - } - - #[test] - fn test_no_version() -> Result<()> { - assert!(!matcher(steampipe::URL, "", &Version::new(0, 0, 0))?); - Ok(()) - } - - #[test] - fn test_invalid_version() -> Result<()> { - let url = format!("{}?postgresql_version=16", steampipe::URL); - assert!(!matcher(url.as_str(), "", &Version::new(0, 0, 0))?); - Ok(()) - } - #[test] - fn test_match_errors() -> Result<()> { - let postgresql_major_version = 15; - let url = format!( - "{}?postgresql_version={postgresql_major_version}.7", - steampipe::URL - ); - let version = Version::parse("0.12.0")?; - let os = get_os(); - let arch = get_arch(); - let names = vec![ - format!("foo_csv.pg{postgresql_major_version}.{os}_{arch}.tar.gz"), - format!("steampipe_postgres_csv.pg.{os}_{arch}.tar.gz"), - format!("steampipe_postgres_csv.pg{postgresql_major_version}.{arch}.tar.gz"), - format!("steampipe_postgres_csv.pg{postgresql_major_version}.{os}.tar.gz"), - format!("steampipe_postgres_csv.pg{postgresql_major_version}.{os}_{arch}"), - format!("steampipe_postgres_csv.pg{postgresql_major_version}.{os}_{arch}.zip"), - ]; - - for name in names { - assert!(!matcher(url.as_str(), name.as_str(), &version)?, "{}", name); - } - Ok(()) - } -} diff --git a/postgresql_extensions/src/repository/steampipe/mod.rs b/postgresql_extensions/src/repository/steampipe/mod.rs index bcb6099..2845726 100644 --- a/postgresql_extensions/src/repository/steampipe/mod.rs +++ b/postgresql_extensions/src/repository/steampipe/mod.rs @@ -1,7 +1,4 @@ mod extensions; -mod matcher; pub mod repository; pub const URL: &str = "https://github.com/turbot"; - -pub use matcher::matcher; diff --git a/postgresql_extensions/src/repository/steampipe/repository.rs b/postgresql_extensions/src/repository/steampipe/repository.rs index 1f15b31..ca19bed 100644 --- a/postgresql_extensions/src/repository/steampipe/repository.rs +++ b/postgresql_extensions/src/repository/steampipe/repository.rs @@ -1,3 +1,4 @@ +use crate::matcher::tar_gz_matcher; use crate::model::AvailableExtension; use crate::repository::steampipe::URL; use crate::repository::{steampipe, Repository}; @@ -5,8 +6,8 @@ use crate::Error::ExtensionNotFound; use crate::Result; use async_trait::async_trait; use flate2::bufread::GzDecoder; +use postgresql_archive::get_archive; use postgresql_archive::repository::github::repository::GitHub; -use postgresql_archive::{get_archive, matcher}; use semver::{Version, VersionReq}; use std::fmt::Debug; use std::fs; @@ -33,7 +34,10 @@ impl Steampipe { /// # Errors /// * If the repository cannot be initialized. pub fn initialize() -> Result<()> { - matcher::registry::register(|url| Ok(url.starts_with(URL)), steampipe::matcher)?; + postgresql_archive::matcher::registry::register( + |url| Ok(url.starts_with(URL)), + tar_gz_matcher, + )?; postgresql_archive::repository::registry::register( |url| Ok(url.starts_with(URL)), Box::new(GitHub::new), diff --git a/postgresql_extensions/src/repository/tensor_chord/matcher.rs b/postgresql_extensions/src/repository/tensor_chord/matcher.rs deleted file mode 100644 index 6803eeb..0000000 --- a/postgresql_extensions/src/repository/tensor_chord/matcher.rs +++ /dev/null @@ -1,88 +0,0 @@ -use postgresql_archive::Result; -use semver::Version; -use std::collections::HashMap; -use url::Url; - -/// Matcher for Tensor Chord binaries from -/// -/// # Errors -/// * If the asset matcher fails. -#[allow(clippy::case_sensitive_file_extension_comparisons)] -pub fn matcher(url: &str, name: &str, version: &Version) -> Result { - let Ok(url) = Url::parse(url) else { - return Ok(false); - }; - let query_parameters: HashMap = url.query_pairs().into_owned().collect(); - let Some(postgresql_version) = query_parameters.get("postgresql_version") else { - return Ok(false); - }; - let postgresql_version = match postgresql_version.split_once('.') { - None => return Ok(false), - Some((major, _)) => major, - }; - let target = target_triple::TARGET; - let expected_name = format!("vectors-pg{postgresql_version}_{target}_{version}.zip"); - Ok(name == expected_name) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::repository::tensor_chord; - - #[test] - fn test_match_success() -> Result<()> { - let postgresql_major_version = 16; - let url = format!( - "{}?postgresql_version={postgresql_major_version}.6", - tensor_chord::URL - ); - let version = Version::parse("0.3.0")?; - let target = target_triple::TARGET; - let name = format!("vectors-pg{postgresql_major_version}_{target}_{version}.zip"); - - assert!(matcher(url.as_str(), name.as_str(), &version)?, "{}", name); - Ok(()) - } - - #[test] - fn test_invalid_url() -> Result<()> { - let url = "^"; - assert!(!matcher(url, "", &Version::new(0, 0, 0))?); - Ok(()) - } - - #[test] - fn test_no_version() -> Result<()> { - assert!(!matcher(tensor_chord::URL, "", &Version::new(0, 0, 0))?); - Ok(()) - } - - #[test] - fn test_invalid_version() -> Result<()> { - let url = format!("{}?postgresql_version=16", tensor_chord::URL); - assert!(!matcher(url.as_str(), "", &Version::new(0, 0, 0))?); - Ok(()) - } - - #[test] - fn test_match_errors() -> Result<()> { - let postgresql_major_version = 16; - let url = format!( - "{}?postgresql_version={postgresql_major_version}.3", - tensor_chord::URL - ); - let version = Version::parse("0.3.0")?; - let target = target_triple::TARGET; - let names = vec![ - format!("vectors-pg{target}_{version}.zip"), - format!("vectors-pg{postgresql_major_version}_{version}.zip"), - format!("vectors-pg{postgresql_major_version}_{target}_{version}.tar.gz"), - ]; - - for name in names { - assert!(!matcher(url.as_str(), name.as_str(), &version)?, "{}", name); - } - Ok(()) - } -} diff --git a/postgresql_extensions/src/repository/tensor_chord/mod.rs b/postgresql_extensions/src/repository/tensor_chord/mod.rs index 1fc34af..bf72915 100644 --- a/postgresql_extensions/src/repository/tensor_chord/mod.rs +++ b/postgresql_extensions/src/repository/tensor_chord/mod.rs @@ -1,6 +1,3 @@ -mod matcher; pub mod repository; pub const URL: &str = "https://github.com/tensorchord"; - -pub use matcher::matcher; diff --git a/postgresql_extensions/src/repository/tensor_chord/repository.rs b/postgresql_extensions/src/repository/tensor_chord/repository.rs index 89dbbc9..cb85593 100644 --- a/postgresql_extensions/src/repository/tensor_chord/repository.rs +++ b/postgresql_extensions/src/repository/tensor_chord/repository.rs @@ -1,10 +1,11 @@ +use crate::matcher::zip_matcher; use crate::model::AvailableExtension; use crate::repository::tensor_chord::URL; -use crate::repository::{tensor_chord, Repository}; +use crate::repository::Repository; use crate::Result; use async_trait::async_trait; +use postgresql_archive::get_archive; use postgresql_archive::repository::github::repository::GitHub; -use postgresql_archive::{get_archive, matcher}; use semver::{Version, VersionReq}; use std::fmt::Debug; use std::io::Cursor; @@ -31,7 +32,10 @@ impl TensorChord { /// # Errors /// * If the repository cannot be initialized. pub fn initialize() -> Result<()> { - matcher::registry::register(|url| Ok(url.starts_with(URL)), tensor_chord::matcher)?; + postgresql_archive::matcher::registry::register( + |url| Ok(url.starts_with(URL)), + zip_matcher, + )?; postgresql_archive::repository::registry::register( |url| Ok(url.starts_with(URL)), Box::new(GitHub::new), From 62edcd5dc5f0f212b42336a85dddb6702c48c2c3 Mon Sep 17 00:00:00 2001 From: brianheineman Date: Sat, 3 Aug 2024 14:44:18 -0600 Subject: [PATCH 2/2] test: add tests for extension matchers --- postgresql_extensions/src/matcher.rs | 80 +++++++++++++++++++++------- 1 file changed, 62 insertions(+), 18 deletions(-) diff --git a/postgresql_extensions/src/matcher.rs b/postgresql_extensions/src/matcher.rs index e55da7b..32c8be0 100644 --- a/postgresql_extensions/src/matcher.rs +++ b/postgresql_extensions/src/matcher.rs @@ -5,32 +5,32 @@ use std::collections::HashMap; use std::env::consts; use url::Url; -/// .zip asset matcher that matches the asset name to the postgresql major version, target triple or -/// OS/CPU architecture. +/// .tar.gz asset matcher that matches the asset name to the postgresql major version, target triple +/// or OS/CPU architecture. /// /// # Errors /// * If the asset matcher fails. #[allow(clippy::case_sensitive_file_extension_comparisons)] -pub fn zip_matcher(url: &str, name: &str, version: &Version) -> Result { +pub fn tar_gz_matcher(url: &str, name: &str, version: &Version) -> Result { if !matcher(url, name, version)? { return Ok(false); } - Ok(name.ends_with(".zip")) + Ok(name.ends_with(".tar.gz")) } -/// .tar.gz asset matcher that matches the asset name to the postgresql major version, target triple -/// or OS/CPU architecture. +/// .zip asset matcher that matches the asset name to the postgresql major version, target triple or +/// OS/CPU architecture. /// /// # Errors /// * If the asset matcher fails. #[allow(clippy::case_sensitive_file_extension_comparisons)] -pub fn tar_gz_matcher(url: &str, name: &str, version: &Version) -> Result { +pub fn zip_matcher(url: &str, name: &str, version: &Version) -> Result { if !matcher(url, name, version)? { return Ok(false); } - Ok(name.ends_with(".tar.gz")) + Ok(name.ends_with(".zip")) } /// Default asset matcher that matches the asset name to the postgresql major version, target triple @@ -136,7 +136,51 @@ mod tests { } #[test] - fn test_asset_match_success() -> Result<()> { + fn test_tar_gz_matcher() -> Result<()> { + let postgresql_major_version = 16; + let url = format!("https://foo?postgresql_version={postgresql_major_version}.3"); + let version = Version::parse("1.2.3")?; + let target = target_triple::TARGET; + + let valid_name = format!("postgresql-pg{postgresql_major_version}-{target}.tar.gz"); + let invalid_name = format!("postgresql-pg{postgresql_major_version}-{target}.zip"); + assert!( + tar_gz_matcher(url.as_str(), valid_name.as_str(), &version)?, + "{}", + valid_name + ); + assert!( + !tar_gz_matcher(url.as_str(), invalid_name.as_str(), &version)?, + "{}", + invalid_name + ); + Ok(()) + } + + #[test] + fn test_zip_matcher() -> Result<()> { + let postgresql_major_version = 16; + let url = format!("https://foo?postgresql_version={postgresql_major_version}.3"); + let version = Version::parse("1.2.3")?; + let target = target_triple::TARGET; + + let valid_name = format!("postgresql-pg{postgresql_major_version}-{target}.zip"); + let invalid_name = format!("postgresql-pg{postgresql_major_version}-{target}.tar.gz"); + assert!( + zip_matcher(url.as_str(), valid_name.as_str(), &version)?, + "{}", + valid_name + ); + assert!( + !zip_matcher(url.as_str(), invalid_name.as_str(), &version)?, + "{}", + invalid_name + ); + Ok(()) + } + + #[test] + fn test_matcher_success() -> Result<()> { let postgresql_major_version = 16; let url = format!("https://foo?postgresql_version={postgresql_major_version}.3"); let version = Version::parse("1.2.3")?; @@ -144,14 +188,14 @@ mod tests { let os = consts::OS; let arch = consts::ARCH; let names = vec![ - format!("postgresql-pg16-{target}.zip"), - format!("postgresql-pg16-{os}-{arch}.zip"), - format!("postgresql-pg16-{target}.tar.gz"), - format!("postgresql-pg16-{os}-{arch}.tar.gz"), - format!("foo.{target}.pg16.tar.gz"), - format!("foo.{os}.{arch}.pg16.tar.gz"), - format!("foo-{arch}-{os}-pg16.tar.gz"), - format!("foo_{arch}_{os}_pg16.tar.gz"), + format!("postgresql-pg{postgresql_major_version}-{target}.zip"), + format!("postgresql-pg{postgresql_major_version}-{os}-{arch}.zip"), + format!("postgresql-pg{postgresql_major_version}-{target}.tar.gz"), + format!("postgresql-pg{postgresql_major_version}-{os}-{arch}.tar.gz"), + format!("foo.{target}.pg{postgresql_major_version}.tar.gz"), + format!("foo.{os}.{arch}.pg{postgresql_major_version}.tar.gz"), + format!("foo-{arch}-{os}-pg{postgresql_major_version}.tar.gz"), + format!("foo_{arch}_{os}_pg{postgresql_major_version}.tar.gz"), ]; for name in names { @@ -161,7 +205,7 @@ mod tests { } #[test] - fn test_asset_match_errors() -> Result<()> { + fn test_matcher_errors() -> Result<()> { let postgresql_major_version = 16; let url = format!("https://foo?postgresql_version={postgresql_major_version}.3"); let version = Version::parse("1.2.3")?;