-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathoptions.go
153 lines (125 loc) · 4.06 KB
/
options.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
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
package aferocopy
import (
"os"
"github.com/spf13/afero"
)
// Options specifies optional actions on copying.
type Options struct {
// Source filesystem.
SrcFs afero.Fs
// Source filesystem.
DestFs afero.Fs
// OnSymlink can specify what to do on symlink.
OnSymlink func(srcFs afero.Fs, src string) SymlinkAction
// OnDirExists can specify what to do when there is a directory already existing in destination.
OnDirExists func(srcFs afero.Fs, src string, destFs afero.Fs, dest string) DirExistsAction
// Skip can specify which files should be skipped
Skip func(srcFs afero.Fs, src string) (bool, error)
// AddPermission to every entities,
// NO MORE THAN 0777
//
// Deprecated: use PermissionControl instead, for example: `PermissionControl: AddPermission(perm)`.
AddPermission os.FileMode
// PermissionControl can control permission of
// every entry.
// When you want to add permission 0222, do like
//
// PermissionControl = AddPermission(0222)
//
// or if you even don't want to touch permission,
//
// PermissionControl = DoNothing
//
// By default, PermissionControl = PreservePermission
PermissionControl PermissionControlFunc
// Sync file after copy.
// Useful in case when file must be on the disk
// (in case crash happens, for example),
// at the expense of some performance penalty
Sync bool
// Preserve the atime and the mtime of the entries.
// On linux we can preserve only up to 1 millisecond accuracy.
PreserveTimes bool
// Preserve the uid and the gid of all entries.
PreserveOwner bool
// The byte size of the buffer to use for copying files.
// If zero, the internal default buffer of 32KB is used.
// See https://golang.org/pkg/io/#CopyBuffer for more information.
CopyBufferSize uint
intent struct {
src string
dest string
}
}
// SymlinkAction represents what to do on symlink.
type SymlinkAction int
const (
// Deep creates hard-copy of contents.
Deep SymlinkAction = iota
// Shallow creates new symlink to the dest of symlink.
Shallow
// Skip does nothing with symlink.
Skip
)
// DirExistsAction represents what to do on dest dir.
type DirExistsAction int
const (
// Merge preserves or overwrites existing files under the dir (default behavior).
Merge DirExistsAction = iota
// Replace deletes all contents under the dir and copy src files.
Replace
// Untouchable does nothing for the dir, and leaves it as it is.
Untouchable
)
// getDefaultOptions provides default options,
// which would be modified by usage-side.
func getDefaultOptions(src, dest string) Options {
return Options{
OnSymlink: func(afero.Fs, string) SymlinkAction {
return Shallow // Do shallow copy
},
OnDirExists: nil, // Default behavior is "Merge".
Skip: func(afero.Fs, string) (bool, error) {
return false, nil // Don't skip
},
AddPermission: 0, // Add nothing
PermissionControl: PreservePermission, // Just preserve permission
Sync: false, // Do not sync
PreserveTimes: false, // Do not preserve the modification time
CopyBufferSize: 0, // Do not specify, use default bufsize (32*1024)
intent: struct {
src string
dest string
}{src, dest},
}
}
// assureOptions assures Options struct, should be called only once.
// All optional values MUST NOT BE nil/zero after assured.
func assureOptions(src, dest string, opts ...Options) Options {
defaults := getDefaultOptions(src, dest)
defaults.SrcFs = afero.NewOsFs()
defaults.DestFs = defaults.SrcFs
if len(opts) == 0 {
return defaults
}
if opts[0].SrcFs == nil {
opts[0].SrcFs = defaults.SrcFs
}
if opts[0].DestFs == nil {
opts[0].DestFs = opts[0].SrcFs
}
if opts[0].OnSymlink == nil {
opts[0].OnSymlink = defaults.OnSymlink
}
if opts[0].Skip == nil {
opts[0].Skip = defaults.Skip
}
if opts[0].AddPermission > 0 {
opts[0].PermissionControl = AddPermission(opts[0].AddPermission)
} else if opts[0].PermissionControl == nil {
opts[0].PermissionControl = PreservePermission
}
opts[0].intent.src = defaults.intent.src
opts[0].intent.dest = defaults.intent.dest
return opts[0]
}