mirror of
https://github.com/hashicorp/terraform.git
synced 2026-06-09 00:42:48 -04:00
94 lines
1.9 KiB
Go
94 lines
1.9 KiB
Go
// Copyright IBM Corp. 2014, 2026
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package configload
|
|
|
|
import (
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
// copyDir copies the src directory contents into dst. Both directories
|
|
// should already exist.
|
|
func copyDir(dst, src string) error {
|
|
src, err := filepath.EvalSymlinks(src)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
walkFn := func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if path == src {
|
|
return nil
|
|
}
|
|
|
|
// The "path" has the src prefixed to it. We need to join our
|
|
// destination with the path without the src on it.
|
|
dstPath := filepath.Join(dst, path[len(src):])
|
|
|
|
// Call os.Stat on dstPath to obtain os.FileInfo since os.SameFile
|
|
// requires FileInfo objects for comparison.
|
|
dstInfo, err := os.Stat(dstPath)
|
|
if err != nil {
|
|
if !os.IsNotExist(err) {
|
|
return err
|
|
}
|
|
} else if os.SameFile(info, dstInfo) {
|
|
// The destination file exists and is the same as the source file;
|
|
// skip copying.
|
|
return nil
|
|
}
|
|
|
|
// If we have a directory, make that subdirectory, then continue
|
|
// the walk.
|
|
if info.IsDir() {
|
|
if path == filepath.Join(src, dst) {
|
|
// dst is in src; don't walk it.
|
|
return nil
|
|
}
|
|
|
|
if err := os.MkdirAll(dstPath, 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// If the current path is a symlink, recreate the symlink relative to
|
|
// the dst directory
|
|
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
|
|
target, err := os.Readlink(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return os.Symlink(target, dstPath)
|
|
}
|
|
|
|
// If we have a file, copy the contents.
|
|
srcF, err := os.Open(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer srcF.Close()
|
|
|
|
dstF, err := os.Create(dstPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer dstF.Close()
|
|
|
|
if _, err := io.Copy(dstF, srcF); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Chmod it
|
|
return os.Chmod(dstPath, info.Mode())
|
|
}
|
|
|
|
return filepath.Walk(src, walkFn)
|
|
}
|