Commit cb6f575
committed
lore-revision: Fix conflict markers glued to hunks lacking a trailing newline
When both sides of a conflict end the file without a trailing newline, the merge glues
the conflict markers onto the content lines and the file becomes unparseable — markers
are only recognizable at the start of a line:
```
<<<<<<< ours
This is line 2 changed.||||||| original
This is line 2.=======
This is line 2 also changed.>>>>>>> theirs
```
git merge-file --diff3 puts every marker on its own line for the same inputs.
Repro is easy: commit a file written with no trailing newline on two branches
from a common base, then `branch merge start`. With trailing newlines the markers come
out fine.
The bug was in the diffy crate. It is fixed there now (bmwill/diffy#85), and 0.5.2 makes
the behaviour selectable (bmwill/diffy#88).
## Updated per review
**No vendoring.** This is now a plain dependency bump to `diffy = "0.5.2"` plus
`MergeOptions::set_incomplete_hunk_style(IncompleteHunkStyle::Git)` in `merge3_text`.
The bump alone is not enough: 0.5.2 defaults to `IncompleteHunkStyle::Diff3`, which is
the old glued behaviour, so the setting is what does the work.
**Tests that resolve restores the content unchanged.** `scripts/test/test_merge_resolve.py`
gains three cases on a file whose last line has no trailing newline:
- every conflict marker occupies a whole line;
- `merge resolve mine` restores the committed bytes exactly;
- `merge resolve theirs` restores the committed bytes exactly.
They compare bytes rather than strings, so an added newline fails the assertion instead of
passing unnoticed. The inserted newline belongs to the marker rendering only — resolving
through the Lore API reads the `~mine` / `~theirs` sidecars and returns the side as it was
committed.
`lore-revision/tests/merge.rs` keeps a unit-level regression test for the marker shape.
## Testing
- `cargo test -p lore-revision` — 4 merge tests, 364 lib tests
- `pytest test_merge_resolve.py test_merge.py test_conflict.py` — 25 passed
- `pytest test_diff.py test_diff_git_baseline.py` — 64 passed (`PatchFormatter` is the
other diffy consumer, so the diff output is covered too)
---
Disclosure: I used Claude to investigate the root cause of this bug and to
implement the fix. I reviewed and tested the changes myself.
```
Imported-PR: #119
Imported-From: 70ee9c0
Imported-Base: 715645d
Imported-Merge: 627c14d
Imported-Merge-Strategy: verbatim
Imported-Merged-Paths: 0
Imported-Author: Jochen Hunz (jochenhz)
Signed-off-by: Jochen Hunz <j.hunz@anchorpoint.app>
GH-URL: #119
```
Lore-RevId: 864
Lore-Signature: 5fd0a5f2f53be5504b8f1c8c002116d01d80bf35c260225822e787e62478fbc31 parent 55eff3a commit cb6f575
5 files changed
Lines changed: 120 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
61 | 61 | | |
62 | 62 | | |
63 | 63 | | |
64 | | - | |
| 64 | + | |
65 | 65 | | |
66 | 66 | | |
67 | 67 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
35 | | - | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
36 | 40 | | |
37 | 41 | | |
38 | 42 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
38 | 68 | | |
39 | 69 | | |
40 | 70 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
584 | 584 | | |
585 | 585 | | |
586 | 586 | | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
0 commit comments