diff --git a/.gitignore b/.gitignore index d72d8a7..56ad88a 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,5 @@ _testmain.go # external packages folder vendor/ -cain \ No newline at end of file +cain +dist/ diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..afd81b9 --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,32 @@ +project_name: cain + +release: + github: + owner: atrox + name: cain + +builds: +- goos: + - linux + - darwin + - windows + goarch: + - amd64 + - 386 + - arm + - arm64 + binary: cain + +archive: + files: + - README.md + - LICENSE + replacements: + 386: i386 + amd64: x86_64 + format_overrides: + - goos: windows + format: zip + +checksum: + name_template: '{{ .ProjectName }}_{{ .Version }}_checksums.txt' diff --git a/Gopkg.lock b/Gopkg.lock index 9bb9c0b..405cefd 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1,6 +1,12 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. +[[projects]] + name = "github.com/apex/log" + packages = ["."] + revision = "0296d6eb16bb28f8a0c55668affcf4876dc269be" + version = "v1.0.0" + [[projects]] branch = "master" name = "github.com/atrox/box" @@ -27,9 +33,87 @@ [[projects]] branch = "master" - name = "github.com/equinox-io/equinox" - packages = [".","internal/go-update","internal/go-update/internal/binarydist","internal/go-update/internal/osext","internal/osext","proto"] - revision = "f24972fa72facf59d05c91c848b65eac38815915" + name = "github.com/c4milo/unpackit" + packages = ["."] + revision = "4ed373e9ef1c895fe04468d813cb628902d89a0a" + +[[projects]] + branch = "master" + name = "github.com/dsnet/compress" + packages = [".","bzip2","bzip2/internal/sais","internal","internal/errors","internal/prefix"] + revision = "c4dbed65594871659ea7347a85e1b8dcd97b9990" + +[[projects]] + branch = "master" + name = "github.com/google/go-github" + packages = ["github"] + revision = "c004bf0c02fcab9d87a7f2e2f002fd008bf0784c" + +[[projects]] + branch = "master" + name = "github.com/google/go-querystring" + packages = ["query"] + revision = "53e6ce116135b80d037921a7fdd5138cf32d7a8a" + +[[projects]] + branch = "master" + name = "github.com/gosuri/uilive" + packages = ["."] + revision = "ac356e6e42cd31fcef8e6aec13ae9ed6fe87713e" + +[[projects]] + branch = "master" + name = "github.com/gosuri/uiprogress" + packages = [".","util/strutil"] + revision = "d0567a9d84a1c40dd7568115ea66f4887bf57b33" + +[[projects]] + name = "github.com/klauspost/compress" + packages = ["flate"] + revision = "6c8db69c4b49dd4df1fff66996cf556176d0b9bf" + version = "v1.2.1" + +[[projects]] + name = "github.com/klauspost/cpuid" + packages = ["."] + revision = "ae7887de9fa5d2db4eaa8174a7eff2c1ac00f2da" + version = "v1.1" + +[[projects]] + name = "github.com/klauspost/crc32" + packages = ["."] + revision = "cb6bfca970f6908083f26f39a79009d608efd5cd" + version = "v1.1" + +[[projects]] + name = "github.com/klauspost/pgzip" + packages = ["."] + revision = "0bf5dcad4ada2814c3c00f996a982270bb81a506" + version = "v1.1" + +[[projects]] + name = "github.com/mattn/go-isatty" + packages = ["."] + revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" + version = "v0.0.3" + +[[projects]] + name = "github.com/pkg/errors" + packages = ["."] + revision = "645ef00459ed84a119197bfb8d8205042c6df63d" + version = "v0.8.0" + +[[projects]] + name = "github.com/tj/go-update" + packages = [".","progress"] + revision = "8831a6e7cfe17e95cc0e3cffdb541518e5985927" + version = "v1.0.0" + +[[projects]] + name = "github.com/ulikunitz/xz" + packages = [".","internal/hash","internal/xlog","lzma"] + revision = "0c6b41e72360850ca4f98dc341fd999726ea007f" + version = "v0.5.4" [[projects]] branch = "v2" @@ -37,6 +121,12 @@ packages = ["."] revision = "b2bf3c5abeb90da407891aecd1df2c5a1f6170c1" +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = ["unix"] + revision = "ebfc5b4631820b793c9010c87fd8fef0f39eb082" + [[projects]] branch = "v2" name = "gopkg.in/yaml.v2" @@ -46,6 +136,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "9321fa9c5df11da6d3ee0d88476b21aab5460ed90082475980b17acf8bb7bab4" + inputs-digest = "f6b0aaa9a65f6751e591bc5f333fc05637978d820168a6e06aef29b7f3503439" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 48a72bc..82a323f 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -33,10 +33,10 @@ name = "github.com/atrox/store" version = "1.0.1" -[[constraint]] - branch = "master" - name = "github.com/equinox-io/equinox" - [[constraint]] branch = "v2" name = "github.com/urfave/cli" + +[[constraint]] + name = "github.com/tj/go-update" + version = "1.0.0" diff --git a/commands/update.go b/commands/update.go index e0d2639..256c1cc 100644 --- a/commands/update.go +++ b/commands/update.go @@ -1,6 +1,8 @@ package commands import ( + "fmt" + "github.com/atrox/cain/updater" "github.com/urfave/cli" ) @@ -12,9 +14,13 @@ var UpdateCommand = &cli.Command{ } func updateAction(c *cli.Context) error { - err := updater.ForceRun() + appUpdater := updater.New(true) + updated, err := appUpdater.Run() if err != nil { return cli.Exit(err, 1) } + if !updated { + b.Println("You are on the newest version", "", fmt.Sprintf("Version %s", updater.Version)) + } return nil } diff --git a/main.go b/main.go index ed661ca..22a9fe3 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,10 @@ var ( appUpdater *updater.Updater ) +func init() { + updater.Version = version +} + func main() { cmds := []*cli.Command{ commands.SetupCommand, @@ -58,7 +62,11 @@ func after(c *cli.Context) error { return nil } - return appUpdater.Run() + _, err := appUpdater.Run() + if err != nil { + return cli.Exit(err, 1) + } + return nil } var logo = strings.TrimLeft(fmt.Sprintf(` diff --git a/updater/equinox.go b/updater/equinox.go deleted file mode 100644 index 11f0cb6..0000000 --- a/updater/equinox.go +++ /dev/null @@ -1,13 +0,0 @@ -package updater - -// appID from equinox -const appID = "app_4SbsY14WUcg" - -// public portion of signing key generated by `equinox genkey` -var publicKey = []byte(` ------BEGIN ECDSA PUBLIC KEY----- -MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEGj6kWvbx0d2YcEmM2KijWSnTenwsSB22 -/AH1+uK39i6Jr4mfIN20WR1+w2jtxCnmqiz0yiomSJA5TxJ9mbyp/G0o3/0Rt/Yq -3F9GZBmWbduYawWwP5pgPduPWZlTDf7Q ------END ECDSA PUBLIC KEY----- -`) diff --git a/updater/updater.go b/updater/updater.go index bf4978d..9b7fc87 100644 --- a/updater/updater.go +++ b/updater/updater.go @@ -1,109 +1,124 @@ package updater import ( + "errors" "fmt" - "log" + "runtime" "time" "github.com/atrox/box" "github.com/atrox/cain/config" - "github.com/equinox-io/equinox" + "github.com/tj/go-update" + "github.com/tj/go-update/progress" ) -var b = box.New() +var ( + Version string + b = box.New() +) type Updater struct { NextCheck time.Time `yaml:"nextCheck"` + project *update.Project automaticUpdate bool - updateAvailable chan *equinox.Response + updateAvailable chan *update.Release } func New(autoUpdate bool) *Updater { updater := new(Updater) config.Storage.Get(updater) + updater.project = &update.Project{ + Command: "cain", + Owner: "Atrox", + Repo: "cain", + Version: Version, + } updater.automaticUpdate = autoUpdate - updater.updateAvailable = make(chan *equinox.Response) + updater.updateAvailable = make(chan *update.Release) go updater.check() return updater } -func (u *Updater) Run() error { - update := <-u.updateAvailable - if update == nil { - return nil +func (u *Updater) Run() (bool, error) { + release := <-u.updateAvailable + if release == nil { + return false, nil } if !u.automaticUpdate { b.Println( - fmt.Sprintf("%s (%s)", update.ReleaseTitle, update.ReleaseDate.Format("02.01.2006")), "", + fmt.Sprintf("%s (%s)", release.Version, release.PublishedAt.Format("02.01.2006")), "", "New Version of Cain is available!", - "Update automatically with 'cain update'") + "Update instantly with 'cain update'") - return nil + return false, nil } - b.Println("Updating...", "", "Please don't close me while I'm working") + return true, u.update(release) +} - // fetch the update and apply it - err := update.Apply() - if err != nil { - return err +func (u *Updater) check() { + if !u.shouldCheck() { + u.updateAvailable <- nil + return } - b.Println(fmt.Sprintf("%s (%s)", update.ReleaseTitle, update.ReleaseDate.Format("02.01.2006")), "", - "Successfully updated!") - return nil -} + u.setNext() -func ForceRun() error { - var opts equinox.Options - err := opts.SetPublicKeyPEM(publicKey) + // fetch latest release + release, err := u.fetchRelease() if err != nil { - log.Fatal(err) + u.updateAvailable <- nil + return } - update, err := equinox.Check(appID, opts) + u.updateAvailable <- release +} + +func (u *Updater) fetchRelease() (*update.Release, error) { + // fetch the new releases + releases, err := u.project.LatestReleases() if err != nil { - return err + return nil, err } - b.Println("Updating...", "", "Please don't close me while I'm working") - - // fetch the update and apply it - err = update.Apply() - if err != nil { - return err + // no updates + if len(releases) == 0 { + return nil, nil } - b.Println(fmt.Sprintf("%s (%s)", update.ReleaseTitle, update.ReleaseDate.Format("02.01.2006")), "", - "Successfully updated!") - return nil + // latest release + latest := releases[0] + return latest, nil } -func (u *Updater) check() { - if !u.shouldCheck() { - u.updateAvailable <- nil - return - } +func (u *Updater) update(release *update.Release) error { + b.Println("Updating...", "", "Please don't close me while I'm working") - u.setNext() + // find the tarball for this system + asset := release.FindTarball(runtime.GOOS, runtime.GOARCH) + if asset == nil { + b.Println("No binary for your system is published", "", "Go to https://github.com/Atrox/cain/releases") + return errors.New("No binary for your system is published on GitHub") + } - var opts equinox.Options - err := opts.SetPublicKeyPEM(publicKey) + // download tarball to a tmp dir + tarball, err := asset.DownloadProxy(progress.Reader) if err != nil { - log.Fatal(err) + return err } - resp, err := equinox.Check(appID, opts) - if err != nil { - u.updateAvailable <- nil - return + // install it + if err := u.project.Install(tarball); err != nil { + return err } - u.updateAvailable <- &resp + b.Println(fmt.Sprintf("%s (%s)", release.Version, release.PublishedAt.Format("02.01.2006")), "", + "Successfully updated!") + return nil } func (u *Updater) shouldCheck() bool {