Replace Fillable interface with a concrete wrapper

Signed-off-by: Solomon Hykes <sh.github.6811@hykes.org>
This commit is contained in:
Solomon Hykes 2021-01-21 16:49:25 -08:00
parent 2ee27e83f3
commit eab6028b70
6 changed files with 35 additions and 29 deletions

View File

@ -52,7 +52,7 @@ func (c *Component) ComputeScript() (*Script, error) {
// 1. Always start with an empty fs state (Execute may receive any state as input) // 1. Always start with an empty fs state (Execute may receive any state as input)
// 2. Always solve at the end (Execute is lazy) // 2. Always solve at the end (Execute is lazy)
// //
func (c *Component) Compute(ctx context.Context, s Solver, out Fillable) (FS, error) { func (c *Component) Compute(ctx context.Context, s Solver, out *Fillable) (FS, error) {
fs, err := c.Execute(ctx, s.Scratch(), out) fs, err := c.Execute(ctx, s.Scratch(), out)
if err != nil { if err != nil {
return fs, err return fs, err
@ -67,7 +67,7 @@ func (c *Component) Compute(ctx context.Context, s Solver, out Fillable) (FS, er
// A component implements the Executable interface by returning its // A component implements the Executable interface by returning its
// compute script. // compute script.
// See Value.Executable(). // See Value.Executable().
func (c *Component) Execute(ctx context.Context, fs FS, out Fillable) (FS, error) { func (c *Component) Execute(ctx context.Context, fs FS, out *Fillable) (FS, error) {
script, err := c.ComputeScript() script, err := c.ComputeScript()
if err != nil { if err != nil {
// If the component has no script, then do not fail. // If the component has no script, then do not fail.

View File

@ -43,7 +43,7 @@ func NewEnv(ctx context.Context, s Solver, bootsrc, inputsrc string) (*Env, erro
if err != nil { if err != nil {
return nil, errors.Wrap(err, "compile boot script") return nil, errors.Wrap(err, "compile boot script")
} }
bootfs, err := boot.Execute(ctx, s.Scratch(), Discard()) bootfs, err := boot.Execute(ctx, s.Scratch(), nil)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "execute boot script") return nil, errors.Wrap(err, "execute boot script")
} }
@ -81,7 +81,7 @@ func NewEnv(ctx context.Context, s Solver, bootsrc, inputsrc string) (*Env, erro
// Compute missing values in env configuration, and write them to state. // Compute missing values in env configuration, and write them to state.
func (env *Env) Compute(ctx context.Context) error { func (env *Env) Compute(ctx context.Context) error {
output, err := env.Walk(ctx, func(ctx context.Context, c *Component, out Fillable) error { output, err := env.Walk(ctx, func(ctx context.Context, c *Component, out *Fillable) error {
lg := log.Ctx(ctx) lg := log.Ctx(ctx)
lg. lg.
@ -119,7 +119,7 @@ func (env *Env) Export(fs FS) (FS, error) {
return fs, nil return fs, nil
} }
type EnvWalkFunc func(context.Context, *Component, Fillable) error type EnvWalkFunc func(context.Context, *Component, *Fillable) error
// Walk components and return any computed values // Walk components and return any computed values
func (env *Env) Walk(ctx context.Context, fn EnvWalkFunc) (*Value, error) { func (env *Env) Walk(ctx context.Context, fn EnvWalkFunc) (*Value, error) {
@ -195,7 +195,7 @@ func (env *Env) Walk(ctx context.Context, fn EnvWalkFunc) (*Value, error) {
return nil, err return nil, err
} }
return cueflow.RunnerFunc(func(t *cueflow.Task) error { return cueflow.RunnerFunc(func(t *cueflow.Task) error {
return fn(ctx, c, t) return fn(ctx, c, NewFillable(t))
}), nil }), nil
} }
// Orchestrate execution with cueflow // Orchestrate execution with cueflow

View File

@ -30,7 +30,7 @@ func (mnt *Mount) LLB(ctx context.Context, s Solver) (llb.RunOption, error) {
if err != nil { if err != nil {
return nil, errors.Wrap(err, "from") return nil, errors.Wrap(err, "from")
} }
fromFS, err := from.Execute(ctx, s.Scratch(), Discard()) fromFS, err := from.Execute(ctx, s.Scratch(), nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -14,7 +14,7 @@ type Op struct {
v *Value v *Value
} }
func (op *Op) Execute(ctx context.Context, fs FS, out Fillable) (FS, error) { func (op *Op) Execute(ctx context.Context, fs FS, out *Fillable) (FS, error) {
action, err := op.Action() action, err := op.Action()
if err != nil { if err != nil {
return fs, err return fs, err
@ -50,7 +50,7 @@ func (op *Op) Walk(ctx context.Context, fn func(*Op) error) error {
return fn(op) return fn(op)
} }
type Action func(context.Context, FS, Fillable) (FS, error) type Action func(context.Context, FS, *Fillable) (FS, error)
func (op *Op) Action() (Action, error) { func (op *Op) Action() (Action, error) {
// An empty struct is allowed as a no-op, to be // An empty struct is allowed as a no-op, to be
@ -88,7 +88,7 @@ func (op *Op) Validate(defs ...string) error {
return op.v.Validate(defs...) return op.v.Validate(defs...)
} }
func (op *Op) Copy(ctx context.Context, fs FS, out Fillable) (FS, error) { func (op *Op) Copy(ctx context.Context, fs FS, out *Fillable) (FS, error) {
// Decode copy options // Decode copy options
src, err := op.Get("src").String() src, err := op.Get("src").String()
if err != nil { if err != nil {
@ -103,7 +103,7 @@ func (op *Op) Copy(ctx context.Context, fs FS, out Fillable) (FS, error) {
return fs, errors.Wrap(err, "from") return fs, errors.Wrap(err, "from")
} }
// Compute source component or script, discarding fs writes & output value // Compute source component or script, discarding fs writes & output value
fromFS, err := from.Execute(ctx, fs.Solver().Scratch(), Discard()) fromFS, err := from.Execute(ctx, fs.Solver().Scratch(), nil)
if err != nil { if err != nil {
return fs, err return fs, err
} }
@ -123,10 +123,10 @@ func (op *Op) Copy(ctx context.Context, fs FS, out Fillable) (FS, error) {
}), nil // lazy solve }), nil // lazy solve
} }
func (op *Op) Nothing(ctx context.Context, fs FS, out Fillable) (FS, error) { func (op *Op) Nothing(ctx context.Context, fs FS, out *Fillable) (FS, error) {
return fs, nil return fs, nil
} }
func (op *Op) Local(ctx context.Context, fs FS, out Fillable) (FS, error) { func (op *Op) Local(ctx context.Context, fs FS, out *Fillable) (FS, error) {
dir, err := op.Get("dir").String() dir, err := op.Get("dir").String()
if err != nil { if err != nil {
return fs, err return fs, err
@ -138,7 +138,7 @@ func (op *Op) Local(ctx context.Context, fs FS, out Fillable) (FS, error) {
return fs.Set(llb.Local(dir, llb.FollowPaths(include))), nil // lazy solve return fs.Set(llb.Local(dir, llb.FollowPaths(include))), nil // lazy solve
} }
func (op *Op) Exec(ctx context.Context, fs FS, out Fillable) (FS, error) { func (op *Op) Exec(ctx context.Context, fs FS, out *Fillable) (FS, error) {
opts := []llb.RunOption{} opts := []llb.RunOption{}
var cmd struct { var cmd struct {
Args []string Args []string
@ -187,7 +187,7 @@ func (op *Op) Exec(ctx context.Context, fs FS, out Fillable) (FS, error) {
}), nil // lazy solve }), nil // lazy solve
} }
func (op *Op) Export(ctx context.Context, fs FS, out Fillable) (FS, error) { func (op *Op) Export(ctx context.Context, fs FS, out *Fillable) (FS, error) {
source, err := op.Get("source").String() source, err := op.Get("source").String()
if err != nil { if err != nil {
return fs, err return fs, err
@ -232,26 +232,26 @@ func (op *Op) Export(ctx context.Context, fs FS, out Fillable) (FS, error) {
return fs, nil return fs, nil
} }
func (op *Op) Load(ctx context.Context, fs FS, out Fillable) (FS, error) { func (op *Op) Load(ctx context.Context, fs FS, out *Fillable) (FS, error) {
from, err := op.Get("from").Executable() from, err := op.Get("from").Executable()
if err != nil { if err != nil {
return fs, errors.Wrap(err, "load") return fs, errors.Wrap(err, "load")
} }
fromFS, err := from.Execute(ctx, fs.Solver().Scratch(), Discard()) fromFS, err := from.Execute(ctx, fs.Solver().Scratch(), nil)
if err != nil { if err != nil {
return fs, errors.Wrap(err, "load: compute source") return fs, errors.Wrap(err, "load: compute source")
} }
return fs.Set(fromFS.LLB()), nil return fs.Set(fromFS.LLB()), nil
} }
func (op *Op) FetchContainer(ctx context.Context, fs FS, out Fillable) (FS, error) { func (op *Op) FetchContainer(ctx context.Context, fs FS, out *Fillable) (FS, error) {
ref, err := op.Get("ref").String() ref, err := op.Get("ref").String()
if err != nil { if err != nil {
return fs, err return fs, err
} }
return fs.Set(llb.Image(ref)), nil return fs.Set(llb.Image(ref)), nil
} }
func (op *Op) FetchGit(ctx context.Context, fs FS, out Fillable) (FS, error) { func (op *Op) FetchGit(ctx context.Context, fs FS, out *Fillable) (FS, error) {
remote, err := op.Get("remote").String() remote, err := op.Get("remote").String()
if err != nil { if err != nil {
return fs, err return fs, err

View File

@ -25,7 +25,7 @@ func (s *Script) Value() *Value {
} }
// Run a dagger script // Run a dagger script
func (s *Script) Execute(ctx context.Context, fs FS, out Fillable) (FS, error) { func (s *Script) Execute(ctx context.Context, fs FS, out *Fillable) (FS, error) {
err := s.v.RangeList(func(idx int, v *Value) error { err := s.v.RangeList(func(idx int, v *Value) error {
// If op not concrete, interrupt without error. // If op not concrete, interrupt without error.
// This allows gradual resolution: // This allows gradual resolution:

View File

@ -2,25 +2,31 @@ package dagger
import ( import (
"context" "context"
cueflow "cuelang.org/go/tools/flow"
) )
// Implemented by Component, Script, Op // Implemented by Component, Script, Op
type Executable interface { type Executable interface {
Execute(context.Context, FS, Fillable) (FS, error) Execute(context.Context, FS, *Fillable) (FS, error)
Walk(context.Context, func(*Op) error) error Walk(context.Context, func(*Op) error) error
} }
// Something which can be filled in-place with a cue value // Something which can be filled in-place with a cue value
type Fillable interface { type Fillable struct {
Fill(interface{}) error t *cueflow.Task
} }
func Discard() Fillable { func NewFillable(t *cueflow.Task) *Fillable {
return discard{} return &Fillable{
t: t,
}
} }
type discard struct{} func (f *Fillable) Fill(x interface{}) error {
// Use a nil pointer receiver to discard all values
func (d discard) Fill(x interface{}) error { if f == nil {
return nil return nil
}
return f.t.Fill(x)
} }