Patcher/main.go

144 lines
3.6 KiB
Go
Raw Normal View History

2024-12-08 17:51:31 +01:00
package main
import (
"bufio"
"flag"
"fmt"
"log"
"os"
"path/filepath"
"strings"
)
func main() {
// Define the --path flag
rootPath := flag.String("path", ".", "Root path for patch application")
flag.Parse()
// Convert root path to an absolute path
absoluteRootPath, err := filepath.Abs(*rootPath)
if err != nil {
log.Fatalf("Failed to resolve absolute path for root: %v", err)
}
fmt.Printf("Starting custom patcher...\nRoot path: %s\n", absoluteRootPath)
patchDir := "./patches"
var successfulPatches, failedPatches []string
err = filepath.Walk(patchDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && strings.HasSuffix(info.Name(), ".patch") {
fmt.Printf("Applying patch: %s\n", path)
err := applyPatch(path, absoluteRootPath)
if err != nil {
fmt.Printf("Failed to apply patch %s: %v\n", path, err)
failedPatches = append(failedPatches, path)
} else {
fmt.Printf("Successfully applied patch: %s\n", path)
successfulPatches = append(successfulPatches, path)
}
}
return nil
})
if err != nil {
log.Fatalf("Error reading patches: %v", err)
}
// Print the summary
fmt.Println("\nSummary:")
fmt.Printf("Successful patches (%d):\n", len(successfulPatches))
for _, patch := range successfulPatches {
fmt.Printf(" - %s\n", patch)
}
fmt.Printf("Failed patches (%d):\n", len(failedPatches))
for _, patch := range failedPatches {
fmt.Printf(" - %s\n", patch)
}
// Exit with appropriate status
if len(failedPatches) > 0 {
fmt.Println("\nPatch process completed with failures.")
os.Exit(1)
} else {
fmt.Println("\nAll patches applied successfully.")
os.Exit(0)
}
}
// applyPatch processes a single patch file
func applyPatch(patchPath, rootPath string) error {
file, err := os.Open(patchPath)
if err != nil {
return fmt.Errorf("failed to open patch file: %v", err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
var inputFilePath, outputFilePath string
var modifications []string
var patchType string
// Parse the patch file
for scanner.Scan() {
line := scanner.Text()
// Check for header type
if strings.HasPrefix(line, "t:") && patchType == "" {
patchType = strings.TrimSpace(strings.TrimPrefix(line, "t:"))
fmt.Printf("Detected patch type: %s\n", patchType)
continue
}
// Detect the input file
if strings.HasPrefix(line, "i:") {
relativePath := strings.TrimSpace(strings.TrimPrefix(line, "i:"))
inputFilePath = filepath.Join(rootPath, relativePath)
continue
}
// Detect the output file
if strings.HasPrefix(line, "o:") {
relativePath := strings.TrimSpace(strings.TrimPrefix(line, "o:"))
outputFilePath = filepath.Join(rootPath, relativePath)
continue
}
// Ignore comment lines
if strings.HasPrefix(strings.TrimSpace(line), "//") {
continue
}
// Collect modifications
modifications = append(modifications, line)
}
if err := scanner.Err(); err != nil {
return fmt.Errorf("failed to read patch file: %v", err)
}
if inputFilePath == "" || outputFilePath == "" {
return fmt.Errorf("patch file must specify both input (i:) and output (o:) files")
}
// Replace the original file with the temporary file
err = os.Rename(inputFilePath, outputFilePath)
if err != nil {
return fmt.Errorf("failed to replace output file: %v", err)
}
// Process based on patch type
switch patchType {
case "pref":
return applyPrefModifications(outputFilePath, modifications)
case "standard":
return applyStandardModifications(outputFilePath, modifications)
default:
fmt.Printf("Type not specified defaulting to standard")
return applyStandardModifications(outputFilePath, modifications)
}
}