Add projectile-replace-undo#2115
Merged
Merged
Conversation
Applying a replace across a whole project is the most destructive thing Projectile does, and the reviewer already knows exactly what it wrote, so recording that and offering an undo is cheap insurance. The apply path now returns the edits it actually wrote (skipped files contribute nothing) and stashes them in a single global record. Undo reverts them bottom-up, per file, and only when the written text is still byte-for-byte where it was put - a file edited, deleted or rewritten by a branch switch is reported and left alone. Open buffers are edited in place rather than written behind, exactly as applying handles them. Reverted files drop out of the record, so a second undo can't revert anything twice.
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.
projectile-replace-undo(s-p u) reverts the last project-wide replace applied through the reviewer. Project-wide replace is the most destructive thing Projectile does and the reviewer already knows exactly what it wrote, so recording it is cheap insurance.projectile-replace--apply-filenow returns the edits it actually wrote rather than a count, so a file that apply skipped contributes nothing to the record. Positions are stored post-edit, accumulating the length delta of each earlier edit in the file, and the replacement text comes from the same--expandcall apply uses, so it's byte-exact.Staleness is the crux, and it's handled per file, all-or-nothing: undo requires every recorded span to still hold exactly the text the replace wrote, otherwise that file is skipped with a reason and the others still revert. Verified adversarially - replace across two files, overwrite one behind Projectile's back, and undo leaves the tampered file alone while reverting the other.
Undo mirrors apply for buffers: it re-resolves
get-file-bufferat undo time, edits a live buffer in place, and only saves it if it was clean - so it never writes behind a modified buffer's back. One global record, in memory, gone on restart; reverted files drop out of it, so a double undo can't double-apply.