Simplify saving logic and make it well behaved - #13916
Closed
RGBCube wants to merge 4 commits into
Closed
Conversation
Previously, Helix did the following when we saved a file:
1. Created a .bck (backup) file, copied the original's contents over.
2. Re-created the original, empty this time. Then wrote to it.
3. If writing or creating failed, it moved the backup back into the original file.
3.1. Though, it did different stuff for hardlinks. Also not ideal.
The issue here is that if helix crashes / gets killed while executing
step 2 or 3, the file would be in an inconsistent state. This is not ideal
at all, file writing isn't atomic with this strategy.
This patch simplifies this logic into:
- Create a temporary file, write the stuff we want to write into it.
- If that fails, we don't need to do anything as the original file is
untouched. Though up for question: should we try to delete the "half-
written" file on write failures (or is that even possible?).
- If it is successful, we rename the temporary file over the actual
write destionation. This is atomic, and if it fails the destination is
unmodified.
There are also other benefits from doing the latter, such as inotify.
Previously, we would get these events for an edit of `.cargo/config.toml`:
Create /Users/pala/Projects/helix/.cargo/config.toml.bck
Write /Users/pala/Projects/helix/.cargo/config.toml.bck
Create /Users/pala/Projects/helix/.cargo/config.toml
Write /Users/pala/Projects/helix/.cargo/config.toml
Remove /Users/pala/Projects/helix/.cargo/config.toml.bck
Now, we get these:
Create /Users/pala/Projects/helix/.cargo/config.toml.tmp
Write /Users/pala/Projects/helix/.cargo/config.toml.tmp
Write /Users/pala/Projects/helix/.cargo/config.toml
This is better and easier to handle, because inotify events
actually look like we are writing to the target file, instead of
re-creating this.
Author
|
I removed the |
Member
|
Saving is not simple and has a lot of edge-cases. This doesn't work with hardlinks, for example: the hard link is destroyed. Instead of writing something novel we should be moving closer to what established editors do, like in #11374 |
Author
|
That's interesting, the main thing that got me to do this was inofity, where Emacs did what was done in this PR. I'll take a look at what it does too, and comment on that PR if necessary |
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.
Previously, Helix did the following when we saved a file:
3.1. Though, it did different stuff for hardlinks. Also not ideal.
The issue here is that if helix crashes / gets killed while executing
step 2 or 3, the file would be in an inconsistent state. This is not ideal
at all, file writing isn't atomic with this strategy.
This patch simplifies this logic into:
untouched. (Though we do delete that tmp file if writing to it or moving it in-place fails)
write destionation. This is atomic, and if it fails the destination is
unmodified.
There are also other benefits from doing the latter, such as inotify.
Previously, we would get these events for an edit of
.cargo/config.toml:Now, we get these:
This is better and easier to handle, because inotify events
actually look like we are writing to the target file, instead of
re-creating it.