mirror of
https://github.com/tw93/Mole.git
synced 2026-02-04 12:41:46 +00:00
Merge pull request #301 from JackPhallen/fix/scanner-race-condition
fix(analyze): Fix race condition in currentPath
This commit is contained in:
@@ -45,9 +45,10 @@ func TestScanPathConcurrentBasic(t *testing.T) {
|
||||
}
|
||||
|
||||
var filesScanned, dirsScanned, bytesScanned int64
|
||||
current := ""
|
||||
current := &atomic.Value{}
|
||||
current.Store("")
|
||||
|
||||
result, err := scanPathConcurrent(root, &filesScanned, &dirsScanned, &bytesScanned, ¤t)
|
||||
result, err := scanPathConcurrent(root, &filesScanned, &dirsScanned, &bytesScanned, current)
|
||||
if err != nil {
|
||||
t.Fatalf("scanPathConcurrent returned error: %v", err)
|
||||
}
|
||||
@@ -361,10 +362,11 @@ func TestScanPathPermissionError(t *testing.T) {
|
||||
}()
|
||||
|
||||
var files, dirs, bytes int64
|
||||
current := ""
|
||||
current := &atomic.Value{}
|
||||
current.Store("")
|
||||
|
||||
// Scanning the locked dir itself should fail.
|
||||
_, err := scanPathConcurrent(lockedDir, &files, &dirs, &bytes, ¤t)
|
||||
_, err := scanPathConcurrent(lockedDir, &files, &dirs, &bytes, current)
|
||||
if err == nil {
|
||||
t.Fatalf("expected error scanning locked directory, got nil")
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ type model struct {
|
||||
filesScanned *int64
|
||||
dirsScanned *int64
|
||||
bytesScanned *int64
|
||||
currentPath *string
|
||||
currentPath *atomic.Value
|
||||
showLargeFiles bool
|
||||
isOverview bool
|
||||
deleteConfirm bool
|
||||
@@ -162,7 +162,8 @@ func main() {
|
||||
|
||||
func newModel(path string, isOverview bool) model {
|
||||
var filesScanned, dirsScanned, bytesScanned int64
|
||||
currentPath := ""
|
||||
currentPath := &atomic.Value{}
|
||||
currentPath.Store("")
|
||||
var overviewFilesScanned, overviewDirsScanned, overviewBytesScanned int64
|
||||
overviewCurrentPath := ""
|
||||
|
||||
@@ -174,7 +175,7 @@ func newModel(path string, isOverview bool) model {
|
||||
filesScanned: &filesScanned,
|
||||
dirsScanned: &dirsScanned,
|
||||
bytesScanned: &bytesScanned,
|
||||
currentPath: ¤tPath,
|
||||
currentPath: currentPath,
|
||||
showLargeFiles: false,
|
||||
isOverview: isOverview,
|
||||
cache: make(map[string]historyEntry),
|
||||
@@ -434,7 +435,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
atomic.StoreInt64(m.dirsScanned, 0)
|
||||
atomic.StoreInt64(m.bytesScanned, 0)
|
||||
if m.currentPath != nil {
|
||||
*m.currentPath = ""
|
||||
m.currentPath.Store("")
|
||||
}
|
||||
return m, tea.Batch(m.scanCmd(m.path), tickCmd())
|
||||
}
|
||||
@@ -712,7 +713,7 @@ func (m model) updateKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
||||
atomic.StoreInt64(m.dirsScanned, 0)
|
||||
atomic.StoreInt64(m.bytesScanned, 0)
|
||||
if m.currentPath != nil {
|
||||
*m.currentPath = ""
|
||||
m.currentPath.Store("")
|
||||
}
|
||||
return m, tea.Batch(m.scanCmd(m.path), tickCmd())
|
||||
case "t", "T":
|
||||
@@ -984,7 +985,7 @@ func (m model) enterSelectedDir() (tea.Model, tea.Cmd) {
|
||||
atomic.StoreInt64(m.dirsScanned, 0)
|
||||
atomic.StoreInt64(m.bytesScanned, 0)
|
||||
if m.currentPath != nil {
|
||||
*m.currentPath = ""
|
||||
m.currentPath.Store("")
|
||||
}
|
||||
|
||||
if cached, ok := m.cache[m.path]; ok && !cached.Dirty {
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
|
||||
var scanGroup singleflight.Group
|
||||
|
||||
func scanPathConcurrent(root string, filesScanned, dirsScanned, bytesScanned *int64, currentPath *string) (scanResult, error) {
|
||||
func scanPathConcurrent(root string, filesScanned, dirsScanned, bytesScanned *int64, currentPath *atomic.Value) (scanResult, error) {
|
||||
children, err := os.ReadDir(root)
|
||||
if err != nil {
|
||||
return scanResult{}, err
|
||||
@@ -293,7 +293,7 @@ func shouldSkipFileForLargeTracking(path string) bool {
|
||||
}
|
||||
|
||||
// calculateDirSizeFast performs concurrent dir sizing using os.ReadDir.
|
||||
func calculateDirSizeFast(root string, filesScanned, dirsScanned, bytesScanned *int64, currentPath *string) int64 {
|
||||
func calculateDirSizeFast(root string, filesScanned, dirsScanned, bytesScanned *int64, currentPath *atomic.Value) int64 {
|
||||
var total int64
|
||||
var wg sync.WaitGroup
|
||||
|
||||
@@ -312,7 +312,7 @@ func calculateDirSizeFast(root string, filesScanned, dirsScanned, bytesScanned *
|
||||
}
|
||||
|
||||
if currentPath != nil && atomic.LoadInt64(filesScanned)%int64(batchUpdateSize) == 0 {
|
||||
*currentPath = dirPath
|
||||
currentPath.Store(dirPath)
|
||||
}
|
||||
|
||||
entries, err := os.ReadDir(dirPath)
|
||||
@@ -429,7 +429,7 @@ func isInFoldedDir(path string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func calculateDirSizeConcurrent(root string, largeFileChan chan<- fileEntry, duSem chan struct{}, filesScanned, dirsScanned, bytesScanned *int64, currentPath *string) int64 {
|
||||
func calculateDirSizeConcurrent(root string, largeFileChan chan<- fileEntry, duSem chan struct{}, filesScanned, dirsScanned, bytesScanned *int64, currentPath *atomic.Value) int64 {
|
||||
children, err := os.ReadDir(root)
|
||||
if err != nil {
|
||||
return 0
|
||||
@@ -507,7 +507,7 @@ func calculateDirSizeConcurrent(root string, largeFileChan chan<- fileEntry, duS
|
||||
|
||||
// Update current path occasionally to prevent UI jitter.
|
||||
if currentPath != nil && atomic.LoadInt64(filesScanned)%int64(batchUpdateSize) == 0 {
|
||||
*currentPath = fullPath
|
||||
currentPath.Store(fullPath)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ func (m model) View() string {
|
||||
colorGreen, humanizeBytes(bytesScanned), colorReset)
|
||||
|
||||
if m.currentPath != nil {
|
||||
currentPath := *m.currentPath
|
||||
currentPath := m.currentPath.Load().(string)
|
||||
if currentPath != "" {
|
||||
shortPath := displayPath(currentPath)
|
||||
shortPath = truncateMiddle(shortPath, 50)
|
||||
|
||||
Reference in New Issue
Block a user