aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/otiai10/copy
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/otiai10/copy')
-rw-r--r--vendor/github.com/otiai10/copy/.gitignore9
-rw-r--r--vendor/github.com/otiai10/copy/LICENSE21
-rw-r--r--vendor/github.com/otiai10/copy/README.md108
-rw-r--r--vendor/github.com/otiai10/copy/copy.go284
-rw-r--r--vendor/github.com/otiai10/copy/copy_namedpipes.go18
-rw-r--r--vendor/github.com/otiai10/copy/copy_namedpipes_x.go15
-rw-r--r--vendor/github.com/otiai10/copy/fileinfo_go1.15.go17
-rw-r--r--vendor/github.com/otiai10/copy/fileinfo_go1.16.go17
-rw-r--r--vendor/github.com/otiai10/copy/options.go143
-rw-r--r--vendor/github.com/otiai10/copy/permission_control.go48
-rw-r--r--vendor/github.com/otiai10/copy/preserve_ltimes.go20
-rw-r--r--vendor/github.com/otiai10/copy/preserve_ltimes_x.go8
-rw-r--r--vendor/github.com/otiai10/copy/preserve_owner.go23
-rw-r--r--vendor/github.com/otiai10/copy/preserve_owner_x.go8
-rw-r--r--vendor/github.com/otiai10/copy/preserve_times.go11
-rw-r--r--vendor/github.com/otiai10/copy/stat_times.go22
-rw-r--r--vendor/github.com/otiai10/copy/stat_times_darwin.go20
-rw-r--r--vendor/github.com/otiai10/copy/stat_times_freebsd.go20
-rw-r--r--vendor/github.com/otiai10/copy/stat_times_js.go20
-rw-r--r--vendor/github.com/otiai10/copy/stat_times_windows.go19
-rw-r--r--vendor/github.com/otiai10/copy/stat_times_x.go18
-rw-r--r--vendor/github.com/otiai10/copy/test/data/case18/assets/README.md1
-rw-r--r--vendor/github.com/otiai10/copy/test_setup.go20
-rw-r--r--vendor/github.com/otiai10/copy/test_setup_x.go17
24 files changed, 907 insertions, 0 deletions
diff --git a/vendor/github.com/otiai10/copy/.gitignore b/vendor/github.com/otiai10/copy/.gitignore
new file mode 100644
index 0000000..a793485
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/.gitignore
@@ -0,0 +1,9 @@
1test/data.copy
2test/owned-by-root
3coverage.txt
4vendor
5.vagrant
6.idea/
7
8# Test Specific
9test/data/case16/large.file
diff --git a/vendor/github.com/otiai10/copy/LICENSE b/vendor/github.com/otiai10/copy/LICENSE
new file mode 100644
index 0000000..1f0cc5d
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/LICENSE
@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2018 otiai10
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
diff --git a/vendor/github.com/otiai10/copy/README.md b/vendor/github.com/otiai10/copy/README.md
new file mode 100644
index 0000000..1cc8fc8
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/README.md
@@ -0,0 +1,108 @@
1# copy
2
3[![Go Reference](https://pkg.go.dev/badge/github.com/otiai10/copy.svg)](https://pkg.go.dev/github.com/otiai10/copy)
4[![Actions Status](https://github.com/otiai10/copy/workflows/Go/badge.svg)](https://github.com/otiai10/copy/actions)
5[![codecov](https://codecov.io/gh/otiai10/copy/branch/main/graph/badge.svg)](https://codecov.io/gh/otiai10/copy)
6[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://github.com/otiai10/copy/blob/main/LICENSE)
7[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fotiai10%2Fcopy.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fotiai10%2Fcopy?ref=badge_shield)
8[![CodeQL](https://github.com/otiai10/copy/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/otiai10/copy/actions/workflows/codeql-analysis.yml)
9[![Go Report Card](https://goreportcard.com/badge/github.com/otiai10/copy)](https://goreportcard.com/report/github.com/otiai10/copy)
10[![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/otiai10/copy?sort=semver)](https://pkg.go.dev/github.com/otiai10/copy)
11[![Docker Test](https://github.com/otiai10/copy/actions/workflows/docker-test.yml/badge.svg)](https://github.com/otiai10/copy/actions/workflows/docker-test.yml)
12[![Vagrant Test](https://github.com/otiai10/copy/actions/workflows/vagrant-test.yml/badge.svg)](https://github.com/otiai10/copy/actions/workflows/vagrant-test.yml)
13
14`copy` copies directories recursively.
15
16# Example Usage
17
18```go
19package main
20
21import (
22 "fmt"
23 cp "github.com/otiai10/copy"
24)
25
26func main() {
27 err := cp.Copy("your/src", "your/dest")
28 fmt.Println(err) // nil
29}
30```
31
32# Advanced Usage
33
34```go
35// Options specifies optional actions on copying.
36type Options struct {
37
38 // OnSymlink can specify what to do on symlink
39 OnSymlink func(src string) SymlinkAction
40
41 // OnDirExists can specify what to do when there is a directory already existing in destination.
42 OnDirExists func(src, dest string) DirExistsAction
43
44 // OnError can let users decide how to handle errors (e.g., you can suppress specific error).
45 OnError func(src, dest, string, err error) error
46
47 // Skip can specify which files should be skipped
48 Skip func(srcinfo os.FileInfo, src, dest string) (bool, error)
49
50 // PermissionControl can control permission of
51 // every entry.
52 // When you want to add permission 0222, do like
53 //
54 // PermissionControl = AddPermission(0222)
55 //
56 // or if you even don't want to touch permission,
57 //
58 // PermissionControl = DoNothing
59 //
60 // By default, PermissionControl = PreservePermission
61 PermissionControl PermissionControlFunc
62
63 // Sync file after copy.
64 // Useful in case when file must be on the disk
65 // (in case crash happens, for example),
66 // at the expense of some performance penalty
67 Sync bool
68
69 // Preserve the atime and the mtime of the entries
70 // On linux we can preserve only up to 1 millisecond accuracy
71 PreserveTimes bool
72
73 // Preserve the uid and the gid of all entries.
74 PreserveOwner bool
75
76 // The byte size of the buffer to use for copying files.
77 // If zero, the internal default buffer of 32KB is used.
78 // See https://golang.org/pkg/io/#CopyBuffer for more information.
79 CopyBufferSize uint
80
81 // If you want to add some limitation on reading src file,
82 // you can wrap the src and provide new reader,
83 // such as `RateLimitReader` in the test case.
84 WrapReader func(src io.Reader) io.Reader
85
86 // If given, copy.Copy refers to this fs.FS instead of the OS filesystem.
87 // e.g., You can use embed.FS to copy files from embedded filesystem.
88 FS fs.FS
89}
90```
91
92```go
93// For example...
94opt := Options{
95 Skip: func(info os.FileInfo, src, dest string) (bool, error) {
96 return strings.HasSuffix(src, ".git"), nil
97 },
98}
99err := Copy("your/directory", "your/directory.copy", opt)
100```
101
102# Issues
103
104- https://github.com/otiai10/copy/issues
105
106
107## License
108[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fotiai10%2Fcopy.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fotiai10%2Fcopy?ref=badge_large) \ No newline at end of file
diff --git a/vendor/github.com/otiai10/copy/copy.go b/vendor/github.com/otiai10/copy/copy.go
new file mode 100644
index 0000000..085db78
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/copy.go
@@ -0,0 +1,284 @@
1package copy
2
3import (
4 "io"
5 "io/fs"
6 "io/ioutil"
7 "os"
8 "path/filepath"
9 "time"
10)
11
12type timespec struct {
13 Mtime time.Time
14 Atime time.Time
15 Ctime time.Time
16}
17
18// Copy copies src to dest, doesn't matter if src is a directory or a file.
19func Copy(src, dest string, opts ...Options) error {
20 opt := assureOptions(src, dest, opts...)
21 if opt.FS != nil {
22 info, err := fs.Stat(opt.FS, src)
23 if err != nil {
24 return onError(src, dest, err, opt)
25 }
26 return switchboard(src, dest, info, opt)
27 }
28 info, err := os.Lstat(src)
29 if err != nil {
30 return onError(src, dest, err, opt)
31 }
32 return switchboard(src, dest, info, opt)
33}
34
35// switchboard switches proper copy functions regarding file type, etc...
36// If there would be anything else here, add a case to this switchboard.
37func switchboard(src, dest string, info os.FileInfo, opt Options) (err error) {
38 if info.Mode()&os.ModeDevice != 0 && !opt.Specials {
39 return onError(src, dest, err, opt)
40 }
41
42 switch {
43 case info.Mode()&os.ModeSymlink != 0:
44 err = onsymlink(src, dest, opt)
45 case info.IsDir():
46 err = dcopy(src, dest, info, opt)
47 case info.Mode()&os.ModeNamedPipe != 0:
48 err = pcopy(dest, info)
49 default:
50 err = fcopy(src, dest, info, opt)
51 }
52
53 return onError(src, dest, err, opt)
54}
55
56// copyNextOrSkip decide if this src should be copied or not.
57// Because this "copy" could be called recursively,
58// "info" MUST be given here, NOT nil.
59func copyNextOrSkip(src, dest string, info os.FileInfo, opt Options) error {
60 if opt.Skip != nil {
61 skip, err := opt.Skip(info, src, dest)
62 if err != nil {
63 return err
64 }
65 if skip {
66 return nil
67 }
68 }
69 return switchboard(src, dest, info, opt)
70}
71
72// fcopy is for just a file,
73// with considering existence of parent directory
74// and file permission.
75func fcopy(src, dest string, info os.FileInfo, opt Options) (err error) {
76
77 var readcloser io.ReadCloser
78 if opt.FS != nil {
79 readcloser, err = opt.FS.Open(src)
80 } else {
81 readcloser, err = os.Open(src)
82 }
83 if err != nil {
84 if os.IsNotExist(err) {
85 return nil
86 }
87 return
88 }
89 defer fclose(readcloser, &err)
90
91 if err = os.MkdirAll(filepath.Dir(dest), os.ModePerm); err != nil {
92 return
93 }
94
95 f, err := os.Create(dest)
96 if err != nil {
97 return
98 }
99 defer fclose(f, &err)
100
101 chmodfunc, err := opt.PermissionControl(info, dest)
102 if err != nil {
103 return err
104 }
105 chmodfunc(&err)
106
107 var buf []byte = nil
108 var w io.Writer = f
109 var r io.Reader = readcloser
110
111 if opt.WrapReader != nil {
112 r = opt.WrapReader(r)
113 }
114
115 if opt.CopyBufferSize != 0 {
116 buf = make([]byte, opt.CopyBufferSize)
117 // Disable using `ReadFrom` by io.CopyBuffer.
118 // See https://github.com/otiai10/copy/pull/60#discussion_r627320811 for more details.
119 w = struct{ io.Writer }{f}
120 // r = struct{ io.Reader }{s}
121 }
122
123 if _, err = io.CopyBuffer(w, r, buf); err != nil {
124 return err
125 }
126
127 if opt.Sync {
128 err = f.Sync()
129 }
130
131 if opt.PreserveOwner {
132 if err := preserveOwner(src, dest, info); err != nil {
133 return err
134 }
135 }
136 if opt.PreserveTimes {
137 if err := preserveTimes(info, dest); err != nil {
138 return err
139 }
140 }
141
142 return
143}
144
145// dcopy is for a directory,
146// with scanning contents inside the directory
147// and pass everything to "copy" recursively.
148func dcopy(srcdir, destdir string, info os.FileInfo, opt Options) (err error) {
149 if skip, err := onDirExists(opt, srcdir, destdir); err != nil {
150 return err
151 } else if skip {
152 return nil
153 }
154
155 // Make dest dir with 0755 so that everything writable.
156 chmodfunc, err := opt.PermissionControl(info, destdir)
157 if err != nil {
158 return err
159 }
160 defer chmodfunc(&err)
161
162 var contents []os.FileInfo
163 if opt.FS != nil {
164 entries, err := fs.ReadDir(opt.FS, srcdir)
165 if err != nil {
166 return err
167 }
168 for _, e := range entries {
169 info, err := e.Info()
170 if err != nil {
171 return err
172 }
173 contents = append(contents, info)
174 }
175 } else {
176 contents, err = ioutil.ReadDir(srcdir)
177 }
178
179 if err != nil {
180 if os.IsNotExist(err) {
181 return nil
182 }
183 return
184 }
185
186 for _, content := range contents {
187 cs, cd := filepath.Join(srcdir, content.Name()), filepath.Join(destdir, content.Name())
188
189 if err = copyNextOrSkip(cs, cd, content, opt); err != nil {
190 // If any error, exit immediately
191 return
192 }
193 }
194
195 if opt.PreserveTimes {
196 if err := preserveTimes(info, destdir); err != nil {
197 return err
198 }
199 }
200
201 if opt.PreserveOwner {
202 if err := preserveOwner(srcdir, destdir, info); err != nil {
203 return err
204 }
205 }
206
207 return
208}
209
210func onDirExists(opt Options, srcdir, destdir string) (bool, error) {
211 _, err := os.Stat(destdir)
212 if err == nil && opt.OnDirExists != nil && destdir != opt.intent.dest {
213 switch opt.OnDirExists(srcdir, destdir) {
214 case Replace:
215 if err := os.RemoveAll(destdir); err != nil {
216 return false, err
217 }
218 case Untouchable:
219 return true, nil
220 } // case "Merge" is default behaviour. Go through.
221 } else if err != nil && !os.IsNotExist(err) {
222 return true, err // Unwelcome error type...!
223 }
224 return false, nil
225}
226
227func onsymlink(src, dest string, opt Options) error {
228 switch opt.OnSymlink(src) {
229 case Shallow:
230 if err := lcopy(src, dest); err != nil {
231 return err
232 }
233 if opt.PreserveTimes {
234 return preserveLtimes(src, dest)
235 }
236 return nil
237 case Deep:
238 orig, err := os.Readlink(src)
239 if err != nil {
240 return err
241 }
242 info, err := os.Lstat(orig)
243 if err != nil {
244 return err
245 }
246 return copyNextOrSkip(orig, dest, info, opt)
247 case Skip:
248 fallthrough
249 default:
250 return nil // do nothing
251 }
252}
253
254// lcopy is for a symlink,
255// with just creating a new symlink by replicating src symlink.
256func lcopy(src, dest string) error {
257 src, err := os.Readlink(src)
258 if err != nil {
259 if os.IsNotExist(err) {
260 return nil
261 }
262 return err
263 }
264 return os.Symlink(src, dest)
265}
266
267// fclose ANYHOW closes file,
268// with asiging error raised during Close,
269// BUT respecting the error already reported.
270func fclose(f io.Closer, reported *error) {
271 if err := f.Close(); *reported == nil {
272 *reported = err
273 }
274}
275
276// onError lets caller to handle errors
277// occured when copying a file.
278func onError(src, dest string, err error, opt Options) error {
279 if opt.OnError == nil {
280 return err
281 }
282
283 return opt.OnError(src, dest, err)
284}
diff --git a/vendor/github.com/otiai10/copy/copy_namedpipes.go b/vendor/github.com/otiai10/copy/copy_namedpipes.go
new file mode 100644
index 0000000..615ddcd
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/copy_namedpipes.go
@@ -0,0 +1,18 @@
1//go:build !windows && !plan9 && !netbsd && !aix && !illumos && !solaris && !js
2// +build !windows,!plan9,!netbsd,!aix,!illumos,!solaris,!js
3
4package copy
5
6import (
7 "os"
8 "path/filepath"
9 "syscall"
10)
11
12// pcopy is for just named pipes
13func pcopy(dest string, info os.FileInfo) error {
14 if err := os.MkdirAll(filepath.Dir(dest), os.ModePerm); err != nil {
15 return err
16 }
17 return syscall.Mkfifo(dest, uint32(info.Mode()))
18}
diff --git a/vendor/github.com/otiai10/copy/copy_namedpipes_x.go b/vendor/github.com/otiai10/copy/copy_namedpipes_x.go
new file mode 100644
index 0000000..38dd9dc
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/copy_namedpipes_x.go
@@ -0,0 +1,15 @@
1//go:build windows || plan9 || netbsd || aix || illumos || solaris || js
2// +build windows plan9 netbsd aix illumos solaris js
3
4package copy
5
6import (
7 "os"
8)
9
10// TODO: check plan9 netbsd aix illumos solaris in future
11
12// pcopy is for just named pipes. Windows doesn't support them
13func pcopy(dest string, info os.FileInfo) error {
14 return nil
15}
diff --git a/vendor/github.com/otiai10/copy/fileinfo_go1.15.go b/vendor/github.com/otiai10/copy/fileinfo_go1.15.go
new file mode 100644
index 0000000..c0708ea
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/fileinfo_go1.15.go
@@ -0,0 +1,17 @@
1//go:build !go1.16
2// +build !go1.16
3
4package copy
5
6import "os"
7
8// This is a cloned definition of os.FileInfo (go1.15) or fs.FileInfo (go1.16~)
9// A FileInfo describes a file and is returned by Stat.
10type fileInfo interface {
11 // Name() string // base name of the file
12 // Size() int64 // length in bytes for regular files; system-dependent for others
13 Mode() os.FileMode // file mode bits
14 // ModTime() time.Time // modification time
15 IsDir() bool // abbreviation for Mode().IsDir()
16 Sys() interface{} // underlying data source (can return nil)
17}
diff --git a/vendor/github.com/otiai10/copy/fileinfo_go1.16.go b/vendor/github.com/otiai10/copy/fileinfo_go1.16.go
new file mode 100644
index 0000000..01b3fd2
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/fileinfo_go1.16.go
@@ -0,0 +1,17 @@
1//go:build go1.16
2// +build go1.16
3
4package copy
5
6import "io/fs"
7
8// This is a cloned definition of os.FileInfo (go1.15) or fs.FileInfo (go1.16~)
9// A FileInfo describes a file and is returned by Stat.
10type fileInfo interface {
11 // Name() string // base name of the file
12 // Size() int64 // length in bytes for regular files; system-dependent for others
13 Mode() fs.FileMode // file mode bits
14 // ModTime() time.Time // modification time
15 IsDir() bool // abbreviation for Mode().IsDir()
16 Sys() interface{} // underlying data source (can return nil)
17}
diff --git a/vendor/github.com/otiai10/copy/options.go b/vendor/github.com/otiai10/copy/options.go
new file mode 100644
index 0000000..1b4e508
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/options.go
@@ -0,0 +1,143 @@
1package copy
2
3import (
4 "io"
5 "io/fs"
6 "os"
7)
8
9// Options specifies optional actions on copying.
10type Options struct {
11
12 // OnSymlink can specify what to do on symlink
13 OnSymlink func(src string) SymlinkAction
14
15 // OnDirExists can specify what to do when there is a directory already existing in destination.
16 OnDirExists func(src, dest string) DirExistsAction
17
18 // OnErr lets called decide whether or not to continue on particular copy error.
19 OnError func(src, dest string, err error) error
20
21 // Skip can specify which files should be skipped
22 Skip func(srcinfo os.FileInfo, src, dest string) (bool, error)
23
24 // Specials includes special files to be copied. default false.
25 Specials bool
26
27 // AddPermission to every entities,
28 // NO MORE THAN 0777
29 // @OBSOLETE
30 // Use `PermissionControl = AddPermission(perm)` instead
31 AddPermission os.FileMode
32
33 // PermissionControl can preserve or even add permission to
34 // every entries, for example
35 //
36 // opt.PermissionControl = AddPermission(0222)
37 //
38 // See permission_control.go for more detail.
39 PermissionControl PermissionControlFunc
40
41 // Sync file after copy.
42 // Useful in case when file must be on the disk
43 // (in case crash happens, for example),
44 // at the expense of some performance penalty
45 Sync bool
46
47 // Preserve the atime and the mtime of the entries.
48 // On linux we can preserve only up to 1 millisecond accuracy.
49 PreserveTimes bool
50
51 // Preserve the uid and the gid of all entries.
52 PreserveOwner bool
53
54 // The byte size of the buffer to use for copying files.
55 // If zero, the internal default buffer of 32KB is used.
56 // See https://golang.org/pkg/io/#CopyBuffer for more information.
57 CopyBufferSize uint
58
59 // If you want to add some limitation on reading src file,
60 // you can wrap the src and provide new reader,
61 // such as `RateLimitReader` in the test case.
62 WrapReader func(src io.Reader) io.Reader
63
64 // If given, copy.Copy refers to this fs.FS instead of the OS filesystem.
65 // e.g., You can use embed.FS to copy files from embedded filesystem.
66 FS fs.FS
67
68 intent struct {
69 src string
70 dest string
71 }
72}
73
74// SymlinkAction represents what to do on symlink.
75type SymlinkAction int
76
77const (
78 // Deep creates hard-copy of contents.
79 Deep SymlinkAction = iota
80 // Shallow creates new symlink to the dest of symlink.
81 Shallow
82 // Skip does nothing with symlink.
83 Skip
84)
85
86// DirExistsAction represents what to do on dest dir.
87type DirExistsAction int
88
89const (
90 // Merge preserves or overwrites existing files under the dir (default behavior).
91 Merge DirExistsAction = iota
92 // Replace deletes all contents under the dir and copy src files.
93 Replace
94 // Untouchable does nothing for the dir, and leaves it as it is.
95 Untouchable
96)
97
98// getDefaultOptions provides default options,
99// which would be modified by usage-side.
100func getDefaultOptions(src, dest string) Options {
101 return Options{
102 OnSymlink: func(string) SymlinkAction {
103 return Shallow // Do shallow copy
104 },
105 OnDirExists: nil, // Default behavior is "Merge".
106 OnError: nil, // Default is "accept error"
107 Skip: nil, // Do not skip anything
108 AddPermission: 0, // Add nothing
109 PermissionControl: PerservePermission, // Just preserve permission
110 Sync: false, // Do not sync
111 Specials: false, // Do not copy special files
112 PreserveTimes: false, // Do not preserve the modification time
113 CopyBufferSize: 0, // Do not specify, use default bufsize (32*1024)
114 WrapReader: nil, // Do not wrap src files, use them as they are.
115 intent: struct {
116 src string
117 dest string
118 }{src, dest},
119 }
120}
121
122// assureOptions struct, should be called only once.
123// All optional values MUST NOT BE nil/zero after assured.
124func assureOptions(src, dest string, opts ...Options) Options {
125 defopt := getDefaultOptions(src, dest)
126 if len(opts) == 0 {
127 return defopt
128 }
129 if opts[0].OnSymlink == nil {
130 opts[0].OnSymlink = defopt.OnSymlink
131 }
132 if opts[0].Skip == nil {
133 opts[0].Skip = defopt.Skip
134 }
135 if opts[0].AddPermission > 0 {
136 opts[0].PermissionControl = AddPermission(opts[0].AddPermission)
137 } else if opts[0].PermissionControl == nil {
138 opts[0].PermissionControl = PerservePermission
139 }
140 opts[0].intent.src = defopt.intent.src
141 opts[0].intent.dest = defopt.intent.dest
142 return opts[0]
143}
diff --git a/vendor/github.com/otiai10/copy/permission_control.go b/vendor/github.com/otiai10/copy/permission_control.go
new file mode 100644
index 0000000..97ae12d
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/permission_control.go
@@ -0,0 +1,48 @@
1package copy
2
3import (
4 "os"
5)
6
7const (
8 // tmpPermissionForDirectory makes the destination directory writable,
9 // so that stuff can be copied recursively even if any original directory is NOT writable.
10 // See https://github.com/otiai10/copy/pull/9 for more information.
11 tmpPermissionForDirectory = os.FileMode(0755)
12)
13
14type PermissionControlFunc func(srcinfo fileInfo, dest string) (chmodfunc func(*error), err error)
15
16var (
17 AddPermission = func(perm os.FileMode) PermissionControlFunc {
18 return func(srcinfo fileInfo, dest string) (func(*error), error) {
19 orig := srcinfo.Mode()
20 if srcinfo.IsDir() {
21 if err := os.MkdirAll(dest, tmpPermissionForDirectory); err != nil {
22 return func(*error) {}, err
23 }
24 }
25 return func(err *error) {
26 chmod(dest, orig|perm, err)
27 }, nil
28 }
29 }
30 PerservePermission PermissionControlFunc = AddPermission(0)
31 DoNothing PermissionControlFunc = func(srcinfo fileInfo, dest string) (func(*error), error) {
32 if srcinfo.IsDir() {
33 if err := os.MkdirAll(dest, srcinfo.Mode()); err != nil {
34 return func(*error) {}, err
35 }
36 }
37 return func(*error) {}, nil
38 }
39)
40
41// chmod ANYHOW changes file mode,
42// with asiging error raised during Chmod,
43// BUT respecting the error already reported.
44func chmod(dir string, mode os.FileMode, reported *error) {
45 if err := os.Chmod(dir, mode); *reported == nil {
46 *reported = err
47 }
48}
diff --git a/vendor/github.com/otiai10/copy/preserve_ltimes.go b/vendor/github.com/otiai10/copy/preserve_ltimes.go
new file mode 100644
index 0000000..cc006d3
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/preserve_ltimes.go
@@ -0,0 +1,20 @@
1//go:build !windows && !plan9 && !js
2// +build !windows,!plan9,!js
3
4package copy
5
6import (
7 "golang.org/x/sys/unix"
8)
9
10func preserveLtimes(src, dest string) error {
11 info := new(unix.Stat_t)
12 if err := unix.Lstat(src, info); err != nil {
13 return err
14 }
15
16 return unix.Lutimes(dest, []unix.Timeval{
17 unix.NsecToTimeval(info.Atim.Nano()),
18 unix.NsecToTimeval(info.Mtim.Nano()),
19 })
20}
diff --git a/vendor/github.com/otiai10/copy/preserve_ltimes_x.go b/vendor/github.com/otiai10/copy/preserve_ltimes_x.go
new file mode 100644
index 0000000..02aec40
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/preserve_ltimes_x.go
@@ -0,0 +1,8 @@
1//go:build windows || js || plan9
2// +build windows js plan9
3
4package copy
5
6func preserveLtimes(src, dest string) error {
7 return nil // Unsupported
8}
diff --git a/vendor/github.com/otiai10/copy/preserve_owner.go b/vendor/github.com/otiai10/copy/preserve_owner.go
new file mode 100644
index 0000000..13ec4f5
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/preserve_owner.go
@@ -0,0 +1,23 @@
1//go:build !windows && !plan9
2// +build !windows,!plan9
3
4package copy
5
6import (
7 "os"
8 "syscall"
9)
10
11func preserveOwner(src, dest string, info fileInfo) (err error) {
12 if info == nil {
13 if info, err = os.Stat(src); err != nil {
14 return err
15 }
16 }
17 if stat, ok := info.Sys().(*syscall.Stat_t); ok {
18 if err := os.Chown(dest, int(stat.Uid), int(stat.Gid)); err != nil {
19 return err
20 }
21 }
22 return nil
23}
diff --git a/vendor/github.com/otiai10/copy/preserve_owner_x.go b/vendor/github.com/otiai10/copy/preserve_owner_x.go
new file mode 100644
index 0000000..9d82574
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/preserve_owner_x.go
@@ -0,0 +1,8 @@
1//go:build windows || plan9
2// +build windows plan9
3
4package copy
5
6func preserveOwner(src, dest string, info fileInfo) (err error) {
7 return nil
8}
diff --git a/vendor/github.com/otiai10/copy/preserve_times.go b/vendor/github.com/otiai10/copy/preserve_times.go
new file mode 100644
index 0000000..d89b128
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/preserve_times.go
@@ -0,0 +1,11 @@
1package copy
2
3import "os"
4
5func preserveTimes(srcinfo os.FileInfo, dest string) error {
6 spec := getTimeSpec(srcinfo)
7 if err := os.Chtimes(dest, spec.Atime, spec.Mtime); err != nil {
8 return err
9 }
10 return nil
11}
diff --git a/vendor/github.com/otiai10/copy/stat_times.go b/vendor/github.com/otiai10/copy/stat_times.go
new file mode 100644
index 0000000..75f45f6
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/stat_times.go
@@ -0,0 +1,22 @@
1//go:build !windows && !darwin && !freebsd && !plan9 && !netbsd && !js
2// +build !windows,!darwin,!freebsd,!plan9,!netbsd,!js
3
4// TODO: add more runtimes
5
6package copy
7
8import (
9 "os"
10 "syscall"
11 "time"
12)
13
14func getTimeSpec(info os.FileInfo) timespec {
15 stat := info.Sys().(*syscall.Stat_t)
16 times := timespec{
17 Mtime: info.ModTime(),
18 Atime: time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec)),
19 Ctime: time.Unix(int64(stat.Ctim.Sec), int64(stat.Ctim.Nsec)),
20 }
21 return times
22}
diff --git a/vendor/github.com/otiai10/copy/stat_times_darwin.go b/vendor/github.com/otiai10/copy/stat_times_darwin.go
new file mode 100644
index 0000000..d4c23d8
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/stat_times_darwin.go
@@ -0,0 +1,20 @@
1//go:build darwin
2// +build darwin
3
4package copy
5
6import (
7 "os"
8 "syscall"
9 "time"
10)
11
12func getTimeSpec(info os.FileInfo) timespec {
13 stat := info.Sys().(*syscall.Stat_t)
14 times := timespec{
15 Mtime: info.ModTime(),
16 Atime: time.Unix(stat.Atimespec.Sec, stat.Atimespec.Nsec),
17 Ctime: time.Unix(stat.Ctimespec.Sec, stat.Ctimespec.Nsec),
18 }
19 return times
20}
diff --git a/vendor/github.com/otiai10/copy/stat_times_freebsd.go b/vendor/github.com/otiai10/copy/stat_times_freebsd.go
new file mode 100644
index 0000000..5309334
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/stat_times_freebsd.go
@@ -0,0 +1,20 @@
1//go:build freebsd
2// +build freebsd
3
4package copy
5
6import (
7 "os"
8 "syscall"
9 "time"
10)
11
12func getTimeSpec(info os.FileInfo) timespec {
13 stat := info.Sys().(*syscall.Stat_t)
14 times := timespec{
15 Mtime: info.ModTime(),
16 Atime: time.Unix(int64(stat.Atimespec.Sec), int64(stat.Atimespec.Nsec)),
17 Ctime: time.Unix(int64(stat.Ctimespec.Sec), int64(stat.Ctimespec.Nsec)),
18 }
19 return times
20}
diff --git a/vendor/github.com/otiai10/copy/stat_times_js.go b/vendor/github.com/otiai10/copy/stat_times_js.go
new file mode 100644
index 0000000..c645771
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/stat_times_js.go
@@ -0,0 +1,20 @@
1//go:build js
2// +build js
3
4package copy
5
6import (
7 "os"
8 "syscall"
9 "time"
10)
11
12func getTimeSpec(info os.FileInfo) timespec {
13 stat := info.Sys().(*syscall.Stat_t)
14 times := timespec{
15 Mtime: info.ModTime(),
16 Atime: time.Unix(int64(stat.Atime), int64(stat.AtimeNsec)),
17 Ctime: time.Unix(int64(stat.Ctime), int64(stat.CtimeNsec)),
18 }
19 return times
20}
diff --git a/vendor/github.com/otiai10/copy/stat_times_windows.go b/vendor/github.com/otiai10/copy/stat_times_windows.go
new file mode 100644
index 0000000..d6a84a7
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/stat_times_windows.go
@@ -0,0 +1,19 @@
1//go:build windows
2// +build windows
3
4package copy
5
6import (
7 "os"
8 "syscall"
9 "time"
10)
11
12func getTimeSpec(info os.FileInfo) timespec {
13 stat := info.Sys().(*syscall.Win32FileAttributeData)
14 return timespec{
15 Mtime: time.Unix(0, stat.LastWriteTime.Nanoseconds()),
16 Atime: time.Unix(0, stat.LastAccessTime.Nanoseconds()),
17 Ctime: time.Unix(0, stat.CreationTime.Nanoseconds()),
18 }
19}
diff --git a/vendor/github.com/otiai10/copy/stat_times_x.go b/vendor/github.com/otiai10/copy/stat_times_x.go
new file mode 100644
index 0000000..886ddd3
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/stat_times_x.go
@@ -0,0 +1,18 @@
1//go:build plan9 || netbsd
2// +build plan9 netbsd
3
4package copy
5
6import (
7 "os"
8)
9
10// TODO: check plan9 netbsd in future
11func getTimeSpec(info os.FileInfo) timespec {
12 times := timespec{
13 Mtime: info.ModTime(),
14 Atime: info.ModTime(),
15 Ctime: info.ModTime(),
16 }
17 return times
18}
diff --git a/vendor/github.com/otiai10/copy/test/data/case18/assets/README.md b/vendor/github.com/otiai10/copy/test/data/case18/assets/README.md
new file mode 100644
index 0000000..5570c7f
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/test/data/case18/assets/README.md
@@ -0,0 +1 @@
# Hello \ No newline at end of file
diff --git a/vendor/github.com/otiai10/copy/test_setup.go b/vendor/github.com/otiai10/copy/test_setup.go
new file mode 100644
index 0000000..64a5292
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/test_setup.go
@@ -0,0 +1,20 @@
1//go:build !windows && !plan9 && !netbsd && !aix && !illumos && !solaris && !js
2// +build !windows,!plan9,!netbsd,!aix,!illumos,!solaris,!js
3
4package copy
5
6import (
7 "os"
8 "syscall"
9 "testing"
10)
11
12func setup(m *testing.M) {
13 os.RemoveAll("test/data.copy")
14 os.MkdirAll("test/data.copy", os.ModePerm)
15 os.Symlink("test/data/case01", "test/data/case03/case01")
16 os.Chmod("test/data/case07/dir_0555", 0o555)
17 os.Chmod("test/data/case07/file_0444", 0o444)
18 syscall.Mkfifo("test/data/case11/foo/bar", 0o555)
19 Copy("test/data/case18/assets", "test/data/case18/assets.backup")
20}
diff --git a/vendor/github.com/otiai10/copy/test_setup_x.go b/vendor/github.com/otiai10/copy/test_setup_x.go
new file mode 100644
index 0000000..4c35b14
--- /dev/null
+++ b/vendor/github.com/otiai10/copy/test_setup_x.go
@@ -0,0 +1,17 @@
1//go:build windows || plan9 || netbsd || aix || illumos || solaris || js
2// +build windows plan9 netbsd aix illumos solaris js
3
4package copy
5
6import (
7 "os"
8 "testing"
9)
10
11func setup(m *testing.M) {
12 os.RemoveAll("test/data.copy")
13 os.MkdirAll("test/data.copy", os.ModePerm)
14 os.Symlink("test/data/case01", "test/data/case03/case01")
15 os.Chmod("test/data/case07/dir_0555", 0555)
16 os.Chmod("test/data/case07/file_0444", 0444)
17}