code: func MaybeUpdateClient(ctx context.Context, opts ClientOptions, targetVersion, clientExe string, digests *digests.ClientDigestsFile) (common.Pin, error) {
  	if err := common.ValidateInstanceVersion(targetVersion); err != nil {
  		return common.Pin{}, err
  	}
  
  	opts.Root = filepath.Dir(clientExe)
  	opts.CacheDir = filepath.Join(opts.Root, ".cipd_client_cache")
  
  	client, err := NewClient(opts)
  	if err != nil {
  		return common.Pin{}, err
  	}
  	impl := client.(*clientImpl)
  
  	fs := fs.NewFileSystem(opts.Root, filepath.Join(opts.CacheDir, "trash"))
  	defer fs.CleanupTrash(ctx)
  
  	pin, err := impl.maybeUpdateClient(ctx, fs, targetVersion, clientExe, digests)
  	if err == nil {
  		impl.ensureClientVersionInfo(ctx, fs, pin, clientExe)
  	}
  	return pin, err
  }
docs: // MaybeUpdateClient will update the client binary at clientExe (given as
  // a native path) to targetVersion if it's out of date (based on its hash).
  //
  // This update is done from the "infra/tools/cipd/${platform}" package, see
  // ClientPackage. The function will use the given ClientOptions to figure out
  // how to establish a connection with the backend. Its Root and CacheDir values
  // are ignored (values derived from clientExe are used instead).
  //
  // If given 'digests' is not nil, will make sure the hash of the downloaded
  // client binary is in 'digests'.
  //
  // Note that this function make sense only in a context of a default CIPD CLI
  // client. Other binaries that link to cipd package should not use it, they'll
  // be "updated" to the CIPD client binary.