1
0
mirror of https://github.com/go-task/task.git synced 2025-11-29 22:48:03 +02:00

feat: implement task sorting with --sort flag (#1105)

* refactor: move deepcopy into its own package

* feat: add generic orderedmap implementation

* refactor: implement tasks with orderedmap

* feat: implement sort flag for all task outputs

* refactor: implement vars with orderedmap

* chore: docs

* fix: linting issues

* fix: non deterministic behavior in tests
This commit is contained in:
Pete Davison
2023-04-06 12:07:57 +01:00
committed by GitHub
parent 719f30219b
commit f22389a824
25 changed files with 678 additions and 242 deletions

58
task.go
View File

@@ -6,8 +6,6 @@ import (
"io"
"os"
"runtime"
"sort"
"strings"
"sync"
"sync/atomic"
"time"
@@ -19,6 +17,7 @@ import (
"github.com/go-task/task/v3/internal/logger"
"github.com/go-task/task/v3/internal/output"
"github.com/go-task/task/v3/internal/slicesext"
"github.com/go-task/task/v3/internal/sort"
"github.com/go-task/task/v3/internal/summary"
"github.com/go-task/task/v3/internal/templater"
"github.com/go-task/task/v3/taskfile"
@@ -60,6 +59,7 @@ type Executor struct {
Compiler compiler.Compiler
Output output.Output
OutputStyle taskfile.Output
TaskSorter sort.TaskSorter
taskvars *taskfile.Vars
fuzzyModel *fuzzy.Model
@@ -357,14 +357,14 @@ func (e *Executor) startExecution(ctx context.Context, t *taskfile.Task, execute
// If multiple tasks contain the same alias or no matches are found an error is returned.
func (e *Executor) GetTask(call taskfile.Call) (*taskfile.Task, error) {
// Search for a matching task
matchingTask, ok := e.Taskfile.Tasks[call.Task]
if ok {
matchingTask := e.Taskfile.Tasks.Get(call.Task)
if matchingTask != nil {
return matchingTask, nil
}
// If didn't find one, search for a task with a matching alias
var aliasedTasks []string
for _, task := range e.Taskfile.Tasks {
for _, task := range e.Taskfile.Tasks.Values() {
if slices.Contains(task.Aliases, call.Task) {
aliasedTasks = append(aliasedTasks, task.Task)
matchingTask = task
@@ -395,28 +395,33 @@ func (e *Executor) GetTask(call taskfile.Call) (*taskfile.Task, error) {
type FilterFunc func(task *taskfile.Task) bool
func (e *Executor) GetTaskList(filters ...FilterFunc) ([]*taskfile.Task, error) {
tasks := make([]*taskfile.Task, 0, len(e.Taskfile.Tasks))
tasks := make([]*taskfile.Task, 0, e.Taskfile.Tasks.Len())
// Create an error group to wait for each task to be compiled
var g errgroup.Group
// Fetch and compile the list of tasks
for key := range e.Taskfile.Tasks {
task := e.Taskfile.Tasks[key]
g.Go(func() error {
// Check if we should filter the task
for _, filter := range filters {
if filter(task) {
return nil
}
// Filter tasks based on the given filter functions
for _, task := range e.Taskfile.Tasks.Values() {
var shouldFilter bool
for _, filter := range filters {
if filter(task) {
shouldFilter = true
}
}
if !shouldFilter {
tasks = append(tasks, task)
}
}
// Compile the task
// Compile the list of tasks
for i := range tasks {
task := tasks[i]
g.Go(func() error {
compiledTask, err := e.FastCompiledTask(taskfile.Call{Task: task.Task})
if err == nil {
task = compiledTask
}
tasks = append(tasks, task)
task = compiledTask
return nil
})
}
@@ -426,20 +431,11 @@ func (e *Executor) GetTaskList(filters ...FilterFunc) ([]*taskfile.Task, error)
return nil, err
}
// Sort the tasks.
// Tasks that are not namespaced should be listed before tasks that are.
// We detect this by searching for a ':' in the task name.
sort.Slice(tasks, func(i, j int) bool {
iContainsColon := strings.Contains(tasks[i].Task, ":")
jContainsColon := strings.Contains(tasks[j].Task, ":")
if iContainsColon == jContainsColon {
return tasks[i].Task < tasks[j].Task
}
if !iContainsColon && jContainsColon {
return true
}
return false
})
// Sort the tasks
if e.TaskSorter == nil {
e.TaskSorter = &sort.AlphaNumericWithRootTasksFirst{}
}
e.TaskSorter.Sort(tasks)
return tasks, nil
}