From 39c8e6a599c2b4b7dcb444fb8f1aec20322ddf97 Mon Sep 17 00:00:00 2001 From: Samuel Phan Date: Tue, 17 Jan 2023 03:25:43 +0100 Subject: [PATCH 1/4] fix: symlink deep copy with relative path fix #97 --- all_test.go | 4 ++++ copy.go | 5 +++++ test_setup.go | 1 + 3 files changed, 10 insertions(+) diff --git a/all_test.go b/all_test.go index 910570a..6990c05 100644 --- a/all_test.go +++ b/all_test.go @@ -22,6 +22,7 @@ func TestMain(m *testing.M) { func teardown(m *testing.M) { os.RemoveAll("test/data/case03/case01") + os.RemoveAll("test/data/case03/relative_case01") os.RemoveAll("test/data.copy") os.RemoveAll("test/data.copyTime") os.RemoveAll("test/owned-by-root") // Do not check the error ;) @@ -123,6 +124,9 @@ func TestOptions_OnSymlink(t *testing.T) { info, err := os.Lstat("test/data.copy/case03.deep/case01") Expect(t, err).ToBe(nil) Expect(t, info.Mode()&os.ModeSymlink).ToBe(os.FileMode(0)) + info, err = os.Lstat("test/data.copy/case03.deep/relative_case01") + Expect(t, err).ToBe(nil) + Expect(t, info.Mode()&os.ModeSymlink).ToBe(os.FileMode(0)) opt = Options{OnSymlink: func(string) SymlinkAction { return Shallow }} err = Copy("test/data/case03", "test/data.copy/case03.shallow", opt) diff --git a/copy.go b/copy.go index 60643dd..2ad0000 100644 --- a/copy.go +++ b/copy.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "os" "path/filepath" + "strings" "time" ) @@ -205,6 +206,10 @@ func onsymlink(src, dest string, opt Options) error { if err != nil { return err } + if strings.HasPrefix(orig, ".") { + // orig is a relative link: need to add src dir to orig + orig = filepath.Join(filepath.Dir(src), orig) + } info, err := os.Lstat(orig) if err != nil { return err diff --git a/test_setup.go b/test_setup.go index f3c2d83..2575a29 100644 --- a/test_setup.go +++ b/test_setup.go @@ -13,6 +13,7 @@ func setup(m *testing.M) { os.RemoveAll("test/data.copy") os.MkdirAll("test/data.copy", os.ModePerm) os.Symlink("test/data/case01", "test/data/case03/case01") + os.Symlink("../case01", "test/data/case03/relative_case01") os.Chmod("test/data/case07/dir_0555", 0o555) os.Chmod("test/data/case07/file_0444", 0o444) syscall.Mkfifo("test/data/case11/foo/bar", 0o555) From 334c7c2e3672977ca19734df94114eab4fb2f412 Mon Sep 17 00:00:00 2001 From: Samuel Phan Date: Wed, 6 Sep 2023 00:52:15 +0200 Subject: [PATCH 2/4] fix: update deps --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f1c6bc2..7f93fc5 100644 --- a/go.mod +++ b/go.mod @@ -4,5 +4,5 @@ go 1.14 require ( github.com/otiai10/mint v1.4.0 - golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 + golang.org/x/sys v0.12.0 ) diff --git a/go.sum b/go.sum index ee2753e..0465854 100644 --- a/go.sum +++ b/go.sum @@ -4,5 +4,5 @@ github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6 github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/otiai10/mint v1.4.0 h1:umwcf7gbpEwf7WFzqmWwSv0CzbeMsae2u9ZvpP8j2q4= github.com/otiai10/mint v1.4.0/go.mod h1:gifjb2MYOoULtKLqUAEILUG/9KONW6f7YsJ6vQLTlFI= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= From 90802d1d7b75c3c6a50a86d9bb2fe8b8905d74a1 Mon Sep 17 00:00:00 2001 From: Samuel Phan Date: Thu, 7 Sep 2023 11:29:32 +0200 Subject: [PATCH 3/4] fix: revert go.mod & go.sum to upstream --- go.mod | 6 +++--- go.sum | 12 ++++-------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index 7f93fc5..2263c9e 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/otiai10/copy -go 1.14 +go 1.18 require ( - github.com/otiai10/mint v1.4.0 - golang.org/x/sys v0.12.0 + github.com/otiai10/mint v1.5.1 + golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 ) diff --git a/go.sum b/go.sum index 0465854..7fc5834 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,4 @@ -github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= -github.com/otiai10/curr v1.0.0 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI= -github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= -github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= -github.com/otiai10/mint v1.4.0 h1:umwcf7gbpEwf7WFzqmWwSv0CzbeMsae2u9ZvpP8j2q4= -github.com/otiai10/mint v1.4.0/go.mod h1:gifjb2MYOoULtKLqUAEILUG/9KONW6f7YsJ6vQLTlFI= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= +github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= From c51b95f0b2122d5c620033dd438148b1ebfcdfb9 Mon Sep 17 00:00:00 2001 From: Denis VAUMORON Date: Thu, 7 Sep 2023 17:42:24 +0200 Subject: [PATCH 4/4] fix: extract symlink_test.go from all_test.go and separate it on os in symlink_test_x.go --- all_test.go | 38 ------------------------------------ symlink_test.go | 49 +++++++++++++++++++++++++++++++++++++++++++++++ symlink_test_x.go | 46 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 38 deletions(-) create mode 100644 symlink_test.go create mode 100644 symlink_test_x.go diff --git a/all_test.go b/all_test.go index 218ea94..e5d82f5 100644 --- a/all_test.go +++ b/all_test.go @@ -166,44 +166,6 @@ func TestCopy_NamedPipe(t *testing.T) { }) } -func TestOptions_OnSymlink(t *testing.T) { - opt := Options{OnSymlink: func(string) SymlinkAction { return Deep }} - err := Copy("test/data/case03", "test/data.copy/case03.deep", opt) - Expect(t, err).ToBe(nil) - info, err := os.Lstat("test/data.copy/case03.deep/case01") - Expect(t, err).ToBe(nil) - Expect(t, info.Mode()&os.ModeSymlink).ToBe(os.FileMode(0)) - info, err = os.Lstat("test/data.copy/case03.deep/relative_case01") - Expect(t, err).ToBe(nil) - Expect(t, info.Mode()&os.ModeSymlink).ToBe(os.FileMode(0)) - - opt = Options{OnSymlink: func(string) SymlinkAction { return Shallow }} - err = Copy("test/data/case03", "test/data.copy/case03.shallow", opt) - Expect(t, err).ToBe(nil) - info, err = os.Lstat("test/data.copy/case03.shallow/case01") - Expect(t, err).ToBe(nil) - Expect(t, info.Mode()&os.ModeSymlink).Not().ToBe(os.FileMode(0)) - - opt = Options{OnSymlink: func(string) SymlinkAction { return Skip }} - err = Copy("test/data/case03", "test/data.copy/case03.skip", opt) - Expect(t, err).ToBe(nil) - _, err = os.Stat("test/data.copy/case03.skip/case01") - Expect(t, os.IsNotExist(err)).ToBe(true) - - err = Copy("test/data/case03", "test/data.copy/case03.default") - Expect(t, err).ToBe(nil) - info, err = os.Lstat("test/data.copy/case03.default/case01") - Expect(t, err).ToBe(nil) - Expect(t, info.Mode()&os.ModeSymlink).Not().ToBe(os.FileMode(0)) - - opt = Options{OnSymlink: nil} - err = Copy("test/data/case03", "test/data.copy/case03.not-specified", opt) - Expect(t, err).ToBe(nil) - info, err = os.Lstat("test/data.copy/case03.not-specified/case01") - Expect(t, err).ToBe(nil) - Expect(t, info.Mode()&os.ModeSymlink).Not().ToBe(os.FileMode(0)) -} - func TestOptions_Skip(t *testing.T) { opt := Options{Skip: func(info os.FileInfo, src, dest string) (bool, error) { switch { diff --git a/symlink_test.go b/symlink_test.go new file mode 100644 index 0000000..9f464cd --- /dev/null +++ b/symlink_test.go @@ -0,0 +1,49 @@ +//go:build !windows && !plan9 && !netbsd && !aix && !illumos && !solaris && !js +// +build !windows,!plan9,!netbsd,!aix,!illumos,!solaris,!js + +package copy + +import ( + "os" + "testing" + + . "github.com/otiai10/mint" +) + +func TestOptions_OnSymlink(t *testing.T) { + opt := Options{OnSymlink: func(string) SymlinkAction { return Deep }} + err := Copy("test/data/case03", "test/data.copy/case03.deep", opt) + Expect(t, err).ToBe(nil) + info, err := os.Lstat("test/data.copy/case03.deep/case01") + Expect(t, err).ToBe(nil) + Expect(t, info.Mode()&os.ModeSymlink).ToBe(os.FileMode(0)) + info, err = os.Lstat("test/data.copy/case03.deep/relative_case01") + Expect(t, err).ToBe(nil) + Expect(t, info.Mode()&os.ModeSymlink).ToBe(os.FileMode(0)) + + opt = Options{OnSymlink: func(string) SymlinkAction { return Shallow }} + err = Copy("test/data/case03", "test/data.copy/case03.shallow", opt) + Expect(t, err).ToBe(nil) + info, err = os.Lstat("test/data.copy/case03.shallow/case01") + Expect(t, err).ToBe(nil) + Expect(t, info.Mode()&os.ModeSymlink).Not().ToBe(os.FileMode(0)) + + opt = Options{OnSymlink: func(string) SymlinkAction { return Skip }} + err = Copy("test/data/case03", "test/data.copy/case03.skip", opt) + Expect(t, err).ToBe(nil) + _, err = os.Stat("test/data.copy/case03.skip/case01") + Expect(t, os.IsNotExist(err)).ToBe(true) + + err = Copy("test/data/case03", "test/data.copy/case03.default") + Expect(t, err).ToBe(nil) + info, err = os.Lstat("test/data.copy/case03.default/case01") + Expect(t, err).ToBe(nil) + Expect(t, info.Mode()&os.ModeSymlink).Not().ToBe(os.FileMode(0)) + + opt = Options{OnSymlink: nil} + err = Copy("test/data/case03", "test/data.copy/case03.not-specified", opt) + Expect(t, err).ToBe(nil) + info, err = os.Lstat("test/data.copy/case03.not-specified/case01") + Expect(t, err).ToBe(nil) + Expect(t, info.Mode()&os.ModeSymlink).Not().ToBe(os.FileMode(0)) +} diff --git a/symlink_test_x.go b/symlink_test_x.go new file mode 100644 index 0000000..523f7f0 --- /dev/null +++ b/symlink_test_x.go @@ -0,0 +1,46 @@ +//go:build windows || plan9 || netbsd || aix || illumos || solaris || js +// +build windows plan9 netbsd aix illumos solaris js + +package copy + +import ( + "os" + "testing" + + . "github.com/otiai10/mint" +) + +func TestOptions_OnSymlink(t *testing.T) { + opt := Options{OnSymlink: func(string) SymlinkAction { return Deep }} + err := Copy("test/data/case03", "test/data.copy/case03.deep", opt) + Expect(t, err).ToBe(nil) + info, err := os.Lstat("test/data.copy/case03.deep/case01") + Expect(t, err).ToBe(nil) + Expect(t, info.Mode()&os.ModeSymlink).ToBe(os.FileMode(0)) + + opt = Options{OnSymlink: func(string) SymlinkAction { return Shallow }} + err = Copy("test/data/case03", "test/data.copy/case03.shallow", opt) + Expect(t, err).ToBe(nil) + info, err = os.Lstat("test/data.copy/case03.shallow/case01") + Expect(t, err).ToBe(nil) + Expect(t, info.Mode()&os.ModeSymlink).Not().ToBe(os.FileMode(0)) + + opt = Options{OnSymlink: func(string) SymlinkAction { return Skip }} + err = Copy("test/data/case03", "test/data.copy/case03.skip", opt) + Expect(t, err).ToBe(nil) + _, err = os.Stat("test/data.copy/case03.skip/case01") + Expect(t, os.IsNotExist(err)).ToBe(true) + + err = Copy("test/data/case03", "test/data.copy/case03.default") + Expect(t, err).ToBe(nil) + info, err = os.Lstat("test/data.copy/case03.default/case01") + Expect(t, err).ToBe(nil) + Expect(t, info.Mode()&os.ModeSymlink).Not().ToBe(os.FileMode(0)) + + opt = Options{OnSymlink: nil} + err = Copy("test/data/case03", "test/data.copy/case03.not-specified", opt) + Expect(t, err).ToBe(nil) + info, err = os.Lstat("test/data.copy/case03.not-specified/case01") + Expect(t, err).ToBe(nil) + Expect(t, info.Mode()&os.ModeSymlink).Not().ToBe(os.FileMode(0)) +}