1
0
mirror of https://github.com/go-task/task.git synced 2025-05-17 22:32:40 +02:00

Add Taskfile struct and start implementing new format

Updates #54, #66 and #77
This commit is contained in:
Andrey Nering 2017-12-29 18:27:32 -02:00
parent 00ff1447ee
commit 134c6b79c4
8 changed files with 93 additions and 24 deletions

11
help.go
View File

@ -18,17 +18,18 @@ func (e *Executor) PrintTasksHelp() {
// Format in tab-separated columns with a tab stop of 8. // Format in tab-separated columns with a tab stop of 8.
w := tabwriter.NewWriter(e.Stdout, 0, 8, 0, '\t', 0) w := tabwriter.NewWriter(e.Stdout, 0, 8, 0, '\t', 0)
for _, task := range tasks { for _, task := range tasks {
fmt.Fprintln(w, fmt.Sprintf("* %s: \t%s", task, e.Tasks[task].Desc)) fmt.Fprintf(w, "* %s: \t%s\n", task.Task, task.Desc)
} }
w.Flush() w.Flush()
} }
func (e *Executor) tasksWithDesc() (tasks []string) { func (e *Executor) tasksWithDesc() (tasks []*Task) {
for name, task := range e.Tasks { tasks = make([]*Task, 0, len(e.Taskfile.Tasks))
for _, task := range e.Taskfile.Tasks {
if task.Desc != "" { if task.Desc != "" {
tasks = append(tasks, name) tasks = append(tasks, task)
} }
} }
sort.Strings(tasks) sort.Slice(tasks, func(i, j int) bool { return tasks[i].Task < tasks[j].Task })
return return
} }

View File

@ -11,7 +11,7 @@ import (
// Status returns an error if any the of given tasks is not up-to-date // Status returns an error if any the of given tasks is not up-to-date
func (e *Executor) Status(calls ...Call) error { func (e *Executor) Status(calls ...Call) error {
for _, call := range calls { for _, call := range calls {
t, ok := e.Tasks[call.Task] t, ok := e.Taskfile.Tasks[call.Task]
if !ok { if !ok {
return &taskNotFoundError{taskName: call.Task} return &taskNotFoundError{taskName: call.Task}
} }

View File

@ -23,7 +23,7 @@ const (
// Executor executes a Taskfile // Executor executes a Taskfile
type Executor struct { type Executor struct {
Tasks Tasks Taskfile *Taskfile
Dir string Dir string
Force bool Force bool
Watch bool Watch bool
@ -78,8 +78,8 @@ func (e *Executor) Run(calls ...Call) error {
e.Stderr = os.Stderr e.Stderr = os.Stderr
} }
e.taskCallCount = make(map[string]*int32, len(e.Tasks)) e.taskCallCount = make(map[string]*int32, len(e.Taskfile.Tasks))
for k := range e.Tasks { for k := range e.Taskfile.Tasks {
e.taskCallCount[k] = new(int32) e.taskCallCount[k] = new(int32)
} }
@ -89,7 +89,7 @@ func (e *Executor) Run(calls ...Call) error {
// check if given tasks exist // check if given tasks exist
for _, c := range calls { for _, c := range calls {
if _, ok := e.Tasks[c.Task]; !ok { if _, ok := e.Taskfile.Tasks[c.Task]; !ok {
// FIXME: move to the main package // FIXME: move to the main package
e.PrintTasksHelp() e.PrintTasksHelp()
return &taskNotFoundError{taskName: c.Task} return &taskNotFoundError{taskName: c.Task}

View File

@ -347,3 +347,26 @@ func TestCyclicDep(t *testing.T) {
assert.NoError(t, e.ReadTaskfile()) assert.NoError(t, e.ReadTaskfile())
assert.IsType(t, &task.MaximumTaskCallExceededError{}, e.Run(task.Call{Task: "task-1"})) assert.IsType(t, &task.MaximumTaskCallExceededError{}, e.Run(task.Call{Task: "task-1"}))
} }
func TestTaskVersion(t *testing.T) {
tests := []struct {
Dir string
Version int
}{
{"testdata/version/v1", 1},
{"testdata/version/v2", 2},
}
for _, test := range tests {
t.Run(test.Dir, func(t *testing.T) {
e := task.Executor{
Dir: test.Dir,
Stdout: ioutil.Discard,
Stderr: ioutil.Discard,
}
assert.NoError(t, e.ReadTaskfile())
assert.Equal(t, test.Version, e.Taskfile.Version)
assert.Equal(t, 2, len(e.Taskfile.Tasks))
})
}
}

View File

@ -10,12 +10,37 @@ import (
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
// Taskfile represents a Taskfile.yml
type Taskfile struct {
// TODO: version is still not used
Version int
Tasks Tasks
}
// UnmarshalYAML implements yaml.Unmarshaler interface
func (tf *Taskfile) UnmarshalYAML(unmarshal func(interface{}) error) error {
if err := unmarshal(&tf.Tasks); err == nil {
return nil
}
var taskfile struct {
Version int
Tasks Tasks
}
if err := unmarshal(&taskfile); err != nil {
return err
}
tf.Version = taskfile.Version
tf.Tasks = taskfile.Tasks
return nil
}
// ReadTaskfile parses Taskfile from the disk // ReadTaskfile parses Taskfile from the disk
func (e *Executor) ReadTaskfile() error { func (e *Executor) ReadTaskfile() error {
path := filepath.Join(e.Dir, TaskFilePath) path := filepath.Join(e.Dir, TaskFilePath)
var err error var err error
e.Tasks, err = e.readTaskfileData(path) e.Taskfile, err = e.readTaskfileData(path)
if err != nil { if err != nil {
return err return err
} }
@ -27,20 +52,22 @@ func (e *Executor) ReadTaskfile() error {
default: default:
return err return err
} }
} } else {
if err := mergo.MapWithOverwrite(&e.Tasks, osTasks); err != nil { if err := mergo.MapWithOverwrite(&e.Taskfile.Tasks, osTasks.Tasks); err != nil {
return err return err
} }
for name, task := range e.Tasks { }
for name, task := range e.Taskfile.Tasks {
task.Task = name task.Task = name
} }
return e.readTaskvars() return e.readTaskvars()
} }
func (e *Executor) readTaskfileData(path string) (tasks map[string]*Task, err error) { func (e *Executor) readTaskfileData(path string) (*Taskfile, error) {
if b, err := ioutil.ReadFile(path + ".yml"); err == nil { if b, err := ioutil.ReadFile(path + ".yml"); err == nil {
return tasks, yaml.UnmarshalStrict(b, &tasks) var taskfile Taskfile
return &taskfile, yaml.UnmarshalStrict(b, &taskfile)
} }
return nil, taskFileNotFound{path} return nil, taskFileNotFound{path}
} }

9
testdata/version/v1/Taskfile.yml vendored Normal file
View File

@ -0,0 +1,9 @@
version: 1
tasks:
foo:
cmds:
- echo "Foo"
bar:
cmds:
- echo "Bar"

9
testdata/version/v2/Taskfile.yml vendored Normal file
View File

@ -0,0 +1,9 @@
version: 2
tasks:
foo:
cmds:
- echo "Foo"
bar:
cmds:
- echo "Bar"

View File

@ -92,7 +92,7 @@ func (v *Var) UnmarshalYAML(unmarshal func(interface{}) error) error {
// 4. Taskvars variables, resolved with access to: // 4. Taskvars variables, resolved with access to:
// - environment variables // - environment variables
func (e *Executor) getVariables(call Call) (Vars, error) { func (e *Executor) getVariables(call Call) (Vars, error) {
t, ok := e.Tasks[call.Task] t, ok := e.Taskfile.Tasks[call.Task]
if !ok { if !ok {
return nil, &taskNotFoundError{call.Task} return nil, &taskNotFoundError{call.Task}
} }
@ -198,7 +198,7 @@ func (e *Executor) handleShVar(v Var) (string, error) {
// CompiledTask returns a copy of a task, but replacing variables in almost all // CompiledTask returns a copy of a task, but replacing variables in almost all
// properties using the Go template package. // properties using the Go template package.
func (e *Executor) CompiledTask(call Call) (*Task, error) { func (e *Executor) CompiledTask(call Call) (*Task, error) {
origTask, ok := e.Tasks[call.Task] origTask, ok := e.Taskfile.Tasks[call.Task]
if !ok { if !ok {
return nil, &taskNotFoundError{call.Task} return nil, &taskNotFoundError{call.Task}
} }