diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index 19eadb0..176d98d 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -6,33 +6,55 @@ permissions: jobs: static_analysis: runs-on: ubuntu-latest + strategy: + fail-fast: false steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: persist-credentials: false - - uses: WillAbides/setup-go-faster@v1.7.0 + - uses: WillAbides/setup-go-faster@v1 with: - go-version: '1.18' + go-version: 'stable' - name: Get dependencies + run: >- + sudo apt-get update && + sudo apt-get install + gcc + libegl1-mesa-dev + libgl1-mesa-dev + libgles2-mesa-dev + libx11-dev + xorg-dev + xvfb + bsdiff + + - name: Install analysis tools run: | go install golang.org/x/tools/cmd/goimports@latest - go install golang.org/x/lint/golint@latest go install github.com/fzipp/gocyclo/cmd/gocyclo@latest - go install honnef.co/go/tools/cmd/staticcheck@v0.3.0 + go install honnef.co/go/tools/cmd/staticcheck@latest + go install github.com/mattn/goveralls@latest - name: Vet run: go vet ./... - name: Goimports - run: test -z $(goimports -e -d . | tee /dev/stderr) - - - name: Lint - run: golint -set_exit_status ./... + run: test -z "$(goimports -e -d . | tee /dev/stderr)" - name: Gocyclo run: gocyclo -over 25 . - name: Staticcheck run: staticcheck ./... + + - name: Update coverage + run: | + set -e + go test -tags coverage -covermode=atomic -coverprofile=coverage.out ./... + + - name: Update PR Coverage + uses: shogo82148/actions-goveralls@v1 + with: + path-to-profile: coverage.out diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1146fd2..4a7270c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,13 +10,13 @@ jobs: strategy: fail-fast: false matrix: - go-version: [1.14, 1.18] + go-version: ['1.19.x', 'stable'] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: persist-credentials: false - - uses: WillAbides/setup-go-faster@v1.7.0 + - uses: WillAbides/setup-go-faster@v1 with: go-version: ${{ matrix.go-version }} @@ -24,17 +24,4 @@ jobs: run: sudo apt-get update && sudo apt-get install bsdiff - name: Test - run: go test -tags ci ./... - - - name: Update coverage - run: | - go get github.com/mattn/goveralls - set -e - go test -tags ci -covermode=atomic -coverprofile=coverage.out ./... - if: ${{ runner.os == 'Linux' }} - - - name: Update PR Coverage - uses: shogo82148/actions-goveralls@v1 - with: - path-to-profile: coverage.out - if: ${{ runner.os == 'Linux' && matrix.go-version == '1.18' }} + run: go test ./... diff --git a/.gitignore b/.gitignore index 148fe70..67bcde5 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ *.dylib cmd/selfupdatectl/selfupdatectl cmd/example/example +internal/binarydist/test.* # Test binary, built with `go test -c` *.test diff --git a/apply.go b/apply.go index 1f5c573..843b3f9 100644 --- a/apply.go +++ b/apply.go @@ -9,14 +9,11 @@ import ( "errors" "fmt" "io" - "io/ioutil" "os" "path/filepath" ) -var ( - openFile = os.OpenFile -) +var openFile = os.OpenFile // Apply performs an update of the current executable (or opts.TargetFile, if set) with the contents of the given io.Reader. // @@ -88,7 +85,7 @@ func apply(update io.Reader, opts *Options) error { } } else { // no patch to apply, go on through - if newBytes, err = ioutil.ReadAll(update); err != nil { + if newBytes, err = io.ReadAll(update); err != nil { return err } } @@ -315,7 +312,7 @@ func (o *Options) verifySignature(updated []byte) error { if publicKey, ok := o.PublicKey.(ed25519.PublicKey); ok { valid := ed25519.Verify(publicKey, updated, o.Signature) if !valid { - return fmt.Errorf("invalid ed25519 signature") + return errors.New("invalid ed25519 signature") } return nil } diff --git a/apply_test.go b/apply_test.go index ecdc266..0725c92 100644 --- a/apply_test.go +++ b/apply_test.go @@ -9,7 +9,6 @@ import ( "crypto/x509" "encoding/pem" "fmt" - "io/ioutil" "os" "testing" @@ -29,7 +28,7 @@ func cleanup(path string) { // we write with a separate name for each test so that we can run them in parallel func writeOldFile(path string, t *testing.T) { - if err := ioutil.WriteFile(path, oldFile, 0777); err != nil { + if err := os.WriteFile(path, oldFile, 0777); err != nil { t.Fatalf("Failed to write file for testing preparation: %v", err) } } @@ -39,7 +38,7 @@ func validateUpdate(path string, err error, t *testing.T) { t.Fatalf("Failed to update: %v", err) } - buf, err := ioutil.ReadFile(path) + buf, err := os.ReadFile(path) if err != nil { t.Fatalf("Failed to read file post-update: %v", err) } diff --git a/cmd/selfupdatectl/check.go b/cmd/selfupdatectl/check.go index 576eac8..03c4b2e 100644 --- a/cmd/selfupdatectl/check.go +++ b/cmd/selfupdatectl/check.go @@ -7,7 +7,6 @@ import ( "encoding/pem" "fmt" "io" - "io/ioutil" "os" "github.com/urfave/cli/v2" @@ -72,7 +71,7 @@ func publicKeyVerifier(publicKey string) (ed25519.PublicKey, error) { } defer publicKeyFile.Close() - b, err := ioutil.ReadAll(publicKeyFile) + b, err := io.ReadAll(publicKeyFile) if err != nil { return []byte{}, err } diff --git a/cmd/selfupdatectl/create_keys.go b/cmd/selfupdatectl/create_keys.go index 34c283e..bb55951 100644 --- a/cmd/selfupdatectl/create_keys.go +++ b/cmd/selfupdatectl/create_keys.go @@ -5,7 +5,7 @@ import ( "crypto/rand" "crypto/x509" "encoding/pem" - "io/ioutil" + "os" "github.com/urfave/cli/v2" ) @@ -55,7 +55,7 @@ func (a *application) createKeys() error { Bytes: b, } - err = ioutil.WriteFile(a.privateKey, pem.EncodeToMemory(block), 0600) + err = os.WriteFile(a.privateKey, pem.EncodeToMemory(block), 0600) if err != nil { return err } @@ -70,6 +70,6 @@ func (a *application) createKeys() error { Bytes: b, } - err = ioutil.WriteFile(a.publicKey, pem.EncodeToMemory(block), 0644) + err = os.WriteFile(a.publicKey, pem.EncodeToMemory(block), 0644) return err } diff --git a/cmd/selfupdatectl/sign.go b/cmd/selfupdatectl/sign.go index d07ba86..964b109 100644 --- a/cmd/selfupdatectl/sign.go +++ b/cmd/selfupdatectl/sign.go @@ -5,7 +5,7 @@ import ( "crypto/x509" "encoding/pem" "fmt" - "io/ioutil" + "io" "os" "github.com/urfave/cli/v2" @@ -62,8 +62,7 @@ func (a *application) sign(executable string) error { return fmt.Errorf("ed25519 signature must be 64 bytes long and was %v", len(signature)) } - err = ioutil.WriteFile(executable+".ed25519", signature, 0644) - return err + return os.WriteFile(executable+".ed25519", signature, 0644) } func privateKeySigner(privateKey string) (ed25519.PrivateKey, error) { @@ -73,7 +72,7 @@ func privateKeySigner(privateKey string) (ed25519.PrivateKey, error) { } defer privateKeyFile.Close() - b, err := ioutil.ReadAll(privateKeyFile) + b, err := io.ReadAll(privateKeyFile) if err != nil { return []byte{}, err } @@ -103,5 +102,5 @@ func executableContent(executable string) ([]byte, error) { } defer executableFile.Close() - return ioutil.ReadAll(executableFile) + return io.ReadAll(executableFile) } diff --git a/doc.go b/doc.go index fc393a1..6815260 100644 --- a/doc.go +++ b/doc.go @@ -3,7 +3,7 @@ Package selfupdate provides functionality to implement secure, self-updating Go For complete updating solutions please see Equinox (https://equinox.io) and go-tuf (https://github.com/flynn/go-tuf). -Basic Example +# Basic Example This example shows how to update a program remotely from a URL. @@ -30,8 +30,7 @@ This example shows how to update a program remotely from a URL. return err } - -Binary Patching +# Binary Patching Go binaries can often be large. It can be advantageous to only ship a binary patch to a client instead of the complete program text of a new version. @@ -56,7 +55,7 @@ may be applied by implementing the Patcher interface. return err } -Checksum Verification +# Checksum Verification Updating executable code on a computer can be a dangerous operation unless you take the appropriate steps to guarantee the authenticity of the new code. While @@ -94,7 +93,7 @@ specified as a hex string. return err } -Cryptographic Signature Verification +# Cryptographic Signature Verification Cryptographic verification of new code from an update is an extremely important way to guarantee the security and integrity of your updates. @@ -149,15 +148,14 @@ with the private key and distribute the signature along with the update. return err } - -Building Single-File Go Binaries +# Building Single-File Go Binaries In order to update a Go application with self-update, you must distributed it as a single executable. This is often easy, but some applications require static assets (like HTML and CSS asset files or TLS certificates). In order to update applications like these, you'll want to make sure to embed those asset files into the distributed binary with a tool like go-bindata (my favorite): https://github.com/jteeuwen/go-bindata -Non-Goals +# Non-Goals Mechanisms and protocols for determining whether an update should be applied and, if so, which one are out of scope for this package. Please consult go-tuf (https://github.com/flynn/go-tuf) or Equinox (https://equinox.io) @@ -167,6 +165,5 @@ selfupdate only works for self-updating applications that are distributed as a s applications that do not have additional assets or dependency files. Updating application that are distributed as mutliple on-disk files is out of scope, although this may change in future versions of this library. - */ package selfupdate diff --git a/go.mod b/go.mod index f758f04..07c10d9 100644 --- a/go.mod +++ b/go.mod @@ -1,24 +1,19 @@ module github.com/fynelabs/selfupdate -go 1.18 +go 1.19 require ( github.com/aws/aws-sdk-go v1.44.28 - github.com/icza/session v1.2.0 - github.com/stretchr/testify v1.7.1 + github.com/stretchr/testify v1.9.0 github.com/urfave/cli/v2 v2.8.1 ) require ( github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect - github.com/davecgh/go-spew v1.1.0 // indirect - github.com/golang/protobuf v1.3.1 // indirect - github.com/icza/mighty v0.0.0-20210726202234-1719e2dcca1b // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect - google.golang.org/appengine v1.6.7 // indirect - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index e87fc66..970e05c 100644 --- a/go.sum +++ b/go.sum @@ -2,14 +2,9 @@ github.com/aws/aws-sdk-go v1.44.28 h1:h/OAqEqY18wq//v6h4GNPMmCkxuzSDrWuGyrvSiRqf github.com/aws/aws-sdk-go v1.44.28/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/icza/mighty v0.0.0-20210726202234-1719e2dcca1b h1:QlxXKayqve7+bZqMOOCe6Klqi838wGZtW6lZQvKl6vc= -github.com/icza/mighty v0.0.0-20210726202234-1719e2dcca1b/go.mod h1:klfNufgs1IcVNz2fWjXufNHkhl2cqIUbFoia2580Iv4= -github.com/icza/session v1.2.0 h1:4ncbGF7UN3Cq/GrZZq2tbnEJZAElIS6vy10Hkt21Lvw= -github.com/icza/session v1.2.0/go.mod h1:YR0WpaAv86zKUYA/9ftt0jgzHB/faiGRPx7Dk9omoew= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -20,30 +15,23 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/urfave/cli/v2 v2.8.1 h1:CGuYNZF9IKZY/rfBe3lJpccSoIY1ytfvmgQT90cNOl4= github.com/urfave/cli/v2 v2.8.1/go.mod h1:Z41J9TPoffeoqP0Iza0YbAhGvymRdZAd2uPmZ5JxRdY= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/hide_noop.go b/hide_noop.go index f4a252a..c00523f 100644 --- a/hide_noop.go +++ b/hide_noop.go @@ -3,6 +3,6 @@ package selfupdate -func hideFile(path string) error { +func hideFile(_ string) error { return nil } diff --git a/hide_windows.go b/hide_windows.go index 67ebd0b..09ff239 100644 --- a/hide_windows.go +++ b/hide_windows.go @@ -9,11 +9,14 @@ func hideFile(path string) error { kernel32 := syscall.NewLazyDLL("kernel32.dll") setFileAttributes := kernel32.NewProc("SetFileAttributesW") - r1, _, err := setFileAttributes.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))), 2) + ptr, err := syscall.UTF16PtrFromString(path) + if err != nil { + return err + } + r1, _, err := setFileAttributes.Call(uintptr(unsafe.Pointer(ptr)), 2) if r1 == 0 { return err - } else { - return nil } + return nil } diff --git a/http_source.go b/http_source.go index df6a370..690ce12 100644 --- a/http_source.go +++ b/http_source.go @@ -2,12 +2,14 @@ package selfupdate import ( "bytes" + "errors" "fmt" "io" "net/http" "os" "path/filepath" "runtime" + "strings" "text/template" ) @@ -54,10 +56,9 @@ func (h *HTTPSource) Get(v *Version) (io.ReadCloser, int64, error) { return nil, 0, err } - if v != nil { - if !v.Date.IsZero() { - request.Header.Add("If-Modified-Since", v.Date.Format(http.TimeFormat)) - } + if v != nil && !v.Date.IsZero() { + request.Header.Add("If-Modified-Since", v.Date.Format(http.TimeFormat)) + } response, err := h.client.Do(request) @@ -105,7 +106,7 @@ func (h *HTTPSource) LatestVersion() (*Version, error) { lastModified := resp.Header.Get("Last-Modified") if lastModified == "" { - return nil, fmt.Errorf("no Last-Modified served") + return nil, errors.New("no Last-Modified served") } t, err := http.ParseTime(lastModified) @@ -145,7 +146,7 @@ func replaceURLTemplate(base string) string { return base } - buf := &bytes.Buffer{} + buf := &strings.Builder{} err = t.Execute(buf, p) if err != nil { return base diff --git a/http_source_test.go b/http_source_test.go index 8fa0511..99272d3 100644 --- a/http_source_test.go +++ b/http_source_test.go @@ -2,7 +2,7 @@ package selfupdate import ( "crypto/ed25519" - "io/ioutil" + "io" "log" "net/http" "runtime" @@ -37,7 +37,7 @@ func TestHTTPSourceCheckSignature(t *testing.T) { assert.NotNil(t, file) assert.Equal(t, int64(19320832), contentLength) - body, err := ioutil.ReadAll(file) + body, err := io.ReadAll(file) assert.Nil(t, err) assert.NotNil(t, body) file.Close() diff --git a/internal/binarydist/common_test.go b/internal/binarydist/common_test.go index af51616..cd42965 100644 --- a/internal/binarydist/common_test.go +++ b/internal/binarydist/common_test.go @@ -3,7 +3,6 @@ package binarydist import ( "crypto/rand" "io" - "io/ioutil" "os" ) @@ -17,7 +16,7 @@ func mustOpen(path string) *os.File { } func mustReadAll(r io.Reader) []byte { - b, err := ioutil.ReadAll(r) + b, err := io.ReadAll(r) if err != nil { panic(err) } @@ -49,12 +48,12 @@ func fileCmp(a, b *os.File) int64 { panic(err) } - pa, err := ioutil.ReadAll(a) + pa, err := io.ReadAll(a) if err != nil { panic(err) } - pb, err := ioutil.ReadAll(b) + pb, err := io.ReadAll(b) if err != nil { panic(err) } diff --git a/internal/binarydist/diff.go b/internal/binarydist/diff.go index bcb910e..6f22899 100644 --- a/internal/binarydist/diff.go +++ b/internal/binarydist/diff.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/binary" "io" - "io/ioutil" ) func swap(a []int, i, j int) { a[i], a[j] = a[j], a[i] } @@ -178,12 +177,12 @@ func search(I []int, obuf, nbuf []byte, st, en int) (pos, n int) { // Diff computes the difference between old and new, according to the bsdiff // algorithm, and writes the result to patch. func Diff(old, new io.Reader, patch io.Writer) error { - obuf, err := ioutil.ReadAll(old) + obuf, err := io.ReadAll(old) if err != nil { return err } - nbuf, err := ioutil.ReadAll(new) + nbuf, err := io.ReadAll(new) if err != nil { return err } diff --git a/internal/binarydist/diff_test.go b/internal/binarydist/diff_test.go index 9baa492..eb5ce27 100644 --- a/internal/binarydist/diff_test.go +++ b/internal/binarydist/diff_test.go @@ -2,7 +2,6 @@ package binarydist import ( "bytes" - "io/ioutil" "os" "os/exec" "testing" @@ -24,13 +23,13 @@ var diffT = []struct { func TestDiff(t *testing.T) { for _, s := range diffT { - got, err := ioutil.TempFile("/tmp", "bspatch.") + got, err := os.CreateTemp("/tmp", "bspatch.") if err != nil { panic(err) } os.Remove(got.Name()) - exp, err := ioutil.TempFile("/tmp", "bspatch.") + exp, err := os.CreateTemp("/tmp", "bspatch.") if err != nil { panic(err) } diff --git a/internal/binarydist/doc.go b/internal/binarydist/doc.go index 3c92d87..9f297ca 100644 --- a/internal/binarydist/doc.go +++ b/internal/binarydist/doc.go @@ -6,13 +6,15 @@ package binarydist var magic = [8]byte{'B', 'S', 'D', 'I', 'F', 'F', '4', '0'} // File format: -// 0 8 "BSDIFF40" -// 8 8 X -// 16 8 Y -// 24 8 sizeof(newfile) -// 32 X bzip2(control block) -// 32+X Y bzip2(diff block) -// 32+X+Y ??? bzip2(extra block) +// +// 0 8 "BSDIFF40" +// 8 8 X +// 16 8 Y +// 24 8 sizeof(newfile) +// 32 X bzip2(control block) +// 32+X Y bzip2(diff block) +// 32+X+Y ??? bzip2(extra block) +// // with control block a set of triples (x,y,z) meaning "add x bytes // from oldfile to x bytes from the diff block; copy y bytes from the // extra block; seek forwards in oldfile by z bytes". diff --git a/internal/binarydist/patch.go b/internal/binarydist/patch.go index d564004..c1229d1 100644 --- a/internal/binarydist/patch.go +++ b/internal/binarydist/patch.go @@ -6,7 +6,6 @@ import ( "encoding/binary" "errors" "io" - "io/ioutil" ) // ErrCorrupt returned when a patch is corrupted @@ -44,7 +43,7 @@ func Patch(old io.Reader, new io.Writer, patch io.Reader) error { // The entire rest of the file is the extra block. epfbz2 := bzip2.NewReader(patch) - obuf, err := ioutil.ReadAll(old) + obuf, err := io.ReadAll(old) if err != nil { return err } diff --git a/internal/binarydist/patch_test.go b/internal/binarydist/patch_test.go index 840a919..3338a1d 100644 --- a/internal/binarydist/patch_test.go +++ b/internal/binarydist/patch_test.go @@ -1,7 +1,6 @@ package binarydist import ( - "io/ioutil" "os" "os/exec" "testing" @@ -11,7 +10,7 @@ func TestPatch(t *testing.T) { mustWriteRandFile("test.old", 1e3) mustWriteRandFile("test.new", 1e3) - got, err := ioutil.TempFile("/tmp", "bspatch.") + got, err := os.CreateTemp("/tmp", "bspatch.") if err != nil { panic(err) } @@ -39,7 +38,7 @@ func TestPatch(t *testing.T) { } func TestPatchHk(t *testing.T) { - got, err := ioutil.TempFile("/tmp", "bspatch.") + got, err := os.CreateTemp("/tmp", "bspatch.") if err != nil { panic(err) } diff --git a/internal/build/coverage.go b/internal/build/coverage.go new file mode 100644 index 0000000..20f59e2 --- /dev/null +++ b/internal/build/coverage.go @@ -0,0 +1,6 @@ +//go:build coverage + +package build + +// HasCoverage indicates if the binary is built with coverage data. +const HasCoverage = true diff --git a/internal/build/nocoverage.go b/internal/build/nocoverage.go new file mode 100644 index 0000000..bb0045f --- /dev/null +++ b/internal/build/nocoverage.go @@ -0,0 +1,6 @@ +//go:build !coverage + +package build + +// HasCoverage indicates if the binary is built with coverage data. +const HasCoverage = false diff --git a/internal/osext/osext_test.go b/internal/osext/osext_test.go index 51e4108..2228d55 100644 --- a/internal/osext/osext_test.go +++ b/internal/osext/osext_test.go @@ -16,6 +16,8 @@ import ( "path/filepath" "runtime" "testing" + + "github.com/fynelabs/selfupdate/internal/build" ) const ( @@ -75,6 +77,11 @@ func TestExecutableMatch(t *testing.T) { if !filepath.IsAbs(outs) { t.Fatalf("Child returned %q, want an absolute path", out) } + + if build.HasCoverage { + return // Executables to not match with coverage data embedded. + } + if !sameFile(outs, ep) { t.Fatalf("Child returned %q, not the same file as %q", out, ep) } @@ -132,6 +139,11 @@ func TestExecutableDelete(t *testing.T) { if !filepath.IsAbs(childPath) { t.Fatalf("Child returned %q, want an absolute path", childPath) } + + if build.HasCoverage { + return // Executables to not match with coverage data embedded. + } + if !sameFile(childPath, fpath) { t.Fatalf("Child returned %q, not the same file as %q", childPath, fpath) } diff --git a/progress_test.go b/progress_test.go index bd9dfd9..7081345 100644 --- a/progress_test.go +++ b/progress_test.go @@ -2,7 +2,7 @@ package selfupdate import ( "bytes" - "io/ioutil" + "io" "testing" "github.com/stretchr/testify/assert" @@ -22,7 +22,7 @@ func Test_ProgressReaderWithContentLength(t *testing.T) { }, } - r, err := ioutil.ReadAll(&pr) + r, err := io.ReadAll(&pr) assert.NotNil(t, r) assert.Nil(t, err) assert.Equal(t, float64(1), lastPercentage) @@ -42,7 +42,7 @@ func Test_ProgressReaderWithoutContentLength(t *testing.T) { }, } - r, err := ioutil.ReadAll(&pr) + r, err := io.ReadAll(&pr) assert.NotNil(t, r) assert.Nil(t, err) assert.Equal(t, float64(1), lastPercentage) diff --git a/updater.go b/updater.go index c881fb4..19b8ecf 100644 --- a/updater.go +++ b/updater.go @@ -213,15 +213,16 @@ func triggerSchedule(updater *Updater) { func delayUntilNextTriggerAt(repeating Repeating, offset time.Time) time.Duration { now := time.Now().In(offset.Location()) - var next time.Time + month, day, hour := now.Month(), now.Day(), now.Hour() switch repeating { - case Hourly: - next = time.Date(now.Year(), now.Month(), now.Day(), now.Hour()+1, offset.Minute(), offset.Second(), offset.Nanosecond(), offset.Location()) - case Daily: - next = time.Date(now.Year(), now.Month(), now.Day()+1, offset.Hour(), offset.Minute(), offset.Second(), offset.Nanosecond(), offset.Location()) case Monthly: - next = time.Date(now.Year(), now.Month()+1, offset.Day(), offset.Hour(), offset.Minute(), offset.Second(), offset.Nanosecond(), offset.Location()) + month++ + case Daily: + day++ + case Hourly: + hour++ } + next := time.Date(now.Year(), month, day, hour, offset.Minute(), offset.Second(), offset.Nanosecond(), offset.Location()) return next.Sub(now) }