diff --git a/internal/gio/copy.go b/internal/gio/copy.go index 365e855f3..942999ee0 100644 --- a/internal/gio/copy.go +++ b/internal/gio/copy.go @@ -35,6 +35,9 @@ func CopyWithMode(src, dst string, mode os.FileMode) error { if info.IsDir() { return os.MkdirAll(dst, info.Mode()) } + if info.Mode()&os.ModeSymlink != 0 { + return copySymlink(path, dst) + } if mode != 0 { return copyFile(path, dst, mode) } @@ -42,6 +45,14 @@ func CopyWithMode(src, dst string, mode os.FileMode) error { }) } +func copySymlink(src, dst string) error { + src, err := os.Readlink(src) + if err != nil { + return err + } + return os.Symlink(src, dst) +} + func copyFile(src, dst string, mode os.FileMode) error { original, err := os.Open(src) if err != nil { diff --git a/internal/gio/copy_test.go b/internal/gio/copy_test.go index f9beb12e4..cfff6ba2c 100644 --- a/internal/gio/copy_test.go +++ b/internal/gio/copy_test.go @@ -17,6 +17,23 @@ func TestCopy(t *testing.T) { requireEqualFiles(t, a, b) } +func TestCopySymlink(t *testing.T) { + tmp := t.TempDir() + a := "testdata/somefile.txt" + b := tmp + "/somefile.txt" + c := tmp + "/somefile2.txt" + require.NoError(t, os.Symlink(a, b)) + require.NoError(t, Copy(b, c)) + + fi, err := os.Lstat(c) + require.NoError(t, err) + require.True(t, fi.Mode()&os.ModeSymlink != 0) + + l, err := os.Readlink(c) + require.NoError(t, err) + require.Equal(t, a, l) +} + func TestEqualFilesModeChanged(t *testing.T) { tmp := t.TempDir() a := "testdata/somefile.txt"