trufflehog/pkg/sources/errors.go
Cody Rose de19a39f2c
Return targeted scan errors (#2995)
Targeted scans should return their errors so that consumers can process them. By creating a type that combines an error with a targeted secret ID, we can return these errors without having to modify the Source interface.
2024-06-21 13:50:56 -04:00

76 lines
1.6 KiB
Go

package sources
import (
"errors"
"strings"
"sync"
)
// ScanErrors is used to collect errors encountered while scanning.
// It ensures that errors are collected in a thread-safe manner.
type ScanErrors struct {
mu sync.RWMutex
errors []error
}
// NewScanErrors creates a new thread safe error collector.
func NewScanErrors() *ScanErrors {
return &ScanErrors{errors: make([]error, 0)}
}
// Add an error to the collection in a thread-safe manner.
func (s *ScanErrors) Add(err error) {
if err == nil {
return
}
s.mu.Lock()
defer s.mu.Unlock()
s.errors = append(s.errors, err)
}
// Count returns the number of errors collected.
func (s *ScanErrors) Count() uint64 {
s.mu.RLock()
defer s.mu.RUnlock()
return uint64(len(s.errors))
}
func (s *ScanErrors) String() string {
s.mu.RLock()
defer s.mu.RUnlock()
var sb strings.Builder
sb.WriteString("[")
for i, err := range s.errors {
sb.WriteString(`"` + err.Error() + `"`)
if i < len(s.errors)-1 {
sb.WriteString(", ")
}
}
sb.WriteString("]")
return sb.String()
}
func (s *ScanErrors) Errors() error {
s.mu.RLock()
defer s.mu.RUnlock()
return errors.Join(s.errors...)
}
// TargetedScanError is an error with a secret ID attached. Collections of them can be returned by targeted scans that
// scan multiple targets in order to associate individual errors with individual scan targets.
type TargetedScanError struct {
Err error
SecretID int64
}
var _ error = (*TargetedScanError)(nil)
func (t TargetedScanError) Error() string {
return t.Err.Error()
}
func (t TargetedScanError) Unwrap() error {
return t.Err
}