@@ -22,7 +22,7 @@ use rustfmt::config::{Config, WriteMode};
22
22
23
23
use std:: env;
24
24
use std:: fs:: { self , File } ;
25
- use std:: io:: { self , Read , Write } ;
25
+ use std:: io:: { self , ErrorKind , Read , Write } ;
26
26
use std:: path:: { Path , PathBuf } ;
27
27
28
28
use getopts:: { Matches , Options } ;
@@ -43,39 +43,56 @@ enum Operation {
43
43
Stdin ( String , WriteMode ) ,
44
44
}
45
45
46
- /// Try to find a project file in the input file directory and its parents.
47
- fn lookup_project_file ( input_file : & Path ) -> io:: Result < PathBuf > {
48
- let mut current = if input_file. is_relative ( ) {
49
- try!( env:: current_dir ( ) ) . join ( input_file)
46
+ /// Try to find a project file in the given directory and its parents. Returns the path of a the
47
+ /// nearest project file if one exists, or `None` if no project file was found.
48
+ fn lookup_project_file ( dir : & Path ) -> io:: Result < Option < PathBuf > > {
49
+ let mut current = if dir. is_relative ( ) {
50
+ try!( env:: current_dir ( ) ) . join ( dir)
50
51
} else {
51
- input_file . to_path_buf ( )
52
+ dir . to_path_buf ( )
52
53
} ;
53
54
54
55
current = try!( fs:: canonicalize ( current) ) ;
55
56
56
57
loop {
57
58
let config_file = current. join ( "rustfmt.toml" ) ;
58
- if let Ok ( md) = fs:: metadata ( & config_file) {
59
- // Properly handle unlikely situation of a directory named `rustfmt.toml`.
60
- if md. is_file ( ) {
61
- return Ok ( config_file) ;
59
+ match fs:: metadata ( & config_file) {
60
+ Ok ( md) => {
61
+ // Properly handle unlikely situation of a directory named `rustfmt.toml`.
62
+ if md. is_file ( ) {
63
+ return Ok ( Some ( config_file) ) ;
64
+ }
65
+ }
66
+ // If it's not found, we continue searching; otherwise something went wrong and we
67
+ // return the error.
68
+ Err ( e) => {
69
+ if e. kind ( ) != ErrorKind :: NotFound {
70
+ return Err ( e) ;
71
+ }
62
72
}
63
73
}
64
74
65
75
// If the current directory has no parent, we're done searching.
66
76
if !current. pop ( ) {
67
- return Err ( io :: Error :: new ( io :: ErrorKind :: NotFound , "Config not found" ) ) ;
77
+ return Ok ( None ) ;
68
78
}
69
79
}
70
80
}
71
81
72
- /// Try to find a project file. If it's found, read it.
73
- fn lookup_and_read_project_file ( input_file : & Path ) -> io:: Result < ( PathBuf , String ) > {
74
- let path = try!( lookup_project_file ( input_file) ) ;
82
+ /// Resolve the config for input in `dir`.
83
+ ///
84
+ /// Returns the `Config` to use, and the path of the project file if there was
85
+ /// one.
86
+ fn resolve_config ( dir : & Path ) -> io:: Result < ( Config , Option < PathBuf > ) > {
87
+ let path = try!( lookup_project_file ( dir) ) ;
88
+ if path. is_none ( ) {
89
+ return Ok ( ( Config :: default ( ) , None ) ) ;
90
+ }
91
+ let path = path. unwrap ( ) ;
75
92
let mut file = try!( File :: open ( & path) ) ;
76
93
let mut toml = String :: new ( ) ;
77
94
try!( file. read_to_string ( & mut toml) ) ;
78
- Ok ( ( path , toml ) )
95
+ Ok ( ( Config :: from_toml ( & toml ) , Some ( path ) ) )
79
96
}
80
97
81
98
fn update_config ( config : & mut Config , matches : & Matches ) {
@@ -127,25 +144,22 @@ fn execute() -> i32 {
127
144
}
128
145
Operation :: Stdin ( input, write_mode) => {
129
146
// try to read config from local directory
130
- let config = match lookup_and_read_project_file ( & Path :: new ( "." ) ) {
131
- Ok ( ( _, toml) ) => Config :: from_toml ( & toml) ,
132
- Err ( _) => Default :: default ( ) ,
133
- } ;
147
+ let ( config, _) = resolve_config ( & env:: current_dir ( ) . unwrap ( ) )
148
+ . expect ( "Error resolving config" ) ;
134
149
135
150
run_from_stdin ( input, write_mode, & config) ;
136
151
0
137
152
}
138
153
Operation :: Format ( files, write_mode) => {
139
154
for file in files {
140
- let mut config = match lookup_and_read_project_file ( & file) {
141
- Ok ( ( path, toml) ) => {
142
- println ! ( "Using rustfmt config file {} for {}" ,
143
- path. display( ) ,
144
- file. display( ) ) ;
145
- Config :: from_toml ( & toml)
146
- }
147
- Err ( _) => Default :: default ( ) ,
148
- } ;
155
+ let ( mut config, path) = resolve_config ( file. parent ( ) . unwrap ( ) )
156
+ . expect ( & format ! ( "Error resolving config for {}" ,
157
+ file. display( ) ) ) ;
158
+ if let Some ( path) = path {
159
+ println ! ( "Using rustfmt config file {} for {}" ,
160
+ path. display( ) ,
161
+ file. display( ) ) ;
162
+ }
149
163
150
164
update_config ( & mut config, & matches) ;
151
165
run ( & file, write_mode, & config) ;
0 commit comments