Skip to content

Commit

Permalink
Fix relative symlinks copying
Browse files Browse the repository at this point in the history
All relative paths of symbolic links should be resolved from the
directory where the link is located. The current working directory
does not affect the resolution of the path. A symbolic link can
be absolute or relative, and may or may not have a leading dot.
Directory content example:
file
symlink -> file
Copying of the directory with such content does not work currently.
When copying `symlink`, `Copy` returns an error because the `file`
does not exist in the current working directory. In the existing
tests, there is a symbolic link named "symlink" that points to a
file named "README.md". However, when resolving the path of the
file, the file is located in the repository's root directory,
not the test case directory, and copying of these dirs work fine.

The solution is to check whether the resolved path is absolute
or not. If it is not, append it to the file's directory path.
  • Loading branch information
psergee committed Jun 6, 2024
1 parent c464078 commit 1ddce65
Show file tree
Hide file tree
Showing 6 changed files with 11 additions and 7 deletions.
2 changes: 1 addition & 1 deletion all_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,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.Remove("test/data/case03/relative_foo")
os.RemoveAll("test/data.copy")
os.RemoveAll("test/data.copyTime")
os.RemoveAll("test/owned-by-root") // Do not check the error ;)
Expand Down
3 changes: 1 addition & 2 deletions copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"io/fs"
"os"
"path/filepath"
"strings"
"time"

"golang.org/x/sync/errgroup"
Expand Down Expand Up @@ -293,7 +292,7 @@ func onsymlink(src, dest string, opt Options) error {
if err != nil {
return err
}
if strings.HasPrefix(orig, ".") {
if !filepath.IsAbs(orig) {
// orig is a relative link: need to add src dir to orig
orig = filepath.Join(filepath.Dir(src), orig)
}
Expand Down
7 changes: 6 additions & 1 deletion symlink_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ 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")
info, err = os.Lstat("test/data.copy/case03.deep/relative_foo")
Expect(t, err).ToBe(nil)
Expect(t, info.Mode()&os.ModeSymlink).ToBe(os.FileMode(0))

Expand All @@ -26,12 +26,17 @@ func TestOptions_OnSymlink(t *testing.T) {
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))
linkTarget, err := os.Readlink("test/data.copy/case03.shallow/relative_foo")
Expect(t, err).ToBe(nil)
Expect(t, linkTarget).ToBe("foo")

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 = os.Stat("test/data.copy/case03.skip/relative_foo")
Expect(t, os.IsNotExist(err)).ToBe(true)

err = Copy("test/data/case03", "test/data.copy/case03.default")
Expect(t, err).ToBe(nil)
Expand Down
Empty file added test/data/case03/foo
Empty file.
4 changes: 2 additions & 2 deletions test_setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
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.Symlink("../case01", "test/data/case03/case01")
os.Symlink("foo", "test/data/case03/relative_foo")
os.Chmod("test/data/case07/dir_0555", 0o555)
os.Chmod("test/data/case07/file_0444", 0o444)
syscall.Mkfifo("test/data/case11/foo/bar", 0o555)
Expand Down
2 changes: 1 addition & 1 deletion test_setup_x_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
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/case01")
os.Chmod("test/data/case07/dir_0555", 0555)
os.Chmod("test/data/case07/file_0444", 0444)
}

0 comments on commit 1ddce65

Please sign in to comment.