Skip to content

Commit

Permalink
refactor: Split common code out of CopyBytes
Browse files Browse the repository at this point in the history
Permission changes, ownership preservation, and access/modify/creation
time presevation is something all implementations need. I brought it
out of the CopyBytes implementation so it can be shared when more
implementations are added later.

A small note:

The "ignore if source file deleted" check had to be brought out of
`CopyBytes`. The way it worked before is it returned no error, which
meant `fcopy` would try and modify the destination file (which was never
created). Instead, I check for the error explicitly in `fcopy`.
  • Loading branch information
eth-p committed Aug 24, 2024
1 parent 7e68063 commit 7bb84a4
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 27 deletions.
41 changes: 40 additions & 1 deletion copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package copy

import (
"context"
"errors"
"io"
"io/fs"
"os"
Expand Down Expand Up @@ -86,7 +87,45 @@ 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) {
return opt.FileCopyFunc.fcopy(src, dest, info, opt)
if err = os.MkdirAll(filepath.Dir(dest), os.ModePerm); err != nil {
return
}

// Use FileCopyMethod to do copy.
if err = opt.FileCopyFunc.fcopy(src, dest, info, opt); err != nil {
if pathError, ok := err.(*os.PathError); ok && errors.Is(err, os.ErrNotExist) && pathError.Path == src {
// Source file deleted. Ignore error.
return nil
}

return err
}

// Change file permissions.
chmodfunc, err := opt.PermissionControl(info, dest)
if err != nil {
return err
}

chmodfunc(&err)
if err != nil {
return err
}

// Preserve file ownership and times.
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
}
}

return
}

// dcopy is for a directory,
Expand Down
26 changes: 0 additions & 26 deletions copy_methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"errors"
"io"
"os"
"path/filepath"
)

// ErrUnsupportedCopyMethod is returned when the FileCopyMethod specified in
Expand All @@ -17,37 +16,23 @@ var ErrUnsupportedCopyMethod = errors.New(
// then writing the buffer back to the destination file.
var CopyBytes = FileCopyMethod{
fcopy: func(src, dest string, info os.FileInfo, opt Options) (err error) {

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)

if err = os.MkdirAll(filepath.Dir(dest), os.ModePerm); err != nil {
return
}

f, err := os.Create(dest)
if err != nil {
return
}
defer fclose(f, &err)

chmodfunc, err := opt.PermissionControl(info, dest)
if err != nil {
return err
}
chmodfunc(&err)

var buf []byte = nil
var w io.Writer = f
var r io.Reader = readcloser
Expand All @@ -72,17 +57,6 @@ var CopyBytes = FileCopyMethod{
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
}
}

return
},
}

0 comments on commit 7bb84a4

Please sign in to comment.