diff --git a/Gopkg.lock b/Gopkg.lock
deleted file mode 100644
index 99184b3..0000000
--- a/Gopkg.lock
+++ /dev/null
@@ -1,28 +0,0 @@
-# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
-
-
-[[projects]]
- name = "github.com/kardianos/osext"
- packages = ["."]
- revision = "6e7f843663477789fac7c02def0d0909e969b4e5"
-
-[[projects]]
- name = "github.com/kr/binarydist"
- packages = ["."]
- revision = "9955b0ab8708602d411341e55fffd7e0700f86bd"
-
-[[projects]]
- branch = "v0"
- name = "gopkg.in/inconshreveable/go-update.v0"
- packages = [
- ".",
- "download"
- ]
- revision = "d8b0b1d421aa1cbf392c05869f8abbc669bb7066"
-
-[solve-meta]
- analyzer-name = "dep"
- analyzer-version = 1
- inputs-digest = "2dc15c6a0e0dda650516ca1c04eb3ce579602cb928acda004089b48b0dce8a9d"
- solver-name = "gps-cdcl"
- solver-version = 1
diff --git a/Gopkg.toml b/Gopkg.toml
deleted file mode 100644
index 245f040..0000000
--- a/Gopkg.toml
+++ /dev/null
@@ -1,34 +0,0 @@
-# Gopkg.toml example
-#
-# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
-# for detailed Gopkg.toml documentation.
-#
-# required = ["github.com/user/thing/cmd/thing"]
-# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
-#
-# [[constraint]]
-# name = "github.com/user/project"
-# version = "1.0.0"
-#
-# [[constraint]]
-# name = "github.com/user/project2"
-# branch = "dev"
-# source = "github.com/myfork/project2"
-#
-# [[override]]
-# name = "github.com/x/y"
-# version = "2.4.0"
-#
-# [prune]
-# non-go = false
-# go-tests = true
-# unused-packages = true
-
-
-[[constraint]]
- branch = "v0"
- name = "gopkg.in/inconshreveable/go-update.v0"
-
-[prune]
- go-tests = true
- unused-packages = true
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..9604122
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,9 @@
+module github.com/sanbornm/go-selfupdate
+
+go 1.15
+
+require (
+ github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
+ github.com/kr/binarydist v0.1.0
+ gopkg.in/inconshreveable/go-update.v0 v0.0.0-20150814200126-d8b0b1d421aa
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..b51589b
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,6 @@
+github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
+github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
+github.com/kr/binarydist v0.1.0 h1:6kAoLA9FMMnNGSehX0s1PdjbEaACznAv/W219j2uvyo=
+github.com/kr/binarydist v0.1.0/go.mod h1:DY7S//GCoz1BCd0B0EVrinCKAZN3pXe+MDaIZbXQVgM=
+gopkg.in/inconshreveable/go-update.v0 v0.0.0-20150814200126-d8b0b1d421aa h1:drvf2JoUL1fz3ttkGNkw+rf3kZa2//7XkYGpSO4NHNA=
+gopkg.in/inconshreveable/go-update.v0 v0.0.0-20150814200126-d8b0b1d421aa/go.mod h1:tuNm0ntQ7IH9VSA39XxzLMpee5c2DwgIbjD4x3ydo8Y=
diff --git a/selfupdate/selfupdate.go b/selfupdate/selfupdate.go
index 6cd4590..414d3a2 100644
--- a/selfupdate/selfupdate.go
+++ b/selfupdate/selfupdate.go
@@ -83,6 +83,8 @@ type Updater struct {
DiffURL string // Base URL for diff downloads.
Dir string // Directory to store selfupdate state.
ForceCheck bool // Check for update regardless of cktime timestamp
+ CheckTime int // Time in hours before next check
+ RandomizeTime int // Time in hours to randomize with CheckTime
Requester Requester //Optional parameter to override existing http request handler
Info struct {
Version string
@@ -102,34 +104,62 @@ func (u *Updater) BackgroundRun() error {
// fail
return err
}
- if u.wantUpdate() {
+ if u.WantUpdate() {
if err := up.CanUpdate(); err != nil {
// fail
return err
}
+
+ u.SetUpdateTime()
+
//self, err := osext.Executable()
//if err != nil {
// fail update, couldn't figure out path to self
//return
//}
// TODO(bgentry): logger isn't on Windows. Replace w/ proper error reports.
- if err := u.update(); err != nil {
+ if err := u.Update(); err != nil {
return err
}
}
return nil
}
-func (u *Updater) wantUpdate() bool {
- path := u.getExecRelativeDir(u.Dir + upcktimePath)
- if u.CurrentVersion == "dev" || (!u.ForceCheck && readTime(path).After(time.Now())) {
+// WantUpdate returns boolean designating if an update is desired
+func (u *Updater) WantUpdate() bool {
+ if u.CurrentVersion == "dev" || (!u.ForceCheck && u.NextUpdate().After(time.Now())) {
return false
}
- wait := 24*time.Hour + randDuration(24*time.Hour)
- return writeTime(path, time.Now().Add(wait))
+
+ return true
}
-func (u *Updater) update() error {
+// NextUpdate returns the next time update should be checked
+func (u *Updater) NextUpdate() time.Time {
+ path := u.getExecRelativeDir(u.Dir + upcktimePath)
+ nextTime := readTime(path)
+
+ return nextTime
+}
+
+// SetUpdateTime writes the next update time to the state file
+func (u *Updater) SetUpdateTime() bool {
+ path := u.getExecRelativeDir(u.Dir + upcktimePath)
+ wait := time.Duration(u.CheckTime) * time.Hour
+ // Add 1 to random time since max is not included
+ waitrand := time.Duration(rand.Intn(u.RandomizeTime+1)) * time.Hour
+
+ return writeTime(path, time.Now().Add(wait+waitrand))
+}
+
+// ClearUpdateState writes current time to state file
+func (u *Updater) ClearUpdateState() {
+ path := u.getExecRelativeDir(u.Dir + upcktimePath)
+ os.Remove(path)
+}
+
+// Update initiates the self update process
+func (u *Updater) Update() error {
path, err := osext.Executable()
if err != nil {
return err
@@ -250,11 +280,6 @@ func (u *Updater) fetchBin() ([]byte, error) {
return buf.Bytes(), nil
}
-// returns a random duration in [0,n).
-func randDuration(n time.Duration) time.Duration {
- return time.Duration(rand.Int63n(int64(n)))
-}
-
func (u *Updater) fetch(url string) (io.ReadCloser, error) {
if u.Requester == nil {
return defaultHTTPRequester.Fetch(url)
diff --git a/selfupdate/selfupdate_test.go b/selfupdate/selfupdate_test.go
index 6def191..e71cb81 100644
--- a/selfupdate/selfupdate_test.go
+++ b/selfupdate/selfupdate_test.go
@@ -6,6 +6,7 @@ import (
"fmt"
"io"
"testing"
+ "time"
)
var testHash = sha256.New()
@@ -17,7 +18,11 @@ func TestUpdaterFetchMustReturnNonNilReaderCloser(t *testing.T) {
return nil, nil
})
updater := createUpdater(mr)
+ updater.CheckTime = 24
+ updater.RandomizeTime = 24
+
err := updater.BackgroundRun()
+
if err != nil {
equals(t, "Fetch was expected to return non-nil ReadCloser", err.Error())
} else {
@@ -34,6 +39,8 @@ func TestUpdaterWithEmptyPayloadNoErrorNoUpdate(t *testing.T) {
return newTestReaderCloser("{}"), nil
})
updater := createUpdater(mr)
+ updater.CheckTime = 24
+ updater.RandomizeTime = 24
err := updater.BackgroundRun()
if err != nil {
@@ -41,6 +48,46 @@ func TestUpdaterWithEmptyPayloadNoErrorNoUpdate(t *testing.T) {
}
}
+func TestUpdaterCheckTime(t *testing.T) {
+ mr := &mockRequester{}
+ mr.handleRequest(
+ func(url string) (io.ReadCloser, error) {
+ equals(t, "http://updates.yourdomain.com/myapp/darwin-amd64.json", url)
+ return newTestReaderCloser("{}"), nil
+ })
+
+ // Run test with various time
+ runTestTimeChecks(t, mr, 0, 0, false)
+ runTestTimeChecks(t, mr, 0, 5, true)
+ runTestTimeChecks(t, mr, 1, 0, true)
+ runTestTimeChecks(t, mr, 100, 100, true)
+}
+
+// Helper function to run check time tests
+func runTestTimeChecks(t *testing.T, mr *mockRequester, checkTime int, randomizeTime int, expectUpdate bool) {
+ updater := createUpdater(mr)
+ updater.ClearUpdateState()
+ updater.CheckTime = checkTime
+ updater.RandomizeTime = randomizeTime
+
+ updater.BackgroundRun()
+
+ if updater.WantUpdate() == expectUpdate {
+ t.Errorf("WantUpdate returned %v; want %v", updater.WantUpdate(), expectUpdate)
+ }
+
+ maxHrs := time.Duration(updater.CheckTime+updater.RandomizeTime) * time.Hour
+ maxTime := time.Now().Add(maxHrs)
+
+ if !updater.NextUpdate().Before(maxTime) {
+ t.Errorf("NextUpdate should less than %s hrs (CheckTime + RandomizeTime) from now; now %s; next update %s", maxHrs, time.Now(), updater.NextUpdate())
+ }
+
+ if maxHrs > 0 && !updater.NextUpdate().After(time.Now()) {
+ t.Errorf("NextUpdate should be after now")
+ }
+}
+
func TestUpdaterWithEmptyPayloadNoErrorNoUpdateEscapedPath(t *testing.T) {
mr := &mockRequester{}
mr.handleRequest(
diff --git a/selfupdate/update/cktime b/selfupdate/update/cktime
new file mode 100644
index 0000000..d88cca7
--- /dev/null
+++ b/selfupdate/update/cktime
@@ -0,0 +1 @@
+2020-12-08T21:11:49-07:00
\ No newline at end of file
diff --git a/vendor/github.com/kardianos/osext/LICENSE b/vendor/github.com/kardianos/osext/LICENSE
deleted file mode 100644
index 7448756..0000000
--- a/vendor/github.com/kardianos/osext/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) 2012 The Go Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/kardianos/osext/README.md b/vendor/github.com/kardianos/osext/README.md
deleted file mode 100644
index 61350ba..0000000
--- a/vendor/github.com/kardianos/osext/README.md
+++ /dev/null
@@ -1,16 +0,0 @@
-### Extensions to the "os" package.
-
-## Find the current Executable and ExecutableFolder.
-
-There is sometimes utility in finding the current executable file
-that is running. This can be used for upgrading the current executable
-or finding resources located relative to the executable file. Both
-working directory and the os.Args[0] value are arbitrary and cannot
-be relied on; os.Args[0] can be "faked".
-
-Multi-platform and supports:
- * Linux
- * OS X
- * Windows
- * Plan 9
- * BSDs.
diff --git a/vendor/github.com/kardianos/osext/osext.go b/vendor/github.com/kardianos/osext/osext.go
deleted file mode 100644
index 0eca579..0000000
--- a/vendor/github.com/kardianos/osext/osext.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Extensions to the standard "os" package.
-package osext // import "github.com/kardianos/osext"
-
-import "path/filepath"
-
-// Executable returns an absolute path that can be used to
-// re-invoke the current program.
-// It may not be valid after the current program exits.
-func Executable() (string, error) {
- p, err := executable()
- return filepath.Clean(p), err
-}
-
-// Returns same path as Executable, returns just the folder
-// path. Excludes the executable name and any trailing slash.
-func ExecutableFolder() (string, error) {
- p, err := Executable()
- if err != nil {
- return "", err
- }
-
- return filepath.Dir(p), nil
-}
diff --git a/vendor/github.com/kardianos/osext/osext_plan9.go b/vendor/github.com/kardianos/osext/osext_plan9.go
deleted file mode 100644
index 655750c..0000000
--- a/vendor/github.com/kardianos/osext/osext_plan9.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package osext
-
-import (
- "os"
- "strconv"
- "syscall"
-)
-
-func executable() (string, error) {
- f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text")
- if err != nil {
- return "", err
- }
- defer f.Close()
- return syscall.Fd2path(int(f.Fd()))
-}
diff --git a/vendor/github.com/kardianos/osext/osext_procfs.go b/vendor/github.com/kardianos/osext/osext_procfs.go
deleted file mode 100644
index b2598bc..0000000
--- a/vendor/github.com/kardianos/osext/osext_procfs.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build linux netbsd openbsd solaris dragonfly
-
-package osext
-
-import (
- "errors"
- "fmt"
- "os"
- "runtime"
- "strings"
-)
-
-func executable() (string, error) {
- switch runtime.GOOS {
- case "linux":
- const deletedTag = " (deleted)"
- execpath, err := os.Readlink("/proc/self/exe")
- if err != nil {
- return execpath, err
- }
- execpath = strings.TrimSuffix(execpath, deletedTag)
- execpath = strings.TrimPrefix(execpath, deletedTag)
- return execpath, nil
- case "netbsd":
- return os.Readlink("/proc/curproc/exe")
- case "openbsd", "dragonfly":
- return os.Readlink("/proc/curproc/file")
- case "solaris":
- return os.Readlink(fmt.Sprintf("/proc/%d/path/a.out", os.Getpid()))
- }
- return "", errors.New("ExecPath not implemented for " + runtime.GOOS)
-}
diff --git a/vendor/github.com/kardianos/osext/osext_sysctl.go b/vendor/github.com/kardianos/osext/osext_sysctl.go
deleted file mode 100644
index b66cac8..0000000
--- a/vendor/github.com/kardianos/osext/osext_sysctl.go
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build darwin freebsd
-
-package osext
-
-import (
- "os"
- "path/filepath"
- "runtime"
- "syscall"
- "unsafe"
-)
-
-var initCwd, initCwdErr = os.Getwd()
-
-func executable() (string, error) {
- var mib [4]int32
- switch runtime.GOOS {
- case "freebsd":
- mib = [4]int32{1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1}
- case "darwin":
- mib = [4]int32{1 /* CTL_KERN */, 38 /* KERN_PROCARGS */, int32(os.Getpid()), -1}
- }
-
- n := uintptr(0)
- // Get length.
- _, _, errNum := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
- if errNum != 0 {
- return "", errNum
- }
- if n == 0 { // This shouldn't happen.
- return "", nil
- }
- buf := make([]byte, n)
- _, _, errNum = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0, 0)
- if errNum != 0 {
- return "", errNum
- }
- if n == 0 { // This shouldn't happen.
- return "", nil
- }
- for i, v := range buf {
- if v == 0 {
- buf = buf[:i]
- break
- }
- }
- var err error
- execPath := string(buf)
- // execPath will not be empty due to above checks.
- // Try to get the absolute path if the execPath is not rooted.
- if execPath[0] != '/' {
- execPath, err = getAbs(execPath)
- if err != nil {
- return execPath, err
- }
- }
- // For darwin KERN_PROCARGS may return the path to a symlink rather than the
- // actual executable.
- if runtime.GOOS == "darwin" {
- if execPath, err = filepath.EvalSymlinks(execPath); err != nil {
- return execPath, err
- }
- }
- return execPath, nil
-}
-
-func getAbs(execPath string) (string, error) {
- if initCwdErr != nil {
- return execPath, initCwdErr
- }
- // The execPath may begin with a "../" or a "./" so clean it first.
- // Join the two paths, trailing and starting slashes undetermined, so use
- // the generic Join function.
- return filepath.Join(initCwd, filepath.Clean(execPath)), nil
-}
diff --git a/vendor/github.com/kardianos/osext/osext_windows.go b/vendor/github.com/kardianos/osext/osext_windows.go
deleted file mode 100644
index 72d282c..0000000
--- a/vendor/github.com/kardianos/osext/osext_windows.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package osext
-
-import (
- "syscall"
- "unicode/utf16"
- "unsafe"
-)
-
-var (
- kernel = syscall.MustLoadDLL("kernel32.dll")
- getModuleFileNameProc = kernel.MustFindProc("GetModuleFileNameW")
-)
-
-// GetModuleFileName() with hModule = NULL
-func executable() (exePath string, err error) {
- return getModuleFileName()
-}
-
-func getModuleFileName() (string, error) {
- var n uint32
- b := make([]uint16, syscall.MAX_PATH)
- size := uint32(len(b))
-
- r0, _, e1 := getModuleFileNameProc.Call(0, uintptr(unsafe.Pointer(&b[0])), uintptr(size))
- n = uint32(r0)
- if n == 0 {
- return "", e1
- }
- return string(utf16.Decode(b[0:n])), nil
-}
diff --git a/vendor/github.com/kr/binarydist/.gitignore b/vendor/github.com/kr/binarydist/.gitignore
deleted file mode 100644
index 653f160..0000000
--- a/vendor/github.com/kr/binarydist/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-test.*
diff --git a/vendor/github.com/kr/binarydist/License b/vendor/github.com/kr/binarydist/License
deleted file mode 100644
index 183c389..0000000
--- a/vendor/github.com/kr/binarydist/License
+++ /dev/null
@@ -1,22 +0,0 @@
-Copyright 2012 Keith Rarick
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/github.com/kr/binarydist/Readme.md b/vendor/github.com/kr/binarydist/Readme.md
deleted file mode 100644
index dadc368..0000000
--- a/vendor/github.com/kr/binarydist/Readme.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# binarydist
-
-Package binarydist implements binary diff and patch as described on
-. It reads and writes files
-compatible with the tools there.
-
-Documentation at .
diff --git a/vendor/github.com/kr/binarydist/bzip2.go b/vendor/github.com/kr/binarydist/bzip2.go
deleted file mode 100644
index a2516b8..0000000
--- a/vendor/github.com/kr/binarydist/bzip2.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package binarydist
-
-import (
- "io"
- "os/exec"
-)
-
-type bzip2Writer struct {
- c *exec.Cmd
- w io.WriteCloser
-}
-
-func (w bzip2Writer) Write(b []byte) (int, error) {
- return w.w.Write(b)
-}
-
-func (w bzip2Writer) Close() error {
- if err := w.w.Close(); err != nil {
- return err
- }
- return w.c.Wait()
-}
-
-// Package compress/bzip2 implements only decompression,
-// so we'll fake it by running bzip2 in another process.
-func newBzip2Writer(w io.Writer) (wc io.WriteCloser, err error) {
- var bw bzip2Writer
- bw.c = exec.Command("bzip2", "-c")
- bw.c.Stdout = w
-
- if bw.w, err = bw.c.StdinPipe(); err != nil {
- return nil, err
- }
-
- if err = bw.c.Start(); err != nil {
- return nil, err
- }
-
- return bw, nil
-}
diff --git a/vendor/github.com/kr/binarydist/diff.go b/vendor/github.com/kr/binarydist/diff.go
deleted file mode 100644
index 1d2d951..0000000
--- a/vendor/github.com/kr/binarydist/diff.go
+++ /dev/null
@@ -1,408 +0,0 @@
-package binarydist
-
-import (
- "bytes"
- "encoding/binary"
- "io"
- "io/ioutil"
-)
-
-func swap(a []int, i, j int) { a[i], a[j] = a[j], a[i] }
-
-func split(I, V []int, start, length, h int) {
- var i, j, k, x, jj, kk int
-
- if length < 16 {
- for k = start; k < start+length; k += j {
- j = 1
- x = V[I[k]+h]
- for i = 1; k+i < start+length; i++ {
- if V[I[k+i]+h] < x {
- x = V[I[k+i]+h]
- j = 0
- }
- if V[I[k+i]+h] == x {
- swap(I, k+i, k+j)
- j++
- }
- }
- for i = 0; i < j; i++ {
- V[I[k+i]] = k + j - 1
- }
- if j == 1 {
- I[k] = -1
- }
- }
- return
- }
-
- x = V[I[start+length/2]+h]
- jj = 0
- kk = 0
- for i = start; i < start+length; i++ {
- if V[I[i]+h] < x {
- jj++
- }
- if V[I[i]+h] == x {
- kk++
- }
- }
- jj += start
- kk += jj
-
- i = start
- j = 0
- k = 0
- for i < jj {
- if V[I[i]+h] < x {
- i++
- } else if V[I[i]+h] == x {
- swap(I, i, jj+j)
- j++
- } else {
- swap(I, i, kk+k)
- k++
- }
- }
-
- for jj+j < kk {
- if V[I[jj+j]+h] == x {
- j++
- } else {
- swap(I, jj+j, kk+k)
- k++
- }
- }
-
- if jj > start {
- split(I, V, start, jj-start, h)
- }
-
- for i = 0; i < kk-jj; i++ {
- V[I[jj+i]] = kk - 1
- }
- if jj == kk-1 {
- I[jj] = -1
- }
-
- if start+length > kk {
- split(I, V, kk, start+length-kk, h)
- }
-}
-
-func qsufsort(obuf []byte) []int {
- var buckets [256]int
- var i, h int
- I := make([]int, len(obuf)+1)
- V := make([]int, len(obuf)+1)
-
- for _, c := range obuf {
- buckets[c]++
- }
- for i = 1; i < 256; i++ {
- buckets[i] += buckets[i-1]
- }
- copy(buckets[1:], buckets[:])
- buckets[0] = 0
-
- for i, c := range obuf {
- buckets[c]++
- I[buckets[c]] = i
- }
-
- I[0] = len(obuf)
- for i, c := range obuf {
- V[i] = buckets[c]
- }
-
- V[len(obuf)] = 0
- for i = 1; i < 256; i++ {
- if buckets[i] == buckets[i-1]+1 {
- I[buckets[i]] = -1
- }
- }
- I[0] = -1
-
- for h = 1; I[0] != -(len(obuf) + 1); h += h {
- var n int
- for i = 0; i < len(obuf)+1; {
- if I[i] < 0 {
- n -= I[i]
- i -= I[i]
- } else {
- if n != 0 {
- I[i-n] = -n
- }
- n = V[I[i]] + 1 - i
- split(I, V, i, n, h)
- i += n
- n = 0
- }
- }
- if n != 0 {
- I[i-n] = -n
- }
- }
-
- for i = 0; i < len(obuf)+1; i++ {
- I[V[i]] = i
- }
- return I
-}
-
-func matchlen(a, b []byte) (i int) {
- for i < len(a) && i < len(b) && a[i] == b[i] {
- i++
- }
- return i
-}
-
-func search(I []int, obuf, nbuf []byte, st, en int) (pos, n int) {
- if en-st < 2 {
- x := matchlen(obuf[I[st]:], nbuf)
- y := matchlen(obuf[I[en]:], nbuf)
-
- if x > y {
- return I[st], x
- } else {
- return I[en], y
- }
- }
-
- x := st + (en-st)/2
- if bytes.Compare(obuf[I[x]:], nbuf) < 0 {
- return search(I, obuf, nbuf, x, en)
- } else {
- return search(I, obuf, nbuf, st, x)
- }
- panic("unreached")
-}
-
-// 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)
- if err != nil {
- return err
- }
-
- nbuf, err := ioutil.ReadAll(new)
- if err != nil {
- return err
- }
-
- pbuf, err := diffBytes(obuf, nbuf)
- if err != nil {
- return err
- }
-
- _, err = patch.Write(pbuf)
- return err
-}
-
-func diffBytes(obuf, nbuf []byte) ([]byte, error) {
- var patch seekBuffer
- err := diff(obuf, nbuf, &patch)
- if err != nil {
- return nil, err
- }
- return patch.buf, nil
-}
-
-func diff(obuf, nbuf []byte, patch io.WriteSeeker) error {
- var lenf int
- I := qsufsort(obuf)
- db := make([]byte, len(nbuf))
- eb := make([]byte, len(nbuf))
- var dblen, eblen int
-
- var hdr header
- hdr.Magic = magic
- hdr.NewSize = int64(len(nbuf))
- err := binary.Write(patch, signMagLittleEndian{}, &hdr)
- if err != nil {
- return err
- }
-
- // Compute the differences, writing ctrl as we go
- pfbz2, err := newBzip2Writer(patch)
- if err != nil {
- return err
- }
- var scan, pos, length int
- var lastscan, lastpos, lastoffset int
- for scan < len(nbuf) {
- var oldscore int
- scan += length
- for scsc := scan; scan < len(nbuf); scan++ {
- pos, length = search(I, obuf, nbuf[scan:], 0, len(obuf))
-
- for ; scsc < scan+length; scsc++ {
- if scsc+lastoffset < len(obuf) &&
- obuf[scsc+lastoffset] == nbuf[scsc] {
- oldscore++
- }
- }
-
- if (length == oldscore && length != 0) || length > oldscore+8 {
- break
- }
-
- if scan+lastoffset < len(obuf) && obuf[scan+lastoffset] == nbuf[scan] {
- oldscore--
- }
- }
-
- if length != oldscore || scan == len(nbuf) {
- var s, Sf int
- lenf = 0
- for i := 0; lastscan+i < scan && lastpos+i < len(obuf); {
- if obuf[lastpos+i] == nbuf[lastscan+i] {
- s++
- }
- i++
- if s*2-i > Sf*2-lenf {
- Sf = s
- lenf = i
- }
- }
-
- lenb := 0
- if scan < len(nbuf) {
- var s, Sb int
- for i := 1; (scan >= lastscan+i) && (pos >= i); i++ {
- if obuf[pos-i] == nbuf[scan-i] {
- s++
- }
- if s*2-i > Sb*2-lenb {
- Sb = s
- lenb = i
- }
- }
- }
-
- if lastscan+lenf > scan-lenb {
- overlap := (lastscan + lenf) - (scan - lenb)
- s := 0
- Ss := 0
- lens := 0
- for i := 0; i < overlap; i++ {
- if nbuf[lastscan+lenf-overlap+i] == obuf[lastpos+lenf-overlap+i] {
- s++
- }
- if nbuf[scan-lenb+i] == obuf[pos-lenb+i] {
- s--
- }
- if s > Ss {
- Ss = s
- lens = i + 1
- }
- }
-
- lenf += lens - overlap
- lenb -= lens
- }
-
- for i := 0; i < lenf; i++ {
- db[dblen+i] = nbuf[lastscan+i] - obuf[lastpos+i]
- }
- for i := 0; i < (scan-lenb)-(lastscan+lenf); i++ {
- eb[eblen+i] = nbuf[lastscan+lenf+i]
- }
-
- dblen += lenf
- eblen += (scan - lenb) - (lastscan + lenf)
-
- err = binary.Write(pfbz2, signMagLittleEndian{}, int64(lenf))
- if err != nil {
- pfbz2.Close()
- return err
- }
-
- val := (scan - lenb) - (lastscan + lenf)
- err = binary.Write(pfbz2, signMagLittleEndian{}, int64(val))
- if err != nil {
- pfbz2.Close()
- return err
- }
-
- val = (pos - lenb) - (lastpos + lenf)
- err = binary.Write(pfbz2, signMagLittleEndian{}, int64(val))
- if err != nil {
- pfbz2.Close()
- return err
- }
-
- lastscan = scan - lenb
- lastpos = pos - lenb
- lastoffset = pos - scan
- }
- }
- err = pfbz2.Close()
- if err != nil {
- return err
- }
-
- // Compute size of compressed ctrl data
- l64, err := patch.Seek(0, 1)
- if err != nil {
- return err
- }
- hdr.CtrlLen = int64(l64 - 32)
-
- // Write compressed diff data
- pfbz2, err = newBzip2Writer(patch)
- if err != nil {
- return err
- }
- n, err := pfbz2.Write(db[:dblen])
- if err != nil {
- pfbz2.Close()
- return err
- }
- if n != dblen {
- pfbz2.Close()
- return io.ErrShortWrite
- }
- err = pfbz2.Close()
- if err != nil {
- return err
- }
-
- // Compute size of compressed diff data
- n64, err := patch.Seek(0, 1)
- if err != nil {
- return err
- }
- hdr.DiffLen = n64 - l64
-
- // Write compressed extra data
- pfbz2, err = newBzip2Writer(patch)
- if err != nil {
- return err
- }
- n, err = pfbz2.Write(eb[:eblen])
- if err != nil {
- pfbz2.Close()
- return err
- }
- if n != eblen {
- pfbz2.Close()
- return io.ErrShortWrite
- }
- err = pfbz2.Close()
- if err != nil {
- return err
- }
-
- // Seek to the beginning, write the header, and close the file
- _, err = patch.Seek(0, 0)
- if err != nil {
- return err
- }
- err = binary.Write(patch, signMagLittleEndian{}, &hdr)
- if err != nil {
- return err
- }
- return nil
-}
diff --git a/vendor/github.com/kr/binarydist/doc.go b/vendor/github.com/kr/binarydist/doc.go
deleted file mode 100644
index 3c92d87..0000000
--- a/vendor/github.com/kr/binarydist/doc.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Package binarydist implements binary diff and patch as described on
-// http://www.daemonology.net/bsdiff/. It reads and writes files
-// compatible with the tools there.
-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)
-// 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".
-type header struct {
- Magic [8]byte
- CtrlLen int64
- DiffLen int64
- NewSize int64
-}
diff --git a/vendor/github.com/kr/binarydist/encoding.go b/vendor/github.com/kr/binarydist/encoding.go
deleted file mode 100644
index 75ba585..0000000
--- a/vendor/github.com/kr/binarydist/encoding.go
+++ /dev/null
@@ -1,53 +0,0 @@
-package binarydist
-
-// SignMagLittleEndian is the numeric encoding used by the bsdiff tools.
-// It implements binary.ByteOrder using a sign-magnitude format
-// and little-endian byte order. Only methods Uint64 and String
-// have been written; the rest panic.
-type signMagLittleEndian struct{}
-
-func (signMagLittleEndian) Uint16(b []byte) uint16 { panic("unimplemented") }
-
-func (signMagLittleEndian) PutUint16(b []byte, v uint16) { panic("unimplemented") }
-
-func (signMagLittleEndian) Uint32(b []byte) uint32 { panic("unimplemented") }
-
-func (signMagLittleEndian) PutUint32(b []byte, v uint32) { panic("unimplemented") }
-
-func (signMagLittleEndian) Uint64(b []byte) uint64 {
- y := int64(b[0]) |
- int64(b[1])<<8 |
- int64(b[2])<<16 |
- int64(b[3])<<24 |
- int64(b[4])<<32 |
- int64(b[5])<<40 |
- int64(b[6])<<48 |
- int64(b[7]&0x7f)<<56
-
- if b[7]&0x80 != 0 {
- y = -y
- }
- return uint64(y)
-}
-
-func (signMagLittleEndian) PutUint64(b []byte, v uint64) {
- x := int64(v)
- neg := x < 0
- if neg {
- x = -x
- }
-
- b[0] = byte(x)
- b[1] = byte(x >> 8)
- b[2] = byte(x >> 16)
- b[3] = byte(x >> 24)
- b[4] = byte(x >> 32)
- b[5] = byte(x >> 40)
- b[6] = byte(x >> 48)
- b[7] = byte(x >> 56)
- if neg {
- b[7] |= 0x80
- }
-}
-
-func (signMagLittleEndian) String() string { return "signMagLittleEndian" }
diff --git a/vendor/github.com/kr/binarydist/patch.go b/vendor/github.com/kr/binarydist/patch.go
deleted file mode 100644
index eb03225..0000000
--- a/vendor/github.com/kr/binarydist/patch.go
+++ /dev/null
@@ -1,109 +0,0 @@
-package binarydist
-
-import (
- "bytes"
- "compress/bzip2"
- "encoding/binary"
- "errors"
- "io"
- "io/ioutil"
-)
-
-var ErrCorrupt = errors.New("corrupt patch")
-
-// Patch applies patch to old, according to the bspatch algorithm,
-// and writes the result to new.
-func Patch(old io.Reader, new io.Writer, patch io.Reader) error {
- var hdr header
- err := binary.Read(patch, signMagLittleEndian{}, &hdr)
- if err != nil {
- return err
- }
- if hdr.Magic != magic {
- return ErrCorrupt
- }
- if hdr.CtrlLen < 0 || hdr.DiffLen < 0 || hdr.NewSize < 0 {
- return ErrCorrupt
- }
-
- ctrlbuf := make([]byte, hdr.CtrlLen)
- _, err = io.ReadFull(patch, ctrlbuf)
- if err != nil {
- return err
- }
- cpfbz2 := bzip2.NewReader(bytes.NewReader(ctrlbuf))
-
- diffbuf := make([]byte, hdr.DiffLen)
- _, err = io.ReadFull(patch, diffbuf)
- if err != nil {
- return err
- }
- dpfbz2 := bzip2.NewReader(bytes.NewReader(diffbuf))
-
- // The entire rest of the file is the extra block.
- epfbz2 := bzip2.NewReader(patch)
-
- obuf, err := ioutil.ReadAll(old)
- if err != nil {
- return err
- }
-
- nbuf := make([]byte, hdr.NewSize)
-
- var oldpos, newpos int64
- for newpos < hdr.NewSize {
- var ctrl struct{ Add, Copy, Seek int64 }
- err = binary.Read(cpfbz2, signMagLittleEndian{}, &ctrl)
- if err != nil {
- return err
- }
-
- // Sanity-check
- if newpos+ctrl.Add > hdr.NewSize {
- return ErrCorrupt
- }
-
- // Read diff string
- _, err = io.ReadFull(dpfbz2, nbuf[newpos:newpos+ctrl.Add])
- if err != nil {
- return ErrCorrupt
- }
-
- // Add old data to diff string
- for i := int64(0); i < ctrl.Add; i++ {
- if oldpos+i >= 0 && oldpos+i < int64(len(obuf)) {
- nbuf[newpos+i] += obuf[oldpos+i]
- }
- }
-
- // Adjust pointers
- newpos += ctrl.Add
- oldpos += ctrl.Add
-
- // Sanity-check
- if newpos+ctrl.Copy > hdr.NewSize {
- return ErrCorrupt
- }
-
- // Read extra string
- _, err = io.ReadFull(epfbz2, nbuf[newpos:newpos+ctrl.Copy])
- if err != nil {
- return ErrCorrupt
- }
-
- // Adjust pointers
- newpos += ctrl.Copy
- oldpos += ctrl.Seek
- }
-
- // Write the new file
- for len(nbuf) > 0 {
- n, err := new.Write(nbuf)
- if err != nil {
- return err
- }
- nbuf = nbuf[n:]
- }
-
- return nil
-}
diff --git a/vendor/github.com/kr/binarydist/seek.go b/vendor/github.com/kr/binarydist/seek.go
deleted file mode 100644
index 96c0346..0000000
--- a/vendor/github.com/kr/binarydist/seek.go
+++ /dev/null
@@ -1,43 +0,0 @@
-package binarydist
-
-import (
- "errors"
-)
-
-type seekBuffer struct {
- buf []byte
- pos int
-}
-
-func (b *seekBuffer) Write(p []byte) (n int, err error) {
- n = copy(b.buf[b.pos:], p)
- if n == len(p) {
- b.pos += n
- return n, nil
- }
- b.buf = append(b.buf, p[n:]...)
- b.pos += len(p)
- return len(p), nil
-}
-
-func (b *seekBuffer) Seek(offset int64, whence int) (ret int64, err error) {
- var abs int64
- switch whence {
- case 0:
- abs = offset
- case 1:
- abs = int64(b.pos) + offset
- case 2:
- abs = int64(len(b.buf)) + offset
- default:
- return 0, errors.New("binarydist: invalid whence")
- }
- if abs < 0 {
- return 0, errors.New("binarydist: negative position")
- }
- if abs >= 1<<31 {
- return 0, errors.New("binarydist: position out of range")
- }
- b.pos = int(abs)
- return abs, nil
-}
diff --git a/vendor/gopkg.in/inconshreveable/go-update.v0/LICENSE b/vendor/gopkg.in/inconshreveable/go-update.v0/LICENSE
deleted file mode 100644
index 5f0d1fb..0000000
--- a/vendor/gopkg.in/inconshreveable/go-update.v0/LICENSE
+++ /dev/null
@@ -1,13 +0,0 @@
-Copyright 2014 Alan Shreve
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/vendor/gopkg.in/inconshreveable/go-update.v0/README.md b/vendor/gopkg.in/inconshreveable/go-update.v0/README.md
deleted file mode 100644
index f070062..0000000
--- a/vendor/gopkg.in/inconshreveable/go-update.v0/README.md
+++ /dev/null
@@ -1,37 +0,0 @@
-# go-update: Automatically update Go programs from the internet
-
-go-update allows a program to update itself by replacing its executable file
-with a new version. It provides the flexibility to implement different updating user experiences
-like auto-updating, or manual user-initiated updates. It also boasts
-advanced features like binary patching and code signing verification.
-
-Updating your program to a new version is as easy as:
-
- err, errRecover := update.New().FromUrl("http://release.example.com/2.0/myprogram")
- if err != nil {
- fmt.Printf("Update failed: %v\n", err)
- }
-
-## Documentation and API Reference
-
-Comprehensive API documentation and code examples are available in the code documentation available on godoc.org:
-
-[](https://godoc.org/github.com/inconshreveable/go-update)
-
-## Features
-
-- Cross platform support (Windows too!)
-- Binary patch application
-- Checksum verification
-- Code signing verification
-- Support for updating arbitrary files
-
-## [equinox.io](https://equinox.io)
-go-update provides the primitives for building self-updating applications, but there a number of other challenges
-involved in a complete updating solution such as hosting, code signing, update channels, gradual rollout,
-dynamically computing binary patches, tracking update metrics like versions and failures, plus more.
-
-I provide this service, a complete solution, free for open source projects, at [equinox.io](https://equinox.io).
-
-## License
-Apache
diff --git a/vendor/gopkg.in/inconshreveable/go-update.v0/download/download.go b/vendor/gopkg.in/inconshreveable/go-update.v0/download/download.go
deleted file mode 100644
index 4552c93..0000000
--- a/vendor/gopkg.in/inconshreveable/go-update.v0/download/download.go
+++ /dev/null
@@ -1,235 +0,0 @@
-package download
-
-import (
- "bytes"
- "compress/gzip"
- "fmt"
- "io"
- "net/http"
- "os"
- "runtime"
-)
-
-type roundTripper struct {
- RoundTripFn func(*http.Request) (*http.Response, error)
-}
-
-func (rt *roundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
- return rt.RoundTripFn(r)
-}
-
-// Download encapsulates the state and parameters to download content
-// from a URL which:
-//
-// - Publishes the percentage of the download completed to a channel.
-// - May resume a previous download that was partially completed.
-//
-// Create an instance with the New() factory function.
-type Download struct {
- // net/http.Client to use when downloading the update.
- // If nil, a default http.Client is used
- HttpClient *http.Client
-
- // As bytes are downloaded, they are written to Target.
- // Download also uses the Target's Seek method to determine
- // the size of partial-downloads so that it may properly
- // request the remaining bytes to resume the download.
- Target Target
-
- // Progress returns the percentage of the download
- // completed as an integer between 0 and 100
- Progress chan (int)
-
- // HTTP Method to use in the download request. Default is "GET"
- Method string
-
- // HTTP URL to issue the download request to
- Url string
-}
-
-// New initializes a new Download object which will download
-// the content from url into target.
-func New(url string, target Target, httpClient *http.Client) *Download {
- return &Download{
- HttpClient: httpClient,
- Progress: make(chan int),
- Method: "GET",
- Url: url,
- Target: target,
- }
-}
-
-// Get() downloads the content of a url to a target destination.
-//
-// Only HTTP/1.1 servers that implement the Range header support resuming a
-// partially completed download.
-//
-// On success, the server must return 200 and the content, or 206 when resuming a partial download.
-// If the HTTP server returns a 3XX redirect, it will be followed according to d.HttpClient's redirect policy.
-//
-func (d *Download) Get() (err error) {
- // Close the progress channel whenever this function completes
- defer close(d.Progress)
-
- // determine the size of the download target to determine if we're resuming a partial download
- offset, err := d.Target.Size()
- if err != nil {
- return
- }
-
- // create the download request
- req, err := http.NewRequest(d.Method, d.Url, nil)
- if err != nil {
- return
- }
-
- // create an http client if one does not exist
- if d.HttpClient == nil {
- d.HttpClient = http.DefaultClient
- }
-
- // we have to add headers like this so they get used across redirects
- trans := d.HttpClient.Transport
- if trans == nil {
- trans = http.DefaultTransport
- }
-
- d.HttpClient.Transport = &roundTripper{
- RoundTripFn: func(r *http.Request) (*http.Response, error) {
- // add header for download continuation
- if offset > 0 {
- r.Header.Add("Range", fmt.Sprintf("%d-", offset))
- }
-
- // ask for gzipped content so that net/http won't unzip it for us
- // and destroy the content length header we need for progress calculations
- r.Header.Add("Accept-Encoding", "gzip")
-
- return trans.RoundTrip(r)
- },
- }
-
- // issue the download request
- resp, err := d.HttpClient.Do(req)
- if err != nil {
- return
- }
- defer resp.Body.Close()
-
- switch resp.StatusCode {
- // ok
- case 200, 206:
-
- // server error
- default:
- err = fmt.Errorf("Non 2XX response when downloading update: %s", resp.Status)
- return
- }
-
- // Determine how much we have to download
- // net/http sets this to -1 when it is unknown
- clength := resp.ContentLength
-
- // Read the content from the response body
- rd := resp.Body
-
- // meter the rate at which we download content for
- // progress reporting if we know how much to expect
- if clength > 0 {
- rd = &meteredReader{rd: rd, totalSize: clength, progress: d.Progress}
- }
-
- // Decompress the content if necessary
- if resp.Header.Get("Content-Encoding") == "gzip" {
- rd, err = gzip.NewReader(rd)
- if err != nil {
- return
- }
- }
-
- // Download the update
- _, err = io.Copy(d.Target, rd)
- if err != nil {
- return
- }
-
- return
-}
-
-// meteredReader wraps a ReadCloser. Calls to a meteredReader's Read() method
-// publish updates to a progress channel with the percentage read so far.
-type meteredReader struct {
- rd io.ReadCloser
- totalSize int64
- progress chan int
- totalRead int64
- ticks int64
-}
-
-func (m *meteredReader) Close() error {
- return m.rd.Close()
-}
-
-func (m *meteredReader) Read(b []byte) (n int, err error) {
- chunkSize := (m.totalSize / 100) + 1
- lenB := int64(len(b))
-
- var nChunk int
- for start := int64(0); start < lenB; start += int64(nChunk) {
- end := start + chunkSize
- if end > lenB {
- end = lenB
- }
-
- nChunk, err = m.rd.Read(b[start:end])
-
- n += nChunk
- m.totalRead += int64(nChunk)
-
- if m.totalRead > (m.ticks * chunkSize) {
- m.ticks += 1
- // try to send on channel, but don't block if it's full
- select {
- case m.progress <- int(m.ticks + 1):
- default:
- }
-
- // give the progress channel consumer a chance to run
- runtime.Gosched()
- }
-
- if err != nil {
- return
- }
- }
-
- return
-}
-
-// A Target is what you can supply to Download,
-// it's just an io.Writer with a Size() method so that
-// the a Download can "resume" an interrupted download
-type Target interface {
- io.Writer
- Size() (int, error)
-}
-
-type FileTarget struct {
- *os.File
-}
-
-func (t *FileTarget) Size() (int, error) {
- if fi, err := t.File.Stat(); err != nil {
- return 0, err
- } else {
- return int(fi.Size()), nil
- }
-}
-
-type MemoryTarget struct {
- bytes.Buffer
-}
-
-func (t *MemoryTarget) Size() (int, error) {
- return t.Buffer.Len(), nil
-}
diff --git a/vendor/gopkg.in/inconshreveable/go-update.v0/hide_noop.go b/vendor/gopkg.in/inconshreveable/go-update.v0/hide_noop.go
deleted file mode 100644
index 3707756..0000000
--- a/vendor/gopkg.in/inconshreveable/go-update.v0/hide_noop.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// +build !windows
-
-package update
-
-func hideFile(path string) error {
- return nil
-}
diff --git a/vendor/gopkg.in/inconshreveable/go-update.v0/hide_windows.go b/vendor/gopkg.in/inconshreveable/go-update.v0/hide_windows.go
deleted file mode 100644
index c368b9c..0000000
--- a/vendor/gopkg.in/inconshreveable/go-update.v0/hide_windows.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package update
-
-import (
- "syscall"
- "unsafe"
-)
-
-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)
-
- if r1 == 0 {
- return err
- } else {
- return nil
- }
-}
diff --git a/vendor/gopkg.in/inconshreveable/go-update.v0/update.go b/vendor/gopkg.in/inconshreveable/go-update.v0/update.go
deleted file mode 100644
index dcfc314..0000000
--- a/vendor/gopkg.in/inconshreveable/go-update.v0/update.go
+++ /dev/null
@@ -1,491 +0,0 @@
-/*
-go-update allows a program to update itself by replacing its executable file
-with a new version. It provides the flexibility to implement different updating user experiences
-like auto-updating, or manual user-initiated updates. It also boasts
-advanced features like binary patching and code signing verification.
-
-Updating your program to a new version is as easy as:
-
- err, errRecover := update.New().FromUrl("http://release.example.com/2.0/myprogram")
- if err != nil {
- fmt.Printf("Update failed: %v\n", err)
- }
-
-You may also choose to update from other data sources such as a file or an io.Reader:
-
- err, errRecover := update.New().FromFile("/path/to/update")
-
-Binary Diff Patching
-
-Binary diff updates are supported and easy to use:
-
- up := update.New().ApplyPatch(update.PATCHTYPE_BSDIFF)
- err, errRecover := up.FromUrl("http://release.example.com/2.0/mypatch")
-
-Checksum Verification
-
-You should also verify the checksum of new updates as well as verify
-the digital signature of an update. Note that even when you choose to apply
-a patch, the checksum is verified against the complete update after that patch
-has been applied.
-
- up := update.New().ApplyPatch(update.PATCHTYPE_BSDIFF).VerifyChecksum(checksum)
- err, errRecover := up.FromUrl("http://release.example.com/2.0/mypatch")
-
-Updating other files
-
-Updating arbitrary files is also supported. You may update files which are
-not the currently running program:
-
- up := update.New().Target("/usr/local/bin/some-program")
- err, errRecover := up.FromUrl("http://release.example.com/2.0/some-program")
-
-Code Signing
-
-Truly secure updates use code signing to verify that the update was issued by a trusted party.
-To do this, you'll need to generate a public/private key pair. You can do this with openssl,
-or the equinox.io client (https://equinox.io/client) can easily generate one for you:
-
- # with equinox client
- equinox genkey --private-key=private.pem --public-key=public.pem
-
- # with openssl
- openssl genrsa -out private.pem 2048
- openssl rsa -in private.pem -out public.pem -pubout
-
-Once you have your key pair, you can instruct your program to validate its updates
-with the public key:
-
- const publicKey = `-----BEGIN PUBLIC KEY-----
- ...
- -----END PUBLIC KEY-----`
-
- up, err := update.New().VerifySignatureWithPEM(publicKey)
- if err != nil {
- return fmt.Errorf("Bad public key: '%v': %v", publicKey, err)
- }
-
-Once you've configured your program this way, it will disallow all updates unless they
-are properly signed. You must now pass in the signature to verify with:
-
- up.VerifySignature(signature).FromUrl("http://dl.example.com/update")
-
-Error Handling and Recovery
-
-To perform an update, the process must be able to read its executable file and to write
-to the directory that contains its executable file. It can be useful to check whether the process
-has the necessary permissions to perform an update before trying to apply one. Use the
-CanUpdate call to provide a useful message to the user if the update can't proceed without
-elevated permissions:
-
- up := update.New().Target("/etc/hosts")
- err := up.CanUpdate()
- if err != nil {
- fmt.Printf("Can't update because: '%v'. Try as root or Administrator\n", err)
- return
- }
- err, errRecover := up.FromUrl("https://example.com/new/hosts")
-
-Although exceedingly unlikely, the update operation itself is not atomic and can fail
-in such a way that a user's computer is left in an inconsistent state. If that happens,
-go-update attempts to recover to leave the system in a good state. If the recovery step
-fails (even more unlikely), a second error, referred to as "errRecover" will be non-nil
-so that you may inform your users of the bad news. You should handle this case as shown
-here:
-
- err, errRecover := up.FromUrl("https://example.com/update")
- if err != nil {
- fmt.Printf("Update failed: %v\n", err)
- if errRecover != nil {
- fmt.Printf("Failed to recover bad update: %v!\n", errRecover)
- fmt.Printf("Program exectuable may be missing!\n")
- }
- }
-
-Subpackages
-
-Sub-package check contains the client functionality for a simple protocol for negotiating
-whether a new update is available, where it is, and the metadata needed for verifying it.
-
-Sub-package download contains functionality for downloading from an HTTP endpoint
-while outputting a progress meter and supports resuming partial downloads.
-*/
-package update
-
-import (
- "bytes"
- "crypto"
- "crypto/rsa"
- "crypto/sha256"
- _ "crypto/sha512" // for tls cipher support
- "crypto/x509"
- "encoding/pem"
- "fmt"
- "io"
- "io/ioutil"
- "net/http"
- "os"
- "path/filepath"
-
- "github.com/kardianos/osext"
- "github.com/kr/binarydist"
- "gopkg.in/inconshreveable/go-update.v0/download"
-)
-
-// The type of a binary patch, if any. Only bsdiff is supported
-type PatchType string
-
-const (
- PATCHTYPE_BSDIFF PatchType = "bsdiff"
- PATCHTYPE_NONE = ""
-)
-
-type Update struct {
- // empty string means "path of the current executable"
- TargetPath string
-
- // type of patch to apply. PATCHTYPE_NONE means "not a patch"
- PatchType
-
- // sha256 checksum of the new binary to verify against
- Checksum []byte
-
- // public key to use for signature verification
- PublicKey *rsa.PublicKey
-
- // signature to use for signature verification
- Signature []byte
-
- // configurable http client can be passed to download
- HTTPClient *http.Client
-}
-
-func (u *Update) getPath() (string, error) {
- if u.TargetPath == "" {
- return osext.Executable()
- } else {
- return u.TargetPath, nil
- }
-}
-
-// New creates a new Update object.
-// A default update object assumes the complete binary
-// content will be used for update (not a patch) and that
-// the intended target is the running executable.
-//
-// Use this as the start of a chain of calls on the Update
-// object to build up your configuration. Example:
-//
-// up := update.New().ApplyPatch(update.PATCHTYPE_BSDIFF).VerifyChecksum(checksum)
-//
-func New() *Update {
- return &Update{
- TargetPath: "",
- PatchType: PATCHTYPE_NONE,
- }
-}
-
-// Target configures the update to update the file at the given path.
-// The emptry string means 'the executable file of the running program'.
-func (u *Update) Target(path string) *Update {
- u.TargetPath = path
- return u
-}
-
-// ApplyPatch configures the update to treat the contents of the update
-// as a patch to apply to the existing to target. You must specify the
-// format of the patch. Only PATCHTYPE_BSDIFF is supported at the moment.
-func (u *Update) ApplyPatch(patchType PatchType) *Update {
- u.PatchType = patchType
- return u
-}
-
-// VerifyChecksum configures the update to verify that the
-// the update has the given sha256 checksum.
-func (u *Update) VerifyChecksum(checksum []byte) *Update {
- u.Checksum = checksum
- return u
-}
-
-// VerifySignature configures the update to verify the given
-// signature of the update. You must also call one of the
-// VerifySignatureWith* functions to specify a public key
-// to use for verification.
-func (u *Update) VerifySignature(signature []byte) *Update {
- u.Signature = signature
- return u
-}
-
-// VerifySignatureWith configures the update to use the given RSA
-// public key to verify the update's signature. You must also call
-// VerifySignature() with a signature to check.
-//
-// You'll probably want to use VerifySignatureWithPEM instead of
-// parsing the public key yourself.
-func (u *Update) VerifySignatureWith(publicKey *rsa.PublicKey) *Update {
- u.PublicKey = publicKey
- return u
-}
-
-// VerifySignatureWithPEM configures the update to use the given PEM-formatted
-// RSA public key to verify the update's signature. You must also call
-// VerifySignature() with a signature to check.
-//
-// A PEM formatted public key typically begins with
-// -----BEGIN PUBLIC KEY-----
-func (u *Update) VerifySignatureWithPEM(publicKeyPEM []byte) (*Update, error) {
- block, _ := pem.Decode(publicKeyPEM)
- if block == nil {
- return u, fmt.Errorf("Couldn't parse PEM data")
- }
-
- pub, err := x509.ParsePKIXPublicKey(block.Bytes)
- if err != nil {
- return u, err
- }
-
- var ok bool
- u.PublicKey, ok = pub.(*rsa.PublicKey)
- if !ok {
- return u, fmt.Errorf("Public key isn't an RSA public key")
- }
-
- return u, nil
-}
-
-// FromUrl updates the target with the contents of the given URL.
-func (u *Update) FromUrl(url string) (err error, errRecover error) {
- target := new(download.MemoryTarget)
- err = download.New(url, target, u.HTTPClient).Get()
- if err != nil {
- return
- }
-
- return u.FromStream(target)
-}
-
-// FromFile updates the target the contents of the given file.
-func (u *Update) FromFile(path string) (err error, errRecover error) {
- // open the new updated contents
- fp, err := os.Open(path)
- if err != nil {
- return
- }
- defer fp.Close()
-
- // do the update
- return u.FromStream(fp)
-}
-
-// FromStream updates the target file with the contents of the supplied io.Reader.
-//
-// FromStream performs the following actions to ensure a safe cross-platform update:
-//
-// 1. If configured, applies the contents of the io.Reader as a binary patch.
-//
-// 2. If configured, computes the sha256 checksum and verifies it matches.
-//
-// 3. If configured, verifies the RSA signature with a public key.
-//
-// 4. Creates a new file, /path/to/.target.new with mode 0755 with the contents of the updated file
-//
-// 5. Renames /path/to/target to /path/to/.target.old
-//
-// 6. Renames /path/to/.target.new to /path/to/target
-//
-// 7. If the rename is successful, deletes /path/to/.target.old, returns no error
-//
-// 8. If the rename fails, attempts to rename /path/to/.target.old back to /path/to/target
-// If this operation fails, it is reported in the errRecover return value so as not to
-// mask the original error that caused the recovery attempt.
-//
-// On Windows, the removal of /path/to/.target.old always fails, so instead,
-// we just make the old file hidden instead.
-func (u *Update) FromStream(updateWith io.Reader) (err error, errRecover error) {
- updatePath, err := u.getPath()
- if err != nil {
- return
- }
-
- var newBytes []byte
- // apply a patch if requested
- switch u.PatchType {
- case PATCHTYPE_BSDIFF:
- newBytes, err = applyPatch(updateWith, updatePath)
- if err != nil {
- return
- }
- case PATCHTYPE_NONE:
- // no patch to apply, go on through
- newBytes, err = ioutil.ReadAll(updateWith)
- if err != nil {
- return
- }
- default:
- err = fmt.Errorf("Unrecognized patch type: %s", u.PatchType)
- return
- }
-
- // verify checksum if requested
- if u.Checksum != nil {
- if err = verifyChecksum(newBytes, u.Checksum); err != nil {
- return
- }
- }
-
- // verify signature if requested
- if u.Signature != nil || u.PublicKey != nil {
- if u.Signature == nil {
- err = fmt.Errorf("No public key specified to verify signature")
- return
- }
-
- if u.PublicKey == nil {
- err = fmt.Errorf("No signature to verify!")
- return
- }
-
- if err = verifySignature(newBytes, u.Signature, u.PublicKey); err != nil {
- return
- }
- }
-
- // get the directory the executable exists in
- updateDir := filepath.Dir(updatePath)
- filename := filepath.Base(updatePath)
-
- // Copy the contents of of newbinary to a the new executable file
- newPath := filepath.Join(updateDir, fmt.Sprintf(".%s.new", filename))
- fp, err := os.OpenFile(newPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0755)
- if err != nil {
- return
- }
- defer fp.Close()
- _, err = io.Copy(fp, bytes.NewReader(newBytes))
-
- // if we don't call fp.Close(), windows won't let us move the new executable
- // because the file will still be "in use"
- fp.Close()
-
- // this is where we'll move the executable to so that we can swap in the updated replacement
- oldPath := filepath.Join(updateDir, fmt.Sprintf(".%s.old", filename))
-
- // delete any existing old exec file - this is necessary on Windows for two reasons:
- // 1. after a successful update, Windows can't remove the .old file because the process is still running
- // 2. windows rename operations fail if the destination file already exists
- _ = os.Remove(oldPath)
-
- // move the existing executable to a new file in the same directory
- err = os.Rename(updatePath, oldPath)
- if err != nil {
- return
- }
-
- // move the new exectuable in to become the new program
- err = os.Rename(newPath, updatePath)
-
- if err != nil {
- // copy unsuccessful
- errRecover = os.Rename(oldPath, updatePath)
- } else {
- // copy successful, remove the old binary
- errRemove := os.Remove(oldPath)
-
- // windows has trouble with removing old binaries, so hide it instead
- if errRemove != nil {
- _ = hideFile(oldPath)
- }
- }
-
- return
-}
-
-// CanUpdate() determines whether the process has the correct permissions to
-// perform the requested update. If the update can proceed, it returns nil, otherwise
-// it returns the error that would occur if an update were attempted.
-func (u *Update) CanUpdate() (err error) {
- // get the directory the file exists in
- path, err := u.getPath()
- if err != nil {
- return
- }
-
- fileDir := filepath.Dir(path)
- fileName := filepath.Base(path)
-
- // attempt to open a file in the file's directory
- newPath := filepath.Join(fileDir, fmt.Sprintf(".%s.new", fileName))
- fp, err := os.OpenFile(newPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0755)
- if err != nil {
- return
- }
- fp.Close()
-
- _ = os.Remove(newPath)
- return
-}
-
-func applyPatch(patch io.Reader, updatePath string) ([]byte, error) {
- // open the file to update
- old, err := os.Open(updatePath)
- if err != nil {
- return nil, err
- }
- defer old.Close()
-
- // apply the patch
- applied := new(bytes.Buffer)
- if err = binarydist.Patch(old, applied, patch); err != nil {
- return nil, err
- }
-
- return applied.Bytes(), nil
-}
-
-func verifyChecksum(updated []byte, expectedChecksum []byte) error {
- checksum, err := ChecksumForBytes(updated)
- if err != nil {
- return err
- }
-
- if !bytes.Equal(expectedChecksum, checksum) {
- return fmt.Errorf("Updated file has wrong checksum. Expected: %x, got: %x", expectedChecksum, checksum)
- }
-
- return nil
-}
-
-// ChecksumForFile returns the sha256 checksum for the given file
-func ChecksumForFile(path string) ([]byte, error) {
- f, err := os.Open(path)
- if err != nil {
- return nil, err
- }
- defer f.Close()
-
- return ChecksumForReader(f)
-}
-
-// ChecksumForReader returns the sha256 checksum for the entire
-// contents of the given reader.
-func ChecksumForReader(rd io.Reader) ([]byte, error) {
- h := sha256.New()
- if _, err := io.Copy(h, rd); err != nil {
- return nil, err
- }
- return h.Sum(nil), nil
-}
-
-// ChecksumForBytes returns the sha256 checksum for the given bytes
-func ChecksumForBytes(source []byte) ([]byte, error) {
- return ChecksumForReader(bytes.NewReader(source))
-}
-
-func verifySignature(source, signature []byte, publicKey *rsa.PublicKey) error {
- checksum, err := ChecksumForBytes(source)
- if err != nil {
- return err
- }
-
- return rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, checksum, signature)
-}