]> git.lizzy.rs Git - micro.git/blob - internal/buffer/backup.go
Support csharp-script syntax. (#1425)
[micro.git] / internal / buffer / backup.go
1 package buffer
2
3 import (
4         "fmt"
5         "io"
6         "os"
7         "path/filepath"
8         "time"
9
10         "github.com/zyedidia/micro/internal/config"
11         "github.com/zyedidia/micro/internal/screen"
12         "github.com/zyedidia/micro/internal/util"
13         "golang.org/x/text/encoding"
14 )
15
16 const backupMsg = `A backup was detected for this file. This likely means that micro
17 crashed while editing this file, or another instance of micro is currently
18 editing this file.
19
20 The backup was created on %s, and the file is
21
22 %s
23
24 * 'recover' will apply the backup as unsaved changes to the current buffer.
25   When the buffer is closed, the backup will be removed.
26 * 'ignore' will ignore the backup, discarding its changes. The backup file
27   will be removed.
28
29 Options: [r]ecover, [i]gnore: `
30
31 // Backup saves the current buffer to ConfigDir/backups
32 func (b *Buffer) Backup(checkTime bool) error {
33         if !b.Settings["backup"].(bool) || b.Path == "" || b.Type != BTDefault {
34                 return nil
35         }
36
37         if checkTime {
38                 sub := time.Now().Sub(b.lastbackup)
39                 if sub < time.Duration(backupTime)*time.Millisecond {
40                         return nil
41                 }
42         }
43
44         b.lastbackup = time.Now()
45
46         backupdir := filepath.Join(config.ConfigDir, "backups")
47         if _, err := os.Stat(backupdir); os.IsNotExist(err) {
48                 os.Mkdir(backupdir, os.ModePerm)
49         }
50
51         name := filepath.Join(backupdir, util.EscapePath(b.AbsPath))
52
53         err := overwriteFile(name, encoding.Nop, func(file io.Writer) (e error) {
54                 if len(b.lines) == 0 {
55                         return
56                 }
57
58                 // end of line
59                 eol := []byte{'\n'}
60
61                 // write lines
62                 if _, e = file.Write(b.lines[0].data); e != nil {
63                         return
64                 }
65
66                 for _, l := range b.lines[1:] {
67                         if _, e = file.Write(eol); e != nil {
68                                 return
69                         }
70                         if _, e = file.Write(l.data); e != nil {
71                                 return
72                         }
73                 }
74                 return
75         }, false)
76
77         return err
78 }
79
80 // RemoveBackup removes any backup file associated with this buffer
81 func (b *Buffer) RemoveBackup() {
82         if !b.Settings["backup"].(bool) || b.Path == "" || b.Type != BTDefault {
83                 return
84         }
85         f := filepath.Join(config.ConfigDir, "backups", util.EscapePath(b.AbsPath))
86         os.Remove(f)
87 }
88
89 // ApplyBackup applies the corresponding backup file to this buffer (if one exists)
90 // Returns true if a backup was applied
91 func (b *Buffer) ApplyBackup(fsize int64) bool {
92         if b.Settings["backup"].(bool) && len(b.Path) > 0 && b.Type == BTDefault {
93                 backupfile := filepath.Join(config.ConfigDir, "backups", util.EscapePath(b.AbsPath))
94                 if info, err := os.Stat(backupfile); err == nil {
95                         backup, err := os.Open(backupfile)
96                         if err == nil {
97                                 defer backup.Close()
98                                 t := info.ModTime()
99                                 msg := fmt.Sprintf(backupMsg, t.Format("Mon Jan _2 at 15:04, 2006"), util.EscapePath(b.AbsPath))
100                                 choice := screen.TermPrompt(msg, []string{"r", "i", "recover", "ignore"}, true)
101
102                                 if choice%2 == 0 {
103                                         // recover
104                                         b.LineArray = NewLineArray(uint64(fsize), FFAuto, backup)
105                                         b.isModified = true
106                                         return true
107                                 } else if choice%2 == 1 {
108                                         // delete
109                                         os.Remove(backupfile)
110                                 }
111                         }
112                 }
113         }
114
115         return false
116 }