87 lines
1.6 KiB
Go
87 lines
1.6 KiB
Go
// ©AngelaMos | 2026
|
|
// scanner.go
|
|
|
|
package scanner
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/CarterPerez-dev/bomber/internal/graph"
|
|
"github.com/CarterPerez-dev/bomber/internal/parser"
|
|
"github.com/CarterPerez-dev/bomber/pkg/types"
|
|
)
|
|
|
|
var skipDirs = map[string]bool{
|
|
"node_modules": true,
|
|
".git": true,
|
|
"vendor": true,
|
|
"__pycache__": true,
|
|
".venv": true,
|
|
"dist": true,
|
|
"build": true,
|
|
".tox": true,
|
|
"target": true,
|
|
}
|
|
|
|
type Scanner struct {
|
|
registry *parser.Registry
|
|
}
|
|
|
|
func New(registry *parser.Registry) *Scanner {
|
|
return &Scanner{registry: registry}
|
|
}
|
|
|
|
func (s *Scanner) Scan(dir string) (*types.ScanResult, error) {
|
|
result := &types.ScanResult{}
|
|
ecosystemSet := make(map[types.Ecosystem]bool)
|
|
|
|
dirs := discoverDirs(dir)
|
|
|
|
for _, d := range dirs {
|
|
matched := s.registry.Detect(d)
|
|
for _, p := range matched {
|
|
g, err := p.Parse(d)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
result.Graphs = append(result.Graphs, g)
|
|
ecosystemSet[p.Ecosystem()] = true
|
|
}
|
|
}
|
|
|
|
for _, g := range result.Graphs {
|
|
all := graph.AllPackages(g)
|
|
result.TotalPkgs += len(all)
|
|
result.DirectPkgs += len(graph.DirectPackages(g))
|
|
}
|
|
|
|
for eco := range ecosystemSet {
|
|
result.Ecosystems = append(result.Ecosystems, eco)
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func discoverDirs(root string) []string {
|
|
dirs := []string{root}
|
|
|
|
entries, err := os.ReadDir(root)
|
|
if err != nil {
|
|
return dirs
|
|
}
|
|
|
|
for _, entry := range entries {
|
|
if !entry.IsDir() {
|
|
continue
|
|
}
|
|
if skipDirs[entry.Name()] {
|
|
continue
|
|
}
|
|
subDir := filepath.Join(root, entry.Name())
|
|
dirs = append(dirs, discoverDirs(subDir)...)
|
|
}
|
|
|
|
return dirs
|
|
}
|