2023-12-29 22:32:03 +02:00
|
|
|
package ast
|
2018-02-17 18:22:18 +02:00
|
|
|
|
2022-12-19 03:11:31 +02:00
|
|
|
import (
|
|
|
|
"fmt"
|
2024-01-27 17:51:43 +02:00
|
|
|
"regexp"
|
|
|
|
"strings"
|
2022-12-19 03:11:31 +02:00
|
|
|
|
|
|
|
"gopkg.in/yaml.v3"
|
2023-04-06 13:07:57 +02:00
|
|
|
|
|
|
|
"github.com/go-task/task/v3/internal/deepcopy"
|
2022-12-19 03:11:31 +02:00
|
|
|
)
|
|
|
|
|
2018-02-17 18:22:18 +02:00
|
|
|
// Task represents a task
|
|
|
|
type Task struct {
|
2022-03-19 23:41:03 +02:00
|
|
|
Task string
|
|
|
|
Cmds []*Cmd
|
|
|
|
Deps []*Dep
|
|
|
|
Label string
|
|
|
|
Desc string
|
2023-06-04 03:33:00 +02:00
|
|
|
Prompt string
|
2022-03-19 23:41:03 +02:00
|
|
|
Summary string
|
2023-06-30 03:13:41 +02:00
|
|
|
Requires *Requires
|
2022-10-02 00:39:44 +02:00
|
|
|
Aliases []string
|
2023-11-30 03:38:12 +02:00
|
|
|
Sources []*Glob
|
|
|
|
Generates []*Glob
|
2022-03-19 23:41:03 +02:00
|
|
|
Status []string
|
|
|
|
Preconditions []*Precondition
|
|
|
|
Dir string
|
2023-01-14 21:41:56 +02:00
|
|
|
Set []string
|
|
|
|
Shopt []string
|
2022-03-19 23:41:03 +02:00
|
|
|
Vars *Vars
|
|
|
|
Env *Vars
|
2022-12-06 02:25:16 +02:00
|
|
|
Dotenv []string
|
2022-03-19 23:41:03 +02:00
|
|
|
Silent bool
|
|
|
|
Interactive bool
|
2022-07-22 04:15:35 +02:00
|
|
|
Internal bool
|
2022-03-19 23:41:03 +02:00
|
|
|
Method string
|
|
|
|
Prefix string
|
|
|
|
IgnoreError bool
|
|
|
|
Run string
|
|
|
|
IncludeVars *Vars
|
|
|
|
IncludedTaskfileVars *Vars
|
2023-01-07 02:38:35 +02:00
|
|
|
Platforms []*Platform
|
2023-03-17 14:34:06 +02:00
|
|
|
Location *Location
|
2023-10-07 23:06:43 +02:00
|
|
|
Watch bool
|
2019-12-08 02:28:02 +02:00
|
|
|
}
|
|
|
|
|
2020-06-03 22:19:12 +02:00
|
|
|
func (t *Task) Name() string {
|
|
|
|
if t.Label != "" {
|
|
|
|
return t.Label
|
|
|
|
}
|
|
|
|
return t.Task
|
|
|
|
}
|
|
|
|
|
2024-01-27 17:51:43 +02:00
|
|
|
// WildcardMatch will check if the given string matches the name of the Task and returns any wildcard values.
|
|
|
|
func (t *Task) WildcardMatch(name string) (bool, []string) {
|
|
|
|
// Convert the name into a regex string
|
|
|
|
regexStr := fmt.Sprintf("^%s$", strings.ReplaceAll(t.Task, "*", "(.*)"))
|
|
|
|
regex := regexp.MustCompile(regexStr)
|
|
|
|
wildcards := regex.FindStringSubmatch(name)
|
|
|
|
wildcardCount := strings.Count(t.Task, "*")
|
|
|
|
|
|
|
|
// If there are no wildcards, return false
|
|
|
|
if len(wildcards) == 0 {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove the first match, which is the full string
|
|
|
|
wildcards = wildcards[1:]
|
|
|
|
|
|
|
|
// If there are more/less wildcards than matches, return false
|
|
|
|
if len(wildcards) != wildcardCount {
|
|
|
|
return false, wildcards
|
|
|
|
}
|
|
|
|
|
|
|
|
return true, wildcards
|
|
|
|
}
|
|
|
|
|
2022-12-19 03:11:31 +02:00
|
|
|
func (t *Task) UnmarshalYAML(node *yaml.Node) error {
|
|
|
|
switch node.Kind {
|
|
|
|
|
|
|
|
// Shortcut syntax for a task with a single command
|
|
|
|
case yaml.ScalarNode:
|
|
|
|
var cmd Cmd
|
|
|
|
if err := node.Decode(&cmd); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-12-08 02:28:02 +02:00
|
|
|
t.Cmds = append(t.Cmds, &cmd)
|
|
|
|
return nil
|
|
|
|
|
2022-12-19 03:11:31 +02:00
|
|
|
// Shortcut syntax for a simple task with a list of commands
|
|
|
|
case yaml.SequenceNode:
|
|
|
|
var cmds []*Cmd
|
|
|
|
if err := node.Decode(&cmds); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-12-08 02:28:02 +02:00
|
|
|
t.Cmds = cmds
|
|
|
|
return nil
|
|
|
|
|
2022-12-19 03:11:31 +02:00
|
|
|
// Full task object
|
|
|
|
case yaml.MappingNode:
|
|
|
|
var task struct {
|
|
|
|
Cmds []*Cmd
|
2023-06-11 03:08:28 +02:00
|
|
|
Cmd *Cmd
|
2022-12-19 03:11:31 +02:00
|
|
|
Deps []*Dep
|
|
|
|
Label string
|
|
|
|
Desc string
|
2023-06-04 03:33:00 +02:00
|
|
|
Prompt string
|
2022-12-19 03:11:31 +02:00
|
|
|
Summary string
|
|
|
|
Aliases []string
|
2023-11-30 03:38:12 +02:00
|
|
|
Sources []*Glob
|
|
|
|
Generates []*Glob
|
2022-12-19 03:11:31 +02:00
|
|
|
Status []string
|
|
|
|
Preconditions []*Precondition
|
|
|
|
Dir string
|
2023-01-14 21:41:56 +02:00
|
|
|
Set []string
|
|
|
|
Shopt []string
|
2022-12-19 03:11:31 +02:00
|
|
|
Vars *Vars
|
|
|
|
Env *Vars
|
|
|
|
Dotenv []string
|
|
|
|
Silent bool
|
|
|
|
Interactive bool
|
|
|
|
Internal bool
|
|
|
|
Method string
|
|
|
|
Prefix string
|
|
|
|
IgnoreError bool `yaml:"ignore_error"`
|
|
|
|
Run string
|
2023-01-07 02:38:35 +02:00
|
|
|
Platforms []*Platform
|
2023-06-30 03:13:41 +02:00
|
|
|
Requires *Requires
|
2023-10-07 23:06:43 +02:00
|
|
|
Watch bool
|
2022-12-19 03:11:31 +02:00
|
|
|
}
|
|
|
|
if err := node.Decode(&task); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-06-11 03:08:28 +02:00
|
|
|
if task.Cmd != nil {
|
|
|
|
if task.Cmds != nil {
|
|
|
|
return fmt.Errorf("yaml: line %d: task cannot have both cmd and cmds", node.Line)
|
|
|
|
}
|
|
|
|
t.Cmds = []*Cmd{task.Cmd}
|
|
|
|
} else {
|
|
|
|
t.Cmds = task.Cmds
|
|
|
|
}
|
2022-12-19 03:11:31 +02:00
|
|
|
t.Deps = task.Deps
|
|
|
|
t.Label = task.Label
|
|
|
|
t.Desc = task.Desc
|
2023-06-04 03:33:00 +02:00
|
|
|
t.Prompt = task.Prompt
|
2022-12-19 03:11:31 +02:00
|
|
|
t.Summary = task.Summary
|
|
|
|
t.Aliases = task.Aliases
|
|
|
|
t.Sources = task.Sources
|
|
|
|
t.Generates = task.Generates
|
|
|
|
t.Status = task.Status
|
|
|
|
t.Preconditions = task.Preconditions
|
|
|
|
t.Dir = task.Dir
|
2023-01-14 21:41:56 +02:00
|
|
|
t.Set = task.Set
|
|
|
|
t.Shopt = task.Shopt
|
2022-12-19 03:11:31 +02:00
|
|
|
t.Vars = task.Vars
|
|
|
|
t.Env = task.Env
|
|
|
|
t.Dotenv = task.Dotenv
|
|
|
|
t.Silent = task.Silent
|
|
|
|
t.Interactive = task.Interactive
|
|
|
|
t.Internal = task.Internal
|
|
|
|
t.Method = task.Method
|
|
|
|
t.Prefix = task.Prefix
|
|
|
|
t.IgnoreError = task.IgnoreError
|
|
|
|
t.Run = task.Run
|
2023-01-07 02:38:35 +02:00
|
|
|
t.Platforms = task.Platforms
|
2023-06-30 03:13:41 +02:00
|
|
|
t.Requires = task.Requires
|
2023-10-07 23:06:43 +02:00
|
|
|
t.Watch = task.Watch
|
2022-12-19 03:11:31 +02:00
|
|
|
return nil
|
2019-12-08 02:28:02 +02:00
|
|
|
}
|
2022-12-19 03:11:31 +02:00
|
|
|
|
|
|
|
return fmt.Errorf("yaml: line %d: cannot unmarshal %s into task", node.Line, node.ShortTag())
|
2018-02-17 18:22:18 +02:00
|
|
|
}
|
2022-10-02 07:45:27 +02:00
|
|
|
|
|
|
|
// DeepCopy creates a new instance of Task and copies
|
|
|
|
// data by value from the source struct.
|
|
|
|
func (t *Task) DeepCopy() *Task {
|
2023-03-25 21:13:06 +02:00
|
|
|
if t == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2022-10-02 07:45:27 +02:00
|
|
|
c := &Task{
|
|
|
|
Task: t.Task,
|
2023-04-06 13:07:57 +02:00
|
|
|
Cmds: deepcopy.Slice(t.Cmds),
|
|
|
|
Deps: deepcopy.Slice(t.Deps),
|
2022-10-02 07:45:27 +02:00
|
|
|
Label: t.Label,
|
|
|
|
Desc: t.Desc,
|
2023-06-04 03:33:00 +02:00
|
|
|
Prompt: t.Prompt,
|
2022-10-02 07:45:27 +02:00
|
|
|
Summary: t.Summary,
|
2023-04-06 13:07:57 +02:00
|
|
|
Aliases: deepcopy.Slice(t.Aliases),
|
|
|
|
Sources: deepcopy.Slice(t.Sources),
|
|
|
|
Generates: deepcopy.Slice(t.Generates),
|
|
|
|
Status: deepcopy.Slice(t.Status),
|
|
|
|
Preconditions: deepcopy.Slice(t.Preconditions),
|
2022-10-02 07:45:27 +02:00
|
|
|
Dir: t.Dir,
|
2023-04-06 13:07:57 +02:00
|
|
|
Set: deepcopy.Slice(t.Set),
|
|
|
|
Shopt: deepcopy.Slice(t.Shopt),
|
2022-10-02 07:45:27 +02:00
|
|
|
Vars: t.Vars.DeepCopy(),
|
|
|
|
Env: t.Env.DeepCopy(),
|
2023-04-06 13:07:57 +02:00
|
|
|
Dotenv: deepcopy.Slice(t.Dotenv),
|
2022-10-02 07:45:27 +02:00
|
|
|
Silent: t.Silent,
|
|
|
|
Interactive: t.Interactive,
|
|
|
|
Internal: t.Internal,
|
|
|
|
Method: t.Method,
|
|
|
|
Prefix: t.Prefix,
|
|
|
|
IgnoreError: t.IgnoreError,
|
|
|
|
Run: t.Run,
|
|
|
|
IncludeVars: t.IncludeVars.DeepCopy(),
|
|
|
|
IncludedTaskfileVars: t.IncludedTaskfileVars.DeepCopy(),
|
2023-04-06 13:07:57 +02:00
|
|
|
Platforms: deepcopy.Slice(t.Platforms),
|
2023-03-17 14:34:06 +02:00
|
|
|
Location: t.Location.DeepCopy(),
|
2023-06-30 03:13:41 +02:00
|
|
|
Requires: t.Requires.DeepCopy(),
|
2022-10-02 07:45:27 +02:00
|
|
|
}
|
|
|
|
return c
|
|
|
|
}
|