func (r Response) Apply() error {
	var req, opts, err = r.applyRequest()
	if err != nil {
		return err
	}
	return r.applyUpdate(req, opts)
}
Apply performs an update of the current executable (or TargetFile, if it was
set on the Options) with the update specified by Response.

Error is nil if and only if the entire update completes successfully.
package equinox
import (
	"bytes"
	"crypto"
	"crypto/sha256"
	"crypto/x509"
	"encoding/hex"
	"encoding/json"
	"encoding/pem"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"runtime"
	"time"
	"github.com/equinox-io/equinox/internal/go-update"
	"github.com/equinox-io/equinox/internal/osext"
	"github.com/equinox-io/equinox/proto"
)
const protocolVersion = "1"
const defaultCheckURL = "https://update.equinox.io/check"
const userAgent = "EquinoxSDK/1.0"
var NotAvailableErr = errors.New("No update available")
type Options struct {
	Channel string
	Version string
	TargetPath string
	TargetMode os.FileMode
	PublicKey crypto.PublicKey
	OS string
	Arch string
	GoARM string
	CurrentVersion string
	CheckURL string
	HTTPClient *http.Client
}
type Response struct {
	ReleaseVersion string
	ReleaseTitle string
	ReleaseDescription string
	ReleaseDate time.Time
	downloadURL string
	checksum    []byte
	signature   []byte
	patch       proto.PatchKind
	opts        Options
}
func (o *Options) SetPublicKeyPEM(pembytes []byte) error {
	block, _ := pem.Decode(pembytes)
	if block == nil {
		return errors.New("couldn't parse PEM data")
	}
	pub, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return err
	}
	o.PublicKey = pub
	return nil
}
func Check(appID string, opts Options) (Response, error) {
	var req, err = checkRequest(appID, &opts)
	if err != nil {
		return Response{}, err
	}
	return doCheckRequest(opts, req)
}
func checkRequest(appID string, opts *Options) (*http.Request, error) {
	if opts.Channel == "" {
		opts.Channel = "stable"
	}
	if opts.TargetPath == "" {
		var err error
		opts.TargetPath, err = osext.Executable()
		if err != nil {
			return nil, err
		}
	}
	if opts.OS == "" {
		opts.OS = runtime.GOOS
	}
	if opts.Arch == "" {
		opts.Arch = runtime.GOARCH
	}
	if opts.CheckURL == "" {
		opts.CheckURL = defaultCheckURL
	}
	if opts.HTTPClient == nil {
		opts.HTTPClient = new(http.Client)
	}
	opts.HTTPClient.Transport = newUserAgentTransport(userAgent, opts.HTTPClient.Transport)
	checksum := computeChecksum(opts.TargetPath)
	payload, err := json.Marshal(proto.Request{
		AppID:          appID,
		Channel:        opts.Channel,
		OS:             opts.OS,
		Arch:           opts.Arch,
		GoARM:          opts.GoARM,
		TargetVersion:  opts.Version,
		CurrentVersion: opts.CurrentVersion,
		CurrentSHA256:  checksum,
	})
	req, err := http.NewRequest("POST", opts.CheckURL, bytes.NewReader(payload))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Accept", fmt.Sprintf("application/json; q=1; version=%s; charset=utf-8", protocolVersion))
	req.Header.Set("Content-Type", "application/json; charset=utf-8")
	req.Close = true
	return req, err
}
func doCheckRequest(opts Options, req *http.Request) (r Response, err error) {
	resp, err := opts.HTTPClient.Do(req)
	if err != nil {
		return r, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		body, _ := ioutil.ReadAll(resp.Body)
		return r, fmt.Errorf("Server responded with %s: %s", resp.Status, body)
	}
	var protoResp proto.Response
	err = json.NewDecoder(resp.Body).Decode(&protoResp)
	if err != nil {
		return r, err
	}
	if !protoResp.Available {
		return r, NotAvailableErr
	}
	r.ReleaseVersion = protoResp.Release.Version
	r.ReleaseTitle = protoResp.Release.Title
	r.ReleaseDescription = protoResp.Release.Description
	r.ReleaseDate = protoResp.Release.CreateDate
	r.downloadURL = protoResp.DownloadURL
	r.patch = protoResp.Patch
	r.opts = opts
	r.checksum, err = hex.DecodeString(protoResp.Checksum)
	if err != nil {
		return r, err
	}
	r.signature, err = hex.DecodeString(protoResp.Signature)
	if err != nil {
		return r, err
	}
	return r, nil
}
func computeChecksum(path string) string {
	f, err := os.Open(path)
	if err != nil {
		return ""
	}
	defer f.Close()
	h := sha256.New()
	_, err = io.Copy(h, f)
	if err != nil {
		return ""
	}
	return hex.EncodeToString(h.Sum(nil))
}