Skip to content

Commit 5554dc6

Browse files
Merge pull request #80 from theseus-rs/configurable-releases-url
feat!: allow releases URL to be configured
2 parents 62186d8 + 0300aeb commit 5554dc6

File tree

16 files changed

+299
-261
lines changed

16 files changed

+299
-261
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ PostgreSQL is covered under [The PostgreSQL License](https://opensource.org/lice
6969

7070
## Notes
7171

72-
Uses PostgreSQL binaries from [theseus-rs/postgresql-binaries](https://github.com/theseus-rs/postgresql_binaries).
72+
Uses PostgreSQL binaries from [theseus-rs/postgresql-binaries](https://github.com/theseus-rs/postgresql_binaries) by
73+
default.
7374

7475
## Contribution
7576

examples/archive_async/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#![forbid(unsafe_code)]
22
#![deny(clippy::pedantic)]
33

4-
use postgresql_archive::{extract, get_archive, Result, LATEST};
4+
use postgresql_archive::{extract, get_archive, Result, DEFAULT_RELEASES_URL, LATEST};
55

66
#[tokio::main]
77
async fn main() -> Result<()> {
8-
let (archive_version, archive) = get_archive(&LATEST).await?;
8+
let (archive_version, archive) = get_archive(DEFAULT_RELEASES_URL, &LATEST).await?;
99
let out_dir = tempfile::tempdir()?.into_path();
1010
extract(&archive, &out_dir).await?;
1111
println!(

examples/archive_sync/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
#![deny(clippy::pedantic)]
33

44
use postgresql_archive::blocking::{extract, get_archive};
5-
use postgresql_archive::{Result, LATEST};
5+
use postgresql_archive::{Result, DEFAULT_RELEASES_URL, LATEST};
66

77
fn main() -> Result<()> {
8-
let (archive_version, archive) = get_archive(&LATEST)?;
8+
let (archive_version, archive) = get_archive(DEFAULT_RELEASES_URL, &LATEST)?;
99
let out_dir = tempfile::tempdir()?.into_path();
1010
extract(&archive, &out_dir)?;
1111
println!(

postgresql_archive/benches/archive.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use bytes::Bytes;
22
use criterion::{criterion_group, criterion_main, Criterion};
33
use postgresql_archive::blocking::{extract, get_archive};
4-
use postgresql_archive::{Result, LATEST};
4+
use postgresql_archive::{Result, DEFAULT_RELEASES_URL, LATEST};
55
use std::fs::{create_dir_all, remove_dir_all};
66
use std::time::Duration;
77

@@ -11,7 +11,7 @@ fn benchmarks(criterion: &mut Criterion) {
1111

1212
fn bench_extract(criterion: &mut Criterion) -> Result<()> {
1313
let version = &LATEST;
14-
let (_archive_version, archive) = get_archive(version)?;
14+
let (_archive_version, archive) = get_archive(DEFAULT_RELEASES_URL, version)?;
1515

1616
criterion.bench_function("extract", |bencher| {
1717
bencher.iter(|| {

postgresql_archive/src/archive.rs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ use tracing::{debug, instrument, warn};
2929

3030
const GITHUB_API_VERSION_HEADER: &str = "X-GitHub-Api-Version";
3131
const GITHUB_API_VERSION: &str = "2022-11-28";
32+
pub const DEFAULT_RELEASES_URL: &str =
33+
"https://api.github.com/repos/theseus-rs/postgresql-binaries/releases";
3234

3335
lazy_static! {
3436
static ref GITHUB_TOKEN: Option<String> = match std::env::var("GITHUB_TOKEN") {
@@ -103,14 +105,13 @@ fn reqwest_client() -> ClientWithMiddleware {
103105
/// Gets a release from GitHub for a given [version](Version) of PostgreSQL. If a release for the
104106
/// [version](Version) is not found, then a [ReleaseNotFound] error is returned.
105107
#[instrument(level = "debug")]
106-
async fn get_release(version: &Version) -> Result<Release> {
107-
let url = "https://api.github.com/repos/theseus-rs/postgresql-binaries/releases";
108+
async fn get_release(releases_url: &str, version: &Version) -> Result<Release> {
108109
let client = reqwest_client();
109110

110111
debug!("Attempting to locate release for version {version}");
111112

112113
if version.minor.is_some() && version.release.is_some() {
113-
let request = client.get(format!("{url}/tags/{version}"));
114+
let request = client.get(format!("{releases_url}/tags/{version}"));
114115
let response = request.send().await?.error_for_status()?;
115116
let release = response.json::<Release>().await?;
116117

@@ -123,7 +124,7 @@ async fn get_release(version: &Version) -> Result<Release> {
123124

124125
loop {
125126
let request = client
126-
.get(url)
127+
.get(releases_url)
127128
.query(&[("page", page.to_string().as_str()), ("per_page", "100")]);
128129
let response = request.send().await?.error_for_status()?;
129130
let response_releases = response.json::<Vec<Release>>().await?;
@@ -169,8 +170,8 @@ async fn get_release(version: &Version) -> Result<Release> {
169170
/// specified, then the latest version is returned. If a release for the [version](Version) is not found, then a
170171
/// [ReleaseNotFound] error is returned.
171172
#[instrument(level = "debug")]
172-
pub async fn get_version(version: &Version) -> Result<Version> {
173-
let release = get_release(version).await?;
173+
pub async fn get_version(releases_url: &str, version: &Version) -> Result<Version> {
174+
let release = get_release(releases_url, version).await?;
174175
Version::from_str(&release.tag_name)
175176
}
176177

@@ -181,8 +182,12 @@ pub async fn get_version(version: &Version) -> Result<Version> {
181182
///
182183
/// Two assets are returned. The first [asset](Asset) is the archive, and the second [asset](Asset) is the archive hash.
183184
#[instrument(level = "debug", skip(target))]
184-
async fn get_asset<S: AsRef<str>>(version: &Version, target: S) -> Result<(Version, Asset, Asset)> {
185-
let release = get_release(version).await?;
185+
async fn get_asset<S: AsRef<str>>(
186+
releases_url: &str,
187+
version: &Version,
188+
target: S,
189+
) -> Result<(Version, Asset, Asset)> {
190+
let release = get_release(releases_url, version).await?;
186191
let asset_version = Version::from_str(&release.tag_name)?;
187192
let mut asset: Option<Asset> = None;
188193
let mut asset_hash: Option<Asset> = None;
@@ -213,8 +218,8 @@ async fn get_asset<S: AsRef<str>>(version: &Version, target: S) -> Result<(Versi
213218
///
214219
/// Returns the archive version and bytes.
215220
#[instrument]
216-
pub async fn get_archive(version: &Version) -> Result<(Version, Bytes)> {
217-
get_archive_for_target(version, target_triple::TARGET).await
221+
pub async fn get_archive(releases_url: &str, version: &Version) -> Result<(Version, Bytes)> {
222+
get_archive_for_target(releases_url, version, target_triple::TARGET).await
218223
}
219224

220225
/// Gets the archive for a given [version](Version) of PostgreSQL and
@@ -226,10 +231,11 @@ pub async fn get_archive(version: &Version) -> Result<(Version, Bytes)> {
226231
#[allow(clippy::cast_precision_loss)]
227232
#[instrument(level = "debug", skip(target))]
228233
pub async fn get_archive_for_target<S: AsRef<str>>(
234+
releases_url: &str,
229235
version: &Version,
230236
target: S,
231237
) -> Result<(Version, Bytes)> {
232-
let (asset_version, asset, asset_hash) = get_asset(version, target).await?;
238+
let (asset_version, asset, asset_hash) = get_asset(releases_url, version, target).await?;
233239

234240
debug!(
235241
"Downloading archive hash {}",
@@ -436,21 +442,22 @@ mod tests {
436442

437443
#[test(tokio::test)]
438444
async fn test_get_release() -> Result<()> {
439-
let _ = get_release(&VERSION).await?;
445+
let _ = get_release(DEFAULT_RELEASES_URL, &VERSION).await?;
440446
Ok(())
441447
}
442448

443449
#[test(tokio::test)]
444450
async fn test_get_release_version_not_found() -> Result<()> {
445-
let release = get_release(&INVALID_VERSION).await;
451+
let release = get_release(DEFAULT_RELEASES_URL, &INVALID_VERSION).await;
446452
assert!(release.is_err());
447453
Ok(())
448454
}
449455

450456
#[test(tokio::test)]
451457
async fn test_get_asset() -> Result<()> {
452458
let target_triple = "x86_64-unknown-linux-musl".to_string();
453-
let (asset_version, asset, asset_hash) = get_asset(&VERSION, &target_triple).await?;
459+
let (asset_version, asset, asset_hash) =
460+
get_asset(DEFAULT_RELEASES_URL, &VERSION, &target_triple).await?;
454461
assert!(asset_version.matches(&VERSION));
455462
assert!(asset.name.contains(&target_triple));
456463
assert!(asset_hash.name.contains(&target_triple));
@@ -462,15 +469,15 @@ mod tests {
462469
#[test(tokio::test)]
463470
async fn test_get_asset_version_not_found() -> Result<()> {
464471
let target_triple = "x86_64-unknown-linux-musl".to_string();
465-
let result = get_asset(&INVALID_VERSION, &target_triple).await;
472+
let result = get_asset(DEFAULT_RELEASES_URL, &INVALID_VERSION, &target_triple).await;
466473
assert!(result.is_err());
467474
Ok(())
468475
}
469476

470477
#[test(tokio::test)]
471478
async fn test_get_asset_target_not_found() -> Result<()> {
472479
let target_triple = "wasm64-unknown-unknown".to_string();
473-
let result = get_asset(&VERSION, &target_triple).await;
480+
let result = get_asset(DEFAULT_RELEASES_URL, &VERSION, &target_triple).await;
474481
assert!(result.is_err());
475482
Ok(())
476483
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
use crate::Version;
2+
use bytes::Bytes;
3+
use std::path::Path;
4+
use tokio::runtime::Runtime;
5+
6+
lazy_static! {
7+
static ref RUNTIME: Runtime = Runtime::new().unwrap();
8+
}
9+
10+
/// Gets the version of PostgreSQL for the specified [version](Version). If the version minor or release is not
11+
/// specified, then the latest version is returned. If a release for the [version](Version) is not found, then a
12+
/// [ReleaseNotFound](crate::Error::ReleaseNotFound) error is returned.
13+
///
14+
/// # Errors
15+
///
16+
/// Returns an error if the version is not found.
17+
pub fn get_version(releases_url: &str, version: &Version) -> crate::Result<Version> {
18+
RUNTIME
19+
.handle()
20+
.block_on(async move { crate::get_version(releases_url, version).await })
21+
}
22+
23+
/// Gets the archive for a given [version](Version) of PostgreSQL for the current target.
24+
/// If the [version](Version) is not found for this target, then an
25+
/// [error](crate::Error) is returned.
26+
///
27+
/// Returns the archive version and bytes.
28+
///
29+
/// # Errors
30+
///
31+
/// Returns an error if the version is not found.
32+
pub fn get_archive(releases_url: &str, version: &Version) -> crate::Result<(Version, Bytes)> {
33+
RUNTIME
34+
.handle()
35+
.block_on(async move { crate::get_archive(releases_url, version).await })
36+
}
37+
38+
/// Gets the archive for a given [version](Version) of PostgreSQL and
39+
/// [target](https://doc.rust-lang.org/nightly/rustc/platform-support.html).
40+
/// If the [version](Version) or [target](https://doc.rust-lang.org/nightly/rustc/platform-support.html)
41+
/// is not found, then an [error](crate::error::Error) is returned.
42+
///
43+
/// Returns the archive version and bytes.
44+
///
45+
/// # Errors
46+
///
47+
/// Returns an error if the version or target is not found.
48+
pub fn get_archive_for_target<S: AsRef<str>>(
49+
releases_url: &str,
50+
version: &Version,
51+
target: S,
52+
) -> crate::Result<(Version, Bytes)> {
53+
RUNTIME
54+
.handle()
55+
.block_on(async move { crate::get_archive_for_target(releases_url, version, target).await })
56+
}
57+
58+
/// Extracts the compressed tar [bytes](Bytes) to the [out_dir](Path).
59+
///
60+
/// # Errors
61+
///
62+
/// Returns an error if the extraction fails.
63+
pub fn extract(bytes: &Bytes, out_dir: &Path) -> crate::Result<()> {
64+
RUNTIME
65+
.handle()
66+
.block_on(async move { crate::extract(bytes, out_dir).await })
67+
}
Lines changed: 2 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,3 @@
1-
use crate::Version;
2-
use bytes::Bytes;
3-
use std::path::Path;
4-
use tokio::runtime::Runtime;
1+
mod archive;
52

6-
lazy_static! {
7-
static ref RUNTIME: Runtime = Runtime::new().unwrap();
8-
}
9-
10-
/// Gets the version of PostgreSQL for the specified [version](Version). If the version minor or release is not
11-
/// specified, then the latest version is returned. If a release for the [version](Version) is not found, then a
12-
/// [ReleaseNotFound](crate::Error::ReleaseNotFound) error is returned.
13-
///
14-
/// # Errors
15-
///
16-
/// Returns an error if the version is not found.
17-
pub fn get_version(version: &Version) -> crate::Result<Version> {
18-
RUNTIME
19-
.handle()
20-
.block_on(async move { crate::get_version(version).await })
21-
}
22-
23-
/// Gets the archive for a given [version](Version) of PostgreSQL for the current target.
24-
/// If the [version](Version) is not found for this target, then an
25-
/// [error](crate::Error) is returned.
26-
///
27-
/// Returns the archive version and bytes.
28-
///
29-
/// # Errors
30-
///
31-
/// Returns an error if the version is not found.
32-
pub fn get_archive(version: &Version) -> crate::Result<(Version, Bytes)> {
33-
RUNTIME
34-
.handle()
35-
.block_on(async move { crate::get_archive(version).await })
36-
}
37-
38-
/// Gets the archive for a given [version](Version) of PostgreSQL and
39-
/// [target](https://doc.rust-lang.org/nightly/rustc/platform-support.html).
40-
/// If the [version](Version) or [target](https://doc.rust-lang.org/nightly/rustc/platform-support.html)
41-
/// is not found, then an [error](crate::error::Error) is returned.
42-
///
43-
/// Returns the archive version and bytes.
44-
///
45-
/// # Errors
46-
///
47-
/// Returns an error if the version or target is not found.
48-
pub fn get_archive_for_target<S: AsRef<str>>(
49-
version: &Version,
50-
target: S,
51-
) -> crate::Result<(Version, Bytes)> {
52-
RUNTIME
53-
.handle()
54-
.block_on(async move { crate::get_archive_for_target(version, target).await })
55-
}
56-
57-
/// Extracts the compressed tar [bytes](Bytes) to the [out_dir](Path).
58-
///
59-
/// # Errors
60-
///
61-
/// Returns an error if the extraction fails.
62-
pub fn extract(bytes: &Bytes, out_dir: &Path) -> crate::Result<()> {
63-
RUNTIME
64-
.handle()
65-
.block_on(async move { crate::extract(bytes, out_dir).await })
66-
}
3+
pub use archive::{extract, get_archive, get_archive_for_target, get_version};

postgresql_archive/src/lib.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121
//! ### Asynchronous API
2222
//!
2323
//! ```no_run
24-
//! use postgresql_archive::{extract, get_archive, Result, LATEST};
24+
//! use postgresql_archive::{extract, get_archive, Result, DEFAULT_RELEASES_URL, LATEST};
2525
//!
2626
//! #[tokio::main]
2727
//! async fn main() -> Result<()> {
28-
//! let (archive_version, archive) = get_archive(&LATEST).await?;
28+
//! let (archive_version, archive) = get_archive(DEFAULT_RELEASES_URL, &LATEST).await?;
2929
//! let out_dir = std::env::temp_dir();
3030
//! extract(&archive, &out_dir).await
3131
//! }
@@ -34,10 +34,10 @@
3434
//! ### Synchronous API
3535
//! ```no_run
3636
//! #[cfg(feature = "blocking")] {
37-
//! use postgresql_archive::LATEST;
37+
//! use postgresql_archive::{DEFAULT_RELEASES_URL, LATEST};
3838
//! use postgresql_archive::blocking::{extract, get_archive};
3939
//!
40-
//! let (archive_version, archive) = get_archive(&LATEST).unwrap();
40+
//! let (archive_version, archive) = get_archive(DEFAULT_RELEASES_URL, &LATEST).unwrap();
4141
//! let out_dir = std::env::temp_dir();
4242
//! let result = extract(&archive, &out_dir).unwrap();
4343
//! }
@@ -106,6 +106,7 @@
106106
#![forbid(unsafe_code)]
107107
#![deny(clippy::pedantic)]
108108
#![allow(clippy::doc_markdown)]
109+
#![allow(clippy::module_name_repetitions)]
109110

110111
#[macro_use]
111112
extern crate lazy_static;
@@ -117,6 +118,7 @@ mod error;
117118
mod github;
118119
mod version;
119120

121+
pub use archive::DEFAULT_RELEASES_URL;
120122
pub use archive::{extract, get_archive, get_archive_for_target, get_version};
121123
pub use error::{Error, Result};
122124
#[allow(deprecated)]

0 commit comments

Comments
 (0)