package execution import ( "fmt" "code.icb4dc0.de/buildr/buildr/modules" ) type taskFactoryOption interface { applyToFactory(f *TaskFactory) } type taskFactoryOptionFunc func(f *TaskFactory) func (f taskFactoryOptionFunc) applyToFactory(factory *TaskFactory) { f(factory) } func WithProvider(p TaskProvider) taskFactoryOption { return taskFactoryOptionFunc(func(f *TaskFactory) { f.providers = append(f.providers, p) }) } func NewTaskFactory(opts ...taskFactoryOption) *TaskFactory { factory := &TaskFactory{ knownTasks: make(map[string]Task), } for i := range opts { opts[i].applyToFactory(factory) } return factory } type TaskFactory struct { knownTasks map[string]Task providers []TaskProvider } func (f *TaskFactory) TaskForModuleWithoutDependencies(module modules.ModuleWithMeta) (Task, error) { var t Task for i := range f.providers { if p := f.providers[i]; p.CanProvide(module) { if task, err := p.Create(module); err != nil { return nil, err } else { t = task } } } if t == nil { return nil, fmt.Errorf("no provider available to handle module %s", module.Name()) } return t, nil } func (f *TaskFactory) TaskForModule(id string, repo *modules.Repository) (Task, error) { if t, ok := f.knownTasks[id]; ok { return t, nil } module := repo.ModuleByID(id) if module == nil { return nil, fmt.Errorf("ID %s could not be resolved to module", id) } var t Task for i := range f.providers { if p := f.providers[i]; p.CanProvide(module) { if task, err := p.Create(module); err != nil { return nil, err } else { t = task } } } if t == nil { return nil, fmt.Errorf("no provider available to handle module %s", module.Name()) } f.knownTasks[id] = t deps := module.Dependencies() for i := range deps { if dependent, err := f.TaskForModule(deps[i], repo); err != nil { return nil, err } else { t.AddDependentTask(dependent) } } return t, nil }