fix: exclude files in copy_to_directory before checking their realpath (#857)
This commit is contained in:
parent
f30debb505
commit
7a8f00cd7f
|
@ -26,7 +26,6 @@ type fileInfo struct {
|
||||||
WorkspacePath string `json:"workspace_path"`
|
WorkspacePath string `json:"workspace_path"`
|
||||||
Hardlink bool `json:"hardlink"`
|
Hardlink bool `json:"hardlink"`
|
||||||
|
|
||||||
Realpath string
|
|
||||||
FileInfo fs.FileInfo
|
FileInfo fs.FileInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,9 +130,6 @@ func (w *walker) copyDir(cfg *config, srcPaths pathSet, file fileInfo) error {
|
||||||
// filepath.WalkDir walks the file tree rooted at root, calling fn for each file or directory in
|
// 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.
|
// the tree, including root. See https://pkg.go.dev/path/filepath#WalkDir for more info.
|
||||||
walkPath := file.Path
|
walkPath := file.Path
|
||||||
if file.Realpath != "" {
|
|
||||||
walkPath = file.Realpath
|
|
||||||
}
|
|
||||||
return filepath.WalkDir(walkPath, func(p string, dirEntry fs.DirEntry, err error) error {
|
return filepath.WalkDir(walkPath, func(p string, dirEntry fs.DirEntry, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -157,53 +153,6 @@ func (w *walker) copyDir(cfg *config, srcPaths pathSet, file fileInfo) error {
|
||||||
return err
|
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 := common.Realpath(p)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return fmt.Errorf("failed to get realpath of dangling symlink %s: %w", p, err)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("failed to get realpath of %s: %w", p, err)
|
|
||||||
}
|
|
||||||
if srcPaths[linkPath] {
|
|
||||||
// recursive symlink; silently ignore
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
stat, err := os.Stat(linkPath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to stat file %s pointed to by symlink %s: %w", linkPath, p, err)
|
|
||||||
}
|
|
||||||
if stat.IsDir() {
|
|
||||||
// symlink points to a directory
|
|
||||||
f := fileInfo{
|
|
||||||
Package: file.Package,
|
|
||||||
Path: linkPath,
|
|
||||||
RootPath: file.RootPath,
|
|
||||||
ShortPath: file.ShortPath,
|
|
||||||
Workspace: file.Workspace,
|
|
||||||
WorkspacePath: file.WorkspacePath,
|
|
||||||
Hardlink: file.Hardlink,
|
|
||||||
FileInfo: stat,
|
|
||||||
}
|
|
||||||
return w.copyDir(cfg, srcPaths, f)
|
|
||||||
} else {
|
|
||||||
// symlink points to a regular file
|
|
||||||
f := fileInfo{
|
|
||||||
Package: file.Package,
|
|
||||||
Path: linkPath,
|
|
||||||
RootPath: file.RootPath,
|
|
||||||
ShortPath: path.Join(file.ShortPath, r),
|
|
||||||
Workspace: file.Workspace,
|
|
||||||
WorkspacePath: path.Join(file.WorkspacePath, r),
|
|
||||||
Hardlink: file.Hardlink,
|
|
||||||
FileInfo: stat,
|
|
||||||
}
|
|
||||||
return w.copyPath(cfg, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// a regular file
|
|
||||||
f := fileInfo{
|
f := fileInfo{
|
||||||
Package: file.Package,
|
Package: file.Package,
|
||||||
Path: p,
|
Path: p,
|
||||||
|
@ -214,7 +163,43 @@ func (w *walker) copyDir(cfg *config, srcPaths pathSet, file fileInfo) error {
|
||||||
Hardlink: file.Hardlink,
|
Hardlink: file.Hardlink,
|
||||||
FileInfo: info,
|
FileInfo: info,
|
||||||
}
|
}
|
||||||
return w.copyPath(cfg, f)
|
|
||||||
|
outputPath, err := w.calculateOutputPath(cfg, f)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to calculate output path for %s: %w", file.WorkspacePath, err)
|
||||||
|
}
|
||||||
|
if outputPath == "" {
|
||||||
|
// this path is excluded
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// if file is a symlink, resolve its realpath
|
||||||
|
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||||
|
realpath, err := common.Realpath(p)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return fmt.Errorf("failed to get realpath of dangling symlink %s: %w", p, err)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("failed to get realpath of %s: %w", p, err)
|
||||||
|
}
|
||||||
|
if srcPaths[realpath] {
|
||||||
|
// recursive symlink; silently ignore
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
stat, err := os.Stat(realpath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to stat file %s pointed to by symlink %s: %w", realpath, p, err)
|
||||||
|
}
|
||||||
|
f.Path = realpath
|
||||||
|
f.FileInfo = stat
|
||||||
|
|
||||||
|
if stat.IsDir() {
|
||||||
|
// symlink points to a directory
|
||||||
|
return w.copyDir(cfg, srcPaths, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return w.copyPath(cfg, f, outputPath)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,16 +290,7 @@ func (w *walker) calculateOutputPath(cfg *config, file fileInfo) (string, error)
|
||||||
return path.Join(cfg.Dst, outputPath), nil
|
return path.Join(cfg.Dst, outputPath), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *walker) copyPath(cfg *config, file fileInfo) error {
|
func (w *walker) copyPath(cfg *config, file fileInfo, outputPath string) error {
|
||||||
outputPath, err := w.calculateOutputPath(cfg, file)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to calculate output path %s: %w", file.WorkspacePath, err)
|
|
||||||
}
|
|
||||||
if outputPath == "" {
|
|
||||||
// this path is excluded
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// add this file to the copy Paths
|
// add this file to the copy Paths
|
||||||
dup, exists := copySet[outputPath]
|
dup, exists := copySet[outputPath]
|
||||||
if exists {
|
if exists {
|
||||||
|
@ -329,7 +305,7 @@ func (w *walker) copyPath(cfg *config, file fileInfo) error {
|
||||||
|
|
||||||
outputDir := path.Dir(outputPath)
|
outputDir := path.Dir(outputPath)
|
||||||
if !mkdirSet[outputDir] {
|
if !mkdirSet[outputDir] {
|
||||||
if err = os.MkdirAll(outputDir, os.ModePerm); err != nil {
|
if err := os.MkdirAll(outputDir, os.ModePerm); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// https://pkg.go.dev/path#Dir
|
// https://pkg.go.dev/path#Dir
|
||||||
|
@ -353,10 +329,27 @@ func (w *walker) copyPaths(cfg *config) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to lstat file %s: %w", file.Path, err)
|
return fmt.Errorf("failed to lstat file %s: %w", file.Path, err)
|
||||||
}
|
}
|
||||||
|
file.FileInfo = info
|
||||||
|
|
||||||
|
// if file is a directory, then short-circuit without calculating the output path
|
||||||
|
if file.FileInfo.IsDir() {
|
||||||
|
if err := w.copyDir(cfg, nil, file); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
outputPath, err := w.calculateOutputPath(cfg, file)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to calculate output path for %s: %w", file.WorkspacePath, err)
|
||||||
|
}
|
||||||
|
if outputPath == "" {
|
||||||
|
// this path is excluded
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// if file is a symlink, resolve its realpath
|
||||||
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
|
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 := common.Realpath(file.Path)
|
realpath, err := common.Realpath(file.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
|
@ -368,21 +361,21 @@ func (w *walker) copyPaths(cfg *config) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to stat file %s pointed to by symlink %s: %w", realpath, file.Path, err)
|
return fmt.Errorf("failed to stat file %s pointed to by symlink %s: %w", realpath, file.Path, err)
|
||||||
}
|
}
|
||||||
file.Realpath = realpath
|
file.Path = realpath
|
||||||
file.FileInfo = stat
|
file.FileInfo = stat
|
||||||
} else {
|
|
||||||
file.FileInfo = info
|
|
||||||
}
|
|
||||||
|
|
||||||
if file.FileInfo.IsDir() {
|
if file.FileInfo.IsDir() {
|
||||||
|
// symlink points to a directory
|
||||||
if err := w.copyDir(cfg, nil, file); err != nil {
|
if err := w.copyDir(cfg, nil, file); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
continue
|
||||||
if err := w.copyPath(cfg, file); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := w.copyPath(cfg, file, outputPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue