@@ -6,8 +6,7 @@ mod sysroot;
66
77use std:: {
88 error:: Error ,
9- fs:: File ,
10- fs:: read_dir,
9+ fs:: { read_dir, File , ReadDir } ,
1110 io:: BufReader ,
1211 path:: { Path , PathBuf } ,
1312 process:: Command ,
@@ -26,15 +25,35 @@ pub use crate::{
2625} ;
2726
2827#[ derive( Clone , PartialEq , Eq , Hash , Debug ) ]
29- pub struct CargoTomlNotFoundError ( pub PathBuf ) ;
28+ pub struct CargoTomlNoneFoundError ( pub PathBuf ) ;
3029
31- impl std:: fmt:: Display for CargoTomlNotFoundError {
30+ #[ derive( Clone , PartialEq , Eq , Hash , Debug ) ]
31+ pub struct CargoTomlMultipleValidFoundError ( pub Vec < PathBuf > ) ;
32+
33+ #[ derive( Clone , PartialEq , Eq , Hash , Debug ) ]
34+ pub struct CargoTomlSearchFileSystemError ( pub PathBuf , pub String ) ;
35+
36+ impl std:: fmt:: Display for CargoTomlNoneFoundError {
3237 fn fmt ( & self , fmt : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
3338 write ! ( fmt, "can't find Cargo.toml at {}" , self . 0 . display( ) )
3439 }
3540}
3641
37- impl Error for CargoTomlNotFoundError { }
42+ impl std:: fmt:: Display for CargoTomlMultipleValidFoundError {
43+ fn fmt ( & self , fmt : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
44+ write ! ( fmt, "found multiple valid Cargo.toml files {:?}" , self . 0 )
45+ }
46+ }
47+
48+ impl std:: fmt:: Display for CargoTomlSearchFileSystemError {
49+ fn fmt ( & self , fmt : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
50+ write ! ( fmt, "a filesystem error occurred while searching for Cargo.toml: {}" , self . 1 )
51+ }
52+ }
53+
54+ impl Error for CargoTomlNoneFoundError { }
55+ impl Error for CargoTomlMultipleValidFoundError { }
56+ impl Error for CargoTomlSearchFileSystemError { }
3857
3958#[ derive( Debug , Clone ) ]
4059pub enum ProjectWorkspace {
@@ -407,7 +426,7 @@ fn find_rust_project_json(path: &Path) -> Option<PathBuf> {
407426 None
408427}
409428
410- fn find_cargo_toml_down_the_fs ( path : & Path ) -> Option < PathBuf > {
429+ fn find_cargo_toml_in_parent_dir ( path : & Path ) -> Option < PathBuf > {
411430 let mut curr = Some ( path) ;
412431 while let Some ( path) = curr {
413432 let candidate = path. join ( "Cargo.toml" ) ;
@@ -416,41 +435,48 @@ fn find_cargo_toml_down_the_fs(path: &Path) -> Option<PathBuf> {
416435 }
417436 curr = path. parent ( ) ;
418437 }
419-
438+
420439 None
421440}
422441
423- fn find_cargo_toml_up_the_fs ( path : & Path ) -> Option < PathBuf > {
424- let entities = match read_dir ( path) {
425- Ok ( entities) => entities,
426- Err ( _) => return None
427- } ;
428-
429- // Only one level up to avoid cycles the easy way and stop a runaway scan with large projects
442+ fn find_cargo_toml_in_child_dir ( entities : ReadDir ) -> Vec < PathBuf > {
443+ // Only one level down to avoid cycles the easy way and stop a runaway scan with large projects
444+ let mut valid_canditates = vec ! [ ] ;
430445 for entity in entities. filter_map ( Result :: ok) {
431446 let candidate = entity. path ( ) . join ( "Cargo.toml" ) ;
432447 if candidate. exists ( ) {
433- return Some ( candidate) ;
448+ valid_canditates . push ( candidate)
434449 }
435450 }
436-
437- None
451+ valid_canditates
438452}
439453
440454fn find_cargo_toml ( path : & Path ) -> Result < PathBuf > {
455+ let path_as_buf = path. to_path_buf ( ) ;
456+
441457 if path. ends_with ( "Cargo.toml" ) {
442458 return Ok ( path. to_path_buf ( ) ) ;
443459 }
444460
445- if let Some ( p) = find_cargo_toml_down_the_fs ( path) {
446- return Ok ( p)
461+ if let Some ( p) = find_cargo_toml_in_parent_dir ( path) {
462+ return Ok ( p) ;
447463 }
448464
449- if let Some ( p) = find_cargo_toml_up_the_fs ( path) {
450- return Ok ( p)
451- }
465+ let entities = match read_dir ( path. join ( "does_not_exist" ) ) {
466+ Ok ( entities) => {
467+ entities
468+ } ,
469+ Err ( e) => {
470+ return Err ( CargoTomlSearchFileSystemError ( path_as_buf, e. to_string ( ) ) . into ( ) )
471+ } ,
472+ } ;
452473
453- Err ( CargoTomlNotFoundError ( path. to_path_buf ( ) ) . into ( ) )
474+ let mut valid_canditates = find_cargo_toml_in_child_dir ( entities) ;
475+ match valid_canditates. len ( ) {
476+ 1 => Ok ( valid_canditates. remove ( 0 ) ) ,
477+ 0 => Err ( CargoTomlNoneFoundError ( path_as_buf) . into ( ) ) ,
478+ _ => Err ( CargoTomlMultipleValidFoundError ( valid_canditates) . into ( ) ) ,
479+ }
454480}
455481
456482pub fn get_rustc_cfg_options ( ) -> CfgOptions {
0 commit comments