func (s storageTransport) ParseStoreReference(store storage.Store, ref string) (*storageReference, error) {
	if ref == "" {
		return nil, errors.Wrapf(ErrInvalidReference, "%q is an empty reference", ref)
	}
	if ref[0] == '[' {
		// Ignore the store specifier.
		closeIndex := strings.IndexRune(ref, ']')
		if closeIndex < 1 {
			return nil, errors.Wrapf(ErrInvalidReference, "store specifier in %q did not end", ref)
		}
		ref = ref[closeIndex+1:]
	}

	// The reference may end with an image ID.  Image IDs and digests use the same "@" separator;
	// here we only peel away an image ID, and leave digests alone.
	split := strings.LastIndex(ref, "@")
	id := ""
	if split != -1 {
		possibleID := ref[split+1:]
		if possibleID == "" {
			return nil, errors.Wrapf(ErrInvalidReference, "empty trailing digest or ID in %q", ref)
		}
		// If it looks like a digest, leave it alone for now.
		if _, err := digest.Parse(possibleID); err != nil {
			// Otherwise…
			if idSum, err := digest.Parse("sha256:" + possibleID); err == nil && idSum.Validate() == nil {
				id = possibleID // … it is a full ID
			} else if img, err := store.Image(possibleID); err == nil && img != nil && len(possibleID) >= minimumTruncatedIDLength && strings.HasPrefix(img.ID, possibleID) {
				// … it is a truncated version of the ID of an image that's present in local storage,
				// so we might as well use the expanded value.
				id = img.ID
			} else {
				return nil, errors.Wrapf(ErrInvalidReference, "%q does not look like an image ID or digest", possibleID)
			}
			// We have recognized an image ID; peel it off.
			ref = ref[:split]
		}
	}

	// If we only have one @-delimited portion, then _maybe_ it's a truncated image ID.  Only check on that if it's
	// at least of what we guess is a reasonable minimum length, because we don't want a really short value
	// like "a" matching an image by ID prefix when the input was actually meant to specify an image name.
	if id == "" && len(ref) >= minimumTruncatedIDLength && !strings.ContainsAny(ref, "@:") {
		if img, err := store.Image(ref); err == nil && img != nil && strings.HasPrefix(img.ID, ref) {
			// It's a truncated version of the ID of an image that's present in local storage;
			// we need to expand it.
			id = img.ID
			ref = ""
		}
	}

	var named reference.Named
	// Unless we have an un-named "ID" or "@ID" reference (where ID might only have been a prefix), which has been
	// completely parsed above, the initial portion should be a name, possibly with a tag and/or a digest..
	if ref != "" {
		var err error
		named, err = reference.ParseNormalizedNamed(ref)
		if err != nil {
			return nil, errors.Wrapf(err, "error parsing named reference %q", ref)
		}
		named = reference.TagNameOnly(named)
	}

	result, err := newReference(storageTransport{store: store, defaultUIDMap: s.defaultUIDMap, defaultGIDMap: s.defaultGIDMap}, named, id)
	if err != nil {
		return nil, err
	}
	logrus.Debugf("parsed reference into %q", result.StringWithinTransport())
	return result, nil
}
func (s storageTransport) ParseStoreReference(store storage.Store, ref string) (*storageReference, error) {
	if ref == "" {
		return nil, errors.Wrapf(ErrInvalidReference, "%q is an empty reference", ref)
	}
	if ref[0] == '[' {
		
		closeIndex := strings.IndexRune(ref, ']')
		if closeIndex < 1 {
			return nil, errors.Wrapf(ErrInvalidReference, "store specifier in %q did not end", ref)
		}
		ref = ref[closeIndex+1:]
	}

	
	
	split := strings.LastIndex(ref, "@")
	id := ""
	if split != -1 {
		possibleID := ref[split+1:]
		if possibleID == "" {
			return nil, errors.Wrapf(ErrInvalidReference, "empty trailing digest or ID in %q", ref)
		}
		
		if _, err := digest.Parse(possibleID); err != nil {
			
			if idSum, err := digest.Parse("sha256:" + possibleID); err == nil && idSum.Validate() == nil {
				id = possibleID 
			} else if img, err := store.Image(possibleID); err == nil && img != nil && len(possibleID) >= minimumTruncatedIDLength && strings.HasPrefix(img.ID, possibleID) {
				
				
				id = img.ID
			} else {
				return nil, errors.Wrapf(ErrInvalidReference, "%q does not look like an image ID or digest", possibleID)
			}
			
			ref = ref[:split]
		}
	}

	
	
	
	if id == "" && len(ref) >= minimumTruncatedIDLength && !strings.ContainsAny(ref, "@:") {
		if img, err := store.Image(ref); err == nil && img != nil && strings.HasPrefix(img.ID, ref) {
			
			
			id = img.ID
			ref = ""
		}
	}

	var named reference.Named
	
	
	if ref != "" {
		var err error
		named, err = reference.ParseNormalizedNamed(ref)
		if err != nil {
			return nil, errors.Wrapf(err, "error parsing named reference %q", ref)
		}
		named = reference.TagNameOnly(named)
	}

	result, err := newReference(storageTransport{store: store, defaultUIDMap: s.defaultUIDMap, defaultGIDMap: s.defaultGIDMap}, named, id)
	if err != nil {
		return nil, err
	}
	logrus.Debugf("parsed reference into %q", result.StringWithinTransport())
	return result, nil
}
func ( s storageTransport ) ParseStoreReference ( store storage . Store , ref string ) ( * storageReference , error ) { if ref == " " { return nil , errors . Wrapf ( ErrInvalidReference , " " , ref ) } if ref [ 0 ] == '[' { // Ignore the store specifier. closeIndex := strings . IndexRune ( ref , ']' ) if closeIndex < 1 { return nil , errors . Wrapf ( ErrInvalidReference , " " , ref ) } ref = ref [ closeIndex + 1 : ] } // The reference may end with an image ID.  Image IDs and digests use the same "@" separator; // here we only peel away an image ID, and leave digests alone. split := strings . LastIndex ( ref , " " ) id := " " if split != - 1 { possibleID := ref [ split + 1 : ] if possibleID == " " { return nil , errors . Wrapf ( ErrInvalidReference , " " , ref ) } // If it looks like a digest, leave it alone for now. if _ , err := digest . Parse ( possibleID ) ; err != nil { // Otherwise… if idSum , err := digest . Parse ( " " + possibleID ) ; err == nil && idSum . Validate ( ) == nil { id = possibleID // … it is a full ID } else if img , err := store . Image ( possibleID ) ; err == nil && img != nil && len ( possibleID ) >= minimumTruncatedIDLength && strings . HasPrefix ( img . ID , possibleID ) { // … it is a truncated version of the ID of an image that's present in local storage, // so we might as well use the expanded value. id = img . ID } else { return nil , errors . Wrapf ( ErrInvalidReference , " " , possibleID ) } // We have recognized an image ID; peel it off. ref = ref [ : split ] } } // If we only have one @-delimited portion, then _maybe_ it's a truncated image ID.  Only check on that if it's // at least of what we guess is a reasonable minimum length, because we don't want a really short value // like "a" matching an image by ID prefix when the input was actually meant to specify an image name. if id == " " && len ( ref ) >= minimumTruncatedIDLength && ! strings . ContainsAny ( ref , " " ) { if img , err := store . Image ( ref ) ; err == nil && img != nil && strings . HasPrefix ( img . ID , ref ) { // It's a truncated version of the ID of an image that's present in local storage; // we need to expand it. id = img . ID ref = " " } } var named reference . Named // Unless we have an un-named "ID" or "@ID" reference (where ID might only have been a prefix), which has been // completely parsed above, the initial portion should be a name, possibly with a tag and/or a digest.. if ref != " " { var err error named , err = reference . ParseNormalizedNamed ( ref ) if err != nil { return nil , errors . Wrapf ( err , " " , ref ) } named = reference . TagNameOnly ( named ) } result , err := newReference ( storageTransport { store : store , defaultUIDMap : s . defaultUIDMap , defaultGIDMap : s . defaultGIDMap } , named , id ) if err != nil { return nil , err } logrus . Debugf ( " " , result . StringWithinTransport ( ) ) return result , nil }
// ParseStoreReference takes a name or an ID, tries to figure out which it is
// relative to the given store, and returns it in a reference object.
ParseStoreReference takes a name or an ID tries to figure out which it is relative to the given store and returns it in a reference object .