in pkg/containerd/reference.go [95:150]
func ParseReference(name string, targetDigest digest.Digest) (Reference, error) {
if strings.Contains(name, "://") {
return nil, fmt.Errorf("invalid reference")
}
u, err := url.Parse("localhost://" + name)
if err != nil {
return nil, err
}
if u.Scheme != "localhost" {
return nil, fmt.Errorf("invalid reference")
}
if u.Host == "" {
return nil, fmt.Errorf("hostname required")
}
var obj string
if idx := separator.FindStringIndex(u.Path); idx != nil {
// This allows us to retain the @ to signify digests or shortened digests in the object.
obj = u.Path[idx[0]:]
if obj[:1] == ":" {
obj = obj[1:]
}
u.Path = u.Path[:idx[0]]
}
tag, dgst := splitTagAndDigest(obj)
tag, _, _ = strings.Cut(tag, "@")
repository := strings.TrimPrefix(u.Path, "/")
if dgst == "" {
dgst = targetDigest
}
if targetDigest != "" && dgst != targetDigest {
return nil, fmt.Errorf("invalid digest, target does not match parsed digest: %v %v", name, dgst)
}
if repository == "" {
return nil, fmt.Errorf("invalid repository: %v", repository)
}
if dgst == "" {
return nil, fmt.Errorf("invalid digest: %v", dgst)
}
return &reference{
name: name,
host: u.Host,
tag: tag,
dgst: dgst,
repo: repository,
}, nil
}