-
Notifications
You must be signed in to change notification settings - Fork 10
/
registry.go
136 lines (114 loc) · 4.32 KB
/
registry.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package taskrunner
import (
"fmt"
"sort"
)
// DefaultRegistry is where tasks are registered to through the package-level functions Add, Group
// and Tasks.
var DefaultRegistry = NewRegistry()
// NewRegistry creates a new task registry.
func NewRegistry() *Registry {
return &Registry{
definitions: make(map[string]*Task),
flagsByTask: make(map[string]map[string]TaskFlag),
}
}
// Registry is an object that keeps track of task definitions.
type Registry struct {
definitions map[string]*Task
flagsByTask map[string]map[string]TaskFlag
}
type TaskOption func(*Task) *Task
// Add registers a task, failing if the name has already been taken.
func (r *Registry) Add(t *Task, opts ...TaskOption) *Task {
for _, opt := range opts {
t = opt(t)
}
if _, ok := r.definitions[t.Name]; ok {
panic(fmt.Sprintf("Duplicate task registered: %s", t.Name))
}
// Validate that both Run and RunWithFlags are not defined,
// displaying a message that prefers RunWithFlags over the deprecated Run.
if t.Run != nil && t.RunWithFlags != nil {
panic(fmt.Sprintf("Both `Run` and `RunWithFlags` are defined on the `%s` task. `Run` is deprecated, please prefer using `RunWithFlags`.", t.Name))
}
r.definitions[t.Name] = t
r.flagsByTask[t.Name] = map[string]TaskFlag{}
for _, flag := range t.Flags {
// Validate that the task Name does not match any of its flag Long/ShortNames.
if t.Name == flag.LongName {
panic(fmt.Sprintf("Task name `%s` and flag LongName `%s` are currently duplicates. Please de-depulicate their names.", t.Name, flag.LongName))
}
if t.Name == string(flag.ShortName) {
panic(fmt.Sprintf("Task name `%s` and flag ShortName `%s` are currently duplicates. Please de-depulicate their names.", t.Name, string(flag.ShortName)))
}
// Validate that the following task TaskFlag fields are provided:
// - LongName or ShortName
// - Disallow --help/-h flags
// - Description
// - ValueType
if flag.LongName == "" && flag.ShortName == 0 {
panic(fmt.Sprintf("Neither LongName nor ShortName are defined for a flag on `%s`. At least one name must be defined.", t.Name))
}
if flag.LongName == "help" {
panic("The LongFlag name `help` is reserved.")
}
if string(flag.ShortName) == "h" {
panic("The ShortFlag name `h` is reserved.")
}
if flag.Description == "" {
var optionName string
if flag.LongName != "" {
optionName = flag.LongName
} else {
optionName = string(flag.ShortName)
}
panic(fmt.Sprintf("Please provide a description for the `%s` flag.", optionName))
}
if flag.ValueType != StringTypeFlag && flag.ValueType != BoolTypeFlag && flag.ValueType != IntTypeFlag && flag.ValueType != Float64TypeFlag && flag.ValueType != DurationTypeFlag {
panic("Please set the flag ValueType with `taskrunner.StringTypeFlag`, `taskrunner.BoolTypeFlag`, `taskrunner.DurationTypeFlag`, `taskrunner.Float64TypeFlag` or `taskrunner.IntTypeFlag`.")
}
// Validate that there are no duplicate LongNames.
if flag.LongName != "" {
_, ok := r.flagsByTask[t.Name][flag.LongName]
if ok {
panic(fmt.Sprintf("Duplicate flag LongName registered: `%s`.", flag.LongName))
}
r.flagsByTask[t.Name][flag.LongName] = flag
}
// Validate that there are no duplicate ShortNames.
if flag.ShortName != 0 {
_, ok := r.flagsByTask[t.Name][string(flag.ShortName)]
if ok {
panic(fmt.Sprintf("Duplicate flag ShortName registered: `%s`.", string(flag.ShortName)))
}
r.flagsByTask[t.Name][string(flag.ShortName)] = flag
}
}
return t
}
// Group creates a pseudo-task that groups other tasks underneath it. It explicitly doesn't expose
// the pseudo-task because groups are not allowed to be dependencies.
func (r *Registry) Group(name string, tasks ...*Task) {
r.Add(&Task{
Name: name,
Dependencies: tasks,
IsGroup: true,
})
}
// Tasks returns all registered tasks in alphabetical order.
func (r *Registry) Tasks() (list []*Task) {
for _, t := range r.definitions {
list = append(list, t)
}
sort.Slice(list, func(i, j int) bool {
return list[i].Name < list[j].Name
})
return list
}
// Add registers a task, failing if the name has already been taken.
var Add = DefaultRegistry.Add
// Group creates a pseudo-task that groups other tasks underneath it.
var Group = DefaultRegistry.Group
// Tasks returns all registered tasks in alphabetical order.
var Tasks = DefaultRegistry.Tasks