Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: handle symlink copying #39

Merged
merged 1 commit into from
Mar 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 31 additions & 4 deletions fileutils/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ package fileutils
import (
"os"
"path"
"path/filepath"
"strings"

"github.com/spf13/afero"
)

// Copy copies a file or folder from one place to another.
func Copy(fs afero.Fs, src, dst string) error {
func Copy(fs afero.Fs, src, dst, scope string) error {
if src = path.Clean("/" + src); src == "" {
return os.ErrNotExist
}
Expand All @@ -31,9 +33,34 @@ func Copy(fs afero.Fs, src, dst string) error {
return err
}

if info.IsDir() {
return CopyDir(fs, src, dst)
switch info.Mode() & os.ModeType {
case os.ModeDir:
return CopyDir(fs, src, dst, scope)
case os.ModeSymlink:
return CopySymLink(fs, src, dst, scope)
default:
return CopyFile(fs, src, dst)
}
}

func CopySymLink(fs afero.Fs, source, dest, scope string) error {
if reader, ok := fs.(afero.LinkReader); ok {
link, err := reader.ReadlinkIfPossible(source)
if err != nil {
return err
}

return CopyFile(fs, src, dst)
if filepath.IsAbs(link) {
link = strings.TrimPrefix(link, scope)
link = filepath.Join(string(os.PathSeparator), link)
} else {
link = filepath.Clean(filepath.Join(filepath.Dir(source), link))
}

if linker, ok := fs.(afero.Linker); ok {
return linker.SymlinkIfPossible(link, dest)
}
return nil
}
return nil
}
18 changes: 11 additions & 7 deletions fileutils/dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package fileutils

import (
"errors"
"os"
"path/filepath"

"github.com/spf13/afero"
Expand All @@ -10,7 +11,7 @@ import (
// CopyDir copies a directory from source to dest and all
// of its sub-directories. It doesn't stop if it finds an error
// during the copy. Returns an error if any.
func CopyDir(fs afero.Fs, source, dest string) error {
func CopyDir(fs afero.Fs, source, dest, scope string) error {
// Get properties of source.
srcinfo, err := fs.Stat(source)
if err != nil {
Expand All @@ -35,16 +36,19 @@ func CopyDir(fs afero.Fs, source, dest string) error {
fsource := source + "/" + obj.Name()
fdest := dest + "/" + obj.Name()

if obj.IsDir() {
switch obj.Mode() & os.ModeType {
case os.ModeDir:
// Create sub-directories, recursively.
err = CopyDir(fs, fsource, fdest)
if err != nil {
if err := CopyDir(fs, fsource, fdest, scope); err != nil {
errs = append(errs, err)
}
} else {
case os.ModeSymlink:
if err := CopySymLink(fs, fsource, fdest, scope); err != nil {
return err
}
default:
// Perform the file copy.
err = CopyFile(fs, fsource, fdest)
if err != nil {
if err := CopyFile(fs, fsource, fdest); err != nil {
errs = append(errs, err)
}
}
Expand Down
14 changes: 7 additions & 7 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"watch": "find ./dist -maxdepth 1 -mindepth 1 ! -name '.gitignore' -exec rm -r {} + && vue-cli-service build --watch --no-clean"
},
"dependencies": {
"ace-builds": "^1.4.7",
"ace-builds": "^1.5.1",
"clipboard": "^2.0.4",
"core-js": "^3.9.1",
"css-vars-ponyfill": "^2.4.3",
Expand Down
2 changes: 1 addition & 1 deletion http/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ func patchAction(ctx context.Context, action, src, dst string, d *data, fileCach
return errors.ErrPermissionDenied
}

return fileutils.Copy(d.user.Fs, src, dst)
return fileutils.Copy(d.user.Fs, src, dst, d.server.Root)
case "rename":
if !d.user.Perm.Rename {
return errors.ErrPermissionDenied
Expand Down