@@ -6,7 +6,6 @@ use console::{style, Emoji};
66use std:: fs;
77use std:: path:: { Path , PathBuf } ;
88use tokio:: process:: Command ;
9- use walkdir:: WalkDir ;
109
1110#[ derive( Args , Debug , Clone ) ]
1211pub struct DoctorArgs {
@@ -382,61 +381,86 @@ fn build_project_checks(workspace_root: &Path) -> Result<Vec<DoctorCheck>> {
382381fn scan_workspace_signals ( workspace_root : & Path ) -> Result < WorkspaceSignals > {
383382 let mut signals = WorkspaceSignals :: default ( ) ;
384383
385- for entry in WalkDir :: new ( workspace_root)
386- . into_iter ( )
387- . filter_entry ( |entry| should_scan ( entry. path ( ) ) )
388- {
384+ scan_workspace_dir ( workspace_root, & mut signals) ?;
385+
386+ Ok ( signals)
387+ }
388+
389+ fn scan_workspace_dir ( dir : & Path , signals : & mut WorkspaceSignals ) -> Result < ( ) > {
390+ if !should_scan ( dir) {
391+ return Ok ( ( ) ) ;
392+ }
393+
394+ for entry in fs:: read_dir ( dir) . with_context ( || format ! ( "failed to read {}" , dir. display( ) ) ) ? {
389395 let entry = entry?;
390- if !entry. file_type ( ) . is_file ( ) || !is_scannable_file ( entry. path ( ) ) {
396+ let path = entry. path ( ) ;
397+
398+ if !should_scan ( & path) {
399+ continue ;
400+ }
401+
402+ let file_type = match entry. file_type ( ) {
403+ Ok ( file_type) => file_type,
404+ Err ( _) => continue ,
405+ } ;
406+
407+ if file_type. is_dir ( ) {
408+ scan_workspace_dir ( & path, signals) ?;
391409 continue ;
392410 }
393411
394- let contents = match fs:: read_to_string ( entry. path ( ) ) {
412+ if !file_type. is_file ( ) || !is_scannable_file ( & path) {
413+ continue ;
414+ }
415+
416+ let contents = match fs:: read_to_string ( & path) {
395417 Ok ( contents) => contents,
396418 Err ( _) => continue ,
397419 } ;
398420
399- signals. production_defaults |= contains_any (
400- & contents,
401- & [ ".production_defaults(" , ".production_defaults_with_config(" ] ,
402- ) ;
403- signals. health_endpoints |= contains_any (
404- & contents,
405- & [
406- ".health_endpoints(" ,
407- ".health_endpoint_config(" ,
408- "HealthEndpointConfig" ,
409- ] ,
410- ) ;
411- signals. health_checks |= contents. contains ( ".with_health_check(" ) ;
412- signals. request_id |= contents. contains ( "RequestIdLayer" ) ;
413- signals. tracing |= contains_any ( & contents, & [ "TracingLayer" , "tracing_subscriber" ] ) ;
414- signals. shutdown |= contents. contains ( "run_with_shutdown(" ) ;
415- signals. shutdown_hooks |= contents. contains ( ".on_shutdown(" ) ;
416- signals. structured_logging |= contains_any (
417- & contents,
418- & [ "StructuredLoggingLayer" , "structured_logging(" ] ,
419- ) ;
420- signals. otel |= contains_any ( & contents, & [ "OtelLayer" , "otel(" ] ) ;
421- signals. rate_limit |= contains_any ( & contents, & [ "RateLimitLayer" , "rate_limit(" ] ) ;
422- signals. security_headers |=
423- contains_any ( & contents, & [ "SecurityHeadersLayer" , "security_headers(" ] ) ;
424- signals. timeout |= contains_any ( & contents, & [ "TimeoutLayer" , "timeout(" ] ) ;
425- signals. cors |= contains_any ( & contents, & [ "CorsLayer" , "cors(" ] ) ;
426- signals. body_limit |= contains_any ( & contents, & [ "BodyLimitLayer" , ".body_limit(" ] ) ;
427- signals. env_production |= contains_any (
428- & contents,
429- & [
430- "RUSTAPI_ENV=production" ,
431- "RUSTAPI_ENV: production" ,
432- "RUSTAPI_ENV = \" production\" " ,
433- "RUSTAPI_ENV','production" ,
434- "RUSTAPI_ENV\" , \" production\" " ,
435- ] ,
436- ) ;
421+ apply_workspace_signals ( signals, & contents) ;
437422 }
438423
439- Ok ( signals)
424+ Ok ( ( ) )
425+ }
426+
427+ fn apply_workspace_signals ( signals : & mut WorkspaceSignals , contents : & str ) {
428+ signals. production_defaults |= contains_any (
429+ contents,
430+ & [ ".production_defaults(" , ".production_defaults_with_config(" ] ,
431+ ) ;
432+ signals. health_endpoints |= contains_any (
433+ contents,
434+ & [
435+ ".health_endpoints(" ,
436+ ".health_endpoint_config(" ,
437+ "HealthEndpointConfig" ,
438+ ] ,
439+ ) ;
440+ signals. health_checks |= contents. contains ( ".with_health_check(" ) ;
441+ signals. request_id |= contents. contains ( "RequestIdLayer" ) ;
442+ signals. tracing |= contains_any ( contents, & [ "TracingLayer" , "tracing_subscriber" ] ) ;
443+ signals. shutdown |= contents. contains ( "run_with_shutdown(" ) ;
444+ signals. shutdown_hooks |= contents. contains ( ".on_shutdown(" ) ;
445+ signals. structured_logging |=
446+ contains_any ( contents, & [ "StructuredLoggingLayer" , "structured_logging(" ] ) ;
447+ signals. otel |= contains_any ( contents, & [ "OtelLayer" , "otel(" ] ) ;
448+ signals. rate_limit |= contains_any ( contents, & [ "RateLimitLayer" , "rate_limit(" ] ) ;
449+ signals. security_headers |=
450+ contains_any ( contents, & [ "SecurityHeadersLayer" , "security_headers(" ] ) ;
451+ signals. timeout |= contains_any ( contents, & [ "TimeoutLayer" , "timeout(" ] ) ;
452+ signals. cors |= contains_any ( contents, & [ "CorsLayer" , "cors(" ] ) ;
453+ signals. body_limit |= contains_any ( contents, & [ "BodyLimitLayer" , ".body_limit(" ] ) ;
454+ signals. env_production |= contains_any (
455+ contents,
456+ & [
457+ "RUSTAPI_ENV=production" ,
458+ "RUSTAPI_ENV: production" ,
459+ "RUSTAPI_ENV = \" production\" " ,
460+ "RUSTAPI_ENV','production" ,
461+ "RUSTAPI_ENV\" , \" production\" " ,
462+ ] ,
463+ ) ;
440464}
441465
442466fn find_workspace_root ( start : & Path ) -> Option < PathBuf > {
0 commit comments