@@ -26,6 +26,8 @@ import (
26
26
"github.com/golangci/golangci-lint/pkg/result/processors"
27
27
)
28
28
29
+ const defaultFileMode = 0644
30
+
29
31
func getDefaultIssueExcludeHelp () string {
30
32
parts := []string {"Use or not use default excludes:" }
31
33
for _ , ep := range config .DefaultExcludePatterns {
@@ -400,44 +402,89 @@ func (e *Executor) runAndPrint(ctx context.Context, args []string) error {
400
402
return err // XXX: don't loose type
401
403
}
402
404
403
- p , err := e .createPrinter ()
404
- if err != nil {
405
- return err
405
+ formats := strings .Split (e .cfg .Output .Format , "," )
406
+ for _ , format := range formats {
407
+ out := strings .SplitN (format , ":" , 2 )
408
+ if len (out ) < 2 {
409
+ out = append (out , "" )
410
+ }
411
+
412
+ err := e .printReports (ctx , issues , out [1 ], out [0 ])
413
+ if err != nil {
414
+ return err
415
+ }
406
416
}
407
417
408
418
e .setExitCodeIfIssuesFound (issues )
409
419
420
+ e .fileCache .PrintStats (e .log )
421
+
422
+ return nil
423
+ }
424
+
425
+ func (e * Executor ) printReports (ctx context.Context , issues []result.Issue , path , format string ) error {
426
+ w , shouldClose , err := e .createWriter (path )
427
+ if err != nil {
428
+ return fmt .Errorf ("can't create output for %s: %w" , path , err )
429
+ }
430
+
431
+ p , err := e .createPrinter (format , w )
432
+ if err != nil {
433
+ if file , ok := w .(io.Closer ); shouldClose && ok {
434
+ _ = file .Close ()
435
+ }
436
+ return err
437
+ }
438
+
410
439
if err = p .Print (ctx , issues ); err != nil {
440
+ if file , ok := w .(io.Closer ); shouldClose && ok {
441
+ _ = file .Close ()
442
+ }
411
443
return fmt .Errorf ("can't print %d issues: %s" , len (issues ), err )
412
444
}
413
445
414
- e .fileCache .PrintStats (e .log )
446
+ if file , ok := w .(io.Closer ); shouldClose && ok {
447
+ _ = file .Close ()
448
+ }
415
449
416
450
return nil
417
451
}
418
452
419
- func (e * Executor ) createPrinter () (printers.Printer , error ) {
453
+ func (e * Executor ) createWriter (path string ) (io.Writer , bool , error ) {
454
+ if path == "" || path == "stdout" {
455
+ return logutils .StdOut , false , nil
456
+ }
457
+ if path == "stderr" {
458
+ return logutils .StdErr , false , nil
459
+ }
460
+ f , err := os .OpenFile (path , os .O_CREATE | os .O_TRUNC | os .O_WRONLY , defaultFileMode )
461
+ if err != nil {
462
+ return nil , false , err
463
+ }
464
+ return f , true , nil
465
+ }
466
+
467
+ func (e * Executor ) createPrinter (format string , w io.Writer ) (printers.Printer , error ) {
420
468
var p printers.Printer
421
- format := e .cfg .Output .Format
422
469
switch format {
423
470
case config .OutFormatJSON :
424
- p = printers .NewJSON (& e .reportData )
471
+ p = printers .NewJSON (& e .reportData , w )
425
472
case config .OutFormatColoredLineNumber , config .OutFormatLineNumber :
426
473
p = printers .NewText (e .cfg .Output .PrintIssuedLine ,
427
474
format == config .OutFormatColoredLineNumber , e .cfg .Output .PrintLinterName ,
428
- e .log .Child ("text_printer" ))
475
+ e .log .Child ("text_printer" ), w )
429
476
case config .OutFormatTab :
430
- p = printers .NewTab (e .cfg .Output .PrintLinterName , e .log .Child ("tab_printer" ))
477
+ p = printers .NewTab (e .cfg .Output .PrintLinterName , e .log .Child ("tab_printer" ), w )
431
478
case config .OutFormatCheckstyle :
432
- p = printers .NewCheckstyle ()
479
+ p = printers .NewCheckstyle (w )
433
480
case config .OutFormatCodeClimate :
434
- p = printers .NewCodeClimate ()
481
+ p = printers .NewCodeClimate (w )
435
482
case config .OutFormatHTML :
436
- p = printers .NewHTML ()
483
+ p = printers .NewHTML (w )
437
484
case config .OutFormatJunitXML :
438
- p = printers .NewJunitXML ()
485
+ p = printers .NewJunitXML (w )
439
486
case config .OutFormatGithubActions :
440
- p = printers .NewGithub ()
487
+ p = printers .NewGithub (w )
441
488
default :
442
489
return nil , fmt .Errorf ("unknown output format %s" , format )
443
490
}
0 commit comments