Skip to content

Commit 49aebe8

Browse files
committed
save+util: Provide a meaningful error message for safe (over-)write fails
1 parent 79ce93f commit 49aebe8

4 files changed

Lines changed: 72 additions & 5 deletions

File tree

cmd/micro/clean.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"bufio"
55
"encoding/gob"
6+
"errors"
67
"fmt"
78
"os"
89
"path/filepath"
@@ -11,6 +12,7 @@ import (
1112

1213
"github.com/zyedidia/micro/v2/internal/buffer"
1314
"github.com/zyedidia/micro/v2/internal/config"
15+
"github.com/zyedidia/micro/v2/internal/util"
1416
)
1517

1618
func shouldContinue() bool {
@@ -42,7 +44,11 @@ func CleanConfig() {
4244
settingsFile := filepath.Join(config.ConfigDir, "settings.json")
4345
err := config.WriteSettings(settingsFile)
4446
if err != nil {
45-
fmt.Println("Error writing settings.json file: " + err.Error())
47+
if errors.Is(err, util.ErrOverwrite) {
48+
fmt.Println(err.Error())
49+
} else {
50+
fmt.Println("Error writing settings.json file: " + err.Error())
51+
}
4652
}
4753

4854
// detect unused options
@@ -80,7 +86,11 @@ func CleanConfig() {
8086

8187
err := config.OverwriteSettings(settingsFile)
8288
if err != nil {
83-
fmt.Println("Error overwriting settings.json file: " + err.Error())
89+
if errors.Is(err, util.ErrOverwrite) {
90+
fmt.Println(err.Error())
91+
} else {
92+
fmt.Println("Error overwriting settings.json file: " + err.Error())
93+
}
8494
}
8595

8696
fmt.Println("Removed unused options")

internal/action/command.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,16 @@ func SetGlobalOptionNative(option string, nativeValue interface{}) error {
658658
delete(b.LocalSettings, option)
659659
}
660660

661-
return config.WriteSettings(filepath.Join(config.ConfigDir, "settings.json"))
661+
err := config.WriteSettings(filepath.Join(config.ConfigDir, "settings.json"))
662+
if err != nil {
663+
if errors.Is(err, util.ErrOverwrite) {
664+
screen.TermMessage(err)
665+
err = errors.Unwrap(err)
666+
}
667+
return err
668+
}
669+
670+
return nil
662671
}
663672

664673
func SetGlobalOption(option, value string) error {
@@ -783,7 +792,11 @@ func (h *BufPane) BindCmd(args []string) {
783792

784793
_, err := TryBindKey(parseKeyArg(args[0]), args[1], true)
785794
if err != nil {
786-
InfoBar.Error(err)
795+
if errors.Is(err, util.ErrOverwrite) {
796+
screen.TermMessage(err)
797+
} else {
798+
InfoBar.Error(err)
799+
}
787800
}
788801
}
789802

@@ -796,7 +809,11 @@ func (h *BufPane) UnbindCmd(args []string) {
796809

797810
err := UnbindKey(parseKeyArg(args[0]))
798811
if err != nil {
799-
InfoBar.Error(err)
812+
if errors.Is(err, util.ErrOverwrite) {
813+
screen.TermMessage(err)
814+
} else {
815+
InfoBar.Error(err)
816+
}
800817
}
801818
}
802819

internal/buffer/save.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,10 @@ func (b *Buffer) saveToFile(filename string, withSudo bool, autoSave bool) error
316316
result := <-saveResponseChan
317317
err = result.err
318318
if err != nil {
319+
if errors.Is(err, util.ErrOverwrite) {
320+
screen.TermMessage(err)
321+
err = errors.Unwrap(err)
322+
}
319323
return err
320324
}
321325

@@ -371,6 +375,7 @@ func (b *Buffer) safeWrite(path string, withSudo bool, newFile bool) (int, error
371375
b.forceKeepBackup = true
372376
size, err := file.Write(b)
373377
if err != nil {
378+
err = util.OverwriteError{err, backupName}
374379
return size, err
375380
}
376381
b.forceKeepBackup = false

internal/util/util.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,44 @@ var (
4545
Stdout *bytes.Buffer
4646
// Sigterm is a channel where micro exits when written
4747
Sigterm chan os.Signal
48+
49+
// To be used for fails on (over-)write with safe writes
50+
ErrOverwrite = OverwriteError{}
4851
)
4952

5053
// To be used for file writes before umask is applied
5154
const FileMode os.FileMode = 0666
5255

56+
const OverwriteFailMsg = `An error occurred while writing to the file:
57+
58+
%s
59+
60+
The file may be corrupted now. The good news is that it has been
61+
successfully backed up. Next time you open this file with Micro,
62+
Micro will ask if you want to recover it from the backup.
63+
64+
The backup path is:
65+
66+
%s`
67+
68+
// OverwriteError is a custom error to add additional information
69+
type OverwriteError struct {
70+
What error
71+
BackupName string
72+
}
73+
74+
func (e OverwriteError) Error() string {
75+
return fmt.Sprintf(OverwriteFailMsg, e.What, e.BackupName)
76+
}
77+
78+
func (e OverwriteError) Is(target error) bool {
79+
return target == ErrOverwrite
80+
}
81+
82+
func (e OverwriteError) Unwrap() error {
83+
return e.What
84+
}
85+
5386
func init() {
5487
var err error
5588
SemVersion, err = semver.Make(Version)
@@ -685,6 +718,8 @@ func SafeWrite(path string, bytes []byte, rename bool) error {
685718
if err != nil {
686719
if rename {
687720
os.Remove(tmp)
721+
} else {
722+
err = OverwriteError{err, tmp}
688723
}
689724
return err
690725
}

0 commit comments

Comments
 (0)