Hallucinate more logs fix(utils/db.go): handle auto migration errors gracefully fix(utils/modifycommand.go): improve file matching accuracy fix(processor/regex.go): improve capture group deduplication logic fix(utils/db.go): add logging for database wrapper initialization feat(processor/regex.go): preserve input order when deduplicating capture groups fix(utils/modifycommand.go): add logging for file matching skips feat(processor/regex.go): add logging for capture group processing feat(main.go): add trace logging for arguments and parallel workers fix(main.go): add trace logging for file content fix(utils/db.go): add logging for database opening fix(main.go): add trace logging for file processing fix(utils/modifycommand.go): improve file matching by using absolute paths feat(modifycommand.go): add trace logging for file matching in AssociateFilesWithCommands feat(main.go): add per-file association summary for better visibility when debugging
143 lines
5.6 KiB
Go
143 lines
5.6 KiB
Go
package utils
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
|
|
logger "git.site.quack-lab.dev/dave/cylogger"
|
|
)
|
|
|
|
// fileLogger is a scoped logger for the utils/file package.
|
|
var fileLogger = logger.Default.WithPrefix("utils/file")
|
|
|
|
func CleanPath(path string) string {
|
|
cleanPathLogger := fileLogger.WithPrefix("CleanPath")
|
|
cleanPathLogger.Debug("Cleaning path: %q", path)
|
|
cleanPathLogger.Trace("Original path: %q", path)
|
|
path = filepath.Clean(path)
|
|
path = strings.ReplaceAll(path, "\\", "/")
|
|
cleanPathLogger.Trace("Cleaned path result: %q", path)
|
|
return path
|
|
}
|
|
|
|
func ToAbs(path string) string {
|
|
toAbsLogger := fileLogger.WithPrefix("ToAbs")
|
|
toAbsLogger.Debug("Converting path to absolute: %q", path)
|
|
toAbsLogger.Trace("Input path: %q", path)
|
|
if filepath.IsAbs(path) {
|
|
toAbsLogger.Debug("Path is already absolute, cleaning it.")
|
|
cleanedPath := CleanPath(path)
|
|
toAbsLogger.Trace("Already absolute path after cleaning: %q", cleanedPath)
|
|
return cleanedPath
|
|
}
|
|
cwd, err := os.Getwd()
|
|
if err != nil {
|
|
toAbsLogger.Error("Error getting current working directory: %v", err)
|
|
return CleanPath(path)
|
|
}
|
|
toAbsLogger.Trace("Current working directory: %q", cwd)
|
|
cleanedPath := CleanPath(filepath.Join(cwd, path))
|
|
toAbsLogger.Trace("Converted absolute path result: %q", cleanedPath)
|
|
return cleanedPath
|
|
}
|
|
|
|
// LimitString truncates a string to maxLen and adds "..." if truncated
|
|
func LimitString(s string, maxLen int) string {
|
|
limitStringLogger := fileLogger.WithPrefix("LimitString").WithField("originalLength", len(s)).WithField("maxLength", maxLen)
|
|
limitStringLogger.Debug("Limiting string length")
|
|
s = strings.ReplaceAll(s, "\n", "\\n")
|
|
if len(s) <= maxLen {
|
|
limitStringLogger.Trace("String length (%d) is within max length (%d), no truncation", len(s), maxLen)
|
|
return s
|
|
}
|
|
limited := s[:maxLen-3] + "..."
|
|
limitStringLogger.Trace("String truncated from %d to %d characters: %q", len(s), len(limited), limited)
|
|
return limited
|
|
}
|
|
|
|
// StrToFloat converts a string to a float64, returning 0 on error.
|
|
func StrToFloat(s string) float64 {
|
|
strToFloatLogger := fileLogger.WithPrefix("StrToFloat").WithField("inputString", s)
|
|
strToFloatLogger.Debug("Attempting to convert string to float")
|
|
f, err := strconv.ParseFloat(s, 64)
|
|
if err != nil {
|
|
strToFloatLogger.Warning("Failed to convert string %q to float, returning 0: %v", s, err)
|
|
return 0
|
|
}
|
|
strToFloatLogger.Trace("Successfully converted %q to float: %f", s, f)
|
|
return f
|
|
}
|
|
|
|
func ResetWhereNecessary(associations map[string]FileCommandAssociation, db DB) error {
|
|
resetWhereNecessaryLogger := fileLogger.WithPrefix("ResetWhereNecessary")
|
|
resetWhereNecessaryLogger.Debug("Starting reset where necessary operation")
|
|
resetWhereNecessaryLogger.Trace("File-command associations input: %v", associations)
|
|
dirtyFiles := make(map[string]struct{})
|
|
for _, association := range associations {
|
|
resetWhereNecessaryLogger.Debug("Processing association for file: %q", association.File)
|
|
for _, command := range association.Commands {
|
|
resetWhereNecessaryLogger.Debug("Checking command %q for reset requirement", command.Name)
|
|
resetWhereNecessaryLogger.Trace("Command details: %v", command)
|
|
if command.Reset {
|
|
resetWhereNecessaryLogger.Debug("Command %q requires reset for file %q, marking as dirty", command.Name, association.File)
|
|
dirtyFiles[association.File] = struct{}{}
|
|
}
|
|
}
|
|
for _, command := range association.IsolateCommands {
|
|
resetWhereNecessaryLogger.Debug("Checking isolate command %q for reset requirement", command.Name)
|
|
resetWhereNecessaryLogger.Trace("Isolate command details: %v", command)
|
|
if command.Reset {
|
|
resetWhereNecessaryLogger.Debug("Isolate command %q requires reset for file %q, marking as dirty", command.Name, association.File)
|
|
dirtyFiles[association.File] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
resetWhereNecessaryLogger.Debug("Identified %d files that need to be reset", len(dirtyFiles))
|
|
resetWhereNecessaryLogger.Trace("Dirty files identified: %v", dirtyFiles)
|
|
|
|
for file := range dirtyFiles {
|
|
resetWhereNecessaryLogger.Debug("Resetting file %q", file)
|
|
fileData, err := db.GetFile(file)
|
|
if err != nil {
|
|
resetWhereNecessaryLogger.Warning("Failed to get original content for file %q from database: %v", file, err)
|
|
continue
|
|
}
|
|
resetWhereNecessaryLogger.Trace("Retrieved original file data length for %q: %d", file, len(fileData))
|
|
resetWhereNecessaryLogger.Debug("Writing original content back to file %q", file)
|
|
err = os.WriteFile(file, fileData, 0644)
|
|
if err != nil {
|
|
resetWhereNecessaryLogger.Warning("Failed to write original content back to file %q: %v", file, err)
|
|
continue
|
|
}
|
|
resetWhereNecessaryLogger.Debug("Successfully reset file %q", file)
|
|
}
|
|
resetWhereNecessaryLogger.Debug("Finished reset where necessary operation")
|
|
return nil
|
|
}
|
|
|
|
func ResetAllFiles(db DB) error {
|
|
resetAllFilesLogger := fileLogger.WithPrefix("ResetAllFiles")
|
|
resetAllFilesLogger.Debug("Starting reset all files operation")
|
|
fileSnapshots, err := db.GetAllFiles()
|
|
if err != nil {
|
|
resetAllFilesLogger.Error("Failed to get all file snapshots from database: %v", err)
|
|
return err
|
|
}
|
|
resetAllFilesLogger.Debug("Found %d files in database to reset", len(fileSnapshots))
|
|
resetAllFilesLogger.Trace("File snapshots retrieved: %v", fileSnapshots)
|
|
|
|
for _, fileSnapshot := range fileSnapshots {
|
|
resetAllFilesLogger.Debug("Resetting file %q", fileSnapshot.FilePath)
|
|
err = os.WriteFile(fileSnapshot.FilePath, fileSnapshot.FileData, 0644)
|
|
if err != nil {
|
|
resetAllFilesLogger.Warning("Failed to write file %q to disk: %v", fileSnapshot.FilePath, err)
|
|
continue
|
|
}
|
|
resetAllFilesLogger.Debug("File %q written to disk successfully", fileSnapshot.FilePath)
|
|
}
|
|
resetAllFilesLogger.Debug("Finished reset all files operation")
|
|
return nil
|
|
}
|