Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3c4bff0

Browse filesBrowse files
committed
Check for existing installations in children before installing.
1 parent fef1ee9 commit 3c4bff0
Copy full SHA for 3c4bff0

File tree

Expand file treeCollapse file tree

3 files changed

+60
-10
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+60
-10
lines changed

‎Cargo.lock

Copy file name to clipboardExpand all lines: Cargo.lock
+1Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎postgresql_embedded/Cargo.toml

Copy file name to clipboardExpand all lines: postgresql_embedded/Cargo.toml
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ thiserror = { workspace = true }
3030
tokio = { workspace = true, features = ["full"], optional = true }
3131
tracing = { workspace = true, features = ["log"] }
3232
url = { workspace = true }
33+
walkdir = "2.5.0"
3334

3435
[dev-dependencies]
3536
anyhow = { workspace = true }

‎postgresql_embedded/src/postgresql.rs

Copy file name to clipboardExpand all lines: postgresql_embedded/src/postgresql.rs
+58-10Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,15 @@ use postgresql_commands::AsyncCommandExecutor;
1313
use postgresql_commands::CommandBuilder;
1414
#[cfg(not(feature = "tokio"))]
1515
use postgresql_commands::CommandExecutor;
16+
use semver::Version;
1617
use sqlx::{PgPool, Row};
18+
use std::ffi::OsStr;
1719
use std::fs::{remove_dir_all, remove_file};
1820
use std::io::prelude::*;
1921
use std::net::TcpListener;
22+
use std::path::PathBuf;
2023
use tracing::{debug, instrument};
24+
use walkdir::WalkDir;
2125

2226
use crate::Error::{CreateDatabaseError, DatabaseExistsError, DropDatabaseError};
2327

@@ -73,7 +77,7 @@ impl PostgreSQL {
7377
Status::Started
7478
} else if self.is_initialized() {
7579
Status::Stopped
76-
} else if self.is_installed() {
80+
} else if self.installed_dir().is_some() {
7781
Status::Installed
7882
} else {
7983
Status::NotInstalled
@@ -86,13 +90,53 @@ impl PostgreSQL {
8690
&self.settings
8791
}
8892

89-
/// Check if the `PostgreSQL` server is installed
90-
fn is_installed(&self) -> bool {
91-
let Some(version) = self.settings.version.exact_version() else {
92-
return false;
93-
};
93+
/// Find a directory where `PostgreSQL` server is installed.
94+
/// This first checks if the installation directory exists and matches the version requirement.
95+
/// If it doesn't, it will search all the child directories for the latest version that matches the requirement.
96+
/// If it returns None, we couldn't find a matching installation.
97+
fn installed_dir(&self) -> Option<PathBuf> {
98+
fn file_name_to_version(name: &OsStr) -> Option<Version> {
99+
Version::parse(name.to_string_lossy().as_ref()).ok()
100+
}
94101
let path = &self.settings.installation_dir;
95-
path.ends_with(version.to_string()) && path.exists()
102+
let maybe_path_version = path
103+
.file_name()
104+
.map(|name| file_name_to_version(name))
105+
.flatten();
106+
// If this directory matches the version requirement, we're done.
107+
if let Some(path_version) = maybe_path_version {
108+
if self.settings.version.matches(&path_version) && path.exists() {
109+
return Some(path.to_path_buf());
110+
}
111+
}
112+
// Otherwise we check the child directories.
113+
let mut max_version: Option<Version> = None;
114+
let mut max_path: Option<PathBuf> = None;
115+
for entry in WalkDir::new(path).min_depth(1).max_depth(1) {
116+
let Some(entry) = entry.ok() else {
117+
// We ignore filesystem errors.
118+
continue;
119+
};
120+
// Skip non-directories
121+
if !entry.file_type().is_dir() {
122+
continue;
123+
}
124+
// If it doesn't look like a version, we ignore it.
125+
let Some(version) = file_name_to_version(entry.file_name()) else {
126+
continue;
127+
};
128+
// If it doesn't match the version requirement, we ignore it.
129+
if !self.settings.version.matches(&version) {
130+
continue;
131+
}
132+
// If we already found a version that's greater or equal, we ignore it.
133+
if max_version.iter().any(|prev_max| *prev_max >= version) {
134+
continue;
135+
}
136+
max_version = Some(version.clone());
137+
max_path = Some(entry.path().to_path_buf());
138+
}
139+
max_path
96140
}
97141

98142
/// Check if the `PostgreSQL` server is initialized
@@ -111,10 +155,14 @@ impl PostgreSQL {
111155
/// If the data directory already exists, the database will not be initialized.
112156
#[instrument(skip(self))]
113157
pub async fn setup(&mut self) -> Result<()> {
114-
if !self.is_installed() {
115-
self.install().await?;
158+
match self.installed_dir() {
159+
Some(installed_dir) => {
160+
self.settings.installation_dir = installed_dir;
161+
}
162+
None => {
163+
self.install().await?;
164+
}
116165
}
117-
118166
if !self.is_initialized() {
119167
self.initialize().await?;
120168
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.