Repository navigation
patch: accept empty-file diffs with no hunk - #7331
Merged
Merged
Conversation
When a new file is empty, git's diff for staging it consists of only a `diff --git` line, a `new file mode` line, and an `index` line -- there is no hunk, since there is no content to show. Parsing such a diff currently fails with "unexpected header line", because the header state machine has no accepting transition out of STATE_INDEX when the header ends there instead of continuing on to a `---`/`+++` pair or a binary marker. The same gap also broke a multi-file patch whose first file was an empty add, since a following `diff --git` line right after STATE_INDEX was likewise unrecognized. Fix this by accepting STATE_INDEX as a second terminal state and by adding a transition that lets a new `diff --git` header begin from STATE_INDEX, mirroring the existing STATE_END handling for both. Fixes libgit2#6778.
Member
|
Makes sense. Thanks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Parsing a diff that adds an empty file fails with
unexpected header line. Staging a new zero-byte file and taking a plaingit diffproduces a header with no hunk:There is no content, so there is no
---/+++pair and no hunk — the header simply ends at theindexline.git_patch_from_buffer/git_diff_from_bufferreject this valid diff.Why it happens
In
parse_header_git()the header state machine reachesSTATE_INDEXafter theindexline but has no accepting transition out of it when the header ends there.STATE_INDEXis not treated as a terminal state, and a followingdiff --git(the multi-file case, where an empty-file add is followed by another file) is not recognized fromSTATE_INDEXeither, so parsing errors out.#5248 previously handled empty files in
git format-patchoutput, which terminate with a--signature line (the{ "-- ", STATE_INDEX, ... }transition). Plaingit diffoutput has no--line, so that path doesn't apply and the header ends directly atindex— the case this change covers.Fix
Two additive changes mirroring the existing
STATE_ENDhandling:STATE_INDEXas a second terminal state (for a header that ends at end-of-buffer):diff --githeader beginning fromSTATE_INDEX(for the multi-file case), mirroring the existing next-patch row forSTATE_END:{ "diff --git ", STATE_INDEX, 0, NULL },A non-empty file diff still transitions out of
STATE_INDEXvia the---row, so real modifications are unaffected. A truncated modification (bareindexwith no hunks) is still rejected by the existingcheck_patch()"patch with no hunks" guard, matchinggit apply.Tests
Adds parser tests in
tests/libgit2/patch/parse.cfor an empty-file add (both at end-of-buffer and followed by a second file in a multi-file patch), reproducing the issue's exact input.Fixes #6778.