gitbutler icon indicating copy to clipboard operation
gitbutler copied to clipboard

"Unexpected hunk with neither newlines or oldlines…"

Open Byron opened this issue 1 month ago • 3 comments

This is the shortest failing set of hunks is this one

[
HunkHeader("-23,8", "+23,6"), 
HunkHeader("-328,1", "+0,0"), 
HunkHeader("-0,0", "+453,1"), 
HunkHeader("-0,0", "+455,1"), 
HunkHeader("-0,0", "+458,1"), 
HunkHeader("-0,0", "+463,1"), 
HunkHeader("-0,0", "+492,1"), 
HunkHeader("-493,8", "+526,8"), 
HunkHeader("-0,0", "+507,1"), 
HunkHeader("-0,0", "+509,1"), 
HunkHeader("-0,0", "+512,1"), 
HunkHeader("-0,0", "+517,1"), 
HunkHeader("-0,0", "+521,1")
]

Byron avatar Nov 05 '25 10:11 Byron

CC @estib-vega

Byron avatar Nov 05 '25 10:11 Byron

It turns out that I can't reproduce this in testing even, as I'd need the workspace data which isn't available in the logs. So it's not breaking for me, but I am sure the numbers I chose aren't sensical.

diff --git a/crates/but-workspace/src/commit_engine/tree/tests.rs b/crates/but-workspace/src/commit_engine/tree/tests.rs
index c025b2208c..794639bcef 100644
--- a/crates/but-workspace/src/commit_engine/tree/tests.rs
+++ b/crates/but-workspace/src/commit_engine/tree/tests.rs
@@ -240,6 +240,53 @@ mod to_additive_hunks {
         "#);
     }
 
+    #[test]
+    fn real_world_issue_10992() {
+        let wth = vec![hunk_header("-1,493", "+1,521")];
+        let wth0 = [
+            hunk_header("-20,8", "+20,6"),
+            hunk_header("-493,8", "+526,8"),
+        ];
+
+        let ui_hunks = [
+            hunk_header("-23,8", "+23,6"),
+            hunk_header("-328,1", "+0,0"),
+            hunk_header("-0,0", "+453,1"),
+            hunk_header("-0,0", "+455,1"),
+            hunk_header("-0,0", "+458,1"),
+            hunk_header("-0,0", "+463,1"),
+            hunk_header("-0,0", "+492,1"),
+            hunk_header("-493,8", "+526,8"),
+            hunk_header("-0,0", "+507,1"),
+            hunk_header("-0,0", "+509,1"),
+            hunk_header("-0,0", "+512,1"),
+            hunk_header("-0,0", "+517,1"),
+            hunk_header("-0,0", "+521,1"),
+        ];
+
+        let actual = to_additive_hunks(ui_hunks, &wth, &wth0).unwrap();
+        insta::assert_debug_snapshot!(actual, @r#"
+        (
+            [],
+            [
+                HunkHeader("-23,8", "+23,6"),
+                HunkHeader("-328,1", "+0,0"),
+                HunkHeader("-0,0", "+453,1"),
+                HunkHeader("-0,0", "+455,1"),
+                HunkHeader("-0,0", "+458,1"),
+                HunkHeader("-0,0", "+463,1"),
+                HunkHeader("-0,0", "+492,1"),
+                HunkHeader("-493,8", "+526,8"),
+                HunkHeader("-0,0", "+507,1"),
+                HunkHeader("-0,0", "+509,1"),
+                HunkHeader("-0,0", "+512,1"),
+                HunkHeader("-0,0", "+517,1"),
+                HunkHeader("-0,0", "+521,1"),
+            ],
+        )
+        "#);
+    }
+
     #[test]
     fn real_world_issue() {
         let wth = vec![hunk_header("-1,214", "+1,55")];

For now I went with improving the logging so next time I should have all the info it takes for a reproduction.

Byron avatar Nov 05 '25 11:11 Byron

This should make for a test case, to see if the backend can handle this.

"worktreeChanges":[{"pathBytes":[99,114,97,116,101,115,47,98,117,116,47,115,114,99,47,98,114,97,110,99,104,47,108,105,115,116,46,114,115],"previousPathBytes":null,"hunkHeaders":[{"newLines":58,"newStart":1,"oldLines":12,"oldStart":1},{"newLines":586,"newStart":61,"oldLines":91,"oldStart":15}]},{"pathBytes":[99,114,97,116,101,115,47,98,117,116,47,115,114,99,47,98,114,97,110,99,104,47,109,111,100,46,114,115],"previousPathBytes":null,"hunkHeaders":[{"newLines":62,"newStart":19,"oldLines":6,"oldStart":18},{"oldStart":52,"oldLines":1,"newStart":0,"newLines":0},{"oldStart":75,"oldLines":1,"newStart":0,"newLines":0},{"oldStart":77,"oldLines":1,"newStart":0,"newLines":0},{"oldStart":0,"oldLines":0,"newStart":108,"newLines":2},{"oldStart":0,"oldLines":0,"newStart":111,"newLines":1},{"oldStart":0,"oldLines":0,"newStart":113,"newLines":13},{"oldStart":0,"oldLines":0,"newStart":166,"newLines":5},{"oldStart":0,"oldLines":0,"newStart":172,"newLines":11}]},{"pathBytes":[99,114,97,116,101,115,47,98,117,116,47,115,114,99,47,108,105,98,46,114,115],"previousPathBytes":null,"hunkHeaders":[{"oldStart":0,"oldLines":0,"newStart":34,"newLines":1}]},{"pathBytes":[99,114,97,116,101,115,47,98,117,116,47,115,114,99,47,116,97,98,108,101,46,114,115],"previousPathBytes":null,"hunkHeaders":[{"newLines":236,"newStart":1,"oldLines":0,"oldStart":1}]},{"pathBytes":[99,114,97,116,101,115,47,98,117,116,47,67,97,114,103,111,46,116,111,109,108],"previousPathBytes":null,"hunkHeaders":[{"newLines":8,"newStart":49,"oldLines":6,"oldStart":49},{"newLines":8,"newStart":78,"oldLines":6,"oldStart":76}]},{"pathBytes":[67,97,114,103,111,46,108,111,99,107],"previousPathBytes":null,"hunkHeaders":[{"newLines":7,"newStart":706,"oldLines":6,"oldStart":706},{"newLines":7,"newStart":737,"oldLines":6,"oldStart":736},{"newLines":13,"newStart":758,"oldLines":11,"oldStart":756},{"newLines":16,"newStart":10461,"oldLines":6,"oldStart":10457}]}]

Byron avatar Nov 14 '25 14:11 Byron