Files
buildx/util/ocilayout/parse.go
Sebastiaan van Stijn a3512c1cfa util/ocilayout: replace regex for matching windows drive-letters
follow-up to bf34a4cbed, which changed the
isWindowsDrivePath function to use a regex for matching the trailing slash.

This reverts it back to te previous implementation to avoid a regex, but
adds a check for the colon to be followed by a forward-slash, which is
faster, and avoids the overhead of `regex.MustCompile` during init.

    BenchmarkRegex-11    39056917      32.45 ns/op     0 B/op    0 allocs/op
    BenchmarkManual-11   1000000000     0.2476 ns/op   0 B/op    0 allocs/op

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-05-04 12:07:18 +02:00

72 lines
1.4 KiB
Go

package ocilayout
import (
"strings"
"github.com/distribution/reference"
digest "github.com/opencontainers/go-digest"
)
type Ref struct {
Path string
Tag string
Digest digest.Digest
}
const prefix = "oci-layout://"
func Parse(s string) (Ref, bool, error) {
if !strings.HasPrefix(s, prefix) {
return Ref{}, false, nil
}
localPath := strings.TrimPrefix(s, prefix)
var out Ref
if i := strings.LastIndex(localPath, "@"); i >= 0 {
after := localPath[i+1:]
if reference.DigestRegexp.MatchString(after) {
dgst, err := digest.Parse(after)
if err != nil {
return Ref{}, true, err
}
localPath, out.Digest = localPath[:i], dgst
}
}
if i := strings.LastIndex(localPath, ":"); i >= 0 && !isWindowsDrivePath(localPath, i) {
after := localPath[i+1:]
if reference.TagRegexp.MatchString(after) {
localPath, out.Tag = localPath[:i], after
}
}
out.Path = localPath
if out.Tag == "" && out.Digest == "" {
out.Tag = "latest"
}
return out, true, nil
}
func (r Ref) String() string {
s := prefix + r.Path
if r.Tag != "" {
s += ":" + r.Tag
}
if r.Digest != "" {
s += "@" + r.Digest.String()
}
return s
}
func isWindowsDrivePath(path string, colon int) bool {
if colon != 1 || len(path) < 3 {
return false
}
if path[2] != '/' && path[2] != '\\' {
return false
}
c := path[0]
return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
}