/
formatter.go
92 lines (80 loc) · 2.12 KB
/
formatter.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
package sourcepolicy
import (
"regexp"
spb "github.com/moby/buildkit/sourcepolicy/pb"
"github.com/moby/buildkit/util/wildcard"
"github.com/pkg/errors"
)
// Source wraps a a protobuf source in order to store cached state such as the compiled regexes.
type selectorCache struct {
*spb.Selector
re *regexp.Regexp
w *wildcardCache
}
// Format formats the provided ref according to the match/type of the source.
//
// For example, if the source is a wildcard, the ref will be formatted with the wildcard in the source replacing the parameters in the destination.
//
// matcher: wildcard source: "docker.io/library/golang:*" match: "docker.io/library/golang:1.19" format: "docker.io/library/golang:${1}-alpine" result: "docker.io/library/golang:1.19-alpine"
func (s *selectorCache) Format(match, format string) (string, error) {
switch s.MatchType {
case spb.MatchType_EXACT:
return s.Identifier, nil
case spb.MatchType_REGEX:
re, err := s.regex()
if err != nil {
return "", err
}
return re.ReplaceAllString(match, format), nil
case spb.MatchType_WILDCARD:
w, err := s.wildcard()
if err != nil {
return "", err
}
m := w.Match(match)
if m == nil {
return match, nil
}
return m.Format(format)
}
return "", errors.Errorf("unknown match type: %s", s.MatchType)
}
// wildcardCache wraps a wildcard.Wildcard to cache returned matches by ref.
// This way a match only needs to be computed once per ref.
type wildcardCache struct {
w *wildcard.Wildcard
m map[string]*wildcard.Match
}
func (w *wildcardCache) Match(ref string) *wildcard.Match {
if w.m == nil {
w.m = make(map[string]*wildcard.Match)
}
if m, ok := w.m[ref]; ok {
return m
}
m := w.w.Match(ref)
w.m[ref] = m
return m
}
func (s *selectorCache) wildcard() (*wildcardCache, error) {
if s.w != nil {
return s.w, nil
}
w, err := wildcard.New(s.Identifier)
if err != nil {
return nil, err
}
s.w = &wildcardCache{w: w}
return s.w, nil
}
func (s *selectorCache) regex() (*regexp.Regexp, error) {
if s.re != nil {
return s.re, nil
}
re, err := regexp.Compile(s.Identifier)
if err != nil {
return nil, err
}
s.re = re
return re, nil
}