code: func (ms *manifests) Put(ctx context.Context, m distribution.Manifest, options ...distribution.ManifestServiceOption) (digest.Digest, error) {
  	ref := ms.name
  	var tagged bool
  
  	for _, option := range options {
  		if opt, ok := option.(distribution.WithTagOption); ok {
  			var err error
  			ref, err = reference.WithTag(ref, opt.Tag)
  			if err != nil {
  				return "", err
  			}
  			tagged = true
  		} else {
  			err := option.Apply(ms)
  			if err != nil {
  				return "", err
  			}
  		}
  	}
  	mediaType, p, err := m.Payload()
  	if err != nil {
  		return "", err
  	}
  
  	if !tagged {
  		// generate a canonical digest and Put by digest
  		_, d, err := distribution.UnmarshalManifest(mediaType, p)
  		if err != nil {
  			return "", err
  		}
  		ref, err = reference.WithDigest(ref, d.Digest)
  		if err != nil {
  			return "", err
  		}
  	}
  
  	manifestURL, err := ms.ub.BuildManifestURL(ref)
  	if err != nil {
  		return "", err
  	}
  
  	putRequest, err := http.NewRequest("PUT", manifestURL, bytes.NewReader(p))
  	if err != nil {
  		return "", err
  	}
  
  	putRequest.Header.Set("Content-Type", mediaType)
  
  	resp, err := ms.client.Do(putRequest)
  	if err != nil {
  		return "", err
  	}
  	defer resp.Body.Close()
  
  	if SuccessStatus(resp.StatusCode) {
  		dgstHeader := resp.Header.Get("Docker-Content-Digest")
  		dgst, err := digest.Parse(dgstHeader)
  		if err != nil {
  			return "", err
  		}
  
  		return dgst, nil
  	}
  
  	return "", HandleErrorResponse(resp)
  }
docs: // Put puts a manifest.  A tag can be specified using an options parameter which uses some shared state to hold the
  // tag name in order to build the correct upload URL.