@@ -3,6 +3,7 @@ use itertools::Itertools;
33use rustc_lexer:: { TokenKind , tokenize} ;
44use shell_escape:: escape;
55use std:: ffi:: { OsStr , OsString } ;
6+ use std:: io:: BufRead ;
67use std:: ops:: ControlFlow ;
78use std:: path:: { Path , PathBuf } ;
89use std:: process:: { self , Command , Stdio } ;
@@ -265,6 +266,42 @@ fn fmt_conf(check: bool) -> Result<(), Error> {
265266 Ok ( ( ) )
266267}
267268
269+ fn find_rustfmt ( ) -> Result < String , Error > {
270+ #[ cfg( windows) ]
271+ const WHICH_BIN : & str = "where" ;
272+
273+ #[ cfg( not( windows) ) ]
274+ const WHICH_BIN : & str = "which" ;
275+
276+ let output = Command :: new ( "rustup" )
277+ . args ( [ "which" , "rustfmt" ] )
278+ . stderr ( Stdio :: inherit ( ) )
279+ . output ( ) ;
280+
281+ if let Ok ( output) = output {
282+ if output. status . success ( ) {
283+ return Ok ( String :: from_utf8 ( output. stdout ) . expect ( "invalid rustfmt path" ) ) ;
284+ }
285+ }
286+
287+ // `rustup which` has failed, fallback to platform-specific built-in command
288+ let output = Command :: new ( WHICH_BIN )
289+ . args ( [ "rustfmt" ] )
290+ . stderr ( Stdio :: inherit ( ) )
291+ . output ( ) ;
292+
293+ if let Ok ( output) = output {
294+ if output. status . success ( ) {
295+ // Since `where` can display multiple results we want to ignore all but one
296+ if let Some ( Ok ( line) ) = output. stdout . lines ( ) . next ( ) {
297+ return Ok ( line) ;
298+ }
299+ }
300+ }
301+
302+ Err ( Error :: RustfmtNotInstalled )
303+ }
304+
268305fn run_rustfmt ( context : & FmtContext ) -> Result < ( ) , Error > {
269306 let project_root = clippy_project_root ( ) ;
270307
@@ -307,16 +344,15 @@ fn run_rustfmt(context: &FmtContext) -> Result<(), Error> {
307344
308345// the "main" function of cargo dev fmt
309346pub fn run ( check : bool , verbose : bool ) {
310- let output = Command :: new ( "rustup" )
311- . args ( [ "which" , "rustfmt" ] )
312- . stderr ( Stdio :: inherit ( ) )
313- . output ( )
314- . expect ( "error running `rustup which rustfmt`" ) ;
315- if !output. status . success ( ) {
316- eprintln ! ( "`rustup which rustfmt` did not execute successfully" ) ;
317- process:: exit ( 1 ) ;
347+ let mut rustfmt_path;
348+ match find_rustfmt ( ) {
349+ Ok ( path) => rustfmt_path = path,
350+ Err ( e) => {
351+ e. display ( ) ;
352+ process:: exit ( 1 ) ;
353+ } ,
318354 }
319- let mut rustfmt_path = String :: from_utf8 ( output . stdout ) . expect ( "invalid rustfmt path" ) ;
355+
320356 rustfmt_path. truncate ( rustfmt_path. trim_end ( ) . len ( ) ) ;
321357
322358 let context = FmtContext {
0 commit comments