From b53628e69886931e2e072fb76dc7fac62beb163a Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Thu, 10 Jul 2025 20:49:39 +0200 Subject: [PATCH] Hallucinate a fix to recurse using doublestar --- main.go | 81 +++++++++++++++++---------------------- util.go | 117 +++++++------------------------------------------------- 2 files changed, 49 insertions(+), 149 deletions(-) diff --git a/main.go b/main.go index a9720d3..89fdf83 100644 --- a/main.go +++ b/main.go @@ -7,7 +7,6 @@ import ( "log" "os" "path/filepath" - "regexp" "sync" "sync/atomic" ) @@ -20,7 +19,6 @@ const ImportantColor = BRed const DefaultColor = Reset const PathColor = Green -var FileRegex, _ = regexp.Compile(`sync\.ya?ml$`) var programName = os.Args[0] var undo = false @@ -145,58 +143,49 @@ func ReadFromFilesRecursively(input string, output chan *LinkInstruction, status files := make(chan string, 128) fileStatus := make(chan error) - var wg sync.WaitGroup go GetSyncFilesRecursively(input, files, fileStatus) - go func() { - wg.Wait() - close(files) - }() - - go func() { - for { - err, ok := <-fileStatus - if !ok { - break - } - if err != nil { - LogError("Failed to get sync files recursively: %v", err) - status <- err - } - } - }() + // Collect all files first + var syncFiles []string for { file, ok := <-files if !ok { - LogInfo("No more files to process") break } - wg.Add(1) - go func() { - defer wg.Done() - LogInfo(file) - file = NormalizePath(file, workdir) - LogInfo("Processing file: %s", FormatPathValue(file)) + syncFiles = append(syncFiles, file) + } - // This "has" to be done because instructions are resolved in relation to cwd - fileDir := FileRegex.FindStringSubmatch(file) - if fileDir == nil { - LogError("Failed to extract directory from %s", FormatSourcePath(file)) - return - } - LogInfo("Changing directory to %s (for %s)", - FormatPathValue(fileDir[1]), - FormatPathValue(file)) - err := os.Chdir(fileDir[1]) - if err != nil { - LogError("Failed to change directory to %s: %v", - FormatSourcePath(fileDir[1]), err) - return - } - ReadFromFile(file, output, status, false) - // Don't return directory, stay where we are - os.Chdir(workdir) - }() + // Check for errors from file search + for { + err, ok := <-fileStatus + if !ok { + break + } + if err != nil { + LogError("Failed to get sync files recursively: %v", err) + status <- err + } + } + + // Process each file + for _, file := range syncFiles { + file = NormalizePath(file, workdir) + LogInfo("Processing file: %s", FormatPathValue(file)) + + // Change to the directory containing the sync file + fileDir := filepath.Dir(file) + originalDir, _ := os.Getwd() + err := os.Chdir(fileDir) + if err != nil { + LogError("Failed to change directory to %s: %v", FormatSourcePath(fileDir), err) + continue + } + + // Read and process the file + ReadFromFile(file, output, status, false) + + // Return to original directory + os.Chdir(originalDir) } } diff --git a/util.go b/util.go index 1162632..23406b8 100644 --- a/util.go +++ b/util.go @@ -5,9 +5,8 @@ import ( "os" "path/filepath" "strings" - "sync" - "sync/atomic" - "time" + + "github.com/bmatcuk/doublestar/v4" ) func IsSymlink(path string) (bool, error) { @@ -76,112 +75,24 @@ func GetSyncFilesRecursively(input string, output chan string, status chan error defer close(output) defer close(status) - var filesProcessed int32 - var foldersProcessed int32 - var activeWorkers int32 + workdir, _ := os.Getwd() + input = NormalizePath(input, workdir) + LogInfo("Searching for sync files recursively starting in %s", FormatPathValue(input)) - progressTicker := time.NewTicker(200 * time.Millisecond) - defer progressTicker.Stop() - - done := make(chan struct{}) - defer close(done) - - directories := make(chan string, 100000) - workerPool := make(chan struct{}, 4000) - directories <- input - - go func() { - for { - select { - case <-progressTicker.C: - dirCount := len(directories) - workers := atomic.LoadInt32(&activeWorkers) - fmt.Printf("\rFiles processed: %d; Folders processed: %d; Active workers: %d; Directory queue: %d", - atomic.LoadInt32(&filesProcessed), - atomic.LoadInt32(&foldersProcessed), - workers, - dirCount) - case <-done: - // Final progress update - fmt.Printf("\nFiles processed: %d; Folders processed: %d; Completed successfully\n", - atomic.LoadInt32(&filesProcessed), - atomic.LoadInt32(&foldersProcessed)) - return - } - } - }() - - allDone := make(chan struct{}) - - go func() { - // WTF is this waitgroup? - // Nowhere is it added... - var wg sync.WaitGroup - - go func() { - for { - if atomic.LoadInt32(&activeWorkers) == 0 && len(directories) == 0 { - time.Sleep(10 * time.Millisecond) - if atomic.LoadInt32(&activeWorkers) == 0 && len(directories) == 0 { - close(allDone) - return - } - } - time.Sleep(50 * time.Millisecond) - } - }() - - for { - select { - case directory, ok := <-directories: - if !ok { - wg.Wait() - return - } - - atomic.AddInt32(&activeWorkers, 1) - - go func(dir string) { - workerPool <- struct{}{} - - atomic.AddInt32(&foldersProcessed, 1) - processDirectory(dir, directories, output, &filesProcessed) - - <-workerPool - atomic.AddInt32(&activeWorkers, -1) - }(directory) - } - } - }() - - <-allDone - - if atomic.LoadInt32(&filesProcessed) > 0 { - LogInfo("Files processed: %d; Folders processed: %d", - atomic.LoadInt32(&filesProcessed), - atomic.LoadInt32(&foldersProcessed)) - } -} - -func processDirectory(directory string, directories chan<- string, output chan<- string, filesProcessed *int32) { - files, err := os.ReadDir(directory) + // Use doublestar to find all sync.yml and sync.yaml files recursively + pattern := "**/sync.y*ml" + files, err := doublestar.Glob(os.DirFS(input), pattern) if err != nil { - LogError("Error reading directory %s: %v", directory, err) + LogError("Failed to search for pattern %s: %v", pattern, err) + status <- err return } for _, file := range files { - if file.IsDir() { - directories <- filepath.Join(directory, file.Name()) - } else { - if IsYAMLSyncFile(file.Name()) { - output <- filepath.Join(directory, file.Name()) - } - atomic.AddInt32(filesProcessed, 1) - } + fullPath := filepath.Join(input, file) + LogInfo("Found sync file: %s", FormatPathValue(fullPath)) + output <- fullPath } -} -func IsYAMLSyncFile(filename string) bool { - return filename == "sync.yaml" || filename == "sync.yml" + LogInfo("Completed recursive search for sync files") }