From 2c487bc443dc9a70177f59c9567dbbaf5a2c6f90 Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Fri, 28 Mar 2025 16:56:39 +0100 Subject: [PATCH] Implement "Isolate" commands Commands that run alone one by one on reading and writing the file This should be used on commands that will modify a large part of the file (or generally large parts) Since that can fuck up the indices of other commands when ran together --- main.go | 43 +++++++++++++++++++++++++++++++++++++----- utils/modifycommand.go | 36 +++++++++++++++++++++++++++++------ 2 files changed, 68 insertions(+), 11 deletions(-) diff --git a/main.go b/main.go index 2528bb3..65697fe 100644 --- a/main.go +++ b/main.go @@ -110,7 +110,7 @@ func main() { // This aggregation is great but what if one modification replaces the whole entire file? // Shit...... // TODO: Add "Isolate" field to modifications which makes them run alone - for file, commands := range associations { + for file, association := range associations { workers <- struct{}{} wg.Add(1) logger.SafeGoWithArgs(func(args ...interface{}) { @@ -120,6 +120,39 @@ func main() { // Track per-file processing time fileStartTime := time.Now() + for _, isolateCommand := range association.IsolateCommands { + fileData, err := os.ReadFile(file) + if err != nil { + logger.Error("Failed to read file %q: %v", file, err) + return + } + logger.Trace("Loaded %d bytes of data for file %q", len(fileData), file) + fileDataStr := string(fileData) + + logger.Info("Processing file %q with isolate command %q", file, isolateCommand.Regex) + modifications, err := processor.ProcessRegex(fileDataStr, isolateCommand, file) + if err != nil { + logger.Error("Failed to process file %q with isolate command %q: %v", file, isolateCommand.Regex, err) + return + } + + if len(modifications) == 0 { + logger.Info("No modifications found for file %q", file) + return + } + + fileDataStr, count := utils.ExecuteModifications(modifications, fileDataStr) + + fileMutex.Lock() + stats.ProcessedFiles++ + stats.TotalModifications += count + fileMutex.Unlock() + + logger.Info("Executed %d isolate modifications for file %q", count, file) + + err = os.WriteFile(file, []byte(fileDataStr), 0644) + } + fileData, err := os.ReadFile(file) if err != nil { logger.Error("Failed to read file %q: %v", file, err) @@ -130,14 +163,14 @@ func main() { // Aggregate all the modifications and execute them modifications := []utils.ReplaceCommand{} - for _, command := range commands { + for _, command := range association.Commands { logger.Info("Processing file %q with command %q", file, command.Regex) - commands, err := processor.ProcessRegex(fileDataStr, command, file) + newModifications, err := processor.ProcessRegex(fileDataStr, command, file) if err != nil { logger.Error("Failed to process file %q with command %q: %v", file, command.Regex, err) return } - modifications = append(modifications, commands...) + modifications = append(modifications, newModifications...) // It is not guranteed that all the commands will be executed... // TODO: Make this better // We'd have to pass the map to executemodifications or something... @@ -145,7 +178,7 @@ func main() { if !ok { count = 0 } - stats.ModificationsPerCommand.Store(command.Name, count.(int)+len(commands)) + stats.ModificationsPerCommand.Store(command.Name, count.(int)+len(newModifications)) } if len(modifications) == 0 { diff --git a/utils/modifycommand.go b/utils/modifycommand.go index 2ca9453..f5f7fa8 100644 --- a/utils/modifycommand.go +++ b/utils/modifycommand.go @@ -18,6 +18,7 @@ type ModifyCommand struct { Git bool `yaml:"git"` Reset bool `yaml:"reset"` LogLevel string `yaml:"loglevel"` + Isolate bool `yaml:"isolate"` } type CookFile []ModifyCommand @@ -39,6 +40,7 @@ func (c *ModifyCommand) Validate() error { // Ehh.. Not much better... Guess this wasn't the big deal var matchesMemoTable map[string]bool = make(map[string]bool) + func Matches(path string, glob string) (bool, error) { key := fmt.Sprintf("%s:%s", path, glob) if matches, ok := matchesMemoTable[key]; ok { @@ -53,10 +55,22 @@ func Matches(path string, glob string) (bool, error) { return matches, nil } -func AssociateFilesWithCommands(files []string, commands []ModifyCommand) (map[string][]ModifyCommand, error) { +type FileCommandAssociation struct { + File string + IsolateCommands []ModifyCommand + Commands []ModifyCommand +} + +func AssociateFilesWithCommands(files []string, commands []ModifyCommand) (map[string]FileCommandAssociation, error) { associationCount := 0 - fileCommands := make(map[string][]ModifyCommand) + fileCommands := make(map[string]FileCommandAssociation) + for _, file := range files { + fileCommands[file] = FileCommandAssociation{ + File: file, + IsolateCommands: []ModifyCommand{}, + Commands: []ModifyCommand{}, + } for _, command := range commands { for _, glob := range command.Files { matches, err := Matches(file, glob) @@ -66,15 +80,25 @@ func AssociateFilesWithCommands(files []string, commands []ModifyCommand) (map[s } if matches { logger.Debug("Found match for file %q and command %q", file, command.Regex) - fileCommands[file] = append(fileCommands[file], command) + association := fileCommands[file] + + if command.Isolate { + association.IsolateCommands = append(association.IsolateCommands, command) + } else { + association.Commands = append(association.Commands, command) + } + fileCommands[file] = association associationCount++ } } } - logger.Debug("Found %d commands for file %q", len(fileCommands[file]), file) - if len(fileCommands[file]) == 0 { + logger.Debug("Found %d commands for file %q", len(fileCommands[file].Commands), file) + if len(fileCommands[file].Commands) == 0 { logger.Info("No commands found for file %q", file) } + if len(fileCommands[file].IsolateCommands) > 0 { + logger.Info("Found %d isolate commands for file %q", len(fileCommands[file].IsolateCommands), file) + } } logger.Info("Found %d associations between %d files and %d commands", associationCount, len(files), len(commands)) return fileCommands, nil @@ -234,4 +258,4 @@ func FilterCommands(commands []ModifyCommand, filter string) []ModifyCommand { } } return filteredCommands -} \ No newline at end of file +}