func ParseReference()

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
}