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"`
|
||||
Hardlink bool `json:"hardlink"`
|
||||
|
||||
Realpath string
|
||||
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
|
||||
// the tree, including root. See https://pkg.go.dev/path/filepath#WalkDir for more info.
|
||||
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
|
||||
|
@ -157,53 +153,6 @@ func (w *walker) copyDir(cfg *config, srcPaths pathSet, file fileInfo) error {
|
|||
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{
|
||||
Package: file.Package,
|
||||
Path: p,
|
||||
|
@ -214,7 +163,43 @@ func (w *walker) copyDir(cfg *config, srcPaths pathSet, file fileInfo) error {
|
|||
Hardlink: file.Hardlink,
|
||||
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
|
||||
}
|
||||
|
||||
func (w *walker) copyPath(cfg *config, file fileInfo) 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
|
||||
}
|
||||
|
||||
func (w *walker) copyPath(cfg *config, file fileInfo, outputPath string) error {
|
||||
// add this file to the copy Paths
|
||||
dup, exists := copySet[outputPath]
|
||||
if exists {
|
||||
|
@ -329,7 +305,7 @@ func (w *walker) copyPath(cfg *config, file fileInfo) error {
|
|||
|
||||
outputDir := path.Dir(outputPath)
|
||||
if !mkdirSet[outputDir] {
|
||||
if err = os.MkdirAll(outputDir, os.ModePerm); err != nil {
|
||||
if err := os.MkdirAll(outputDir, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
// https://pkg.go.dev/path#Dir
|
||||
|
@ -353,10 +329,27 @@ func (w *walker) copyPaths(cfg *config) error {
|
|||
if err != nil {
|
||||
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 {
|
||||
// On Windows, filepath.WalkDir doesn't like directory symlinks so we must
|
||||
// call filepath.WalkDir on the realpath
|
||||
realpath, err := common.Realpath(file.Path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
|
@ -368,20 +361,20 @@ func (w *walker) copyPaths(cfg *config) error {
|
|||
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.Path = realpath
|
||||
file.FileInfo = stat
|
||||
} else {
|
||||
file.FileInfo = info
|
||||
|
||||
if file.FileInfo.IsDir() {
|
||||
// symlink points to a directory
|
||||
if err := w.copyDir(cfg, nil, file); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if file.FileInfo.IsDir() {
|
||||
if err := w.copyDir(cfg, nil, file); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := w.copyPath(cfg, file); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := w.copyPath(cfg, file, outputPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
Loading…
Reference in New Issue