blob: 81eda8c5e3d745144b0a19bd3457c35d688d887d [file] [log] [blame]
/*
Copyright © 2021 Aspect Build Systems Inc
Not licensed for re-use.
*/
package hooks
import (
"aspect.build/cli/pkg/aspecterrors"
"aspect.build/cli/pkg/ioutils"
)
// Hooks represent the possible hook points from the plugin system. It accepts
// registrations and can execute them as requested at the appropriate times.
type Hooks struct {
postBuild *hookList
}
// New instantiates a new Hooks.
func New() *Hooks {
return &Hooks{
postBuild: &hookList{},
}
}
// RegisterPostBuild registers a post-build hook function.
func (hooks *Hooks) RegisterPostBuild(fn PostBuildFn) {
hooks.postBuild.insert(fn)
}
// ExecutePostBuild executes the post-build hook functions in sequence they were
// registered.
func (hooks *Hooks) ExecutePostBuild(isInteractiveMode bool) *aspecterrors.ErrorList {
errors := &aspecterrors.ErrorList{}
node := hooks.postBuild.head
for node != nil {
// promptRunner is nil here because it has to satisfy the PostBuild
// signature to comply with the go-plugin library. The real promptRunner is
// instantiated when the gRPC call is made.
if err := node.fn.(PostBuildFn)(isInteractiveMode, nil); err != nil {
errors.Insert(err)
}
node = node.next
}
return errors
}
// PostBuildFn matches the plugin PostBuildHook method signature.
type PostBuildFn func(isInteractiveMode bool, promptRunner ioutils.PromptRunner) error
type hookList struct {
head *hookNode
tail *hookNode
}
func (l *hookList) insert(fn interface{}) {
node := &hookNode{fn: fn}
if l.head == nil {
l.head = node
} else {
l.tail.next = node
}
l.tail = node
}
type hookNode struct {
next *hookNode
fn interface{}
}