diff --git a/internal/buffer/backup.go b/internal/buffer/backup.go index 9470c663..e93cb069 100644 --- a/internal/buffer/backup.go +++ b/internal/buffer/backup.go @@ -92,35 +92,51 @@ func (b *SharedBuffer) keepBackup() bool { return b.forceKeepBackup || b.Settings["permbackup"].(bool) } -// Backup saves the current buffer to the backups directory +func (b *SharedBuffer) writeBackup(path string) (string, error) { + backupdir := b.backupDir() + if _, err := os.Stat(backupdir); err != nil { + if !errors.Is(err, fs.ErrNotExist) { + return "", err + } + if err = os.Mkdir(backupdir, os.ModePerm); err != nil { + return "", err + } + } + + name := util.DetermineEscapePath(backupdir, path) + + // If no existing backup, just write the backup. + if _, err := os.Stat(name); errors.Is(err, fs.ErrNotExist) { + _, err = b.overwriteFile(name) + if err != nil { + os.Remove(name) + } + return name, err + } + + // If a backup already exists, replace it atomically. + tmp := util.AppendBackupSuffix(name) + _, err := b.overwriteFile(tmp) + if err != nil { + os.Remove(tmp) + return name, err + } + err = os.Rename(tmp, name) + if err != nil { + os.Remove(tmp) + return name, err + } + + return name, nil +} + +// Backup saves the buffer to the backups directory func (b *SharedBuffer) Backup() error { if !b.Settings["backup"].(bool) || b.Path == "" || b.Type != BTDefault { return nil } - backupdir := b.backupDir() - if _, err := os.Stat(backupdir); errors.Is(err, fs.ErrNotExist) { - os.Mkdir(backupdir, os.ModePerm) - } - - name := util.DetermineEscapePath(backupdir, b.AbsPath) - if _, err := os.Stat(name); errors.Is(err, fs.ErrNotExist) { - _, err = b.overwriteFile(name) - return err - } - - tmp := util.AppendBackupSuffix(name) - _, err := b.overwriteFile(tmp) - if err != nil { - os.Remove(tmp) - return err - } - err = os.Rename(tmp, name) - if err != nil { - os.Remove(tmp) - return err - } - + _, err := b.writeBackup(b.AbsPath) return err } diff --git a/internal/buffer/save.go b/internal/buffer/save.go index d2cd3533..7d943929 100644 --- a/internal/buffer/save.go +++ b/internal/buffer/save.go @@ -333,27 +333,6 @@ func (b *Buffer) saveToFile(filename string, withSudo bool, autoSave bool) error return err } -func (b *SharedBuffer) writeBackup(path string) (string, error) { - backupDir := b.backupDir() - if _, err := os.Stat(backupDir); err != nil { - if !errors.Is(err, fs.ErrNotExist) { - return "", err - } - if err = os.Mkdir(backupDir, os.ModePerm); err != nil { - return "", err - } - } - - backupName := util.DetermineEscapePath(backupDir, path) - _, err := b.overwriteFile(backupName) - if err != nil { - os.Remove(backupName) - return "", err - } - - return backupName, nil -} - // safeWrite writes the buffer to a file in a "safe" way, preventing loss of the // contents of the file if it fails to write the new contents. // This means that the file is not overwritten directly but by writing to the