馃Ч Dependency Scanner and Pruner
go dependency dependencies
at main 134 lines 2.7 kB view raw
1package main 2 3import ( 4 "io/fs" 5 "os" 6 "path/filepath" 7 "runtime" 8 "sync" 9) 10 11var knownDependencyDirectories = map[string]bool{ 12 "node_modules": true, 13 "target": true, 14 ".next": true, 15 ".nuxt": true, 16 "__pycache__": true, 17 ".venv": true, 18 "venv": true, 19 ".gradle": true, 20 "Pods": true, 21 ".zig-cache": true, 22 "zig-cache": true, 23 "zig-out": true, 24 "_build": true, 25 ".dart_tool": true, 26} 27var ignoredDirectories = map[string]bool{ 28 ".git": true, 29 ".hg": true, 30 ".svn": true, 31} 32 33type DependencyDirectory struct { 34 Path string 35 RelativePath string 36 SizeBytes int64 37 DirectoryType string 38} 39 40func scanForDependencies(rootPath string) ([]DependencyDirectory, error) { 41 var foundDirectories []DependencyDirectory 42 43 walkError := filepath.WalkDir(rootPath, func(currentPath string, entry fs.DirEntry, accessError error) error { 44 if accessError != nil { 45 return filepath.SkipDir 46 } 47 48 if !entry.IsDir() { 49 return nil 50 } 51 52 if ignoredDirectories[entry.Name()] { 53 return filepath.SkipDir 54 } 55 56 if knownDependencyDirectories[entry.Name()] { 57 relativePath, _ := filepath.Rel(rootPath, currentPath) 58 foundDirectories = append(foundDirectories, DependencyDirectory{ 59 Path: currentPath, 60 RelativePath: relativePath, 61 DirectoryType: entry.Name(), 62 }) 63 64 return filepath.SkipDir 65 } 66 67 return nil 68 }) 69 70 if walkError != nil { 71 return nil, walkError 72 } 73 74 var waitGroup sync.WaitGroup 75 76 semaphore := make(chan struct{}, runtime.NumCPU()) 77 78 for directoryIndex := range foundDirectories { 79 waitGroup.Add(1) 80 81 go func(targetIndex int) { 82 defer waitGroup.Done() 83 84 semaphore <- struct{}{} 85 86 defer func() { <-semaphore }() 87 88 foundDirectories[targetIndex].SizeBytes = calculateDirectorySize(foundDirectories[targetIndex].Path) 89 }(directoryIndex) 90 } 91 92 waitGroup.Wait() 93 94 return foundDirectories, nil 95} 96 97func calculateDirectorySize(directoryPath string) int64 { 98 var totalSize int64 99 100 _ = filepath.WalkDir(directoryPath, func(_ string, entry fs.DirEntry, walkError error) error { 101 if walkError != nil || entry.IsDir() { 102 return nil 103 } 104 105 fileInformation, informationError := entry.Info() 106 107 if informationError == nil { 108 totalSize += fileInformation.Size() 109 } 110 111 return nil 112 }) 113 114 return totalSize 115} 116 117func deleteDependencies(dependencies []DependencyDirectory, selected map[int]bool) (int64, int) { 118 var freedBytes int64 119 var deletedCount int 120 121 for dependencyIndex, dependency := range dependencies { 122 if !selected[dependencyIndex] { 123 continue 124 } 125 126 if removeError := os.RemoveAll(dependency.Path); removeError == nil { 127 freedBytes += dependency.SizeBytes 128 129 deletedCount++ 130 } 131 } 132 133 return freedBytes, deletedCount 134}