forked from rafecolton/go-fileutils
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfileutils.go
More file actions
181 lines (151 loc) · 3.51 KB
/
fileutils.go
File metadata and controls
181 lines (151 loc) · 3.51 KB
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// Package fileutils wraps or implements common file operations with familiar function names.
package fileutils
import (
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
)
// List of arguments which can be passed to the CpWithArgs method
type CpArgs struct {
Recursive bool
PreserveLinks bool
PreserveTimestamps bool
}
// ChmodR is like `chmod -R`
func ChmodR(name string, mode os.FileMode) error {
return filepath.Walk(name, func(path string, info os.FileInfo, err error) error {
if err == nil {
err = os.Chmod(path, mode)
}
return err
})
}
// ChownR is like `chown -R`
func ChownR(path string, uid, gid int) error {
return filepath.Walk(path, func(name string, info os.FileInfo, err error) error {
if err == nil {
err = os.Chown(name, uid, gid)
}
return err
})
}
// Cp is like `cp`
func Cp(src, dest string) (err error) {
return CpWithArgs(src, dest, CpArgs{})
}
func cpSymlink(src, dest string) (err error) {
var linkTarget string
linkTarget, err = os.Readlink(src)
if err != nil {
return
}
return os.Symlink(linkTarget, dest)
}
func cpFollowLinks(src, dest string) (err error) {
return CpWithArgs(src, dest, CpArgs{})
}
func cpPreserveLinks(src, dest string) (err error) {
return CpWithArgs(src, dest, CpArgs{PreserveLinks: true})
}
/*
CpR is like `cp -R`
*/
func CpR(source, dest string) (err error) {
return CpWithArgs(source, dest, CpArgs{Recursive: true})
}
func CpWithArgs(source, dest string, args CpArgs) (err error) {
sourceInfo, err := os.Stat(source)
if err != nil {
return
}
if sourceInfo.IsDir() {
// Handle the dir case
if !args.Recursive {
return errors.New("source is a directory")
}
// ensure dest dir does not already exist
if _, err = os.Open(dest); !os.IsNotExist(err) {
return errors.New("destination already exists")
}
// create dest dir
if err = os.MkdirAll(dest, sourceInfo.Mode()); err != nil {
return
}
files, err := ioutil.ReadDir(source)
if err != nil {
return err
}
for _, file := range files {
sourceFilePath := fmt.Sprintf("%s/%s", source, file.Name())
destFilePath := fmt.Sprintf("%s/%s", dest, file.Name())
if err = CpWithArgs(sourceFilePath, destFilePath, args); err != nil {
return err
}
}
} else {
// Handle the file case
si, err := os.Lstat(source)
if err != nil {
return err
}
if args.PreserveLinks && !si.Mode().IsRegular() {
return cpSymlink(source, dest)
}
//open source
in, err := os.Open(source)
if err != nil {
return err
}
defer in.Close()
//create dest
out, err := os.Create(dest)
if err != nil {
return err
}
defer func() {
cerr := out.Close()
if err == nil {
err = cerr
}
}()
//copy to dest from source
if _, err = io.Copy(out, in); err != nil {
return err
}
if err = out.Chmod(si.Mode()); err != nil {
return err
}
if args.PreserveTimestamps {
if err = os.Chtimes(dest, si.ModTime(), si.ModTime()); err != nil {
return err
}
}
//sync dest to disk
err = out.Sync()
}
return
}
// MkdirP is `mkdir -p` / os.MkdirAll
func MkdirP(path string, perm os.FileMode) error {
return os.MkdirAll(path, perm)
}
// Mv is `mv` / os.Rename
func Mv(oldname, newname string) error {
return os.Rename(oldname, newname)
}
// Rm is `rm` / os.Remove
func Rm(name string) error {
return os.Remove(name)
}
// RmRF is `rm -rf` / os.RemoveAll
func RmRF(path string) error {
return os.RemoveAll(path)
}
// Which is `which` / exec.LookPath
func Which(file string) (string, error) {
return exec.LookPath(file)
}