-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
save: Perform write process safe #3273
base: master
Are you sure you want to change the base?
Conversation
7d663d8
to
afdc7a1
Compare
1ea6aaf
to
3510fcc
Compare
Still a lot of rework left, but thank your for your time reviewing this! 👍 |
3510fcc
to
97a4e83
Compare
I did a lot of (commit) refactoring, but still I'm not fully happy with it. |
IIUC, basically, all these troubles are due to the need to avoid circular dependencies between packages? If so, it seems we could avoid these troubles by implementing overwrite & backup stuff as a part of the So maybe instead, simply provide separate implementations of overwrite & backup stuff for different kinds of files, in both A very rough idea:
and a common
Or maybe even P.S. Side note: maybe let's name it |
ea4176c
to
474f98d
Compare
Yes, I know dc701a1 doesn't really belong to the PR in the first place, but I touched some |
474f98d
to
8c6835c
Compare
42e896f
to
b92a6cd
Compare
If the new URL encoded path is found then it has precedence over the '%' escaped path. In case none of both is found the new URL approach is used.
02c5bfd
to
edc190d
Compare
edc190d
to
3f0e289
Compare
This is fully handled within the buffers `save` domain.
…cess SafeWrite() will create a temporary intermediate file.
- extract the open logic into `openFile()` and return a `wrappedFile` - extract the closing logic into `Close()` and make a method of `wrappedFile` - rename `writeFile()` into `Write()` and make a method of `wrappedFile` This allows to use the split parts alone while keeping overwriteFile() as simple interface to use all in a row.
As advantage we don't need to synchonize them any longer and don't need further insufficient lock mechanisms.
Now the main go routine takes care of the backup synchronization.
3f0e289
to
fd97574
Compare
@@ -153,26 +197,27 @@ func (b *Buffer) saveToFile(filename string, withSudo bool, autoSave bool) error | |||
} | |||
} | |||
|
|||
filename, _ = util.ReplaceHome(filename) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more thought: it doesn't seem quite ok that we just ignore the error here...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume we should treat absFilename, _ := filepath.Abs(filename)
then the same and care about the error.
Furthermore...
// Update the last time this file was updated after saving
defer func() {
b.ModTime, _ = util.GetModTime(filename)
err = b.Serialize()
}()
...should be moved behind the actual successful save request or even to the end of the saveToFile()
function. Because otherwise the modification time will be updated and the buffer serialized without the safe and successful save.
return wrappedFile{}, err | ||
} | ||
} else { | ||
writeCloser, err = os.OpenFile(name, os.O_WRONLY|os.O_CREATE, util.FileMode) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly to util.SafeWrite()
, for newly created files: we successfully create an empty file, then we fail to write this file, we report the error but keep this empty file around?
So when micro at exit tries to save the command history and fails to do that, it fails silently [*], and when I start micro next time, I see [*] Formally, it does report the error, but in such a way that no one can see it. |
Thanks for spotting. |
The target situation shall be, that
micro
checks if the file to be stored already exists and if so it shall work with a temporary file first, before the target file is overwritten respective the temporary file renamed to the target file.Possible symlinks pointing to the target file will be resolved, before the save takes place. This shall guarantee that this symlink isn't renamed by the new approach.
TODOs:
overwriteFile()
interface (see: save: Perform write process safe #3273 (comment))util.EscapePath(b.AbsPath)
does not uniquely encode the file path (see: https://github.com/zyedidia/micro/pull/3273/files#r1599137940)b.Backup()
executed asynchronously (frombackupThread
) is accessing the line array without locking. (see: https://github.com/zyedidia/micro/pull/3273/files#r1599137940)Fixes #1916
Fixes #3148
Fixes #3196