@@ -14,18 +14,17 @@ use std::{
1414 collections:: { HashMap , HashSet } ,
1515 env:: args,
1616 ffi:: OsStr ,
17- fs:: { read_to_string , File } ,
18- io:: IsTerminal ,
17+ fs:: File ,
18+ io:: { BufRead , IsTerminal } ,
1919 path:: { Path , PathBuf } ,
20- process:: { exit, Command } ,
20+ process:: { exit, Command , Stdio } ,
2121 str:: FromStr ,
2222 sync:: atomic:: { AtomicBool , Ordering } ,
2323 time:: { Duration , SystemTime } ,
2424} ;
2525use tempfile:: TempDir ;
2626use termcolor:: { ColorChoice , ColorSpec , StandardStream , WriteColor } ;
2727use toml:: { Table , Value } ;
28- use walkdir:: WalkDir ;
2928
3029mod curl;
3130mod flush;
@@ -809,14 +808,30 @@ fn clone_repository(pkg: &Package, purpose: Purpose) -> Result<RepoStatus<PathBu
809808 }
810809}
811810
811+ const LINE_PREFIX : & str = "D " ;
812+
812813fn membership_in_clone ( pkg : & Package , repo_dir : & Path ) -> Result < bool > {
813- for entry in WalkDir :: new ( repo_dir) {
814- let entry = entry?;
815- let path = entry. path ( ) ;
814+ let mut command = Command :: new ( "git" ) ;
815+ command. args ( [ "status" , "--porcelain" ] ) ;
816+ command. current_dir ( repo_dir) ;
817+ command. stdout ( Stdio :: piped ( ) ) ;
818+ let mut child = command
819+ . spawn ( )
820+ . with_context ( || format ! ( "command failed: {command:?}" ) ) ?;
821+ #[ allow( clippy:: unwrap_used) ]
822+ let stdout = child. stdout . take ( ) . unwrap ( ) ;
823+ let reader = std:: io:: BufReader :: new ( stdout) ;
824+ for result in reader. lines ( ) {
825+ let line = result. with_context ( || format ! ( "failed to read `{}`" , repo_dir. display( ) ) ) ?;
826+ #[ allow( clippy:: panic) ]
827+ let path = line. strip_prefix ( LINE_PREFIX ) . map_or_else (
828+ || panic ! ( "cache is corrupt at `{}`" , repo_dir. display( ) ) ,
829+ Path :: new,
830+ ) ;
816831 if path. file_name ( ) != Some ( OsStr :: new ( "Cargo.toml" ) ) {
817832 continue ;
818833 }
819- let contents = read_to_string ( path ) . with_context ( || format ! ( "failed to read { path:?}" ) ) ?;
834+ let contents = show ( repo_dir , path) ?;
820835 let Ok ( table) = contents. parse :: < Table > ( )
821836 /* smoelius: This "failed to parse" warning is a little too noisy.
822837 .map_err(|error| {
@@ -843,6 +858,26 @@ fn membership_in_clone(pkg: &Package, repo_dir: &Path) -> Result<bool> {
843858 Ok ( false )
844859}
845860
861+ fn show ( repo_dir : & Path , path : & Path ) -> Result < String > {
862+ let mut command = Command :: new ( "git" ) ;
863+ command. args ( [ "show" , & format ! ( "HEAD:{}" , path. display( ) ) ] ) ;
864+ command. current_dir ( repo_dir) ;
865+ command. stdout ( Stdio :: piped ( ) ) ;
866+ let output = command
867+ . output ( )
868+ . with_context ( || format ! ( "failed to run command: {command:?}" ) ) ?;
869+ if !output. status . success ( ) {
870+ let error = String :: from_utf8 ( output. stderr ) ?;
871+ bail ! (
872+ "failed to read `{}` in `{}`: {}" ,
873+ path. display( ) ,
874+ repo_dir. display( ) ,
875+ error
876+ ) ;
877+ }
878+ String :: from_utf8 ( output. stdout ) . map_err ( Into :: into)
879+ }
880+
846881fn display_unmaintained_pkgs ( unmaintained_pkgs : & [ UnmaintainedPkg ] ) -> Result < ( ) > {
847882 let mut pkgs_needing_warning = Vec :: new ( ) ;
848883 let mut at_least_one_newer_version_is_available = false ;
0 commit comments