Skip to content

WIP: Handle hunk-based operations for file additions/removals#12607

Draft
mtsgrd wants to merge 1 commit intomasterfrom
hunk-based-add-remove-support
Draft

WIP: Handle hunk-based operations for file additions/removals#12607
mtsgrd wants to merge 1 commit intomasterfrom
hunk-based-add-remove-support

Conversation

@mtsgrd
Copy link
Contributor

@mtsgrd mtsgrd commented Feb 26, 2026

Allow hunk-based uncommit operations to work on files that were added or
removed by treating a missing "before" entry as an empty blob and None
state. This lets unified-patch computation proceed for additions,
applies hunks against an empty before state, and correctly handles the
case where removing all hunks from an added file should delete the file
from the tree. Also preserve the correct file mode when the resulting
contents match the before or after state and clean up builder
upsert/remove logic accordingly.

Allow hunk-based uncommit operations to work on files that were added or
removed by treating a missing "before" entry as an empty blob and None
state. This lets unified-patch computation proceed for additions,
applies hunks against an empty before state, and correctly handles the
case where removing all hunks from an added file should delete the file
from the tree. Also preserve the correct file mode when the resulting
contents match the before or after state and clean up builder
upsert/remove logic accordingly.
Copilot AI review requested due to automatic review settings February 26, 2026 10:25
@vercel
Copy link

vercel bot commented Feb 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
gitbutler-web Ignored Ignored Preview Feb 26, 2026 10:25am

Request Review

@github-actions github-actions bot added the rust Pull requests that update Rust code label Feb 26, 2026
@mtsgrd mtsgrd marked this pull request as draft February 26, 2026 10:25
@mtsgrd mtsgrd changed the title Handle hunk-based operations for file additions/removals WIP: Handle hunk-based operations for file additions/removals Feb 26, 2026
@mtsgrd
Copy link
Contributor Author

mtsgrd commented Feb 26, 2026

@Caleb-T-Owens here it is

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request enhances the create_tree_without_diff function to support hunk-based operations on file additions and removals. Previously, attempting hunk-based operations on added or deleted files would fail with an error. The PR allows treating missing "before" entries as empty blobs, enabling unified-patch computation and hunk application for file additions. It also correctly handles the edge case where removing all hunks from an added file should delete the file from the tree.

Changes:

  • Allow hunk-based uncommit operations on file additions by treating missing before_entry as None state with empty content
  • Handle file deletion when all hunks are removed from an added file
  • Preserve correct file mode based on whether the resulting contents match before or after state

id: be.id().detach(),
kind: be.mode().kind(),
}),
blob.data.clone(),
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The call to blob.data.clone() at line 144 could be avoided by using blob.data directly or by moving the blob instead of cloning. Since blob is consumed right after this, cloning adds unnecessary memory allocation. Consider restructuring to avoid the clone.

Copilot uses AI. Check for mistakes.
Comment on lines +134 to +148
// For file additions (no before_entry), use None/empty as
// the "before" state so the hunk subtraction still works.
let (before_state, before_data): (Option<ChangeState>, Vec<u8>) =
if let Some(ref be) = before_entry {
let blob = be.object()?.into_blob();
(
Some(ChangeState {
id: be.id().detach(),
kind: be.mode().kind(),
}),
blob.data.clone(),
)
} else {
(None, Vec::new())
};
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new feature allowing hunk-based operations on file additions lacks test coverage. While whole-file uncommit operations have tests in tests/workspace/commit/uncommit_changes.rs, there are no tests that verify hunk-based uncommit on added files, or the specific case where all hunks are removed from an added file (which should delete the file). Consider adding tests for these scenarios.

Copilot uses AI. Check for mistakes.
Comment on lines +221 to +223
// Keep the mode of the after state. We _should_ at some
// point introduce the mode specifically as part of the
// DiscardSpec, but for now, we can just use the after state.
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment "Keep the mode of the after state" is now misleading. The code actually uses the before state's mode when the contents match the before state (line 210-215), and only uses the after state's mode when the contents differ. The comment should be updated to reflect this conditional logic.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rust Pull requests that update Rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants