github.com/tilt-dev/tilt@v0.36.0/internal/testutils/tempdir/temp_dir_fixture.go (about) 1 package tempdir 2 3 import ( 4 "os" 5 "path/filepath" 6 "regexp" 7 "strings" 8 "testing" 9 10 "github.com/stretchr/testify/require" 11 ) 12 13 type TempDirFixture struct { 14 t testing.TB 15 dir string 16 oldDir string 17 } 18 19 // everything not listed in this character class will get replaced by _, so that it's a safe filename 20 var sanitizeForFilenameRe = regexp.MustCompile("[^a-zA-Z0-9.]") 21 22 func SanitizeFileName(name string) string { 23 return sanitizeForFilenameRe.ReplaceAllString(name, "_") 24 } 25 26 func NewTempDirFixture(t testing.TB) *TempDirFixture { 27 dir := t.TempDir() 28 29 dir, err := filepath.EvalSymlinks(dir) 30 require.NoError(t, err) 31 32 f := &TempDirFixture{ 33 t: t, 34 dir: dir, 35 } 36 t.Cleanup(f.tearDown) 37 return f 38 } 39 40 func (f *TempDirFixture) T() testing.TB { 41 return f.t 42 } 43 44 func (f *TempDirFixture) Path() string { 45 return f.dir 46 } 47 48 func (f *TempDirFixture) Chdir() { 49 cwd, err := os.Getwd() 50 if err != nil { 51 f.t.Fatal(err) 52 } 53 54 f.oldDir = cwd 55 56 err = os.Chdir(f.Path()) 57 if err != nil { 58 f.t.Fatal(err) 59 } 60 } 61 62 func (f *TempDirFixture) JoinPath(path ...string) string { 63 p := []string{} 64 isAbs := len(path) > 0 && filepath.IsAbs(path[0]) 65 if isAbs { 66 if !strings.HasPrefix(path[0], f.Path()) { 67 f.t.Fatalf("Path outside fixture tempdir are forbidden: %s", path[0]) 68 } 69 } else { 70 p = append(p, f.Path()) 71 } 72 73 p = append(p, path...) 74 return filepath.Join(p...) 75 } 76 77 func (f *TempDirFixture) JoinPaths(paths []string) []string { 78 joined := make([]string, len(paths)) 79 for i, p := range paths { 80 joined[i] = f.JoinPath(p) 81 } 82 return joined 83 } 84 85 // Returns the full path to the file written. 86 func (f *TempDirFixture) WriteFile(path string, contents string) string { 87 fullPath := f.JoinPath(path) 88 base := filepath.Dir(fullPath) 89 err := os.MkdirAll(base, os.FileMode(0777)) 90 if err != nil { 91 f.t.Fatal(err) 92 } 93 err = os.WriteFile(fullPath, []byte(contents), os.FileMode(0777)) 94 if err != nil { 95 f.t.Fatal(err) 96 } 97 return fullPath 98 } 99 100 // Returns the full path to the file written. 101 func (f *TempDirFixture) CopyFile(originalPath, newPath string) { 102 contents, err := os.ReadFile(originalPath) 103 if err != nil { 104 f.t.Fatal(err) 105 } 106 f.WriteFile(newPath, string(contents)) 107 } 108 109 // Read the file. 110 func (f *TempDirFixture) ReadFile(path string) string { 111 fullPath := f.JoinPath(path) 112 contents, err := os.ReadFile(fullPath) 113 if err != nil { 114 f.t.Fatal(err) 115 } 116 return string(contents) 117 } 118 119 func (f *TempDirFixture) WriteSymlink(linkContents, destPath string) { 120 fullDestPath := f.JoinPath(destPath) 121 err := os.MkdirAll(filepath.Dir(fullDestPath), os.FileMode(0777)) 122 if err != nil { 123 f.t.Fatal(err) 124 } 125 err = os.Symlink(linkContents, fullDestPath) 126 if err != nil { 127 f.t.Fatal(err) 128 } 129 } 130 131 func (f *TempDirFixture) MkdirAll(path string) { 132 fullPath := f.JoinPath(path) 133 err := os.MkdirAll(fullPath, os.FileMode(0777)) 134 if err != nil { 135 f.t.Fatal(err) 136 } 137 } 138 139 func (f *TempDirFixture) TouchFiles(paths []string) { 140 for _, p := range paths { 141 f.WriteFile(p, "") 142 } 143 } 144 145 func (f *TempDirFixture) Rm(pathInRepo string) { 146 fullPath := f.JoinPath(pathInRepo) 147 err := os.RemoveAll(fullPath) 148 if err != nil { 149 f.t.Fatal(err) 150 } 151 } 152 153 func (f *TempDirFixture) NewFile(prefix string) (*os.File, error) { 154 return os.CreateTemp(f.dir, prefix) 155 } 156 157 func (f *TempDirFixture) TempDir(prefix string) string { 158 name, err := os.MkdirTemp(f.dir, prefix) 159 if err != nil { 160 f.t.Fatal(err) 161 } 162 return name 163 } 164 165 func (f *TempDirFixture) tearDown() { 166 if f.oldDir != "" { 167 err := os.Chdir(f.oldDir) 168 if err != nil { 169 f.t.Fatal(err) 170 } 171 } 172 }