Skip to content

Commit

Permalink
Merge pull request #92 from otiai10/breaking-change/skip-with-fileinfo
Browse files Browse the repository at this point in the history
[Breaking Change] Skip now accepts FileInfo
  • Loading branch information
otiai10 authored Nov 9, 2022
2 parents 705b76e + fa129b1 commit 4c7c24d
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 30 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ type Options struct {
OnDirExists func(src, dest string) DirExistsAction

// Skip can specify which files should be skipped
Skip func(src string) (bool, error)
Skip func(srcinfo os.FileInfo, src, dest string) (bool, error)

// PermissionControl can control permission of
// every entry.
Expand Down Expand Up @@ -80,7 +80,7 @@ type Options struct {
```go
// For example...
opt := Options{
Skip: func(src string) (bool, error) {
Skip: func(info os.FileInfo, src, dest string) (bool, error) {
return strings.HasSuffix(src, ".git"), nil
},
}
Expand Down
8 changes: 4 additions & 4 deletions all_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func TestOptions_OnSymlink(t *testing.T) {
}

func TestOptions_Skip(t *testing.T) {
opt := Options{Skip: func(src string) (bool, error) {
opt := Options{Skip: func(info os.FileInfo, src, dest string) (bool, error) {
switch {
case strings.HasSuffix(src, "_skip"):
return true, nil
Expand Down Expand Up @@ -186,7 +186,7 @@ func TestOptions_Skip(t *testing.T) {

Because(t, "if Skip func returns error, Copy should be interrupted", func(t *testing.T) {
errInsideSkipFunc := errors.New("Something wrong inside Skip")
opt := Options{Skip: func(src string) (bool, error) {
opt := Options{Skip: func(info os.FileInfo, src, dest string) (bool, error) {
return false, errInsideSkipFunc
}}
err := Copy("test/data/case06", "test/data.copy/case06.01", opt)
Expand Down Expand Up @@ -357,9 +357,9 @@ func TestOptions_CopyRateLimit(t *testing.T) {

start := time.Now()
err = Copy("test/data/case16", "test/data.copy/case16", opt)
elasped := time.Since(start)
elapsed := time.Since(start)
Expect(t, err).ToBe(nil)
Expect(t, elasped > 5*time.Second).ToBe(true)
Expect(t, elapsed > 5*time.Second).ToBe(true)
}

type SleepyReader struct {
Expand Down
47 changes: 29 additions & 18 deletions copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@ func switchboard(src, dest string, info os.FileInfo, opt Options) (err error) {
// Because this "copy" could be called recursively,
// "info" MUST be given here, NOT nil.
func copyNextOrSkip(src, dest string, info os.FileInfo, opt Options) error {
skip, err := opt.Skip(src)
if err != nil {
return err
}
if skip {
return nil
if opt.Skip != nil {
skip, err := opt.Skip(info, src, dest)
if err != nil {
return err
}
if skip {
return nil
}
}
return switchboard(src, dest, info, opt)
}
Expand Down Expand Up @@ -129,18 +131,10 @@ func fcopy(src, dest string, info os.FileInfo, opt Options) (err error) {
// and pass everything to "copy" recursively.
func dcopy(srcdir, destdir string, info os.FileInfo, opt Options) (err error) {

_, err = os.Stat(destdir)
if err == nil && opt.OnDirExists != nil && destdir != opt.intent.dest {
switch opt.OnDirExists(srcdir, destdir) {
case Replace:
if err := os.RemoveAll(destdir); err != nil {
return err
}
case Untouchable:
return nil
} // case "Merge" is default behaviour. Go through.
} else if err != nil && !os.IsNotExist(err) {
return err // Unwelcome error type...!
if skip, err := onDirExists(opt, srcdir, destdir); err != nil {
return err
} else if skip {
return nil
}

// Make dest dir with 0755 so that everything writable.
Expand Down Expand Up @@ -179,6 +173,23 @@ func dcopy(srcdir, destdir string, info os.FileInfo, opt Options) (err error) {
return
}

func onDirExists(opt Options, srcdir, destdir string) (bool, error) {
_, err := os.Stat(destdir)
if err == nil && opt.OnDirExists != nil && destdir != opt.intent.dest {
switch opt.OnDirExists(srcdir, destdir) {
case Replace:
if err := os.RemoveAll(destdir); err != nil {
return false, err
}
case Untouchable:
return true, nil
} // case "Merge" is default behaviour. Go through.
} else if err != nil && !os.IsNotExist(err) {
return true, err // Unwelcome error type...!
}
return false, nil
}

func onsymlink(src, dest string, opt Options) error {
switch opt.OnSymlink(src) {
case Shallow:
Expand Down
2 changes: 1 addition & 1 deletion example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func ExampleOptions() {
"test/data/example",
"test/data.copy/example_with_options",
Options{
Skip: func(src string) (bool, error) {
Skip: func(info os.FileInfo, src, dest string) (bool, error) {
return strings.HasSuffix(src, ".git-like"), nil
},
OnSymlink: func(src string) SymlinkAction {
Expand Down
8 changes: 3 additions & 5 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type Options struct {
OnDirExists func(src, dest string) DirExistsAction

// Skip can specify which files should be skipped
Skip func(src string) (bool, error)
Skip func(srcinfo os.FileInfo, src, dest string) (bool, error)

// Specials includes special files to be copied. default false.
Specials bool
Expand Down Expand Up @@ -94,10 +94,8 @@ func getDefaultOptions(src, dest string) Options {
OnSymlink: func(string) SymlinkAction {
return Shallow // Do shallow copy
},
OnDirExists: nil, // Default behavior is "Merge".
Skip: func(string) (bool, error) {
return false, nil // Don't skip
},
OnDirExists: nil, // Default behavior is "Merge".
Skip: nil, // Do not skip anything
AddPermission: 0, // Add nothing
PermissionControl: PerservePermission, // Just preserve permission
Sync: false, // Do not sync
Expand Down

0 comments on commit 4c7c24d

Please sign in to comment.