diff --git a/tools/copy_to_directory/main.go b/tools/copy_to_directory/main.go index aadf7481d..9518f05ec 100644 --- a/tools/copy_to_directory/main.go +++ b/tools/copy_to_directory/main.go @@ -157,6 +157,26 @@ func (w *walker) copyDir(cfg *config, srcPaths pathSet, file fileInfo) error { return err } + f := fileInfo{ + Package: file.Package, + Path: p, + RootPath: file.RootPath, + ShortPath: path.Join(file.ShortPath, r), + Workspace: file.Workspace, + WorkspacePath: path.Join(file.WorkspacePath, r), + Hardlink: file.Hardlink, + FileInfo: info, + } + + outputPath, err := w.calculateOutputPath(cfg, f) + if err != nil { + return fmt.Errorf("failed to calculate output path %s: %w", file.WorkspacePath, err) + } + if outputPath == "" { + // this path is excluded + return nil + } + 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) @@ -174,9 +194,12 @@ func (w *walker) copyDir(cfg *config, srcPaths pathSet, file fileInfo) error { if err != nil { return fmt.Errorf("failed to stat file %s pointed to by symlink %s: %w", linkPath, p, err) } + f.Path = linkPath + f.FileInfo = stat + if stat.IsDir() { // symlink points to a directory - f := fileInfo{ + f = fileInfo{ Package: file.Package, Path: linkPath, RootPath: file.RootPath, @@ -187,34 +210,10 @@ func (w *walker) copyDir(cfg *config, srcPaths pathSet, file fileInfo) error { 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, - RootPath: file.RootPath, - ShortPath: path.Join(file.ShortPath, r), - Workspace: file.Workspace, - WorkspacePath: path.Join(file.WorkspacePath, r), - Hardlink: file.Hardlink, - FileInfo: info, - } - return w.copyPath(cfg, f) + return w.copyPath(cfg, f, outputPath) }) } @@ -305,16 +304,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 +319,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,9 +343,28 @@ 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 %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 + // 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 { @@ -370,19 +379,19 @@ func (w *walker) copyPaths(cfg *config) error { } file.Realpath = realpath file.FileInfo = stat - } else { - file.FileInfo = info - } - 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 file.FileInfo.IsDir() { + // symlink points to a directory + if err := w.copyDir(cfg, nil, file); err != nil { + return err + } + continue } } + + if err := w.copyPath(cfg, file, outputPath); err != nil { + return err + } } return nil }