/
soltarget.go
153 lines (144 loc) · 4.41 KB
/
soltarget.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
package spec
import (
"fmt"
"github.com/apigear-io/cli/pkg/helper"
"github.com/apigear-io/cli/pkg/repos"
)
type SolutionTarget struct {
Name string `json:"name" yaml:"name"`
Description string `json:"description" yaml:"description"`
Inputs []string `json:"inputs" yaml:"inputs"`
Output string `json:"output" yaml:"output"`
Template string `json:"template" yaml:"template"`
Features []string `json:"features" yaml:"features"`
Force bool `json:"force" yaml:"force"`
// computed fields
computed bool `json:"-" yaml:"-"`
// expandedInputs is the inputs with the variables expanded
expandedInputs []string `json:"-"` // expanded inputs
// dependencies are the dependencies of the target
dependencies []string `json:"-"` // dependencies of the target
// TemplateDir is the directory of the template
TemplateDir string `json:"-" yaml:"-"`
// TemplatesDir is the "templates" directory inside the template dir
TemplatesDir string `json:"-" yaml:"-"`
// RulesFile is the "rules.yaml" file inside the template dir
RulesFile string `json:"-" yaml:"-"`
}
// GetOutputDir returns the output dir.
// The output dir can be relative to the root dir of the solution.
func (l *SolutionTarget) GetOutputDir(rootDir string) string {
return helper.Join(rootDir, l.Output)
}
func (l *SolutionTarget) Validate(doc *SolutionDoc) error {
// basic validation
if l.Output == "" {
return fmt.Errorf("target %s: output is required", l.Name)
}
if l.Template == "" {
return fmt.Errorf("target %s: template is required", l.Name)
}
if l.Inputs == nil {
l.Inputs = make([]string, 0)
}
if l.Features == nil {
// if no features, use all
l.Features = []string{"all"}
}
// compute derived fields
if err := l.compute(doc); err != nil {
return err
}
// extended validation
if !helper.IsDir(l.TemplateDir) {
return fmt.Errorf("target %s: template dir not found: %s", l.Name, l.TemplateDir)
}
if !helper.IsDir(l.TemplatesDir) {
return fmt.Errorf("target %s: templates dir not found: %s", l.Name, l.TemplatesDir)
}
if !helper.IsFile(l.RulesFile) {
return fmt.Errorf("target %s: rules file not found: %s", l.Name, l.RulesFile)
}
// check inputs
for _, input := range l.expandedInputs {
result, err := CheckFile(input)
if err != nil {
return err
}
if !result.Valid() {
for _, e := range result.Errors {
log.Warn().Msg(e.String())
}
return fmt.Errorf("target %s: invalid file: %s", l.Name, input)
}
}
return nil
}
// compute computes the dependencies and expanded inputs of a target.
func (l *SolutionTarget) compute(doc *SolutionDoc) error {
if l.computed {
return nil
}
// compute template dir
tplDir := helper.Join(doc.RootDir, l.Template)
if helper.IsDir(tplDir) {
l.TemplateDir = tplDir
l.TemplatesDir = helper.Join(tplDir, "templates")
l.RulesFile = helper.Join(tplDir, "rules.yaml")
} else {
// try to find the template dir in the templates dir
repoId, err := repos.GetOrInstallTemplateFromRepoID(l.Template)
if err != nil {
log.Err(err).Msgf("failed to get template %s", l.Template)
return err
}
tplDir, err := repos.Cache.GetTemplateDir(repoId)
if err != nil {
log.Err(err).Msgf("failed to get template dir %s", l.Template)
return err
}
l.Template = repoId
l.TemplateDir = tplDir
l.TemplatesDir = helper.Join(tplDir, "templates")
l.RulesFile = helper.Join(tplDir, "rules.yaml")
}
// record dependencies
if l.dependencies == nil {
l.dependencies = make([]string, 0)
}
if len(l.dependencies) == 0 {
if l.TemplatesDir != "" {
l.dependencies = append(l.dependencies, l.TemplatesDir)
}
if l.RulesFile != "" {
l.dependencies = append(l.dependencies, l.RulesFile)
}
l.dependencies = append(l.dependencies, l.expandedInputs...)
}
// expand inputs
if l.expandedInputs == nil {
l.expandedInputs = make([]string, 0)
}
if len(l.expandedInputs) == 0 {
expanded, err := helper.ExpandInputs(doc.RootDir, l.Inputs...)
if err != nil {
return err
}
l.expandedInputs = append(l.expandedInputs, expanded...)
}
l.dependencies = append(l.dependencies, l.expandedInputs...)
l.computed = true
return nil
}
func (l *SolutionTarget) Dependencies() []string {
if !l.computed {
log.Error().Msg("target not computed, dependencies not available")
}
return l.dependencies
}
func (l *SolutionTarget) ExpandedInputs() []string {
if !l.computed {
log.Error().Msg("target not computed, expanded inputs not available")
}
return l.expandedInputs
}