From d684e59b6aa1e796fcef3f95e810106a290b0b0e Mon Sep 17 00:00:00 2001 From: Pete Davison Date: Thu, 4 Jan 2024 00:17:30 +0000 Subject: [PATCH] feat: store namespace directly in include --- taskfile/ast/include.go | 3 +++ taskfile/merge.go | 33 ++++++++++++++++++++++++--------- taskfile/read.go | 11 ++--------- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/taskfile/ast/include.go b/taskfile/ast/include.go index 97d3ffef..fee856b2 100644 --- a/taskfile/ast/include.go +++ b/taskfile/ast/include.go @@ -14,6 +14,7 @@ import ( // Include represents information about included taskfiles type Include struct { + Namespace string Taskfile string Dir string Optional bool @@ -45,6 +46,7 @@ func (includes *Includes) UnmarshalYAML(node *yaml.Node) error { if err := valueNode.Decode(&v); err != nil { return err } + v.Namespace = keyNode.Value includes.Set(keyNode.Value, v) } return nil @@ -128,6 +130,7 @@ func (include *Include) DeepCopy() *Include { return nil } return &Include{ + Namespace: include.Namespace, Taskfile: include.Taskfile, Dir: include.Dir, Optional: include.Optional, diff --git a/taskfile/merge.go b/taskfile/merge.go index 658a0e7f..1f877157 100644 --- a/taskfile/merge.go +++ b/taskfile/merge.go @@ -11,7 +11,7 @@ import ( const NamespaceSeparator = ":" // Merge merges the second Taskfile into the first -func Merge(t1, t2 *ast.Taskfile, include *ast.Include, namespaces ...string) error { +func Merge(t1, t2 *ast.Taskfile, include *ast.Include) error { if !t1.Version.Equal(t2.Version) { return fmt.Errorf(`task: Taskfiles versions should match. First is "%s" but second is "%s"`, t1.Version, t2.Version) } @@ -28,7 +28,7 @@ func Merge(t1, t2 *ast.Taskfile, include *ast.Include, namespaces ...string) err t1.Vars.Merge(t2.Vars) t1.Env.Merge(t2.Env) - return t2.Tasks.Range(func(k string, v *ast.Task) error { + if err := t2.Tasks.Range(func(k string, v *ast.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() @@ -40,16 +40,16 @@ func Merge(t1, t2 *ast.Taskfile, include *ast.Include, namespaces ...string) err // Add namespaces to dependencies, commands and aliases for _, dep := range task.Deps { if dep != nil && dep.Task != "" { - dep.Task = taskNameWithNamespace(dep.Task, namespaces...) + dep.Task = taskNameWithNamespace(dep.Task, include.Namespace) } } for _, cmd := range task.Cmds { if cmd != nil && cmd.Task != "" { - cmd.Task = taskNameWithNamespace(cmd.Task, namespaces...) + cmd.Task = taskNameWithNamespace(cmd.Task, include.Namespace) } } for i, alias := range task.Aliases { - task.Aliases[i] = taskNameWithNamespace(alias, namespaces...) + task.Aliases[i] = taskNameWithNamespace(alias, include.Namespace) } // Add namespace aliases if include != nil { @@ -62,17 +62,32 @@ func Merge(t1, t2 *ast.Taskfile, include *ast.Include, namespaces ...string) err } // Add the task to the merged taskfile - taskNameWithNamespace := taskNameWithNamespace(k, namespaces...) + 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...) + } + + return nil } -func taskNameWithNamespace(taskName string, namespaces ...string) string { +func taskNameWithNamespace(taskName string, namespace string) string { if strings.HasPrefix(taskName, NamespaceSeparator) { return strings.TrimPrefix(taskName, NamespaceSeparator) } - return strings.Join(append(namespaces, taskName), NamespaceSeparator) + return fmt.Sprintf("%s%s%s", namespace, NamespaceSeparator, taskName) } diff --git a/taskfile/read.go b/taskfile/read.go index d010131b..cfe81110 100644 --- a/taskfile/read.go +++ b/taskfile/read.go @@ -175,6 +175,7 @@ func Read( err = t.Includes.Range(func(namespace string, include ast.Include) error { tr := templater.Templater{Vars: t.Vars} include = ast.Include{ + Namespace: include.Namespace, Taskfile: tr.Replace(include.Taskfile), Dir: tr.Replace(include.Dir), Optional: include.Optional, @@ -252,18 +253,10 @@ func Read( } } - if err = Merge(t, includedTaskfile, &include, namespace); err != nil { + if err = Merge(t, includedTaskfile, &include); err != nil { return err } - if includedTaskfile.Tasks.Get("default") != nil && t.Tasks.Get(namespace) == nil { - defaultTaskName := fmt.Sprintf("%s:default", namespace) - task := t.Tasks.Get(defaultTaskName) - task.Aliases = append(task.Aliases, namespace) - task.Aliases = append(task.Aliases, include.Aliases...) - t.Tasks.Set(defaultTaskName, task) - } - return nil }) if err != nil {