Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions postgresql_archive/src/configuration/zonky/extractor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,10 @@ pub fn extract(bytes: &Vec<u8>, extract_directories: &ExtractDirectories) -> Res
debug!("Extracting archive to {}", extract_dir.to_string_lossy());

let reader = Cursor::new(bytes);
let mut archive = ZipArchive::new(reader).map_err(|error| Unexpected(error.to_string()))?;
let mut archive = ZipArchive::new(reader)?;
let mut archive_bytes = Vec::new();
for i in 0..archive.len() {
let mut file = archive
.by_index(i)
.map_err(|error| Unexpected(error.to_string()))?;
let mut file = archive.by_index(i)?;
let file_name = file.name().to_string();
if file_name.ends_with(".txz") {
debug!("Found archive file: {file_name}");
Expand Down
54 changes: 54 additions & 0 deletions postgresql_archive/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::sync::PoisonError;

/// PostgreSQL archive result type
pub type Result<T, E = Error> = core::result::Result<T, E>;

Expand Down Expand Up @@ -111,6 +113,29 @@ impl From<url::ParseError> for Error {
}
}

#[cfg(feature = "maven")]
/// Converts a [`quick_xml::DeError`] into a [`ParseError`](Error::ParseError)
impl From<quick_xml::DeError> for Error {
fn from(error: quick_xml::DeError) -> Self {
Error::ParseError(error.to_string())
}
}

#[cfg(feature = "zip")]
/// Converts a [`zip::result::ZipError`] into a [`ParseError`](Error::Unexpected)
impl From<zip::result::ZipError> for Error {
fn from(error: zip::result::ZipError) -> Self {
Error::Unexpected(error.to_string())
}
}

/// Converts a [`std::sync::PoisonError<T>`] into a [`ParseError`](Error::PoisonedLock)
impl<T> From<PoisonError<T>> for Error {
fn from(value: PoisonError<T>) -> Self {
Error::PoisonedLock(value.to_string())
}
}

/// These are relatively low value tests; they are here to reduce the coverage gap and
/// ensure that the error conversions are working as expected.
#[cfg(test)]
Expand Down Expand Up @@ -199,4 +224,33 @@ mod test {
let error = Error::from(parse_error);
assert_eq!(error.to_string(), "empty host");
}

#[cfg(feature = "maven")]
#[test]
fn test_from_quick_xml_error() {
let xml = "<invalid>";
let quick_xml_error = quick_xml::de::from_str::<String>(xml).expect_err("quick_xml error");
let error = Error::from(quick_xml_error);
assert!(matches!(error, Error::ParseError(_)));
}

#[cfg(feature = "zip")]
#[test]
fn test_from_zip_error() {
let zip_error = zip::result::ZipError::FileNotFound;
let error = Error::from(zip_error);
assert!(matches!(error, Error::Unexpected(_)));
assert!(
error
.to_string()
.contains("specified file not found in archive")
);
}

#[test]
fn test_from_poisoned_lock() {
let error = Error::from(std::sync::PoisonError::new(()));
assert!(matches!(error, Error::PoisonedLock(_)));
assert!(error.to_string().contains("poisoned lock"));
}
}
21 changes: 6 additions & 15 deletions postgresql_archive/src/extractor/registry.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::Error::{PoisonedLock, UnsupportedExtractor};
use crate::Error::UnsupportedExtractor;
use crate::Result;
#[cfg(feature = "theseus")]
use crate::configuration::theseus;
Expand Down Expand Up @@ -45,13 +45,10 @@ impl RepositoryRegistry {
/// * If the URL is not supported.
fn get(&self, url: &str) -> Result<ExtractFn> {
for (supports_fn, extractor_fn) in &self.extractors {
let supports_function = supports_fn
.read()
.map_err(|error| PoisonedLock(error.to_string()))?;
let supports_function = supports_fn.read()?;

if supports_function(url)? {
let extractor_function = extractor_fn
.read()
.map_err(|error| PoisonedLock(error.to_string()))?;
let extractor_function = extractor_fn.read()?;
return Ok(*extractor_function);
}
}
Expand All @@ -77,10 +74,7 @@ impl Default for RepositoryRegistry {
/// # Errors
/// * If the registry is poisoned.
pub fn register(supports_fn: SupportsFn, extractor_fn: ExtractFn) -> Result<()> {
let mut registry = REGISTRY
.lock()
.map_err(|error| PoisonedLock(error.to_string()))?;
registry.register(supports_fn, extractor_fn);
REGISTRY.lock()?.register(supports_fn, extractor_fn);
Ok(())
}

Expand All @@ -89,10 +83,7 @@ pub fn register(supports_fn: SupportsFn, extractor_fn: ExtractFn) -> Result<()>
/// # Errors
/// * If the URL is not supported.
pub fn get(url: &str) -> Result<ExtractFn> {
let registry = REGISTRY
.lock()
.map_err(|error| PoisonedLock(error.to_string()))?;
registry.get(url)
REGISTRY.lock()?.get(url)
}

#[cfg(test)]
Expand Down
6 changes: 2 additions & 4 deletions postgresql_archive/src/extractor/zip_extractor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,11 @@ use zip::ZipArchive;
pub fn extract(bytes: &Vec<u8>, extract_directories: &ExtractDirectories) -> Result<Vec<PathBuf>> {
let mut files = Vec::new();
let reader = Cursor::new(bytes);
let mut archive = ZipArchive::new(reader).map_err(|_| io::Error::other("Zip error"))?;
let mut archive = ZipArchive::new(reader)?;
let mut extracted_bytes = 0;

for i in 0..archive.len() {
let mut file = archive
.by_index(i)
.map_err(|_| io::Error::other("Zip error"))?;
let mut file = archive.by_index(i)?;
let file_path = PathBuf::from(file.name());
let file_path = PathBuf::from(file_path.file_name().unwrap_or_default());
let file_name = file_path.to_string_lossy();
Expand Down
20 changes: 5 additions & 15 deletions postgresql_archive/src/hasher/registry.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::Error::{PoisonedLock, UnsupportedHasher};
use crate::Error::UnsupportedHasher;
use crate::Result;
#[cfg(feature = "theseus")]
use crate::configuration::theseus;
Expand Down Expand Up @@ -54,13 +54,9 @@ impl HasherRegistry {
let url = url.as_ref();
let extension = extension.as_ref();
for (supports_fn, hasher_fn) in &self.hashers {
let supports_function = supports_fn
.read()
.map_err(|error| PoisonedLock(error.to_string()))?;
let supports_function = supports_fn.read()?;
if supports_function(url, extension)? {
let hasher_function = hasher_fn
.read()
.map_err(|error| PoisonedLock(error.to_string()))?;
let hasher_function = hasher_fn.read()?;
return Ok(*hasher_function);
}
}
Expand Down Expand Up @@ -109,10 +105,7 @@ impl Default for HasherRegistry {
/// # Errors
/// * If the registry is poisoned.
pub fn register(supports_fn: SupportsFn, hasher_fn: HasherFn) -> Result<()> {
let mut registry = REGISTRY
.lock()
.map_err(|error| PoisonedLock(error.to_string()))?;
registry.register(supports_fn, hasher_fn);
REGISTRY.lock()?.register(supports_fn, hasher_fn);
Ok(())
}

Expand All @@ -121,10 +114,7 @@ pub fn register(supports_fn: SupportsFn, hasher_fn: HasherFn) -> Result<()> {
/// # Errors
/// * If the registry is poisoned.
pub fn get<S: AsRef<str>>(url: S, extension: S) -> Result<HasherFn> {
let registry = REGISTRY
.lock()
.map_err(|error| PoisonedLock(error.to_string()))?;
registry.get(url, extension)
REGISTRY.lock()?.get(url, extension)
}

#[cfg(test)]
Expand Down
20 changes: 5 additions & 15 deletions postgresql_archive/src/matcher/registry.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::Error::{PoisonedLock, UnsupportedMatcher};
use crate::Error::UnsupportedMatcher;
use crate::Result;
#[cfg(feature = "theseus")]
use crate::configuration::theseus;
Expand Down Expand Up @@ -46,13 +46,9 @@ impl MatchersRegistry {
fn get<S: AsRef<str>>(&self, url: S) -> Result<MatcherFn> {
let url = url.as_ref();
for (supports_fn, matcher_fn) in &self.matchers {
let supports_function = supports_fn
.read()
.map_err(|error| PoisonedLock(error.to_string()))?;
let supports_function = supports_fn.read()?;
if supports_function(url)? {
let matcher_function = matcher_fn
.read()
.map_err(|error| PoisonedLock(error.to_string()))?;
let matcher_function = matcher_fn.read()?;
return Ok(*matcher_function);
}
}
Expand All @@ -79,10 +75,7 @@ impl Default for MatchersRegistry {
/// # Errors
/// * If the registry is poisoned.
pub fn register(supports_fn: SupportsFn, matcher_fn: MatcherFn) -> Result<()> {
let mut registry = REGISTRY
.lock()
.map_err(|error| PoisonedLock(error.to_string()))?;
registry.register(supports_fn, matcher_fn);
REGISTRY.lock()?.register(supports_fn, matcher_fn);
Ok(())
}

Expand All @@ -91,10 +84,7 @@ pub fn register(supports_fn: SupportsFn, matcher_fn: MatcherFn) -> Result<()> {
/// # Errors
/// * If the registry is poisoned.
pub fn get<S: AsRef<str>>(url: S) -> Result<MatcherFn> {
let registry = REGISTRY
.lock()
.map_err(|error| PoisonedLock(error.to_string()))?;
registry.get(url)
REGISTRY.lock()?.get(url)
}

#[cfg(test)]
Expand Down
5 changes: 2 additions & 3 deletions postgresql_archive/src/repository/maven/repository.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::Error::{ArchiveHashMismatch, ParseError, RepositoryFailure, VersionNotFound};
use crate::Error::{ArchiveHashMismatch, RepositoryFailure, VersionNotFound};
use crate::repository::Archive;
use crate::repository::maven::models::Metadata;
use crate::repository::model::Repository;
Expand Down Expand Up @@ -60,8 +60,7 @@ impl Maven {
let request = client.get(&url).headers(Self::headers());
let response = request.send().await?.error_for_status()?;
let text = response.text().await?;
let metadata: Metadata =
quick_xml::de::from_str(&text).map_err(|error| ParseError(error.to_string()))?;
let metadata: Metadata = quick_xml::de::from_str(&text)?;
let artifact = metadata.artifact_id;
let mut result = None;
for version in &metadata.versioning.versions.version {
Expand Down
20 changes: 5 additions & 15 deletions postgresql_archive/src/repository/registry.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::Error::{PoisonedLock, UnsupportedRepository};
use crate::Error::UnsupportedRepository;
use crate::Result;
#[cfg(feature = "theseus")]
use crate::configuration::theseus;
Expand Down Expand Up @@ -46,13 +46,9 @@ impl RepositoryRegistry {
/// * If the URL is not supported.
fn get(&self, url: &str) -> Result<Box<dyn Repository>> {
for (supports_fn, new_fn) in &self.repositories {
let supports_function = supports_fn
.read()
.map_err(|error| PoisonedLock(error.to_string()))?;
let supports_function = supports_fn.read()?;
if supports_function(url)? {
let new_function = new_fn
.read()
.map_err(|error| PoisonedLock(error.to_string()))?;
let new_function = new_fn.read()?;
return new_function(url);
}
}
Expand Down Expand Up @@ -84,10 +80,7 @@ impl Default for RepositoryRegistry {
/// # Errors
/// * If the registry is poisoned.
pub fn register(supports_fn: SupportsFn, new_fn: Box<NewFn>) -> Result<()> {
let mut registry = REGISTRY
.lock()
.map_err(|error| PoisonedLock(error.to_string()))?;
registry.register(supports_fn, new_fn);
REGISTRY.lock()?.register(supports_fn, new_fn);
Ok(())
}

Expand All @@ -96,10 +89,7 @@ pub fn register(supports_fn: SupportsFn, new_fn: Box<NewFn>) -> Result<()> {
/// # Errors
/// * If the URL is not supported.
pub fn get(url: &str) -> Result<Box<dyn Repository>> {
let registry = REGISTRY
.lock()
.map_err(|error| PoisonedLock(error.to_string()))?;
registry.get(url)
REGISTRY.lock()?.get(url)
}

#[cfg(test)]
Expand Down
21 changes: 21 additions & 0 deletions postgresql_extensions/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::sync::PoisonError;

/// PostgreSQL extensions result type
pub type Result<T, E = Error> = core::result::Result<T, E>;

Expand Down Expand Up @@ -29,3 +31,22 @@ pub enum Error {
#[error("unsupported namespace '{0}'")]
UnsupportedNamespace(String),
}

/// Converts a [`std::sync::PoisonError<T>`] into a [`ParseError`](Error::PoisonedLock)
impl<T> From<PoisonError<T>> for Error {
fn from(value: PoisonError<T>) -> Self {
Error::PoisonedLock(value.to_string())
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_from_poison_error() {
let error = Error::from(std::sync::PoisonError::new(()));
assert!(matches!(error, Error::PoisonedLock(_)));
assert!(error.to_string().contains("poisoned lock"));
}
}
21 changes: 5 additions & 16 deletions postgresql_extensions/src/repository/registry.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::Error::{PoisonedLock, UnsupportedNamespace};
use crate::Error::UnsupportedNamespace;
use crate::Result;
use crate::repository::model::Repository;
#[cfg(feature = "portal-corp")]
Expand Down Expand Up @@ -44,9 +44,7 @@ impl RepositoryRegistry {
let Some(new_fn) = self.repositories.get(&namespace) else {
return Err(UnsupportedNamespace(namespace.to_string()));
};
let new_function = new_fn
.read()
.map_err(|error| PoisonedLock(error.to_string()))?;
let new_function = new_fn.read()?;
new_function()
}
}
Expand Down Expand Up @@ -79,10 +77,7 @@ impl Default for RepositoryRegistry {
/// # Errors
/// * If the registry is poisoned.
pub fn register(namespace: &str, new_fn: Box<NewFn>) -> Result<()> {
let mut registry = REGISTRY
.lock()
.map_err(|error| PoisonedLock(error.to_string()))?;
registry.register(namespace, new_fn);
REGISTRY.lock()?.register(namespace, new_fn);
Ok(())
}

Expand All @@ -91,21 +86,15 @@ pub fn register(namespace: &str, new_fn: Box<NewFn>) -> Result<()> {
/// # Errors
/// * If the namespace is not supported.
pub fn get(namespace: &str) -> Result<Box<dyn Repository>> {
let registry = REGISTRY
.lock()
.map_err(|error| PoisonedLock(error.to_string()))?;
registry.get(namespace)
REGISTRY.lock()?.get(namespace)
}

/// Gets the namespaces of the registered repositories.
///
/// # Errors
/// * If the registry is poisoned.
pub fn get_namespaces() -> Result<Vec<String>> {
let registry = REGISTRY
.lock()
.map_err(|error| PoisonedLock(error.to_string()))?;
Ok(registry.repositories.keys().cloned().collect())
Ok(REGISTRY.lock()?.repositories.keys().cloned().collect())
}

/// Gets all the registered repositories.
Expand Down
Loading