Merge pull request #41745 from AkihiroSuda/vendor-bk-080

vendor: BuildKit 950603da215ae03b843f3f66fbe86c4876a6f5a1
diff --git a/distribution/errors.go b/distribution/errors.go
index 194287d..02f5870 100644
--- a/distribution/errors.go
+++ b/distribution/errors.go
@@ -112,6 +112,23 @@
 	return errdefs.Unknown(err)
 }
 
+func isNotFound(err error) bool {
+	switch v := err.(type) {
+	case errcode.Errors:
+		for _, e := range v {
+			if isNotFound(e) {
+				return true
+			}
+		}
+	case errcode.Error:
+		switch v.Code {
+		case errcode.ErrorCodeDenied, v2.ErrorCodeManifestUnknown, v2.ErrorCodeNameUnknown:
+			return true
+		}
+	}
+	return false
+}
+
 // continueOnError returns true if we should fallback to the next endpoint
 // as a result of this error.
 func continueOnError(err error, mirrorEndpoint bool) bool {
diff --git a/distribution/pull_v2.go b/distribution/pull_v2.go
index b5db4ee..12497ea 100644
--- a/distribution/pull_v2.go
+++ b/distribution/pull_v2.go
@@ -343,16 +343,19 @@
 		dgst        digest.Digest
 		mt          string
 		size        int64
+		tagged      reference.NamedTagged
+		isTagged    bool
 	)
 	if digested, isDigested := ref.(reference.Canonical); isDigested {
 		dgst = digested.Digest()
 		tagOrDigest = digested.String()
-	} else if tagged, isTagged := ref.(reference.NamedTagged); isTagged {
+	} else if tagged, isTagged = ref.(reference.NamedTagged); isTagged {
 		tagService := p.repo.Tags(ctx)
 		desc, err := tagService.Get(ctx, tagged.Tag())
 		if err != nil {
 			return false, allowV1Fallback(err)
 		}
+
 		dgst = desc.Digest
 		tagOrDigest = tagged.Tag()
 		mt = desc.MediaType
@@ -367,13 +370,40 @@
 			"remote": ref,
 		}))
 
-	manifest, err := p.manifestStore.Get(ctx, specs.Descriptor{
+	desc := specs.Descriptor{
 		MediaType: mt,
 		Digest:    dgst,
 		Size:      size,
-	})
+	}
+	manifest, err := p.manifestStore.Get(ctx, desc)
 	if err != nil {
-		return false, err
+		if isTagged && isNotFound(errors.Cause(err)) {
+			logrus.WithField("ref", ref).WithError(err).Debug("Falling back to pull manifest by tag")
+
+			msg := `%s Failed to pull manifest by the resolved digest. This registry does not
+	appear to conform to the distribution registry specification; falling back to
+	pull by tag.  This fallback is DEPRECATED, and will be removed in a future
+	release.  Please contact admins of %s. %s
+`
+
+			warnEmoji := "\U000026A0\U0000FE0F"
+			progress.Messagef(p.config.ProgressOutput, "WARNING", msg, warnEmoji, p.endpoint.URL, warnEmoji)
+
+			// Fetch by tag worked, but fetch by digest didn't.
+			// This is a broken registry implementation.
+			// We'll fallback to the old behavior and get the manifest by tag.
+			var ms distribution.ManifestService
+			ms, err = p.repo.Manifests(ctx)
+			if err != nil {
+				return false, err
+			}
+
+			manifest, err = ms.Get(ctx, "", distribution.WithTag(tagged.Tag()))
+			err = errors.Wrap(err, "error after falling back to get manifest by tag")
+		}
+		if err != nil {
+			return false, err
+		}
 	}
 
 	if manifest == nil {
@@ -818,11 +848,12 @@
 		return "", "", err
 	}
 
-	manifest, err := p.manifestStore.Get(ctx, specs.Descriptor{
+	desc := specs.Descriptor{
 		Digest:    match.Digest,
 		Size:      match.Size,
 		MediaType: match.MediaType,
-	})
+	}
+	manifest, err := p.manifestStore.Get(ctx, desc)
 	if err != nil {
 		return "", "", err
 	}