forked from go-task/task
-
Notifications
You must be signed in to change notification settings - Fork 0
/
included_taskfile.go
167 lines (146 loc) · 4.21 KB
/
included_taskfile.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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package taskfile
import (
"errors"
"fmt"
"path/filepath"
"github.com/go-task/task/v3/internal/execext"
"github.com/go-task/task/v3/internal/filepathext"
"golang.org/x/exp/slices"
"gopkg.in/yaml.v3"
)
// IncludedTaskfile represents information about included taskfiles
type IncludedTaskfile struct {
Taskfile string
Dir string
Optional bool
Internal bool
Aliases []string
AdvancedImport bool
Vars *Vars
BaseDir string // The directory from which the including taskfile was loaded; used to resolve relative paths
}
// IncludedTaskfiles represents information about included tasksfiles
type IncludedTaskfiles struct {
Keys []string
Mapping map[string]IncludedTaskfile
}
// UnmarshalYAML implements the yaml.Unmarshaler interface.
func (tfs *IncludedTaskfiles) UnmarshalYAML(node *yaml.Node) error {
if node.Kind != yaml.MappingNode {
return errors.New("task: includes is not a map")
}
// NOTE(@andreynering): on this style of custom unmarsheling,
// even number contains the keys, while odd numbers contains
// the values.
for i := 0; i < len(node.Content); i += 2 {
keyNode := node.Content[i]
valueNode := node.Content[i+1]
var v IncludedTaskfile
if err := valueNode.Decode(&v); err != nil {
return err
}
tfs.Set(keyNode.Value, v)
}
return nil
}
// Len returns the length of the map
func (tfs *IncludedTaskfiles) Len() int {
if tfs == nil {
return 0
}
return len(tfs.Keys)
}
// Merge merges the given IncludedTaskfiles into the caller one
func (tfs *IncludedTaskfiles) Merge(other *IncludedTaskfiles) {
_ = other.Range(func(key string, value IncludedTaskfile) error {
tfs.Set(key, value)
return nil
})
}
// Set sets a value to a given key
func (tfs *IncludedTaskfiles) Set(key string, includedTaskfile IncludedTaskfile) {
if tfs.Mapping == nil {
tfs.Mapping = make(map[string]IncludedTaskfile, 1)
}
if !slices.Contains(tfs.Keys, key) {
tfs.Keys = append(tfs.Keys, key)
}
tfs.Mapping[key] = includedTaskfile
}
// Range allows you to loop into the included taskfiles in its right order
func (tfs *IncludedTaskfiles) Range(yield func(key string, includedTaskfile IncludedTaskfile) error) error {
if tfs == nil {
return nil
}
for _, k := range tfs.Keys {
if err := yield(k, tfs.Mapping[k]); err != nil {
return err
}
}
return nil
}
// UnmarshalYAML implements yaml.Unmarshaler interface
func (it *IncludedTaskfile) UnmarshalYAML(unmarshal func(interface{}) error) error {
var str string
if err := unmarshal(&str); err == nil {
it.Taskfile = str
return nil
}
var includedTaskfile struct {
Taskfile string
Dir string
Optional bool
Internal bool
Aliases []string
Vars *Vars
}
if err := unmarshal(&includedTaskfile); err != nil {
return err
}
it.Taskfile = includedTaskfile.Taskfile
it.Dir = includedTaskfile.Dir
it.Optional = includedTaskfile.Optional
it.Internal = includedTaskfile.Internal
it.Aliases = includedTaskfile.Aliases
it.AdvancedImport = true
it.Vars = includedTaskfile.Vars
return nil
}
// DeepCopy creates a new instance of IncludedTaskfile and copies
// data by value from the source struct.
func (it *IncludedTaskfile) DeepCopy() *IncludedTaskfile {
if it == nil {
return nil
}
return &IncludedTaskfile{
Taskfile: it.Taskfile,
Dir: it.Dir,
Optional: it.Optional,
Internal: it.Internal,
AdvancedImport: it.AdvancedImport,
Vars: it.Vars.DeepCopy(),
BaseDir: it.BaseDir,
}
}
// FullTaskfilePath returns the fully qualified path to the included taskfile
func (it *IncludedTaskfile) FullTaskfilePath() (string, error) {
return it.resolvePath(it.Taskfile)
}
// FullDirPath returns the fully qualified path to the included taskfile's working directory
func (it *IncludedTaskfile) FullDirPath() (string, error) {
return it.resolvePath(it.Dir)
}
func (it *IncludedTaskfile) resolvePath(path string) (string, error) {
path, err := execext.Expand(path)
if err != nil {
return "", err
}
if filepath.IsAbs(path) {
return path, nil
}
result, err := filepath.Abs(filepathext.SmartJoin(it.BaseDir, path))
if err != nil {
return "", fmt.Errorf("task: error resolving path %s relative to %s: %w", path, it.BaseDir, err)
}
return result, nil
}