CrazyMax fe17ebda89
correctly remove duplicated secrets and ssh keys
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2025-02-28 15:24:16 +01:00

148 lines
2.5 KiB
Go

package buildflags
import (
"cmp"
"encoding/json"
"slices"
"strings"
controllerapi "github.com/docker/buildx/controller/pb"
"github.com/moby/buildkit/util/gitutil"
)
type SSHKeys []*SSH
func (s SSHKeys) Merge(other SSHKeys) SSHKeys {
if other == nil {
s.Normalize()
return s
} else if s == nil {
other.Normalize()
return other
}
return append(s, other...).Normalize()
}
func (s SSHKeys) Normalize() SSHKeys {
if len(s) == 0 {
return nil
}
return removeSSHDupes(s)
}
func (s SSHKeys) ToPB() []*controllerapi.SSH {
if len(s) == 0 {
return nil
}
entries := make([]*controllerapi.SSH, len(s))
for i, entry := range s {
entries[i] = entry.ToPB()
}
return entries
}
type SSH struct {
ID string `json:"id,omitempty" cty:"id"`
Paths []string `json:"paths,omitempty" cty:"paths"`
}
func (s *SSH) Equal(other *SSH) bool {
return s.Less(other) == 0
}
func (s *SSH) Less(other *SSH) int {
if s.ID != other.ID {
return cmp.Compare(s.ID, other.ID)
}
return slices.Compare(s.Paths, other.Paths)
}
func (s *SSH) String() string {
if len(s.Paths) == 0 {
return s.ID
}
var b csvBuilder
paths := strings.Join(s.Paths, ",")
b.Write(s.ID, paths)
return b.String()
}
func (s *SSH) ToPB() *controllerapi.SSH {
return &controllerapi.SSH{
ID: s.ID,
Paths: s.Paths,
}
}
func (s *SSH) UnmarshalJSON(data []byte) error {
var v struct {
ID string `json:"id,omitempty"`
Paths []string `json:"paths,omitempty"`
}
if err := json.Unmarshal(data, &v); err != nil {
return err
}
s.ID = v.ID
s.Paths = v.Paths
return nil
}
func (s *SSH) UnmarshalText(text []byte) error {
parts := strings.SplitN(string(text), "=", 2)
s.ID = parts[0]
if len(parts) > 1 {
s.Paths = strings.Split(parts[1], ",")
} else {
s.Paths = nil
}
return nil
}
func ParseSSHSpecs(sl []string) ([]*controllerapi.SSH, error) {
var outs []*controllerapi.SSH
if len(sl) == 0 {
return nil, nil
}
for _, s := range sl {
if s == "" {
continue
}
var out SSH
if err := out.UnmarshalText([]byte(s)); err != nil {
return nil, err
}
outs = append(outs, out.ToPB())
}
return outs, nil
}
// IsGitSSH returns true if the given repo URL is accessed over ssh
func IsGitSSH(repo string) bool {
url, err := gitutil.ParseURL(repo)
if err != nil {
return false
}
return url.Scheme == gitutil.SSHProtocol
}
func removeSSHDupes(s []*SSH) []*SSH {
var res []*SSH
m := map[string]int{}
for _, ssh := range s {
if i, ok := m[ssh.ID]; ok {
res[i] = ssh
} else {
m[ssh.ID] = len(res)
res = append(res, ssh)
}
}
return res
}