Skip to content

fix: don't misclassify deletion-only hunks as already applied - #22

Merged
wolfv merged 1 commit into
prefix-dev:mainfrom
wolfv:fix-deletion-only-already-applied
Jul 30, 2026
Merged

fix: don't misclassify deletion-only hunks as already applied#22
wolfv merged 1 commit into
prefix-dev:mainfrom
wolfv:fix-deletion-only-already-applied

Conversation

@wolfv

@wolfv wolfv commented Jul 30, 2026

Copy link
Copy Markdown
Member

The bug

Since #20, a hunk containing only context and deletion lines, with ≥1 leading context line and 0 trailing context lines, is silently dropped by apply_bytes_reporting — exit code 0, no diagnostic, the patch just doesn't happen:

@@ -1,6 +1,1 @@
 l1
-l2
-l3
-l4
-l5
-l6

→ file unchanged.

Root cause: is_diff_applied_with_config declares a hunk already applied when its post-image (context + inserted lines) occurs contiguously in the file. For a deletion-only hunk whose deletions sit at the hunk's edge, the post-image is just its context lines — which the unpatched file also contains contiguously. So the hunk is classified AlreadyApplied and skipped. Any trailing context, or any insertion, makes the post-image unambiguous, which is why only this shape was affected. The mirror shape (deletion at the start of the hunk with only trailing context) had the same latent bug.

Real-world impact: this is how php-feedstock's 0001-win-iconv-compat.patch broke under rattler-build ≥ 0.70 (which bumped flickzeug to 0.5.3). The hunk emptying ext/iconv/php_iconv.def (one EXPORTS context line followed by deletions to EOF) vanished while the patch's other 5 hunks applied, leaving stale exports in php8ts.dll.def and an LNK2001 on _libiconv_version.

The fix

For a hunk with no insertions, a post-image match alone is no longer sufficient evidence: additionally require that its pre-image (context plus deleted lines) is absent from the file — i.e. the deleted lines are actually gone. Hunks with insertions keep the existing behavior, since their post-image contains lines the unpatched file doesn't have. find_post_image_position is refactored into a generic find_lines_position used for both searches.

Testing

  • 3 new regression tests: the php-feedstock shape (deletion to EOF), the same shape mid-file, and the mirror case (no leading context) — each asserting Applied on the pre-image and AlreadyApplied on the post-image, so already-applied detection still works for these hunks.
  • All existing tests and doctests pass (96 + 11), including test_is_diff_applied_pure_deletion and test_deletion_patch_with_stale_context_is_not_already_applied from fix: detect already-applied diffs via post-image matching #20.
  • Verified end-to-end: built rattler-build 0.72.0 against this branch and ran a 7-case reproducer covering all hunk shapes — all pass, including the three previously-failing deletion shapes.

🤖 Generated with Claude Code

A hunk that only deletes lines, with its deletions at the hunk's edge
(e.g. leading context and no trailing context), has a post-image that
consists solely of its context lines - which the *un*patched file also
contains contiguously. The post-image search from prefix-dev#20 therefore reported
such hunks as already applied, and apply_bytes_reporting silently
skipped them: exit code 0, no diagnostic, no change.

This is how php-feedstock's 0001-win-iconv-compat.patch broke under
rattler-build 0.70+: the hunk emptying ext/iconv/php_iconv.def
(one EXPORTS context line followed by deletions to EOF) vanished while
the other hunks applied, leaving stale .def exports and an LNK2001 on
_libiconv_version.

For a hunk with no insertions, now additionally require that its
pre-image (context plus deleted lines) is absent from the file before
declaring it already applied. Hunks with insertions are unaffected:
their post-image contains lines the unpatched file doesn't have.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@wolfv
wolfv merged commit e40a91d into prefix-dev:main Jul 30, 2026
3 checks passed
@wolfv wolfv mentioned this pull request Jul 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant