diff --git a/taskfile/ast/taskfile.go b/taskfile/ast/taskfile.go index deb955fb44..a05556c0a1 100644 --- a/taskfile/ast/taskfile.go +++ b/taskfile/ast/taskfile.go @@ -2,7 +2,6 @@ package ast import ( "fmt" - "strings" "time" "github.com/Masterminds/semver/v3" @@ -40,7 +39,6 @@ func (t1 *Taskfile) Merge(t2 *Taskfile, include *Include) error { if t2.Output.IsSet() { t1.Output = t2.Output } - if t1.Vars == nil { t1.Vars = &Vars{} } @@ -49,61 +47,7 @@ func (t1 *Taskfile) Merge(t2 *Taskfile, include *Include) error { } t1.Vars.Merge(t2.Vars) t1.Env.Merge(t2.Env) - - if err := t2.Tasks.Range(func(k string, v *Task) error { - // We do a deep copy of the task struct here to ensure that no data can - // be changed elsewhere once the taskfile is merged. - task := v.DeepCopy() - - // Set the task to internal if EITHER the included task or the included - // taskfile are marked as internal - task.Internal = task.Internal || (include != nil && include.Internal) - - // Add namespaces to dependencies, commands and aliases - for _, dep := range task.Deps { - if dep != nil && dep.Task != "" { - dep.Task = taskNameWithNamespace(dep.Task, include.Namespace) - } - } - for _, cmd := range task.Cmds { - if cmd != nil && cmd.Task != "" { - cmd.Task = taskNameWithNamespace(cmd.Task, include.Namespace) - } - } - for i, alias := range task.Aliases { - task.Aliases[i] = taskNameWithNamespace(alias, include.Namespace) - } - // Add namespace aliases - if include != nil { - for _, namespaceAlias := range include.Aliases { - task.Aliases = append(task.Aliases, taskNameWithNamespace(task.Task, namespaceAlias)) - for _, alias := range v.Aliases { - task.Aliases = append(task.Aliases, taskNameWithNamespace(alias, namespaceAlias)) - } - } - } - - // Add the task to the merged taskfile - taskNameWithNamespace := taskNameWithNamespace(k, include.Namespace) - task.Task = taskNameWithNamespace - t1.Tasks.Set(taskNameWithNamespace, task) - - return nil - }); err != nil { - return err - } - - // If the included Taskfile has a default task and the parent namespace has - // no task with a matching name, we can add an alias so that the user can - // run the included Taskfile's default task without specifying its full - // name. If the parent namespace has aliases, we add another alias for each - // of them. - if t2.Tasks.Get("default") != nil && t1.Tasks.Get(include.Namespace) == nil { - defaultTaskName := fmt.Sprintf("%s:default", include.Namespace) - t1.Tasks.Get(defaultTaskName).Aliases = append(t1.Tasks.Get(defaultTaskName).Aliases, include.Namespace) - t1.Tasks.Get(defaultTaskName).Aliases = append(t1.Tasks.Get(defaultTaskName).Aliases, include.Aliases...) - } - + t1.Tasks.Merge(t2.Tasks, include) return nil } @@ -152,10 +96,3 @@ func (tf *Taskfile) UnmarshalYAML(node *yaml.Node) error { return fmt.Errorf("yaml: line %d: cannot unmarshal %s into taskfile", node.Line, node.ShortTag()) } - -func taskNameWithNamespace(taskName string, namespace string) string { - if strings.HasPrefix(taskName, NamespaceSeparator) { - return strings.TrimPrefix(taskName, NamespaceSeparator) - } - return fmt.Sprintf("%s%s%s", namespace, NamespaceSeparator, taskName) -} diff --git a/taskfile/ast/tasks.go b/taskfile/ast/tasks.go index 4f632428d5..4083466997 100644 --- a/taskfile/ast/tasks.go +++ b/taskfile/ast/tasks.go @@ -2,6 +2,7 @@ package ast import ( "fmt" + "strings" "gopkg.in/yaml.v3" @@ -13,6 +14,60 @@ type Tasks struct { omap.OrderedMap[string, *Task] } +func (t1 *Tasks) Merge(t2 Tasks, include *Include) { + _ = t2.Range(func(k string, v *Task) error { + // We do a deep copy of the task struct here to ensure that no data can + // be changed elsewhere once the taskfile is merged. + task := v.DeepCopy() + + // Set the task to internal if EITHER the included task or the included + // taskfile are marked as internal + task.Internal = task.Internal || (include != nil && include.Internal) + + // Add namespaces to dependencies, commands and aliases + for _, dep := range task.Deps { + if dep != nil && dep.Task != "" { + dep.Task = taskNameWithNamespace(dep.Task, include.Namespace) + } + } + for _, cmd := range task.Cmds { + if cmd != nil && cmd.Task != "" { + cmd.Task = taskNameWithNamespace(cmd.Task, include.Namespace) + } + } + for i, alias := range task.Aliases { + task.Aliases[i] = taskNameWithNamespace(alias, include.Namespace) + } + // Add namespace aliases + if include != nil { + for _, namespaceAlias := range include.Aliases { + task.Aliases = append(task.Aliases, taskNameWithNamespace(task.Task, namespaceAlias)) + for _, alias := range v.Aliases { + task.Aliases = append(task.Aliases, taskNameWithNamespace(alias, namespaceAlias)) + } + } + } + + // Add the task to the merged taskfile + taskNameWithNamespace := taskNameWithNamespace(k, include.Namespace) + task.Task = taskNameWithNamespace + t1.Set(taskNameWithNamespace, task) + + return nil + }) + + // If the included Taskfile has a default task and the parent namespace has + // no task with a matching name, we can add an alias so that the user can + // run the included Taskfile's default task without specifying its full + // name. If the parent namespace has aliases, we add another alias for each + // of them. + if t2.Get("default") != nil && t1.Get(include.Namespace) == nil { + defaultTaskName := fmt.Sprintf("%s:default", include.Namespace) + t1.Get(defaultTaskName).Aliases = append(t1.Get(defaultTaskName).Aliases, include.Namespace) + t1.Get(defaultTaskName).Aliases = append(t1.Get(defaultTaskName).Aliases, include.Aliases...) + } +} + func (t *Tasks) UnmarshalYAML(node *yaml.Node) error { switch node.Kind { case yaml.MappingNode: @@ -52,3 +107,10 @@ func (t *Tasks) UnmarshalYAML(node *yaml.Node) error { return fmt.Errorf("yaml: line %d: cannot unmarshal %s into tasks", node.Line, node.ShortTag()) } + +func taskNameWithNamespace(taskName string, namespace string) string { + if strings.HasPrefix(taskName, NamespaceSeparator) { + return strings.TrimPrefix(taskName, NamespaceSeparator) + } + return fmt.Sprintf("%s%s%s", namespace, NamespaceSeparator, taskName) +}