nogit.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package scan
  2. import (
  3. "bufio"
  4. "context"
  5. "os"
  6. "path/filepath"
  7. "sync"
  8. "github.com/zricethezav/gitleaks/v7/report"
  9. "golang.org/x/sync/errgroup"
  10. )
  11. // NoGitScanner is a scanner that absolutely despises git
  12. type NoGitScanner struct {
  13. BaseScanner
  14. leakChan chan report.Leak
  15. leakWG *sync.WaitGroup
  16. leaks []report.Leak
  17. }
  18. // NewNoGitScanner creates and returns a nogit scanner. This is used for scanning files and directories
  19. func NewNoGitScanner(base BaseScanner) *NoGitScanner {
  20. ngs := &NoGitScanner{
  21. BaseScanner: base,
  22. leakChan: make(chan report.Leak),
  23. leakWG: &sync.WaitGroup{},
  24. }
  25. go ngs.receiveLeaks()
  26. ngs.scannerType = typeNoGitScanner
  27. return ngs
  28. }
  29. // Scan kicks off a NoGitScanner Scan
  30. func (ngs *NoGitScanner) Scan() (report.Report, error) {
  31. var scannerReport report.Report
  32. g, _ := errgroup.WithContext(context.Background())
  33. paths := make(chan string)
  34. semaphore := make(chan bool, howManyThreads(ngs.opts.Threads))
  35. wg := sync.WaitGroup{}
  36. g.Go(func() error {
  37. defer close(paths)
  38. return filepath.Walk(ngs.opts.Path,
  39. func(path string, fInfo os.FileInfo, err error) error {
  40. if err != nil {
  41. return err
  42. }
  43. if fInfo.Mode().IsRegular() {
  44. paths <- path
  45. }
  46. return nil
  47. })
  48. })
  49. for path := range paths {
  50. p := path
  51. wg.Add(1)
  52. semaphore <- true
  53. g.Go(func() error {
  54. defer func() {
  55. <-semaphore
  56. wg.Done()
  57. }()
  58. f, err := os.Open(p)
  59. if err != nil {
  60. return err
  61. }
  62. scanner := bufio.NewScanner(f)
  63. line := 0
  64. for scanner.Scan() {
  65. line++
  66. leaks := checkRules(ngs.BaseScanner, emptyCommit(), "", f.Name(), scanner.Text())
  67. for _, leak := range leaks {
  68. leak.LineNumber = line
  69. if ngs.opts.Verbose {
  70. logLeak(leak, ngs.opts.Redact)
  71. }
  72. ngs.leakWG.Add(1)
  73. ngs.leakChan <- leak
  74. }
  75. }
  76. return f.Close()
  77. })
  78. }
  79. wg.Wait()
  80. ngs.leakWG.Wait()
  81. scannerReport.Leaks = ngs.leaks
  82. return scannerReport, nil
  83. }
  84. func (ngs *NoGitScanner) receiveLeaks() {
  85. for leak := range ngs.leakChan {
  86. ngs.leaks = append(ngs.leaks, leak)
  87. ngs.leakWG.Done()
  88. }
  89. }