@@ -17,9 +17,9 @@ use std::path::Path;
1717use std:: { path:: PathBuf , sync:: Arc } ;
1818use tracing:: warn;
1919
20- use recoco_splitters:: pattern_matcher:: PatternMatcher ;
2120use crate :: base:: field_attrs;
2221use crate :: { fields_value, ops:: sdk:: * } ;
22+ use recoco_splitters:: pattern_matcher:: PatternMatcher ;
2323
2424#[ derive( Debug , Serialize , Deserialize ) ]
2525pub struct Spec {
@@ -51,6 +51,24 @@ async fn ensure_metadata<'a>(
5151 Ok ( metadata. as_ref ( ) . unwrap ( ) )
5252}
5353
54+ async fn try_ensure_metadata < ' a > (
55+ path : & Path ,
56+ metadata : & ' a mut Option < Metadata > ,
57+ ) -> Option < & ' a Metadata > {
58+ if metadata. is_none ( ) {
59+ // Follow symlinks.
60+ match tokio:: fs:: metadata ( path) . await {
61+ Ok ( m) => {
62+ * metadata = Some ( m) ;
63+ }
64+ Err ( e) => {
65+ warn ! ( "Failed to get metadata for {}: {e}" , path. display( ) ) ;
66+ }
67+ }
68+ }
69+ metadata. as_ref ( )
70+ }
71+
5472#[ async_trait]
5573impl SourceExecutor for Executor {
5674 async fn list (
@@ -78,20 +96,21 @@ impl SourceExecutor for Executor {
7896 let mut metadata: Option <Metadata > = None ;
7997
8098 // For symlinks, if the target doesn't exist, log and skip.
81- let file_type = entry. file_type( ) . await ?;
82- if file_type. is_symlink( )
83- && let Err ( e) = ensure_metadata( & path, & mut metadata) . await {
84- if e. kind( ) == std:: io:: ErrorKind :: NotFound {
85- warn!( "Skipped broken symlink: {}" , path. display( ) ) ;
86- continue ;
87- }
88- Err ( e) ?;
99+ let file_type = match entry. file_type( ) . await {
100+ Ok ( ft) => ft,
101+ Err ( e) => {
102+ warn!( "Failed to get file type for {}: {e}" , path. display( ) ) ;
103+ continue ;
89104 }
105+ } ;
90106 let is_dir = if file_type. is_dir( ) {
91107 true
92108 } else if file_type. is_symlink( ) {
93109 // Follow symlinks to classify the target.
94- ensure_metadata( & path, & mut metadata) . await ?. is_dir( )
110+ let Some ( m) = try_ensure_metadata( & path, & mut metadata) . await else {
111+ continue ;
112+ } ;
113+ m. is_dir( )
95114 } else {
96115 false
97116 } ;
@@ -102,13 +121,17 @@ impl SourceExecutor for Executor {
102121 } else if self . pattern_matcher. is_file_included( relative_path) {
103122 // Check file size limit
104123 if let Some ( max_size) = self . max_file_size
105- && let Ok ( metadata) = ensure_metadata( & path, & mut metadata) . await
106- && metadata. len( ) > max_size as u64
124+ && try_ensure_metadata( & path, & mut metadata)
125+ . await
126+ . is_none_or( |m| m. len( ) > max_size as u64 )
107127 {
108128 continue ;
109129 }
110130 let ordinal: Option <Ordinal > = if options. include_ordinal {
111- let metadata = ensure_metadata( & path, & mut metadata) . await ?;
131+ let Some ( metadata) = try_ensure_metadata( & path, & mut metadata) . await
132+ else {
133+ continue ;
134+ } ;
112135 Some ( metadata. modified( ) ?. try_into( ) ?)
113136 } else {
114137 None
@@ -256,26 +279,28 @@ impl SourceExecutor for Executor {
256279 let ( tx, mut rx) = mpsc:: channel :: < PathBuf > ( 100 ) ;
257280
258281 let mut watcher = RecommendedWatcher :: new (
259- move |res : notify:: Result < notify:: Event > | {
260- match res {
261- Ok ( event) => {
262- for path in event. paths {
263- if let Err ( err) = tx. try_send ( path) {
264- use tokio:: sync:: mpsc:: error:: TrySendError ;
265- match err {
266- TrySendError :: Full ( _) => {
267- warn ! ( "File watcher channel is full; dropping file change event" ) ;
268- }
269- TrySendError :: Closed ( _) => {
270- warn ! ( "File watcher channel is closed; dropping file change event" ) ;
271- }
282+ move |res : notify:: Result < notify:: Event > | match res {
283+ Ok ( event) => {
284+ for path in event. paths {
285+ if let Err ( err) = tx. try_send ( path) {
286+ use tokio:: sync:: mpsc:: error:: TrySendError ;
287+ match err {
288+ TrySendError :: Full ( _) => {
289+ warn ! (
290+ "File watcher channel is full; dropping file change event"
291+ ) ;
292+ }
293+ TrySendError :: Closed ( _) => {
294+ warn ! (
295+ "File watcher channel is closed; dropping file change event"
296+ ) ;
272297 }
273298 }
274299 }
275300 }
276- Err ( e ) => {
277- warn ! ( "File watcher error: {}" , e ) ;
278- }
301+ }
302+ Err ( e ) => {
303+ warn ! ( "File watcher error: {}" , e ) ;
279304 }
280305 } ,
281306 Config :: default ( ) ,
0 commit comments