code: func (pm *Manager) Upgrade(ctx context.Context, ref reference.Named, name string, metaHeader http.Header, authConfig *types.AuthConfig, privileges types.PluginPrivileges, outStream io.Writer) (err error) {
  	p, err := pm.config.Store.GetV2Plugin(name)
  	if err != nil {
  		return err
  	}
  
  	if p.IsEnabled() {
  		return errors.Wrap(enabledError(p.Name()), "plugin must be disabled before upgrading")
  	}
  
  	pm.muGC.RLock()
  	defer pm.muGC.RUnlock()
  
  	// revalidate because Pull is public
  	if _, err := reference.ParseNormalizedNamed(name); err != nil {
  		return errors.Wrapf(errdefs.InvalidParameter(err), "failed to parse %q", name)
  	}
  
  	tmpRootFSDir, err := ioutil.TempDir(pm.tmpDir(), ".rootfs")
  	if err != nil {
  		return errors.Wrap(errdefs.System(err), "error preparing upgrade")
  	}
  	defer os.RemoveAll(tmpRootFSDir)
  
  	dm := &downloadManager{
  		tmpDir:    tmpRootFSDir,
  		blobStore: pm.blobStore,
  	}
  
  	pluginPullConfig := &distribution.ImagePullConfig{
  		Config: distribution.Config{
  			MetaHeaders:      metaHeader,
  			AuthConfig:       authConfig,
  			RegistryService:  pm.config.RegistryService,
  			ImageEventLogger: pm.config.LogPluginEvent,
  			ImageStore:       dm,
  		},
  		DownloadManager: dm, // todo: reevaluate if possible to substitute distribution/xfer dependencies instead
  		Schema2Types:    distribution.PluginTypes,
  	}
  
  	err = pm.pull(ctx, ref, pluginPullConfig, outStream)
  	if err != nil {
  		go pm.GC()
  		return err
  	}
  
  	if err := pm.upgradePlugin(p, dm.configDigest, dm.blobs, tmpRootFSDir, &privileges); err != nil {
  		return err
  	}
  	p.PluginObj.PluginReference = ref.String()
  	return nil
  }
docs: // Upgrade upgrades a plugin