mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-24 16:10:46 -06:00
internal/configs/configload: prune copyDir() (#581)
This commit is contained in:
parent
daf275ffbe
commit
7b799c9305
@ -1,118 +0,0 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
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):])
|
||||
|
||||
// we don't want to try and copy the same file over itself.
|
||||
if eq, err := sameFile(path, dstPath); eq {
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// sameFile tried to determine if to paths are the same file.
|
||||
// If the paths don't match, we lookup the inode on supported systems.
|
||||
func sameFile(a, b string) (bool, error) {
|
||||
if a == b {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
aIno, err := inode(a)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
bIno, err := inode(b)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
if aIno > 0 && aIno == bIno {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package configload
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestCopyDir_symlinks sets up a directory with two submodules,
|
||||
// one being a symlink to the other
|
||||
//
|
||||
// The resultant file structure is as follows:
|
||||
// ├── modules
|
||||
// │ ├── symlink-module -> test-module
|
||||
// │ └── test-module
|
||||
// │ └── main.tf
|
||||
// └── target
|
||||
// ├── symlink-module -> test-module
|
||||
// └── test-module
|
||||
// └── main.tf
|
||||
|
||||
func TestCopyDir_symlinks(t *testing.T) {
|
||||
tmpdir := t.TempDir()
|
||||
|
||||
moduleDir := filepath.Join(tmpdir, "modules")
|
||||
err := os.Mkdir(moduleDir, os.ModePerm)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
subModuleDir := filepath.Join(moduleDir, "test-module")
|
||||
err = os.Mkdir(subModuleDir, os.ModePerm)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = os.WriteFile(filepath.Join(subModuleDir, "main.tf"), []byte("hello"), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = os.Symlink("test-module", filepath.Join(moduleDir, "symlink-module"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
targetDir := filepath.Join(tmpdir, "target")
|
||||
os.Mkdir(targetDir, os.ModePerm)
|
||||
|
||||
err = copyDir(targetDir, moduleDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err = os.Lstat(filepath.Join(targetDir, "test-module", "main.tf")); os.IsNotExist(err) {
|
||||
t.Fatal("target test-module/main.tf was not created")
|
||||
}
|
||||
|
||||
if _, err = os.Lstat(filepath.Join(targetDir, "symlink-module", "main.tf")); os.IsNotExist(err) {
|
||||
t.Fatal("target symlink-module/main.tf was not created")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCopyDir_symlink_file(t *testing.T) {
|
||||
tmpdir := t.TempDir()
|
||||
|
||||
moduleDir := filepath.Join(tmpdir, "modules")
|
||||
err := os.Mkdir(moduleDir, os.ModePerm)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = os.WriteFile(filepath.Join(moduleDir, "main.tf"), []byte("hello"), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = os.Symlink("main.tf", filepath.Join(moduleDir, "symlink.tf"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
targetDir := filepath.Join(tmpdir, "target")
|
||||
os.Mkdir(targetDir, os.ModePerm)
|
||||
|
||||
err = copyDir(targetDir, moduleDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err = os.Lstat(filepath.Join(targetDir, "main.tf")); os.IsNotExist(err) {
|
||||
t.Fatal("target/main.tf was not created")
|
||||
}
|
||||
|
||||
if _, err = os.Lstat(filepath.Join(targetDir, "symlink.tf")); os.IsNotExist(err) {
|
||||
t.Fatal("target/symlink.tf was not created")
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
//go:build linux || darwin || openbsd || netbsd || solaris || dragonfly
|
||||
// +build linux darwin openbsd netbsd solaris dragonfly
|
||||
|
||||
package configload
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// lookup the inode of a file on posix systems
|
||||
func inode(path string) (uint64, error) {
|
||||
stat, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if st, ok := stat.Sys().(*syscall.Stat_t); ok {
|
||||
return st.Ino, nil
|
||||
}
|
||||
return 0, fmt.Errorf("could not determine file inode")
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
//go:build freebsd
|
||||
// +build freebsd
|
||||
|
||||
package configload
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// lookup the inode of a file on posix systems
|
||||
func inode(path string) (uint64, error) {
|
||||
stat, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if st, ok := stat.Sys().(*syscall.Stat_t); ok {
|
||||
return uint64(st.Ino), nil
|
||||
}
|
||||
return 0, fmt.Errorf("could not determine file inode")
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package configload
|
||||
|
||||
// no syscall.Stat_t on windows, return 0 for inodes
|
||||
func inode(path string) (uint64, error) {
|
||||
return 0, nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user