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  }