diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 39f75cd..a6b05d2 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -5,7 +5,6 @@ on: branches: [ main, develop ] pull_request: branches: [ main, develop ] - workflow_dispatch: jobs: diff --git a/copy.go b/copy.go index b938adc..f9787cd 100644 --- a/copy.go +++ b/copy.go @@ -86,38 +86,66 @@ func copyNextOrSkip(src, dest string, info os.FileInfo, opt Options) error { // with considering existence of parent directory // and file permission. func fcopy(src, dest string, info os.FileInfo, opt Options) (err error) { - if err = os.MkdirAll(filepath.Dir(dest), os.ModePerm); err != nil { + + var readcloser io.ReadCloser + if opt.FS != nil { + readcloser, err = opt.FS.Open(src) + } else { + readcloser, err = os.Open(src) + } + if err != nil { + if os.IsNotExist(err) { + return nil + } return } + defer fclose(readcloser, &err) - // Use FileCopyMethod to do copy. - err, skipFile := opt.FileCopyMethod.fcopy(src, dest, info, opt) - if skipFile { - return nil + if err = os.MkdirAll(filepath.Dir(dest), os.ModePerm); err != nil { + return } + f, err := os.Create(dest) if err != nil { - return err + return } + defer fclose(f, &err) - // Change file permissions. chmodfunc, err := opt.PermissionControl(info, dest) if err != nil { return err } - chmodfunc(&err) - if err != nil { + + var buf []byte = nil + var w io.Writer = f + var r io.Reader = readcloser + + if opt.WrapReader != nil { + r = opt.WrapReader(r) + } + + if opt.CopyBufferSize != 0 { + buf = make([]byte, opt.CopyBufferSize) + // Disable using `ReadFrom` by io.CopyBuffer. + // See https://github.com/otiai10/copy/pull/60#discussion_r627320811 for more details. + w = struct{ io.Writer }{f} + // r = struct{ io.Reader }{s} + } + + if _, err = io.CopyBuffer(w, r, buf); err != nil { return err } - // Preserve file ownership and times. + if opt.Sync { + err = f.Sync() + } + if opt.PreserveOwner { if err := preserveOwner(src, dest, info); err != nil { return err } } - if opt.PreserveTimes { if err := preserveTimes(info, dest); err != nil { return err diff --git a/copy_methods.go b/copy_methods.go deleted file mode 100644 index 7245fe4..0000000 --- a/copy_methods.go +++ /dev/null @@ -1,65 +0,0 @@ -package copy - -import ( - "errors" - "io" - "os" -) - -// ErrUnsupportedCopyMethod is returned when the FileCopyMethod specified in -// Options is not supported. -var ErrUnsupportedCopyMethod = errors.New( - "copy method not supported", -) - -// CopyBytes copies the file contents by reading the source file into a buffer, -// then writing the buffer back to the destination file. -var CopyBytes = FileCopyMethod{ - fcopy: func(src, dest string, info os.FileInfo, opt Options) (err error, skipFile bool) { - var readcloser io.ReadCloser - if opt.FS != nil { - readcloser, err = opt.FS.Open(src) - } else { - readcloser, err = os.Open(src) - } - if err != nil { - if os.IsNotExist(err) { - return nil, true - } - return - } - defer fclose(readcloser, &err) - - f, err := os.Create(dest) - if err != nil { - return - } - defer fclose(f, &err) - - var buf []byte = nil - var w io.Writer = f - var r io.Reader = readcloser - - if opt.WrapReader != nil { - r = opt.WrapReader(r) - } - - if opt.CopyBufferSize != 0 { - buf = make([]byte, opt.CopyBufferSize) - // Disable using `ReadFrom` by io.CopyBuffer. - // See https://github.com/otiai10/copy/pull/60#discussion_r627320811 for more details. - w = struct{ io.Writer }{f} - // r = struct{ io.Reader }{s} - } - - if _, err = io.CopyBuffer(w, r, buf); err != nil { - return err, false - } - - if opt.Sync { - err = f.Sync() - } - - return - }, -} diff --git a/options.go b/options.go index 709c7f4..c1db48c 100644 --- a/options.go +++ b/options.go @@ -27,16 +27,6 @@ type Options struct { // RenameDestination can specify the destination file or dir name if needed to rename. RenameDestination func(src, dest string) (string, error) - // FileCopyMethod specifies the method by which a regular file is copied. - // The default is CopyBytes. - // - // Available implementations: - // - CopyBytes (best compatibility) - // - // Some implementations may not be supported on the target GOOS, or on - // the user's filesystem. When these fail, an error will be returned. - FileCopyMethod FileCopyMethod - // Specials includes special files to be copied. default false. Specials bool @@ -129,11 +119,6 @@ const ( Untouchable ) -// FileCopyMethod represents one of the ways that a regular file can be copied. -type FileCopyMethod struct { - fcopy func(src, dest string, info os.FileInfo, opt Options) (err error, skipFile bool) -} - // getDefaultOptions provides default options, // which would be modified by usage-side. func getDefaultOptions(src, dest string) Options { @@ -149,7 +134,6 @@ func getDefaultOptions(src, dest string) Options { Sync: false, // Do not sync Specials: false, // Do not copy special files PreserveTimes: false, // Do not preserve the modification time - FileCopyMethod: CopyBytes, // Copy by bytes CopyBufferSize: 0, // Do not specify, use default bufsize (32*1024) WrapReader: nil, // Do not wrap src files, use them as they are. intent: intent{src, dest, nil, nil}, @@ -174,9 +158,6 @@ func assureOptions(src, dest string, opts ...Options) Options { } else if opts[0].PermissionControl == nil { opts[0].PermissionControl = PerservePermission } - if opts[0].FileCopyMethod.fcopy == nil { - opts[0].FileCopyMethod = defopt.FileCopyMethod - } opts[0].intent.src = defopt.intent.src opts[0].intent.dest = defopt.intent.dest return opts[0]