Skip to content

Add projectile-replace-undo#2115

Merged
bbatsov merged 1 commit into
masterfrom
feature/replace-undo
Jul 21, 2026
Merged

Add projectile-replace-undo#2115
bbatsov merged 1 commit into
masterfrom
feature/replace-undo

Conversation

@bbatsov

@bbatsov bbatsov commented Jul 21, 2026

Copy link
Copy Markdown
Owner

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-file now 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 --expand call 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-buffer at 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.

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.
@bbatsov
bbatsov merged commit a1036de into master Jul 21, 2026
10 checks passed
@bbatsov
bbatsov deleted the feature/replace-undo branch July 21, 2026 10:11
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