Skip to content

Commit 0ef2c97

Browse files
Merge pull request #82 from theseus-rs/refactor-version
refactor!: move version from PostgreSQL::new() to Settings
2 parents 4055763 + 589596b commit 0ef2c97

File tree

5 files changed

+90
-88
lines changed

5 files changed

+90
-88
lines changed

postgresql_embedded/src/blocking/postgresql.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate::{Result, Settings, Status};
22
use lazy_static::lazy_static;
3-
use postgresql_archive::Version;
43
use tokio::runtime::Runtime;
54

65
lazy_static! {
@@ -17,9 +16,9 @@ pub struct PostgreSQL {
1716
impl PostgreSQL {
1817
/// Create a new [`crate::postgresql::PostgreSQL`] instance
1918
#[must_use]
20-
pub fn new(version: Version, settings: Settings) -> Self {
19+
pub fn new(settings: Settings) -> Self {
2120
Self {
22-
inner: crate::postgresql::PostgreSQL::new(version, settings),
21+
inner: crate::postgresql::PostgreSQL::new(settings),
2322
}
2423
}
2524

@@ -29,12 +28,6 @@ impl PostgreSQL {
2928
self.inner.status()
3029
}
3130

32-
/// Get the [version](Version) of the `PostgreSQL` server
33-
#[must_use]
34-
pub fn version(&self) -> &Version {
35-
self.inner.version()
36-
}
37-
3831
/// Get the [settings](Settings) of the `PostgreSQL` server
3932
#[must_use]
4033
pub fn settings(&self) -> &Settings {
@@ -123,13 +116,17 @@ impl PostgreSQL {
123116
#[cfg(test)]
124117
mod test {
125118
use super::*;
119+
use postgresql_archive::Version;
126120

127121
#[test]
128122
fn test_postgresql() {
129-
let version = Version::new(16, Some(2), Some(0));
130-
let postgresql = PostgreSQL::new(version, Settings::default());
123+
let version = Version::new(16, Some(3), Some(0));
124+
let settings = Settings {
125+
version,
126+
..Settings::default()
127+
};
128+
let postgresql = PostgreSQL::new(settings);
131129
let initial_statuses = [Status::NotInstalled, Status::Installed, Status::Stopped];
132130
assert!(initial_statuses.contains(&postgresql.status()));
133-
assert_eq!(postgresql.version(), &version);
134131
}
135132
}

postgresql_embedded/src/postgresql.rs

Lines changed: 26 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::error::Error::{DatabaseInitializationError, DatabaseStartError, DatabaseStopError};
22
use crate::error::Result;
33
use crate::settings::{Settings, BOOTSTRAP_SUPERUSER};
4+
use postgresql_archive::get_version;
45
use postgresql_archive::{extract, get_archive};
5-
use postgresql_archive::{get_version, Version};
66
use postgresql_commands::initdb::InitDbBuilder;
77
use postgresql_commands::pg_ctl::Mode::{Start, Stop};
88
use postgresql_commands::pg_ctl::PgCtlBuilder;
@@ -16,26 +16,10 @@ use postgresql_commands::CommandExecutor;
1616
use std::fs::{remove_dir_all, remove_file};
1717
use std::io::prelude::*;
1818
use std::net::TcpListener;
19-
#[cfg(feature = "bundled")]
20-
use std::str::FromStr;
2119
use tracing::{debug, instrument};
2220

2321
use crate::Error::{CreateDatabaseError, DatabaseExistsError, DropDatabaseError};
2422

25-
#[cfg(feature = "bundled")]
26-
lazy_static::lazy_static! {
27-
#[allow(clippy::unwrap_used)]
28-
pub(crate) static ref ARCHIVE_VERSION: Version = {
29-
let version_string = include_str!(concat!(std::env!("OUT_DIR"), "/postgresql.version"));
30-
let version = Version::from_str(version_string).unwrap();
31-
debug!("Bundled installation archive version {version}");
32-
version
33-
};
34-
}
35-
36-
#[cfg(feature = "bundled")]
37-
pub(crate) const ARCHIVE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/postgresql.tar.gz"));
38-
3923
const PGDATABASE: &str = "PGDATABASE";
4024

4125
/// `PostgreSQL` status
@@ -54,21 +38,21 @@ pub enum Status {
5438
/// `PostgreSQL` server
5539
#[derive(Clone, Debug)]
5640
pub struct PostgreSQL {
57-
version: Version,
5841
settings: Settings,
5942
}
6043

6144
/// `PostgreSQL` server methods
6245
impl PostgreSQL {
6346
/// Create a new [`PostgreSQL`] instance
6447
#[must_use]
65-
pub fn new(version: Version, settings: Settings) -> Self {
66-
let mut postgresql = PostgreSQL { version, settings };
48+
pub fn new(settings: Settings) -> Self {
49+
let mut postgresql = PostgreSQL { settings };
6750

6851
// If the minor and release version are set, append the version to the installation directory
6952
// to avoid conflicts with other versions. This will also facilitate setting the status
7053
// of the server to the correct initial value. If the minor and release version are not set,
7154
// the installation directory will be determined dynamically during the installation process.
55+
let version = postgresql.settings.version;
7256
if version.minor.is_some() && version.release.is_some() {
7357
let path = &postgresql.settings.installation_dir;
7458
let version_string = version.to_string();
@@ -82,20 +66,6 @@ impl PostgreSQL {
8266
postgresql
8367
}
8468

85-
/// Get the default version used if not otherwise specified
86-
#[must_use]
87-
pub fn default_version() -> Version {
88-
#[cfg(feature = "bundled")]
89-
{
90-
*ARCHIVE_VERSION
91-
}
92-
93-
#[cfg(not(feature = "bundled"))]
94-
{
95-
postgresql_archive::LATEST
96-
}
97-
}
98-
9969
/// Get the [status](Status) of the PostgreSQL server
10070
#[instrument(level = "debug", skip(self))]
10171
pub fn status(&self) -> Status {
@@ -110,12 +80,6 @@ impl PostgreSQL {
11080
}
11181
}
11282

113-
/// Get the [version](Version) of the `PostgreSQL` server
114-
#[must_use]
115-
pub fn version(&self) -> &Version {
116-
&self.version
117-
}
118-
11983
/// Get the [settings](Settings) of the `PostgreSQL` server
12084
#[must_use]
12185
pub fn settings(&self) -> &Settings {
@@ -124,12 +88,13 @@ impl PostgreSQL {
12488

12589
/// Check if the `PostgreSQL` server is installed
12690
fn is_installed(&self) -> bool {
127-
if self.version.minor.is_none() || self.version.release.is_none() {
91+
let version = self.settings.version;
92+
if version.minor.is_none() || version.release.is_none() {
12893
return false;
12994
}
13095

13196
let path = &self.settings.installation_dir;
132-
path.ends_with(self.version.to_string()) && path.exists()
97+
path.ends_with(version.to_string()) && path.exists()
13398
}
13499

135100
/// Check if the `PostgreSQL` server is initialized
@@ -166,18 +131,21 @@ impl PostgreSQL {
166131
/// returned.
167132
#[instrument(skip(self))]
168133
async fn install(&mut self) -> Result<()> {
169-
debug!("Starting installation process for version {}", self.version);
134+
debug!(
135+
"Starting installation process for version {}",
136+
self.settings.version
137+
);
170138

171139
// If the minor and release version are not set, determine the latest version and update the
172140
// version and installation directory accordingly. This is an optimization to avoid downloading
173141
// the archive if the latest version is already installed.
174-
if self.version.minor.is_none() || self.version.release.is_none() {
175-
let version = get_version(&self.settings.releases_url, &self.version).await?;
176-
self.version = version;
142+
if self.settings.version.minor.is_none() || self.settings.version.release.is_none() {
143+
self.settings.version =
144+
get_version(&self.settings.releases_url, &self.settings.version).await?;
177145
self.settings.installation_dir = self
178146
.settings
179147
.installation_dir
180-
.join(self.version.to_string());
148+
.join(self.settings.version.to_string());
181149
}
182150

183151
if self.settings.installation_dir.exists() {
@@ -189,22 +157,26 @@ impl PostgreSQL {
189157
// If the requested version is the same as the version of the bundled archive, use the bundled
190158
// archive. This avoids downloading the archive in environments where internet access is
191159
// restricted or undesirable.
192-
let (version, bytes) = if *ARCHIVE_VERSION == self.version {
160+
let (version, bytes) = if *crate::settings::ARCHIVE_VERSION == self.settings.version {
193161
debug!("Using bundled installation archive");
194-
(self.version, bytes::Bytes::copy_from_slice(ARCHIVE))
162+
(
163+
self.settings.version,
164+
bytes::Bytes::copy_from_slice(crate::settings::ARCHIVE),
165+
)
195166
} else {
196-
get_archive(&self.settings.releases_url, &self.version).await?
167+
get_archive(&self.settings.releases_url, &self.settings.version).await?
197168
};
198169

199170
#[cfg(not(feature = "bundled"))]
200-
let (version, bytes) = { get_archive(&self.settings.releases_url, &self.version).await? };
171+
let (version, bytes) =
172+
{ get_archive(&self.settings.releases_url, &self.settings.version).await? };
201173

202-
self.version = version;
174+
self.settings.version = version;
203175
extract(&bytes, &self.settings.installation_dir).await?;
204176

205177
debug!(
206178
"Installed PostgreSQL version {} to {}",
207-
self.version,
179+
self.settings.version,
208180
self.settings.installation_dir.to_string_lossy()
209181
);
210182

@@ -433,9 +405,7 @@ impl PostgreSQL {
433405
/// Default `PostgreSQL` server
434406
impl Default for PostgreSQL {
435407
fn default() -> Self {
436-
let version = PostgreSQL::default_version();
437-
let settings = Settings::default();
438-
Self::new(version, settings)
408+
Self::new(Settings::default())
439409
}
440410
}
441411

@@ -459,12 +429,3 @@ impl Drop for PostgreSQL {
459429
}
460430
}
461431
}
462-
463-
#[cfg(test)]
464-
mod tests {
465-
#[test]
466-
#[cfg(feature = "bundled")]
467-
fn test_archive_version() {
468-
assert!(!super::ARCHIVE_VERSION.to_string().is_empty());
469-
}
470-
}

postgresql_embedded/src/settings.rs

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::error::{Error, Result};
22
use home::home_dir;
3-
use postgresql_archive::DEFAULT_RELEASES_URL;
3+
use postgresql_archive::{Version, DEFAULT_RELEASES_URL};
44
use rand::distributions::Alphanumeric;
55
use rand::Rng;
66
use std::collections::HashMap;
@@ -12,6 +12,20 @@ use std::str::FromStr;
1212
use std::time::Duration;
1313
use url::Url;
1414

15+
#[cfg(feature = "bundled")]
16+
lazy_static::lazy_static! {
17+
#[allow(clippy::unwrap_used)]
18+
pub(crate) static ref ARCHIVE_VERSION: Version = {
19+
let version_string = include_str!(concat!(std::env!("OUT_DIR"), "/postgresql.version"));
20+
let version = Version::from_str(version_string).unwrap();
21+
tracing::debug!("Bundled installation archive version {version}");
22+
version
23+
};
24+
}
25+
26+
#[cfg(feature = "bundled")]
27+
pub(crate) const ARCHIVE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/postgresql.tar.gz"));
28+
1529
/// `PostgreSQL` superuser
1630
pub const BOOTSTRAP_SUPERUSER: &str = "postgres";
1731

@@ -20,6 +34,8 @@ pub const BOOTSTRAP_SUPERUSER: &str = "postgres";
2034
pub struct Settings {
2135
/// URL for the releases location of the `PostgreSQL` installation archives
2236
pub releases_url: String,
37+
/// Version of `PostgreSQL` to install
38+
pub version: Version,
2339
/// `PostgreSQL` installation directory
2440
pub installation_dir: PathBuf,
2541
/// `PostgreSQL` password file
@@ -75,6 +91,7 @@ impl Settings {
7591

7692
Self {
7793
releases_url: DEFAULT_RELEASES_URL.to_string(),
94+
version: default_version(),
7895
installation_dir: home_dir.join(".theseus").join("postgresql"),
7996
password_file,
8097
data_dir,
@@ -128,6 +145,9 @@ impl Settings {
128145
if let Some(releases_url) = query_parameters.get("releases_url") {
129146
settings.releases_url = releases_url.to_string();
130147
}
148+
if let Some(version) = query_parameters.get("version") {
149+
settings.version = Version::from_str(version)?;
150+
}
131151
if let Some(installation_dir) = query_parameters.get("installation_dir") {
132152
if let Ok(path) = PathBuf::from_str(installation_dir) {
133153
settings.installation_dir = path;
@@ -214,11 +234,31 @@ impl Default for Settings {
214234
}
215235
}
216236

237+
/// Get the default version used if not otherwise specified
238+
#[must_use]
239+
fn default_version() -> Version {
240+
#[cfg(feature = "bundled")]
241+
{
242+
*ARCHIVE_VERSION
243+
}
244+
245+
#[cfg(not(feature = "bundled"))]
246+
{
247+
postgresql_archive::LATEST
248+
}
249+
}
250+
217251
#[cfg(test)]
218252
mod tests {
219253
use super::*;
220254
use test_log::test;
221255

256+
#[test]
257+
#[cfg(feature = "bundled")]
258+
fn test_archive_version() {
259+
assert!(!super::ARCHIVE_VERSION.to_string().is_empty());
260+
}
261+
222262
#[test]
223263
fn test_settings_new() {
224264
let settings = Settings::new();
@@ -248,17 +288,19 @@ mod tests {
248288
fn test_settings_from_url() -> Result<()> {
249289
let base_url = "postgresql://postgres:password@localhost:5432/test";
250290
let releases_url = "releases_url=https%3A%2F%2Fgithub.com";
291+
let version = "version=16.3.0";
251292
let installation_dir = "installation_dir=/tmp/postgresql";
252293
let password_file = "password_file=/tmp/.pgpass";
253294
let data_dir = "data_dir=/tmp/data";
254295
let temporary = "temporary=false";
255296
let timeout = "timeout=10";
256297
let configuration = "configuration.max_connections=42";
257-
let url = format!("{base_url}?{releases_url}&{installation_dir}&{password_file}&{data_dir}&{temporary}&{temporary}&{timeout}&{configuration}");
298+
let url = format!("{base_url}?{releases_url}&{version}&{installation_dir}&{password_file}&{data_dir}&{temporary}&{temporary}&{timeout}&{configuration}");
258299

259300
let settings = Settings::from_url(url)?;
260301

261302
assert_eq!("https://github.com", settings.releases_url);
303+
assert_eq!(Version::new(16, Some(3), Some(0)), settings.version);
262304
assert_eq!(PathBuf::from("/tmp/postgresql"), settings.installation_dir);
263305
assert_eq!(PathBuf::from("/tmp/.pgpass"), settings.password_file);
264306
assert_eq!(PathBuf::from("/tmp/data"), settings.data_dir);
@@ -280,6 +322,11 @@ mod tests {
280322
assert!(Settings::from_url("^`~").is_err());
281323
}
282324

325+
#[test]
326+
fn test_settings_from_url_invalid_version() {
327+
assert!(Settings::from_url("postgresql://?version=foo").is_err());
328+
}
329+
283330
#[test]
284331
fn test_settings_from_url_invalid_timeout() {
285332
assert!(Settings::from_url("postgresql://?timeout=foo").is_err());

0 commit comments

Comments
 (0)