fix: on Windows you must call filepath.Walkdir on the realpath and not the symlink path (#335)
This commit is contained in:
parent
ce043b299d
commit
74caa5c097
8
deps.bzl
8
deps.bzl
|
@ -21,6 +21,14 @@ def go_dependencies():
|
|||
sum = "h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=",
|
||||
version = "v0.5.8",
|
||||
)
|
||||
go_repository(
|
||||
name = "com_github_yookoala_realpath",
|
||||
build_file_proto_mode = "disable_global",
|
||||
importpath = "github.com/yookoala/realpath",
|
||||
sum = "h1:7OA9pj4FZd+oZDsyvXWQvjn5oBdcHRTV44PpdMSuImQ=",
|
||||
version = "v1.0.0",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "org_golang_x_exp",
|
||||
build_file_proto_mode = "disable_global",
|
||||
|
|
1
go.mod
1
go.mod
|
@ -4,5 +4,6 @@ go 1.19
|
|||
|
||||
require (
|
||||
github.com/bmatcuk/doublestar/v4 v4.6.0
|
||||
github.com/yookoala/realpath v1.0.0
|
||||
golang.org/x/exp v0.0.0-20221230185412-738e83a70c30
|
||||
)
|
||||
|
|
2
go.sum
2
go.sum
|
@ -1,4 +1,6 @@
|
|||
github.com/bmatcuk/doublestar/v4 v4.6.0 h1:HTuxyug8GyFbRkrffIpzNCSK4luc0TY3wzXvzIZhEXc=
|
||||
github.com/bmatcuk/doublestar/v4 v4.6.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||
github.com/yookoala/realpath v1.0.0 h1:7OA9pj4FZd+oZDsyvXWQvjn5oBdcHRTV44PpdMSuImQ=
|
||||
github.com/yookoala/realpath v1.0.0/go.mod h1:gJJMA9wuX7AcqLy1+ffPatSCySA1FQ2S8Ya9AIoYBpE=
|
||||
golang.org/x/exp v0.0.0-20221230185412-738e83a70c30 h1:m9O6OTJ627iFnN2JIWfdqlZCzneRO6EEBsHXI25P8ws=
|
||||
golang.org/x/exp v0.0.0-20221230185412-738e83a70c30/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package common
|
||||
|
||||
import "path/filepath"
|
||||
import (
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// Same as filepath.Rel except that it normalizes result to forward slashes
|
||||
// slashes since filepath.Rel will convert to system slashes
|
||||
|
|
|
@ -5,7 +5,10 @@ go_library(
|
|||
srcs = ["main.go"],
|
||||
importpath = "github.com/aspect-build/bazel-lib/tools/copy_directory",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//tools/common"],
|
||||
deps = [
|
||||
"//tools/common",
|
||||
"@com_github_yookoala_realpath//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
|
|
|
@ -5,11 +5,11 @@ import (
|
|||
"io/fs"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/aspect-build/bazel-lib/tools/common"
|
||||
"github.com/yookoala/realpath"
|
||||
)
|
||||
|
||||
type pathSet map[string]bool
|
||||
|
@ -46,13 +46,10 @@ func copyDir(src string, dst string) error {
|
|||
|
||||
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||
// symlink to directories are intentionally never followed by filepath.Walk to avoid infinite recursion
|
||||
linkPath, err := os.Readlink(p)
|
||||
linkPath, err := realpath.Realpath(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !path.IsAbs(linkPath) {
|
||||
linkPath = path.Join(path.Dir(p), linkPath)
|
||||
}
|
||||
if srcPaths[linkPath] {
|
||||
// recursive symlink; silently ignore
|
||||
return nil
|
||||
|
|
|
@ -8,6 +8,7 @@ go_library(
|
|||
deps = [
|
||||
"//tools/common",
|
||||
"@com_github_bmatcuk_doublestar_v4//:doublestar",
|
||||
"@com_github_yookoala_realpath//:go_default_library",
|
||||
"@org_golang_x_exp//maps",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
|
||||
"github.com/aspect-build/bazel-lib/tools/common"
|
||||
"github.com/bmatcuk/doublestar/v4"
|
||||
"github.com/yookoala/realpath"
|
||||
"golang.org/x/exp/maps"
|
||||
)
|
||||
|
||||
|
@ -26,6 +27,7 @@ type fileInfo struct {
|
|||
WorkspacePath string `json:"workspace_path"`
|
||||
Hardlink bool `json:"hardlink"`
|
||||
|
||||
Realpath string
|
||||
FileInfo fs.FileInfo
|
||||
}
|
||||
|
||||
|
@ -124,7 +126,11 @@ func copyDir(cfg *config, srcPaths pathSet, file fileInfo) error {
|
|||
srcPaths[file.Path] = true
|
||||
// filepath.WalkDir walks the file tree rooted at root, calling fn for each file or directory in
|
||||
// the tree, including root. See https://pkg.go.dev/path/filepath#WalkDir for more info.
|
||||
return filepath.WalkDir(file.Path, func(p string, dirEntry fs.DirEntry, err error) error {
|
||||
walkPath := file.Path
|
||||
if file.Realpath != "" {
|
||||
walkPath = file.Realpath
|
||||
}
|
||||
return filepath.WalkDir(walkPath, func(p string, dirEntry fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -142,20 +148,17 @@ func copyDir(cfg *config, srcPaths pathSet, file fileInfo) error {
|
|||
return err
|
||||
}
|
||||
|
||||
r, err := common.FileRel(file.Path, p)
|
||||
r, err := common.FileRel(walkPath, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||
// symlink to directories are intentionally never followed by filepath.Walk to avoid infinite recursion
|
||||
linkPath, err := os.Readlink(p)
|
||||
linkPath, err := realpath.Realpath(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !path.IsAbs(linkPath) {
|
||||
linkPath = path.Join(path.Dir(p), linkPath)
|
||||
}
|
||||
if srcPaths[linkPath] {
|
||||
// recursive symlink; silently ignore
|
||||
return nil
|
||||
|
@ -330,11 +333,28 @@ func copyPath(cfg *config, file fileInfo) error {
|
|||
|
||||
func copyPaths(cfg *config) error {
|
||||
for _, file := range cfg.Files {
|
||||
stat, err := os.Stat(file.Path)
|
||||
info, err := os.Lstat(file.Path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to stat file %s: %w", file.Path, err)
|
||||
return fmt.Errorf("failed to lstat file %s: %w", file.Path, err)
|
||||
}
|
||||
file.FileInfo = stat
|
||||
|
||||
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||
// On Windows, filepath.WalkDir doesn't like directory symlinks so we must
|
||||
// call filepath.WalkDir on the realpath
|
||||
realpath, err := realpath.Realpath(file.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stat, err := os.Stat(realpath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to stat file %s pointed to by symlink %s: %w", realpath, file.Path, err)
|
||||
}
|
||||
file.Realpath = realpath
|
||||
file.FileInfo = stat
|
||||
} else {
|
||||
file.FileInfo = info
|
||||
}
|
||||
|
||||
if file.FileInfo.IsDir() {
|
||||
if err := copyDir(cfg, nil, file); err != nil {
|
||||
return err
|
||||
|
|
Loading…
Reference in New Issue