124 lines
3.1 KiB
Go
124 lines
3.1 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
var exitCodeMarkerRe = regexp.MustCompile(`^\[(\d+|\*)\]$`)
|
|
|
|
func rewriteFile(file ShoutFile, results []CommandResult, originalContent string) string {
|
|
lines := strings.Split(originalContent, "\n")
|
|
var output []string
|
|
|
|
cmdIdx := 0
|
|
|
|
for i := 0; i < len(lines); i++ {
|
|
line := lines[i]
|
|
|
|
if strings.HasPrefix(line, "$ ") {
|
|
output = append(output, line)
|
|
|
|
if cmdIdx >= len(file.Commands) || cmdIdx >= len(results) {
|
|
// Out of bounds — skip past expected output, preserving original lines
|
|
j := i + 1
|
|
for j < len(lines) && !strings.HasPrefix(lines[j], "$ ") {
|
|
j++
|
|
}
|
|
output = append(output, lines[i+1:j]...)
|
|
i = j - 1
|
|
cmdIdx++
|
|
continue
|
|
}
|
|
|
|
cmd := file.Commands[cmdIdx]
|
|
result := results[cmdIdx]
|
|
|
|
// Skip past old expected output lines
|
|
j := i + 1
|
|
for j < len(lines) && !strings.HasPrefix(lines[j], "$ ") {
|
|
j++
|
|
}
|
|
|
|
oldExpectedRaw := lines[i+1 : j]
|
|
|
|
// Count trailing blank lines
|
|
trailingBlanks := 0
|
|
for k := len(oldExpectedRaw) - 1; k >= 0; k-- {
|
|
if oldExpectedRaw[k] == "" {
|
|
trailingBlanks++
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
|
|
outputMatch := matchOutput(cmd.Expected, result.Actual)
|
|
ecMatch := exitCodeOK(cmd.ExitCodeType, cmd.ExitCodeValue, result.ExitCode)
|
|
|
|
if outputMatch && ecMatch {
|
|
// Both match — preserve original verbatim
|
|
output = append(output, oldExpectedRaw...)
|
|
} else if outputMatch {
|
|
// Output matches but exit code changed — preserve output, fix exit code
|
|
raw := oldExpectedRaw
|
|
rawTrailing := 0
|
|
for k := len(raw) - 1; k >= 0; k-- {
|
|
if raw[k] == "" {
|
|
rawTrailing++
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
content := raw[:len(raw)-rawTrailing]
|
|
// Strip old exit code marker if present
|
|
if len(content) > 0 && exitCodeMarkerRe.MatchString(content[len(content)-1]) {
|
|
content = content[:len(content)-1]
|
|
}
|
|
output = append(output, content...)
|
|
marker := updateExitCodeMarker(cmd, result.ExitCode)
|
|
if marker != "" {
|
|
output = append(output, marker)
|
|
}
|
|
for k := 0; k < rawTrailing; k++ {
|
|
output = append(output, "")
|
|
}
|
|
} else {
|
|
// Output doesn't match — rewrite everything
|
|
output = append(output, result.Actual...)
|
|
marker := updateExitCodeMarker(cmd, result.ExitCode)
|
|
if marker != "" {
|
|
output = append(output, marker)
|
|
} else if len(result.Actual) > 0 && exitCodeMarkerRe.MatchString(result.Actual[len(result.Actual)-1]) {
|
|
output = append(output, "[0]")
|
|
}
|
|
for k := 0; k < trailingBlanks; k++ {
|
|
output = append(output, "")
|
|
}
|
|
}
|
|
|
|
i = j - 1
|
|
cmdIdx++
|
|
} else {
|
|
output = append(output, line)
|
|
}
|
|
}
|
|
|
|
return strings.Join(output, "\n")
|
|
}
|
|
|
|
// updateExitCodeMarker returns the exit code marker to write, preserving [*]
|
|
// wildcards when the command still exits non-zero.
|
|
func updateExitCodeMarker(cmd Command, actualExitCode int) string {
|
|
if cmd.ExitCodeType == ExitCodeWildcard && actualExitCode != 0 {
|
|
return "[*]"
|
|
}
|
|
if actualExitCode != 0 {
|
|
return fmt.Sprintf("[%d]", actualExitCode)
|
|
}
|
|
if cmd.ExitCodeType == ExitCodeWildcard || cmd.ExitCodeType == ExitCodeExact {
|
|
return "[0]"
|
|
}
|
|
return ""
|
|
}
|