diff --git a/main.go b/main.go index 2e449df..e2bbf1f 100755 --- a/main.go +++ b/main.go @@ -87,8 +87,9 @@ func applyPatchWrapper(patchPath, rootPath string, successfulPatches, failedPatc fmt.Printf("Applying patch: %s\n", patchPath) err := applyPatch(patchPath, rootPath) if err != nil { - fmt.Printf("Failed to apply patch %s: %v\n", patchPath, err) - *failedPatches = append(*failedPatches, patchPath) + errorMsg := fmt.Sprintf("Failed to apply patch '%s': %v", patchPath, err) + fmt.Println(errorMsg) + *failedPatches = append(*failedPatches, errorMsg) // Log detailed error message } else { fmt.Printf("Successfully applied patch: %s\n", patchPath) *successfulPatches = append(*successfulPatches, patchPath) diff --git a/pref.go b/pref.go index b5a4648..cb1ccd0 100644 --- a/pref.go +++ b/pref.go @@ -16,6 +16,7 @@ func applyPrefModifications(targetFilePath string, modifications []string) error } defer targetFile.Close() + // Create a temporary file tempFilePath := targetFilePath + ".tmp" tempFile, err := os.Create(tempFilePath) if err != nil { @@ -23,30 +24,32 @@ func applyPrefModifications(targetFilePath string, modifications []string) error } defer tempFile.Close() - scanner := bufio.NewScanner(targetFile) - modMap := map[string]string{} - - // Prepare the modification map + // Parse modifications into a map for easy lookup + modMap := make(map[string]string) for _, mod := range modifications { if strings.HasPrefix(mod, "+pref") { // Strip the `+` and extract the key within parentheses start := strings.Index(mod, "(") end := strings.LastIndex(mod, ")") if start > 0 && end > start { - key := strings.TrimSpace(mod[start+1 : end]) - modMap[key] = strings.TrimPrefix(mod, "+") // Remove the `+` prefix + key := strings.TrimSpace(mod[start+1 : end]) // Extract the preference key + modMap[key] = mod // Full modification line } } } - modifiedLines := map[string]bool{} + scanner := bufio.NewScanner(targetFile) + modifiedLines := map[string]bool{} // Tracks applied modifications + + // Process each line of the target file for scanner.Scan() { line := scanner.Text() + lineModified := false // Check if the line matches any modification key - lineModified := false for key, replacement := range modMap { if strings.Contains(line, key) && !modifiedLines[key] { + // Write the replacement line fmt.Printf("Replacing line: %s\n", line) if _, err := tempFile.WriteString(replacement + "\n"); err != nil { return fmt.Errorf("failed to write to temp file: %v", err) @@ -69,21 +72,25 @@ func applyPrefModifications(targetFilePath string, modifications []string) error return fmt.Errorf("failed to read target file: %v", err) } - // Write remaining modifications (new preferences) + // Append remaining modifications that were not in the file for key, replacement := range modMap { if !modifiedLines[key] { - // Remove the `+` prefix before writing - cleanReplacement := strings.TrimPrefix(replacement, "+") - if _, err := tempFile.WriteString(cleanReplacement + "\n"); err != nil { - return fmt.Errorf("failed to write new preference to temp file: %v", err) + fmt.Printf("Adding new preference: %s\n", replacement) + if _, err := tempFile.WriteString(replacement + "\n"); err != nil { + return fmt.Errorf("failed to append new preference to temp file: %v", err) } } } - // Replace the original file with the temporary file + // Close the files to ensure proper cleanup + tempFile.Close() + targetFile.Close() + + // Replace the original file with the modified temp file if err := os.Rename(tempFilePath, targetFilePath); err != nil { return fmt.Errorf("failed to replace target file: %v", err) } + fmt.Println("Preferences successfully modified.") return nil } diff --git a/standard.go b/standard.go index 7eaf71b..1a88e51 100644 --- a/standard.go +++ b/standard.go @@ -7,89 +7,96 @@ import ( "strings" ) -// applyStandardModifications applies standard modifications +// applyStandardModifications handles `standard` type patches func applyStandardModifications(targetFilePath string, modifications []string) error { - // Open the target file - targetFile, err := os.Open(targetFilePath) - if err != nil { - return fmt.Errorf("failed to open target file: %v", err) - } - defer targetFile.Close() + fmt.Printf("Applying standard modifications to file: %s\n", targetFilePath) - // Prepare a temporary file for output - tempFilePath := targetFilePath + ".tmp" - tempFile, err := os.Create(tempFilePath) + // Open the target file for reading and writing + file, err := os.OpenFile(targetFilePath, os.O_RDWR, 0644) if err != nil { - return fmt.Errorf("failed to create temp file: %v", err) + return fmt.Errorf("failed to open target file '%s': %v", targetFilePath, err) } - defer tempFile.Close() + defer file.Close() - scanner := bufio.NewScanner(targetFile) - var targetLines []string + scanner := bufio.NewScanner(file) + targetLines := []string{} + + // Read all lines from the target file for scanner.Scan() { targetLines = append(targetLines, scanner.Text()) } - if err := scanner.Err(); err != nil { - return fmt.Errorf("failed to read target file: %v", err) + return fmt.Errorf("failed to read target file '%s': %v", targetFilePath, err) } - // Apply the modifications - updatedLines, err := applyModifications(targetLines, modifications) - if err != nil { - return err - } + modifiedLines := map[string]bool{} + modMap := parseModifications(modifications) - // Write the updated lines to the temporary file - for _, line := range updatedLines { - _, err := fmt.Fprintln(tempFile, line) - if err != nil { - return fmt.Errorf("failed to write to temp file: %v", err) + var updatedContent strings.Builder + + // Apply modifications to the target lines + for _, line := range targetLines { + lineModified := false + + for key, mod := range modMap { + if strings.Contains(line, key) && !modifiedLines[key] { + fmt.Printf("Replacing line in file '%s': %s -> %s\n", targetFilePath, line, mod) + updatedContent.WriteString(mod + "\n") + modifiedLines[key] = true + lineModified = true + break + } + } + + // Write the original line if no modification matches + if !lineModified { + updatedContent.WriteString(line + "\n") } } - // Replace the original file with the updated file - err = os.Rename(tempFilePath, targetFilePath) - if err != nil { - return fmt.Errorf("failed to replace target file: %v", err) + // Append any remaining modifications that were not applied + for key, mod := range modMap { + if !modifiedLines[key] { + fmt.Printf("Adding new line to file '%s': %s\n", targetFilePath, mod) + updatedContent.WriteString(mod + "\n") + } } + // Truncate and rewrite the file with updated content + if err := file.Truncate(0); err != nil { + return fmt.Errorf("failed to truncate file '%s': %v", targetFilePath, err) + } + if _, err := file.Seek(0, 0); err != nil { + return fmt.Errorf("failed to reset file pointer for '%s': %v", targetFilePath, err) + } + if _, err := file.WriteString(updatedContent.String()); err != nil { + return fmt.Errorf("failed to write updated content to file '%s': %v", targetFilePath, err) + } + + fmt.Printf("Standard modifications successfully applied to file: %s\n", targetFilePath) return nil } -// applyModifications applies the changes from the patch file to the target lines -func applyModifications(targetLines, modifications []string) ([]string, error) { - var result []string - i := 0 - +// parseModifications converts a list of modification strings into a map for processing +func parseModifications(modifications []string) map[string]string { + modMap := map[string]string{} for _, mod := range modifications { - switch { - case strings.HasPrefix(mod, "-"): // Delete or replace - mod = strings.TrimPrefix(mod, "-") - for i < len(targetLines) { - if strings.TrimSpace(targetLines[i]) == strings.TrimSpace(mod) { - i++ // Skip this line (delete) - break - } - result = append(result, targetLines[i]) - i++ - } - case strings.HasPrefix(mod, "+"): // Add or replace - mod = strings.TrimPrefix(mod, "+") - result = append(result, mod) - default: // Keep existing lines - if i < len(targetLines) { - result = append(result, targetLines[i]) - i++ - } + if strings.HasPrefix(mod, "+") || strings.HasPrefix(mod, "-") { + trimmed := strings.TrimSpace(strings.TrimPrefix(mod, "+")) + trimmed = strings.TrimPrefix(trimmed, "-") + key := extractKey(trimmed) + modMap[key] = trimmed } } - - // Append remaining lines from the original file - for i < len(targetLines) { - result = append(result, targetLines[i]) - i++ - } - - return result, nil + return modMap +} + +// extractKey extracts the key from a modification string +func extractKey(line string) string { + start := strings.Index(line, "(") + end := strings.LastIndex(line, ")") + if start > 0 && end > start { + return strings.TrimSpace(line[start+1 : end]) + } + return line // Fallback: return the full line }