@@ -205,33 +205,34 @@ func Run(v *viper.Viper, statz *stats.Stats, cmd *cobra.Command, paths []string)
205
205
return fmt .Errorf ("failed to create walker: %w" , err )
206
206
}
207
207
208
+ // start traversing
208
209
files := make ([]* walk.File , BatchSize )
210
+
209
211
for {
212
+ // read the next batch
210
213
ctx , cancel := context .WithTimeout (ctx , 1 * time .Second )
211
-
212
214
n , err := reader .Read (ctx , files )
213
215
214
- for idx := 0 ; idx < n ; idx ++ {
215
- file := files [ idx ]
216
+ // ensure context is cancelled to release resources
217
+ cancel ()
216
218
217
- // check if this file is new or has changed when compared to the cache entry
218
- if file .Cache == nil || file .Cache .HasChanged (file .Info ) {
219
- filesCh <- file
220
- statz .Add (stats .Emitted , 1 )
221
- }
219
+ // pass each file into the file channel for processing
220
+ for idx := 0 ; idx < n ; idx ++ {
221
+ filesCh <- files [idx ]
222
222
}
223
223
224
- cancel ()
225
-
226
224
if errors .Is (err , io .EOF ) {
225
+ // we have finished traversing
227
226
break
228
227
} else if err != nil {
228
+ // something went wrong
229
229
log .Errorf ("failed to read files: %v" , err )
230
230
cancel ()
231
231
break
232
232
}
233
233
}
234
234
235
+ // indicate no further files for processing
235
236
close (filesCh )
236
237
237
238
// wait for everything to complete
@@ -263,6 +264,8 @@ func applyFormatters(
263
264
// formatters which should be applied to their respective files
264
265
batches := make (map [string ][]* format.Task )
265
266
267
+ // apply check if the given batch key has enough tasks to trigger processing
268
+ // flush is used to force processing regardless of the number of tasks
266
269
apply := func (key string , flush bool ) {
267
270
// lookup the batch and exit early if it's empty
268
271
batch := batches [key ]
@@ -304,6 +307,7 @@ func applyFormatters(
304
307
}
305
308
}
306
309
310
+ // tryApply batches tasks by their batch key and processes the batch if there is enough ready
307
311
tryApply := func (task * format.Task ) {
308
312
// append to batch
309
313
key := task .BatchKey
@@ -314,53 +318,68 @@ func applyFormatters(
314
318
315
319
return func () error {
316
320
defer func () {
317
- // close processed channel
321
+ // indicate processing has finished
318
322
close (formattedCh )
319
323
}()
320
324
325
+ // parse unmatched log level
321
326
unmatchedLevel , err := log .ParseLevel (cfg .OnUnmatched )
322
327
if err != nil {
323
328
return fmt .Errorf ("invalid on-unmatched value: %w" , err )
324
329
}
325
330
326
- // iterate the files channel
331
+ // iterate the file channel
327
332
for file := range filesCh {
328
333
334
+ // a list of formatters that match this file
335
+ var matches []* format.Formatter
336
+
329
337
// first check if this file has been globally excluded
330
338
if format .PathMatches (file .RelPath , globalExcludes ) {
331
339
log .Debugf ("path matched global excludes: %s" , file .RelPath )
332
- // mark it as processed and continue to the next
333
- formattedCh <- & format.Task {
334
- File : file ,
340
+ } else {
341
+ // otherwise, check if any formatters are interested in it
342
+ for _ , formatter := range formatters {
343
+ if formatter .Wants (file ) {
344
+ matches = append (matches , formatter )
345
+ }
335
346
}
336
- continue
337
347
}
338
348
339
- // check if any formatters are interested in this file
340
- var matches []* format.Formatter
341
- for _ , formatter := range formatters {
342
- if formatter .Wants (file ) {
343
- matches = append (matches , formatter )
344
- }
345
- }
349
+ // indicates no further processing
350
+ var release bool
346
351
347
- // see if any formatters matched
352
+ // check if there were no matches
348
353
if len (matches ) == 0 {
349
-
354
+ // log that there was no match, exiting with an error if the unmatched level was set to fatal
350
355
if unmatchedLevel == log .FatalLevel {
351
356
return fmt .Errorf ("no formatter for path: %s" , file .RelPath )
352
357
}
358
+
353
359
log .Logf (unmatchedLevel , "no formatter for path: %s" , file .RelPath )
354
- // mark it as processed and continue to the next
355
- formattedCh <- & format.Task {
356
- File : file ,
357
- }
360
+
361
+ // no further processing
362
+ release = true
358
363
} else {
359
- // record the match
364
+ // record there was a match
360
365
statz .Add (stats .Matched , 1 )
361
- // create a new format task, add it to a batch based on its batch key and try to apply if the batch is full
362
- task := format .NewTask (file , matches )
363
- tryApply (& task )
366
+
367
+ // check if the file is new or has changed when compared to the cache entry
368
+ if file .Cache == nil || file .Cache .HasChanged (file .Info ) {
369
+ // if so, generate a format task, add it to the relevant batch (by batch key) and try to process
370
+ task := format .NewTask (file , matches )
371
+ tryApply (& task )
372
+ } else {
373
+ // indicate no further processing
374
+ release = true
375
+ }
376
+ }
377
+
378
+ if release {
379
+ // release the file as there is no more processing to be done on it
380
+ if err := file .Release (); err != nil {
381
+ return fmt .Errorf ("failed to release file: %w" , err )
382
+ }
364
383
}
365
384
}
366
385
@@ -398,16 +417,20 @@ func postProcessing(
398
417
break LOOP
399
418
}
400
419
401
- // check if the file has changed
420
+ // grab the underlying file reference
402
421
file := task .File
422
+
423
+ // check if the file has changed
403
424
changed , newInfo , err := file .Stat ()
404
425
if err != nil {
405
426
return err
406
427
}
407
428
429
+ statz .Add (stats .Formatted , 1 )
430
+
408
431
if changed {
409
- // record the change
410
- statz .Add (stats .Formatted , 1 )
432
+ // record that a change in the underlying file occurred
433
+ statz .Add (stats .Changed , 1 )
411
434
412
435
logMethod := log .Debug
413
436
if cfg .FailOnChange {
@@ -434,8 +457,8 @@ func postProcessing(
434
457
}
435
458
}
436
459
437
- // if fail on change has been enabled, check that no files were actually formatted , throwing an error if so
438
- if cfg .FailOnChange && statz .Value (stats .Formatted ) != 0 {
460
+ // if fail on change has been enabled, check that no files were actually changed , throwing an error if so
461
+ if cfg .FailOnChange && statz .Value (stats .Changed ) != 0 {
439
462
return ErrFailOnChange
440
463
}
441
464
0 commit comments