116 lines
3.6 KiB
Rust
116 lines
3.6 KiB
Rust
use crate::matching::match_output;
|
|
use crate::parse::{ShoutFile, is_comment_line, trim_trailing_empty};
|
|
use crate::run::CommandResult;
|
|
|
|
fn escape_dollar(line: &str) -> String {
|
|
if line.starts_with("$ ") {
|
|
format!("\\{line}")
|
|
} else {
|
|
line.to_string()
|
|
}
|
|
}
|
|
|
|
pub fn rewrite_file(
|
|
file: &ShoutFile,
|
|
results: &[CommandResult],
|
|
original_content: &str,
|
|
) -> String {
|
|
let lines: Vec<&str> = original_content.split('\n').collect();
|
|
let mut output: Vec<String> = Vec::new();
|
|
let mut cmd_idx = 0;
|
|
let mut i = 0;
|
|
|
|
while i < lines.len() {
|
|
let line = lines[i];
|
|
|
|
if is_comment_line(line) {
|
|
output.push(line.to_string());
|
|
i += 1;
|
|
} else if line.starts_with("$ ") && !line.starts_with("\\$ ") {
|
|
// Emit the command line as-is
|
|
output.push(line.to_string());
|
|
|
|
let cmd = file.commands.get(cmd_idx);
|
|
let result = results.get(cmd_idx);
|
|
|
|
if cmd.is_none() || result.is_none() {
|
|
cmd_idx += 1;
|
|
i += 1;
|
|
continue;
|
|
}
|
|
let cmd = cmd.unwrap();
|
|
let result = result.unwrap();
|
|
|
|
// Skip past old expected output lines in the original
|
|
let mut j = i + 1;
|
|
while j < lines.len()
|
|
&& !is_comment_line(lines[j])
|
|
&& !(lines[j].starts_with("$ ") && !lines[j].starts_with("\\$ "))
|
|
{
|
|
j += 1;
|
|
}
|
|
|
|
// Collect old expected lines
|
|
let old_expected_raw: Vec<String> = lines[i + 1..j].iter().map(|s| s.to_string()).collect();
|
|
|
|
// Check if old expected output had an exit code marker
|
|
let old_trimmed = trim_trailing_empty(&old_expected_raw);
|
|
let old_exit_marker = if let Some(last) = old_trimmed.last() {
|
|
if last.starts_with('[') && last.ends_with(']') {
|
|
let inner = &last[1..last.len() - 1];
|
|
if inner == "*" || inner.parse::<i32>().is_ok() {
|
|
Some(last.clone())
|
|
} else {
|
|
None
|
|
}
|
|
} else {
|
|
None
|
|
}
|
|
} else {
|
|
None
|
|
};
|
|
|
|
// Count trailing blank lines
|
|
let mut trailing_blanks = 0;
|
|
for k in (0..old_expected_raw.len()).rev() {
|
|
if old_expected_raw[k].is_empty() {
|
|
trailing_blanks += 1;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If wildcards match, keep original expected output
|
|
if match_output(&cmd.expected, &result.actual) {
|
|
for ol in &old_expected_raw {
|
|
output.push(ol.clone());
|
|
}
|
|
} else {
|
|
// Replace with actual output
|
|
for al in &result.actual {
|
|
output.push(escape_dollar(al));
|
|
}
|
|
// Re-add exit code marker if it existed
|
|
if let Some(marker) = old_exit_marker {
|
|
output.push(marker);
|
|
}
|
|
// Preserve trailing blank lines as separators
|
|
for _ in 0..trailing_blanks {
|
|
output.push(String::new());
|
|
}
|
|
}
|
|
|
|
i = j;
|
|
cmd_idx += 1;
|
|
} else if cmd_idx == 0 {
|
|
// Lines before first command (directives, etc.)
|
|
output.push(line.to_string());
|
|
i += 1;
|
|
} else {
|
|
i += 1;
|
|
}
|
|
}
|
|
|
|
output.join("\n")
|
|
}
|