-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
files.go
126 lines (106 loc) · 4.02 KB
/
files.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Package files allows to interact with files on a file system.
package files
import (
"io/ioutil"
"os"
"path/filepath"
"strings"
)
// FileExists returns true if the given file exists.
func FileExists(path string) bool {
_, err := os.Stat(path)
return err == nil
}
// CopyTerraformFolderToTemp creates a copy of the given folder and all its contents in a temp folder with a unique name and the given prefix.
// This is useful when running multiple tests in parallel against the same set of Terraform files to ensure the
// tests don't overwrite each other's .terraform working directory and terraform.tfstate files. This method returns
// the path to the temp folder with the copied contents. Hidden files and folders, Terraform state files, and
// terraform.tfvars files are not copied to this temp folder, as you typically don't want them interfering with your
// tests.
func CopyTerraformFolderToTemp(folderPath string, tempFolderPrefix string) (string, error) {
tmpDir, err := ioutil.TempDir("", tempFolderPrefix)
if err != nil {
return "", err
}
// Inside of the temp folder, we create a subfolder that preserves the name of the folder we're copying from.
absFolderPath, err := filepath.Abs(folderPath)
if err != nil {
return "", err
}
folderName := filepath.Base(absFolderPath)
destFolder := filepath.Join(tmpDir, folderName)
if err := os.MkdirAll(destFolder, 0777); err != nil {
return "", err
}
filter := func(path string) bool {
return !PathContainsHiddenFileOrFolder(path) && !PathContainsTerraformStateOrVars(path)
}
if err := CopyFolderContentsWithFilter(folderPath, destFolder, filter); err != nil {
return "", err
}
return destFolder, nil
}
// CopyFolderContents copies all the files and folders within the given source folder to the destination folder.
func CopyFolderContents(source string, destination string) error {
return CopyFolderContentsWithFilter(source, destination, func(path string) bool {
return true
})
}
// CopyFolderContentsWithFilter copies the files and folders within the given source folder that pass the given filter (return true) to the
// destination folder.
func CopyFolderContentsWithFilter(source string, destination string, filter func(path string) bool) error {
files, err := ioutil.ReadDir(source)
if err != nil {
return err
}
for _, file := range files {
src := filepath.Join(source, file.Name())
dest := filepath.Join(destination, file.Name())
if !filter(src) {
continue
} else if file.IsDir() {
if err := os.MkdirAll(dest, file.Mode()); err != nil {
return err
}
if err := CopyFolderContentsWithFilter(src, dest, filter); err != nil {
return err
}
} else {
if err := CopyFile(src, dest); err != nil {
return err
}
}
}
return nil
}
// PathContainsTerraformStateOrVars returns true if the path corresponds to a Terraform state file or .tfvars file.
func PathContainsTerraformStateOrVars(path string) bool {
filename := filepath.Base(path)
return filename == "terraform.tfstate" || filename == "terraform.tfstate.backup" || filename == "terraform.tfvars"
}
// PathContainsHiddenFileOrFolder returns true if the given path contains a hidden file or folder.
func PathContainsHiddenFileOrFolder(path string) bool {
pathParts := strings.Split(path, string(filepath.Separator))
for _, pathPart := range pathParts {
if strings.HasPrefix(pathPart, ".") && pathPart != "." && pathPart != ".." {
return true
}
}
return false
}
// CopyFile copies a file from source to destination.
func CopyFile(source string, destination string) error {
contents, err := ioutil.ReadFile(source)
if err != nil {
return err
}
return WriteFileWithSamePermissions(source, destination, contents)
}
// WriteFileWithSamePermissions writes a file to the given destination with the given contents using the same permissions as the file at source.
func WriteFileWithSamePermissions(source string, destination string, contents []byte) error {
fileInfo, err := os.Stat(source)
if err != nil {
return err
}
return ioutil.WriteFile(destination, contents, fileInfo.Mode())
}