@@ -239,7 +239,7 @@ func (r *Runtime) LookupImage(name string, options *LookupImageOptions) (*Image,
239239 // Docker compat: strip off the tag iff name is tagged and digested
240240 // (e.g., fedora:latest@sha256...). In that case, the tag is stripped
241241 // off and entirely ignored. The digest is the sole source of truth.
242- normalizedName , err := normalizeTaggedDigestedString (name )
242+ normalizedName , namedName , err := normalizeTaggedDigestedString (name )
243243 if err != nil {
244244 return nil , "" , err
245245 }
@@ -316,19 +316,36 @@ func (r *Runtime) LookupImage(name string, options *LookupImageOptions) (*Image,
316316 return img , name , err
317317 }
318318
319- return r .lookupImageInDigestsAndRepoTags (name , options )
319+ return r .lookupImageInRepoTags (name , namedName , options )
320320}
321321
322322// lookupImageInLocalStorage looks up the specified candidate for name in the
323323// storage and checks whether it's matching the system context.
324324func (r * Runtime ) lookupImageInLocalStorage (name , candidate string , options * LookupImageOptions ) (* Image , error ) {
325325 logrus .Debugf ("Trying %q ..." , candidate )
326+
327+ // First, try store.Image() which will properly work on IDs (but not on
328+ // digests).
326329 img , err := r .store .Image (candidate )
327330 if err != nil && ! errors .Is (err , storage .ErrImageUnknown ) {
328331 return nil , err
329332 }
330333 if img == nil {
331- return nil , nil
334+ // Second, try parsing the candidate into a storage reference
335+ // which will work with digests. However, we must reparse the
336+ // reference another time below since an ordinary image may
337+ // have been referenced via its parent (manifest list) digest.
338+ ref , err := storageTransport .Transport .ParseStoreReference (r .store , candidate )
339+ if err != nil {
340+ return nil , nil
341+ }
342+ img , err = storageTransport .Transport .GetStoreImage (r .store , ref )
343+ if err != nil && ! errors .Is (err , storage .ErrImageUnknown ) {
344+ return nil , err
345+ }
346+ if img == nil {
347+ return nil , nil
348+ }
332349 }
333350 ref , err := storageTransport .Transport .ParseStoreReference (r .store , img .ID )
334351 if err != nil {
@@ -414,61 +431,34 @@ func (r *Runtime) lookupImageInLocalStorage(name, candidate string, options *Loo
414431 return image , nil
415432}
416433
417- // lookupImageInDigestsAndRepoTags attempts to match name against any image in
418- // the local containers storage. If name is digested, it will be compared
419- // against image digests. Otherwise, it will be looked up in the repo tags.
420- func (r * Runtime ) lookupImageInDigestsAndRepoTags (name string , options * LookupImageOptions ) (* Image , string , error ) {
421- // Until now, we've tried very hard to find an image but now it is time
422- // for limbo. If the image includes a digest that we couldn't detect
423- // verbatim in the storage, we must have a look at all digests of all
424- // images. Those may change over time (e.g., via manifest lists).
425- // Both Podman and Buildah want us to do that dance.
426- allImages , err := r .ListImages (context .Background (), nil , nil )
427- if err != nil {
428- return nil , "" , err
429- }
430-
431- ref , err := reference .Parse (name ) // Warning! This is not ParseNormalizedNamed
432- if err != nil {
433- return nil , "" , err
434- }
435- named , isNamed := ref .(reference.Named )
436- if ! isNamed {
434+ // lookupImageInRepoTags attempts to match named against any image in the local
435+ // containers storage by comparing the name to all known repo tags.
436+ func (r * Runtime ) lookupImageInRepoTags (name string , namedName reference.Named , options * LookupImageOptions ) (* Image , string , error ) {
437+ if namedName == nil {
437438 return nil , "" , fmt .Errorf ("%s: %w" , name , storage .ErrImageUnknown )
438439 }
439440
440- digested , isDigested := named .(reference.Digested )
441- if isDigested {
442- logrus .Debug ("Looking for image with matching recorded digests" )
443- digest := digested .Digest ()
444- for _ , image := range allImages {
445- for _ , d := range image .Digests () {
446- if d != digest {
447- continue
448- }
449- // Also make sure that the matching image fits all criteria (e.g., manifest list).
450- if _ , err := r .lookupImageInLocalStorage (name , image .ID (), options ); err != nil {
451- return nil , "" , err
452- }
453- return image , name , nil
454-
455- }
456- }
441+ if _ , isDigested := namedName .(reference.Digested ); isDigested {
457442 return nil , "" , fmt .Errorf ("%s: %w" , name , storage .ErrImageUnknown )
458443 }
459444
460445 if ! shortnames .IsShortName (name ) {
461446 return nil , "" , fmt .Errorf ("%s: %w" , name , storage .ErrImageUnknown )
462447 }
463448
464- named = reference .TagNameOnly (named ) // Make sure to add ":latest" if needed
465- namedTagged , isNammedTagged := named .(reference.NamedTagged )
449+ namedName = reference .TagNameOnly (namedName ) // Docker compat: make sure to add ":latest" if needed
450+ namedTagged , isNammedTagged := namedName .(reference.NamedTagged )
466451 if ! isNammedTagged {
467452 // NOTE: this should never happen since we already know it's
468453 // not a digested reference.
469454 return nil , "" , fmt .Errorf ("%s: %w (could not cast to tagged)" , name , storage .ErrImageUnknown )
470455 }
471456
457+ allImages , err := r .ListImages (context .Background (), nil , nil )
458+ if err != nil {
459+ return nil , "" , err
460+ }
461+
472462 for _ , image := range allImages {
473463 named , err := image .inRepoTags (namedTagged )
474464 if err != nil {
0 commit comments