Skip to content

Commit 849fed0

Browse files
committed
fix(vcs): preserve literal => filenames in numstat parsing
Git numstat normalization should only rewrite actual rename syntax, not ordinary filenames that happen to contain `=>`. That keeps per-file VCS stats aligned with status entries for valid literal paths. Constraint: Rename normalization still needs to cover both plain `old => new` output and brace-form renames Rejected: Remove normalization entirely | renamed entries would stop matching status paths again Confidence: high Scope-risk: narrow Directive: Treat `=>` as a rename marker only when Git emits its rename formatting, not when it appears inside a literal filename
1 parent 4b165a0 commit 849fed0

1 file changed

Lines changed: 14 additions & 3 deletions

File tree

crates/taskers-core/src/vcs.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,7 @@ fn parse_git_numstat_z(raw: &str) -> HashMap<String, (u32, u32)> {
822822
}
823823

824824
fn normalize_git_numstat_path(path: &str) -> String {
825-
if !path.contains("=>") {
825+
if !path.contains(" => ") {
826826
return path.to_string();
827827
}
828828

@@ -836,7 +836,7 @@ fn normalize_git_numstat_path(path: &str) -> String {
836836
return path.to_string();
837837
};
838838
let inner = &after_start[..end];
839-
if let Some((_, destination)) = inner.split_once("=>") {
839+
if let Some((_, destination)) = inner.split_once(" => ") {
840840
normalized.push_str(destination.trim());
841841
} else {
842842
normalized.push_str(inner);
@@ -847,7 +847,7 @@ fn normalize_git_numstat_path(path: &str) -> String {
847847
return normalized;
848848
}
849849

850-
path.rsplit_once("=>")
850+
path.rsplit_once(" => ")
851851
.map(|(_, destination)| destination.trim().to_string())
852852
.unwrap_or_else(|| path.to_string())
853853
}
@@ -1228,6 +1228,17 @@ mod tests {
12281228
assert_eq!(stats["src/main.rs"], (5, 2));
12291229
}
12301230

1231+
#[test]
1232+
fn preserves_literal_filenames_containing_arrow_text() {
1233+
let plain = "1\t0\ta=>b.txt\n";
1234+
let plain_stats = parse_git_numstat(plain);
1235+
assert_eq!(plain_stats["a=>b.txt"], (1, 0));
1236+
1237+
let nul = "2\t1\ta=>b.txt\0";
1238+
let nul_stats = parse_git_numstat(nul);
1239+
assert_eq!(nul_stats["a=>b.txt"], (2, 1));
1240+
}
1241+
12311242
#[test]
12321243
fn git_recent_commit_log_args_include_a_limit() {
12331244
assert_eq!(

0 commit comments

Comments
 (0)