4
4
package templatestore
5
5
6
6
import (
7
+ "cmp"
7
8
"errors"
8
9
"fmt"
9
10
"io/fs"
10
11
"os"
11
12
"path/filepath"
13
+ "slices"
12
14
"strings"
13
15
"unicode"
14
16
@@ -21,25 +23,33 @@ type Template struct {
21
23
Location string `json:"location"`
22
24
}
23
25
24
- func Read ( name string ) ([]byte , error ) {
25
- var pathList []string
26
+ func TemplatesPaths ( ) ([]string , error ) {
27
+ var paths []string
26
28
if tmplPath := os .Getenv ("LIMA_TEMPLATES_PATH" ); tmplPath != "" {
27
- pathList = strings .Split (tmplPath , string (filepath .ListSeparator ))
29
+ paths = strings .Split (tmplPath , string (filepath .ListSeparator ))
28
30
} else {
29
31
dir , err := usrlocalsharelima .Dir ()
30
32
if err != nil {
31
33
return nil , err
32
34
}
33
- pathList = []string {filepath .Join (dir , "templates" )}
35
+ paths = []string {filepath .Join (dir , "templates" )}
36
+ }
37
+ return paths , nil
38
+ }
39
+
40
+ func Read (name string ) ([]byte , error ) {
41
+ paths , err := TemplatesPaths ()
42
+ if err != nil {
43
+ return nil , err
34
44
}
35
45
ext := filepath .Ext (name )
36
46
// Append .yaml extension if name doesn't have an extension, or if it starts with a digit.
37
47
// So "docker.sh" would remain unchanged but "ubuntu-24.04" becomes "ubuntu-24.04.yaml".
38
48
if len (ext ) < 2 || unicode .IsDigit (rune (ext [1 ])) {
39
49
name += ".yaml"
40
50
}
41
- for _ , path := range pathList {
42
- filePath , err := securejoin .SecureJoin (path , name )
51
+ for _ , templatesDir := range paths {
52
+ filePath , err := securejoin .SecureJoin (templatesDir , name )
43
53
if err != nil {
44
54
return nil , err
45
55
}
@@ -53,31 +63,36 @@ func Read(name string) ([]byte, error) {
53
63
const Default = "default"
54
64
55
65
func Templates () ([]Template , error ) {
56
- usrlocalsharelimaDir , err := usrlocalsharelima . Dir ()
66
+ paths , err := TemplatesPaths ()
57
67
if err != nil {
58
68
return nil , err
59
69
}
60
- templatesDir := filepath .Join (usrlocalsharelimaDir , "templates" )
61
70
62
- var res []Template
63
- walkDirFn := func (p string , _ fs.DirEntry , err error ) error {
64
- if err != nil {
65
- return err
66
- }
67
- base := filepath .Base (p )
68
- if strings .HasPrefix (base , "." ) || ! strings .HasSuffix (base , ".yaml" ) {
71
+ templates := make (map [string ]string )
72
+ for _ , templatesDir := range paths {
73
+ walkDirFn := func (p string , _ fs.DirEntry , err error ) error {
74
+ if err != nil {
75
+ return err
76
+ }
77
+ base := filepath .Base (p )
78
+ if strings .HasPrefix (base , "." ) || ! strings .HasSuffix (base , ".yaml" ) {
79
+ return nil
80
+ }
81
+ // Name is like "default", "debian", "deprecated/centos-7", ...
82
+ name := strings .TrimSuffix (strings .TrimPrefix (p , templatesDir + "/" ), ".yaml" )
83
+ if _ , ok := templates [name ]; ! ok {
84
+ templates [name ] = p
85
+ }
69
86
return nil
70
87
}
71
- x := Template {
72
- // Name is like "default", "debian", "deprecated/centos-7", ...
73
- Name : strings .TrimSuffix (strings .TrimPrefix (p , templatesDir + "/" ), ".yaml" ),
74
- Location : p ,
88
+ if err = filepath .WalkDir (templatesDir , walkDirFn ); err != nil {
89
+ return nil , err
75
90
}
76
- res = append (res , x )
77
- return nil
78
91
}
79
- if err = filepath .WalkDir (templatesDir , walkDirFn ); err != nil {
80
- return nil , err
92
+ var res []Template
93
+ for name , loc := range templates {
94
+ res = append (res , Template {Name : name , Location : loc })
81
95
}
96
+ slices .SortFunc (res , func (i , j Template ) int { return cmp .Compare (i .Name , j .Name ) })
82
97
return res , nil
83
98
}
0 commit comments