Skip to content

Commit e094bd0

Browse files
committed
update template installer from solution
1 parent d3ff0a8 commit e094bd0

File tree

13 files changed

+119
-104
lines changed

13 files changed

+119
-104
lines changed

Taskfile.yml

+10-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ env:
44
GO111MODULE: on
55
CGO_ENABLED: 0
66

7+
vars:
8+
GIT_COMMIT:
9+
sh: git rev-parse --short HEAD
10+
GIT_TAG:
11+
sh: git describe --tags --abbrev=0 --exact-match 2>/dev/null || echo "latest"
12+
BUILD_DATA:
13+
sh: date -u '+%Y-%m-%dT%H:%M:%SZ'
14+
715
tasks:
816
setup:
917
desc: Setup the project
@@ -12,13 +20,13 @@ tasks:
1220
build:
1321
desc: Build the project
1422
cmds:
15-
- go build -o ./bin/apigear ./cmd/apigear
23+
- go build -o ./bin/apigear -ldflags="-X main.version={{.GIT_TAG}} -X main.commit={{.GIT_COMMIT}} -X main.date={{.BUILD_DATA}}" ./cmd/apigear ./cmd/apigear
1624
sources:
1725
- "**/*.go"
1826
install:
1927
desc: Install the project
2028
cmds:
21-
- go install ./cmd/apigear
29+
- go install -ldflags="-X main.version={{.GIT_TAG}} -X main.commit={{.GIT_COMMIT}} -X main.date={{.BUILD_DATA}}" ./cmd/apigear
2230
lint:
2331
desc: Lint the project
2432
cmds:

pkg/cmd/registry/info.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ func NewInfoCommand() *cobra.Command {
1313
Args: cobra.ExactArgs(1),
1414
Run: func(cmd *cobra.Command, args []string) {
1515
name := args[0]
16-
info, err := repos.Registry.Info(name)
16+
info, err := repos.Registry.Get(name)
1717
if err != nil {
1818
cmd.PrintErrln(err)
1919
return

pkg/cmd/registry/install.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ func NewInstallCommand() *cobra.Command {
1717
Args: cobra.ExactArgs(1),
1818
Run: func(cmd *cobra.Command, args []string) {
1919
repoID := args[0]
20-
cmd.Printf("installing template from %s\n", repoID)
21-
err := repos.InstallTemplateFromRepoID(repoID)
20+
fixedRepoId, err := repos.GetOrInstallTemplateFromRepoID(repoID)
21+
cmd.Printf("using template %s\n", fixedRepoId)
2222
if err != nil {
2323
cmd.PrintErrln(err)
2424
return

pkg/gen/generator.go

+15-7
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,22 @@ func (s *GeneratorStats) TotalFiles() int {
4343
}
4444

4545
type GeneratorOptions struct {
46-
OutputDir string
46+
// OutputDir is the directory where files are written
47+
OutputDir string
48+
// TemplatesDir is the directory where templates are located
4749
TemplatesDir string
48-
System *model.System
50+
// System is the root system model
51+
System *model.System
52+
// UserFeatures is a list of features defined by user
4953
UserFeatures []string
50-
UserForce bool
51-
Output Output
52-
DryRun bool
53-
Meta map[string]any
54+
// UserForce forces overwrite of existing files
55+
UserForce bool
56+
// Output is the output writer
57+
Output OutputWriter
58+
// DryRun does not write files
59+
DryRun bool
60+
// Meta is a map of metadata
61+
Meta map[string]any
5462
}
5563

5664
// generator applies template transformation on a set of files define in rules
@@ -64,7 +72,7 @@ type generator struct {
6472
OutputDir string
6573
DryRun bool
6674
Stats GeneratorStats
67-
Output Output
75+
Output OutputWriter
6876
Meta map[string]any
6977
}
7078

pkg/gen/out.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"github.com/apigear-io/cli/pkg/helper"
88
)
99

10-
type Output interface {
10+
type OutputWriter interface {
1111
Write(input []byte, target string, force bool) error
1212
Copy(source, target string, force bool) error
1313
Compare(input []byte, target string) (bool, error)

pkg/git/info.go

+5
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ func SortRepoInfo(infos []*RepoInfo) {
5454
sort.Slice(infos, func(i, j int) bool {
5555
return infos[i].Name < infos[j].Name
5656
})
57+
for _, info := range infos {
58+
sort.Slice(info.Versions, func(i, j int) bool {
59+
return info.Versions[i].Name >= info.Versions[j].Name
60+
})
61+
}
5762
}
5863

5964
func LocalRepoInfo(source string) (*RepoInfo, error) {

pkg/log/reporter.go renamed to pkg/log/eventwriter.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ type ReportEvent struct {
1919
Error string `json:"error,omitempty"`
2020
}
2121

22-
type ReportWriter struct {
22+
type EventLogWriter struct {
2323
}
2424

25-
func NewReportWriter() io.Writer {
26-
return &ReportWriter{}
25+
func NewEventLogWriter() io.Writer {
26+
return &EventLogWriter{}
2727
}
2828

29-
func (w *ReportWriter) Write(p []byte) (n int, err error) {
29+
func (w *EventLogWriter) Write(p []byte) (n int, err error) {
3030
if bytesEmitter != nil {
3131
bytesEmitter(string(p))
3232
}

pkg/log/logger.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func init() {
2626
console := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: "15:04:05"}
2727
multi := zerolog.MultiLevelWriter(
2828
console,
29-
NewReportWriter(),
29+
NewEventLogWriter(),
3030
newRollingFile(logFile),
3131
)
3232
logger = zerolog.New(multi).With().Timestamp().Logger().Level(level)

pkg/repos/cache.go

+9
Original file line numberDiff line numberDiff line change
@@ -208,3 +208,12 @@ func (c *cache) UpgradeAll() error {
208208
}
209209
return c.Upgrade(names)
210210
}
211+
212+
func (c *cache) GetTemplateDir(repoId string) (string, error) {
213+
repoId = EnsureRepoID(repoId)
214+
target := helper.Join(c.cacheDir, repoId)
215+
if !helper.IsDir(target) {
216+
return "", fmt.Errorf("template %s not found", repoId)
217+
}
218+
return target, nil
219+
}

pkg/repos/install.go

+13-21
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,26 @@
11
package repos
22

3-
import (
4-
"fmt"
5-
)
6-
73
// InstallTemplateFromFQN tries to install a template
84
// from a fully qualified name (e.g. name@version)
9-
func InstallTemplateFromRepoID(repoID string) error {
10-
version := VersionFromRepoID(repoID)
11-
info, err := Registry.Get(repoID)
5+
func GetOrInstallTemplateFromRepoID(repoID string) (string, error) {
6+
fixedRepoId, err := Registry.FixRepoId(repoID)
127
if err != nil {
13-
return err
8+
return "", err
149
}
15-
if version == "latest" {
16-
version = info.Latest.Name
17-
if version == "" {
18-
return fmt.Errorf("no version found for template: %s", repoID)
19-
}
20-
repoID = MakeRepoID(info.Name, version)
21-
log.Info().Msgf("use latest version %s ", repoID)
10+
if Cache.Exists(fixedRepoId) {
11+
log.Info().Msgf("template %s already installed", fixedRepoId)
12+
return fixedRepoId, nil
2213
}
23-
if Cache.Exists(repoID) {
24-
log.Info().Msgf("template %s already installed", repoID)
25-
return nil
14+
info, err := Registry.Get(fixedRepoId)
15+
if err != nil {
16+
return "", err
2617
}
2718
url := info.Git
28-
log.Info().Msgf("installing template %s@%s from %s", repoID, version, url)
19+
log.Info().Msgf("installing template %s from %s", fixedRepoId, url)
20+
version := VersionFromRepoID(fixedRepoId)
2921
_, err = Cache.Install(url, version)
3022
if err != nil {
31-
return err
23+
return "", err
3224
}
33-
return nil
25+
return fixedRepoId, nil
3426
}

pkg/repos/registry.go

+12-15
Original file line numberDiff line numberDiff line change
@@ -85,21 +85,6 @@ func (r *registry) List() ([]*git.RepoInfo, error) {
8585
return r.Registry.Entries, nil
8686
}
8787

88-
// Info returns the template info
89-
func (r *registry) Info(repoID string) (*git.RepoInfo, error) {
90-
repoID = NameFromRepoID(repoID)
91-
err := r.ensureRegistry()
92-
if err != nil {
93-
return nil, err
94-
}
95-
for _, info := range r.Registry.Entries {
96-
if info.Name == repoID {
97-
return info, nil
98-
}
99-
}
100-
return nil, fmt.Errorf("template not found: %s", repoID)
101-
}
102-
10388
// Search searches for templates in the registry
10489
func (c *registry) Search(pattern string) ([]*git.RepoInfo, error) {
10590
err := c.ensureRegistry()
@@ -177,3 +162,15 @@ func (r *registry) Reset() error {
177162
}
178163
return git.CloneOrPull(r.RegistryURL, r.RegistryDir)
179164
}
165+
166+
func (r *registry) FixRepoId(repoID string) (string, error) {
167+
version := VersionFromRepoID(repoID)
168+
if !IsRepoID(repoID) || version == "latest" {
169+
info, err := r.Get(repoID)
170+
if err != nil {
171+
return "", err
172+
}
173+
repoID = MakeRepoID(info.Name, info.Latest.Name)
174+
}
175+
return repoID, nil
176+
}

pkg/sol/runner.go

+26-9
Original file line numberDiff line numberDiff line change
@@ -133,18 +133,35 @@ func runSolution(doc *spec.SolutionDoc) error {
133133
if name == "" {
134134
name = helper.BaseName(outDir)
135135
}
136-
err := repos.InstallTemplateFromRepoID(layer.Template)
137-
if err != nil {
138-
log.Info().Err(err).Msgf("not a registry template %s. Try local template", layer.Template)
136+
// check for local template
137+
tplDir := helper.Join(rootDir, layer.Template)
138+
if helper.IsDir(tplDir) {
139+
log.Info().Msgf("using local template %s", tplDir)
140+
} else {
141+
log.Info().Msgf("try to detect registered template %s", layer.Template)
142+
repoId, err := repos.GetOrInstallTemplateFromRepoID(layer.Template)
143+
if err != nil {
144+
return err
145+
}
146+
tplDir, err = repos.Cache.GetTemplateDir(repoId)
147+
if err != nil {
148+
return fmt.Errorf("can't find template %s", layer.Template)
149+
}
150+
// update template id based on the resolved repo id
151+
layer.Template = repoId
152+
log.Info().Msgf("using registered template %s", tplDir)
139153
}
140-
tplDir := layer.GetTemplatesDir(rootDir)
141154
if tplDir == "" {
142-
return fmt.Errorf("template dir does not exist")
155+
// we don't have a template
156+
return fmt.Errorf("template is neither local nor registry template: %s", layer.Template)
143157
}
144-
rulesFile := layer.GetRulesFile(rootDir)
145-
if rulesFile == "" {
146-
return fmt.Errorf("no rules document or document is empty")
158+
log.Info().Msgf("using template dir %s", tplDir)
159+
rulesFile := helper.Join(tplDir, "rules.yaml")
160+
if !helper.IsFile(rulesFile) {
161+
return fmt.Errorf("rules document not found: %s", rulesFile)
147162
}
163+
log.Debug().Msgf("using rules document %s", rulesFile)
164+
layer.UpdateTemplateDependencies(tplDir, rulesFile)
148165
err = checkInputs(layer.ComputeExpandedInputs(rootDir))
149166
if err != nil {
150167
return err
@@ -160,7 +177,7 @@ func runSolution(doc *spec.SolutionDoc) error {
160177
}
161178
opts := gen.GeneratorOptions{
162179
OutputDir: outDir,
163-
TemplatesDir: tplDir,
180+
TemplatesDir: helper.Join(tplDir, "templates"),
164181
System: system,
165182
UserFeatures: layer.Features,
166183
UserForce: layer.Force,

pkg/spec/sollayer.go

+20-41
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package spec
33
import (
44
"fmt"
55

6-
"github.com/apigear-io/cli/pkg/cfg"
76
"github.com/apigear-io/cli/pkg/helper"
87
)
98

@@ -17,20 +16,8 @@ type SolutionLayer struct {
1716
Force bool `json:"force" yaml:"force"`
1817
expandedInputs []string `json:"-"` // expanded inputs
1918
dependencies []string `json:"-"` // dependencies of the layer
20-
}
21-
22-
// ResolveTemplateDir resolves the template dir.
23-
// The template dir can be a relative path to the root dir of the solution.
24-
// If the template dir is not a relative path, it is considered as a template name.
25-
// The template name is used to find the template dir in the template cache dir.
26-
func (l *SolutionLayer) ResolveTemplateDir(rootDir string) string {
27-
if helper.IsDir(helper.Join(rootDir, l.Template)) {
28-
return helper.Join(rootDir, l.Template)
29-
}
30-
if helper.IsDir(helper.Join(cfg.CacheDir(), l.Template)) {
31-
return helper.Join(cfg.CacheDir(), l.Template)
32-
}
33-
return ""
19+
templateDir string `json:"-"` // template dir
20+
rulesFile string `json:"-"` // rules file
3421
}
3522

3623
// GetOutputDir returns the output dir.
@@ -39,26 +26,6 @@ func (l *SolutionLayer) GetOutputDir(rootDir string) string {
3926
return helper.Join(rootDir, l.Output)
4027
}
4128

42-
// GetTemplatesDir returns the templates dir.
43-
// The templates dir is a sub directory of the template dir.
44-
func (l *SolutionLayer) GetTemplatesDir(rootDir string) string {
45-
tDir := l.ResolveTemplateDir(rootDir)
46-
if tDir == "" {
47-
return ""
48-
}
49-
return helper.Join(tDir, "templates")
50-
}
51-
52-
// GetRulesFile returns the rules file.
53-
// The rules file is a file in the template dir.
54-
func (l *SolutionLayer) GetRulesFile(rootDir string) string {
55-
tDir := l.ResolveTemplateDir(rootDir)
56-
if tDir == "" {
57-
return ""
58-
}
59-
return helper.Join(tDir, "rules.yaml")
60-
}
61-
6229
func (l *SolutionLayer) Validate() error {
6330
if l.Output == "" {
6431
return fmt.Errorf("layer output is required")
@@ -76,25 +43,31 @@ func (l *SolutionLayer) Validate() error {
7643
return nil
7744
}
7845

46+
// ComputeDependencies computes the dependencies of a layer.
47+
// The dependencies are used for file system watchers.
48+
// The dependencies of a layer are the rules file, the templates dir and the expanded inputs.
49+
// The rules file is a file in the template dir.
50+
// The templates dir is a sub directory of the template dir.
51+
// The expanded inputs are the inputs with the variables expanded.
7952
func (l *SolutionLayer) ComputeDependencies(rootDir string) []string {
8053
if l.dependencies == nil {
8154
l.dependencies = make([]string, 0)
8255
}
8356
if len(l.dependencies) == 0 {
84-
rulesFile := l.GetRulesFile(rootDir)
85-
if rulesFile != "" {
86-
l.dependencies = append(l.dependencies, rulesFile)
57+
if l.templateDir != "" {
58+
l.dependencies = append(l.dependencies, l.templateDir)
8759
}
88-
tplsDir := l.GetTemplatesDir(rootDir)
89-
if tplsDir != "" {
90-
l.dependencies = append(l.dependencies, tplsDir)
60+
if l.rulesFile != "" {
61+
l.dependencies = append(l.dependencies, l.rulesFile)
9162
}
9263
inputs := l.ComputeExpandedInputs(rootDir)
9364
l.dependencies = append(l.dependencies, inputs...)
9465
}
9566
return l.dependencies
9667
}
9768

69+
// ComputeExpandedInputs computes the expanded inputs of a layer.
70+
// The expanded inputs are the inputs with the variables expanded.
9871
func (l *SolutionLayer) ComputeExpandedInputs(rootDir string) []string {
9972
if l.expandedInputs == nil {
10073
l.expandedInputs = make([]string, 0)
@@ -115,3 +88,9 @@ func (l *SolutionLayer) Compute(rootDir string) error {
11588
l.ComputeExpandedInputs(rootDir)
11689
return nil
11790
}
91+
92+
// UpdateTemplateDependencies updates the template dir and rules file of a layer.
93+
func (l *SolutionLayer) UpdateTemplateDependencies(templateDir, rulesFile string) {
94+
l.templateDir = templateDir
95+
l.rulesFile = rulesFile
96+
}

0 commit comments

Comments
 (0)