github.com/grahambrereton-form3/tilt@v0.10.18/internal/tiltfile/io/io.go (about) 1 package io 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 9 "go.starlark.net/starlark" 10 11 "github.com/windmilleng/tilt/internal/sliceutils" 12 "github.com/windmilleng/tilt/internal/tiltfile/starkit" 13 "github.com/windmilleng/tilt/internal/tiltfile/value" 14 ) 15 16 type Extension struct{} 17 18 func NewExtension() Extension { 19 return Extension{} 20 } 21 22 func (Extension) NewState() interface{} { 23 return ReadState{} 24 } 25 26 func (Extension) OnStart(e *starkit.Environment) error { 27 err := e.AddBuiltin("read_file", readFile) 28 if err != nil { 29 return err 30 } 31 32 err = e.AddBuiltin("watch_file", watchFile) 33 if err != nil { 34 return err 35 } 36 37 err = e.AddBuiltin("listdir", listdir) 38 if err != nil { 39 return err 40 } 41 42 err = e.AddBuiltin("blob", blob) 43 if err != nil { 44 return err 45 } 46 47 return nil 48 } 49 50 func (Extension) OnExec(t *starlark.Thread, tiltfilePath string) error { 51 return RecordReadFile(t, tiltfilePath) 52 } 53 54 func readFile(thread *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { 55 var path starlark.Value 56 defaultReturn := "" 57 err := starkit.UnpackArgs(thread, fn.Name(), args, kwargs, "paths", &path, "default?", &defaultReturn) 58 if err != nil { 59 return nil, err 60 } 61 62 p, err := value.ValueToAbsPath(thread, path) 63 if err != nil { 64 return nil, fmt.Errorf("invalid type for paths: %v", err) 65 } 66 67 bs, err := ReadFile(thread, p) 68 if os.IsNotExist(err) { 69 bs = []byte(defaultReturn) 70 } else if err != nil { 71 return nil, err 72 } 73 74 return NewBlob(string(bs), fmt.Sprintf("file: %s", p)), nil 75 } 76 77 func watchFile(thread *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { 78 var path starlark.Value 79 err := starkit.UnpackArgs(thread, fn.Name(), args, kwargs, "paths", &path) 80 if err != nil { 81 return nil, err 82 } 83 84 p, err := value.ValueToAbsPath(thread, path) 85 if err != nil { 86 return nil, fmt.Errorf("invalid type for paths: %v", err) 87 } 88 89 err = RecordReadFile(thread, p) 90 if err != nil { 91 return nil, err 92 } 93 94 return starlark.None, nil 95 } 96 97 func listdir(thread *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { 98 var dir starlark.String 99 var recursive bool 100 err := starkit.UnpackArgs(thread, fn.Name(), args, kwargs, "dir", &dir, "recursive?", &recursive) 101 if err != nil { 102 return nil, err 103 } 104 105 localPath, err := value.ValueToAbsPath(thread, dir) 106 if err != nil { 107 return nil, fmt.Errorf("Argument 0 (paths): %v", err) 108 } 109 110 err = RecordReadFile(thread, localPath) 111 if err != nil { 112 return nil, err 113 } 114 115 var files []string 116 err = filepath.Walk(localPath, func(path string, info os.FileInfo, err error) error { 117 if path == localPath { 118 return nil 119 } 120 if !info.IsDir() { 121 files = append(files, path) 122 } else if info.IsDir() && !recursive { 123 return filepath.SkipDir 124 } 125 return nil 126 }) 127 if err != nil { 128 return nil, err 129 } 130 131 var ret []starlark.Value 132 for _, f := range files { 133 ret = append(ret, starlark.String(f)) 134 } 135 136 return starlark.NewList(ret), nil 137 } 138 139 func blob(thread *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { 140 var input starlark.String 141 err := starkit.UnpackArgs(thread, fn.Name(), args, kwargs, "input", &input) 142 if err != nil { 143 return nil, err 144 } 145 146 return NewBlob(input.GoString(), "Tiltfile blob() call"), nil 147 } 148 149 // Track all the files read while loading 150 type ReadState struct { 151 Files []string 152 } 153 154 func ReadFile(thread *starlark.Thread, p string) ([]byte, error) { 155 err := RecordReadFile(thread, p) 156 if err != nil { 157 return nil, err 158 } 159 return ioutil.ReadFile(p) 160 } 161 162 func RecordReadFile(t *starlark.Thread, files ...string) error { 163 return starkit.SetState(t, func(s ReadState) ReadState { 164 s.Files = sliceutils.AppendWithoutDupes(s.Files, files...) 165 return s 166 }) 167 } 168 169 var _ starkit.StatefulExtension = Extension{} 170 var _ starkit.OnExecExtension = Extension{} 171 172 func MustState(model starkit.Model) ReadState { 173 state, err := GetState(model) 174 if err != nil { 175 panic(err) 176 } 177 return state 178 } 179 180 func GetState(m starkit.Model) (ReadState, error) { 181 var state ReadState 182 err := m.Load(&state) 183 return state, err 184 }