@@ -15,13 +15,11 @@ use postgresql_commands::CommandBuilder;
1515use postgresql_commands:: CommandExecutor ;
1616use semver:: Version ;
1717use sqlx:: { PgPool , Row } ;
18- use std:: ffi:: OsStr ;
19- use std:: fs:: { remove_dir_all, remove_file} ;
18+ use std:: fs:: { read_dir, remove_dir_all, remove_file} ;
2019use std:: io:: prelude:: * ;
2120use std:: net:: TcpListener ;
2221use std:: path:: PathBuf ;
2322use tracing:: { debug, instrument} ;
24- use walkdir:: WalkDir ;
2523
2624use crate :: Error :: { CreateDatabaseError , DatabaseExistsError , DropDatabaseError } ;
2725
@@ -95,48 +93,43 @@ impl PostgreSQL {
9593 /// If it doesn't, it will search all the child directories for the latest version that matches the requirement.
9694 /// If it returns None, we couldn't find a matching installation.
9795 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- }
10196 let path = & self . settings . installation_dir ;
10297 let maybe_path_version = path
10398 . file_name ( )
104- . map ( |name| file_name_to_version ( name) )
105- . flatten ( ) ;
99+ . and_then ( |file_name| Version :: parse ( & file_name. to_string_lossy ( ) ) . ok ( ) ) ;
106100 // If this directory matches the version requirement, we're done.
107101 if let Some ( path_version) = maybe_path_version {
108102 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 ;
103+ return Some ( path. clone ( ) ) ;
123104 }
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 ( ) ) ;
138105 }
139- max_path
106+
107+ // Get all directories in the path as versions.
108+ let mut versions = read_dir ( path)
109+ . ok ( ) ?
110+ . filter_map ( |entry| {
111+ let Some ( entry) = entry. ok ( ) else {
112+ // We ignore filesystem errors.
113+ return None ;
114+ } ;
115+ // Skip non-directories
116+ if !entry. file_type ( ) . ok ( ) ?. is_dir ( ) {
117+ return None ;
118+ }
119+ let file_name = entry. file_name ( ) ;
120+ let version = Version :: parse ( & file_name. to_string_lossy ( ) ) . ok ( ) ?;
121+ if self . settings . version . matches ( & version) {
122+ Some ( ( version, entry. path ( ) ) )
123+ } else {
124+ None
125+ }
126+ } )
127+ . collect :: < Vec < _ > > ( ) ;
128+ // Sort the versions in descending order i.e. latest version first
129+ versions. sort_by ( |( a, _) , ( b, _) | b. cmp ( a) ) ;
130+ // Get the first matching version as the best match
131+ let version_path = versions. first ( ) . map ( |( _, path) | path. clone ( ) ) ;
132+ version_path
140133 }
141134
142135 /// Check if the `PostgreSQL` server is initialized
0 commit comments