forked from smallstep/cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
write.go
70 lines (61 loc) · 1.5 KB
/
write.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package utils
import (
"bufio"
"fmt"
"io"
"io/ioutil"
"os"
"strings"
"syscall"
"github.com/pkg/errors"
"golang.org/x/crypto/ssh/terminal"
)
var (
// ErrFileExists is the error returned if a file exists.
ErrFileExists = errors.New("file exists")
// ErrIsDir is the error returned if the file is a directory.
ErrIsDir = errors.New("file is a directory")
)
// WriteFile wraps ioutil.WriteFile with a prompt to overwrite a file if the
// file exists. It returns ErrFileExists if the user picks to not overwrite
// the file.
func WriteFile(filename string, data []byte, perm os.FileMode) error {
st, err := os.Stat(filename)
if err != nil {
if os.IsNotExist(err) {
return ioutil.WriteFile(filename, data, perm)
}
return errors.Wrapf(err, "error reading information for %s", filename)
}
if st.IsDir() {
return ErrIsDir
}
// The file exists
var r io.Reader
if terminal.IsTerminal(syscall.Stdin) {
r = os.Stdin
} else {
tty, err := os.Open("/dev/tty")
if err != nil {
return errors.Wrap(err, "error allocating terminal")
}
r = tty
defer tty.Close()
}
br := bufio.NewReader(r)
for cont := true; cont; {
fmt.Fprintf(os.Stderr, "Would you like to overwrite %s [Y/n]: ", filename)
str, err := br.ReadString('\n')
if err != nil {
return errors.Wrap(err, "error reading line")
}
str = strings.ToLower(strings.TrimSpace(str))
switch str {
case "", "y", "yes":
cont = false
case "n", "no":
return ErrFileExists
}
}
return ioutil.WriteFile(filename, data, perm)
}